Question about timer0 and relative branch out of reach error

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
.include "m2560def.inc"

    
.equ cf = 3 ;current floor
.equ ef = 5 ; expect floor
.equ direction = 0 ;0 down 1 up 




Start:
    clr r20
    clr r21
    clr r22
    ser r16
    out DDRC, r16 // set Port A for output
    ser r16
    out DDRG, r18 //
    ldi r20,cf
    ldi r21,ef
    ldi r22,direction

Loop:

    cpi r20,ef
    rjmp Go_up  //error here !!!!!!!!!
    breq end


Go_down:
    ldi r22,0
    rjmp Condition

Go_up:
    ldi r22,1
    rjmp Condition



Condition:
    cpi r20, 1
    breq First_Floor
    cpi r20, 2
    breq Second_Floor
    cpi r20, 3
    breq Third_Floor
    cpi r20, 4
    breq Forth_Floor
    cpi r20, 5
    breq Fifth_Floor
    cpi r20, 6
    breq Sixth_Floor
    cpi r20, 7
    breq Seventh_Floor
    cpi r20, 8
    breq Eighth_Floor
    cpi r20, 9
    breq Ninth_Floor
    cpi r20, 10
    breq Tenth_Floor


First_Floor:

    ldi r16, 0x00  // write the pattern
    out PORTC, r16
    ldi r18, 0x04
    out PORTG, r18

    cpi r22,1   //error here !!!!!!!!!
    breq goup
    rjmp godown

Second_Floor:

    ldi r16, 0x00  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Third_Floor:

    ldi r16, 0x01  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Forth_Floor:

    ldi r16, 0x03  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Fifth_Floor:

    ldi r16, 0x07  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Sixth_Floor:

    ldi r16, 0x0F  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Seventh_Floor:

    ldi r16, 0x1F  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Eighth_Floor:

    ldi r16, 0x3F  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Ninth_Floor:

    ldi r16, 0x7F  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

Tenth_Floor:

    ldi r16, 0xFF  // write the pattern
    out PORTC, r16
    ldi r18, 0x0C
    out PORTG, r18

    cpi r22,1
    breq goup
    rjmp godown

goup:
    inc r22
    rjmp Loop


godown:
    dec r22
    rjmp Loop

end:
    rjmp end

Line 26 and 70 have the error about "relative branch out of reach "

How could I fix it?

Moreover, I am asked to use timer0 to count 2 seconds for each loop, could anyone tell me how to do this?

 

Thanks a lot!

Last Edited: Mon. Mar 25, 2019 - 06:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings and Welcome to AVR Freaks =

 

rjmp (relative jump) has a VERY limited jump range. Use one of the absolute jump instructions, instead. Though, that jump does not look particularly large.

 

The cpi seems OK. You reference a register in the upper 16, as required, and the constant is in the range of 0 to 255. Don't see a problem, there.

 

Are you certain that you are referencing the correct lines, because the cpi instruction does not involve any jumps. But the nearby branch does.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Mon. Mar 25, 2019 - 06:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheTrueManHere wrote:
How could I fix it?

 

place the goup / godwn functions after floor6 and before floor7 code, in other words, move the function down lower in the code so each call to it is a shorter distance!

 

As for the timer question, go read the tutorial in the tutorial forum on timers, you should find your answer there.

 

Jim

PS:  Welcome to AVRFreaks.

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheTrueManHere wrote:
Moreover, I am asked to use timer0 to count 2 seconds for each loop, could anyone tell me how to do this?

 

MUST you use assembler?  C would be so much easier.

 

 

But anyway, WHat is your AVR clock speed, and do you have the DIV8 fuse programmed?  From there one can figure out what timer to use to make a 'tick' every 10 milliseconds and generate an interrupt where a counter can be incremented.

 

Your main code looks at this counter and determine if enough 'ticks' have passed for two seconds.  Once this has happened you 'do something', clear the counter and repeat the process.

 

Jim

I would rather attempt something great and fail, than attempt nothing and succeed - Fortune Cookie

 

"The critical shortage here is not stuff, but time." - Johan Ekdahl

 

"Step N is required before you can do step N+1!" - ka7ehk

 

"If you want a career with a known path - become an undertaker. Dead people don't sue!" - Kartman

"Why is there a "Highway to Hell" and only a "Stairway to Heaven"? A prediction of the expected traffic load?"  - Lee "theusch"

 

Speak sweetly. It makes your words easier to digest when at a later date you have to eat them ;-)  - Source Unknown

Please Read: Code-of-Conduct

Atmel Studio6.2/AS7, DipTrace, Quartus, MPLAB, RSLogix user

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Wouldn't it be a lot clearer if you told use the content of the lines, for which you only gave line numbers?

 

Yes, sometimes you can re-arrange your code to avoid branches out of reach.  But you need to lean how to handle the situation if you are going to write in assembler.  The situation will arise wit all [?] micro processor/controller work, not just AVR.

 

There are prior threads on this.  Try searching them out.

 

A common method is to reverse the sense of the comparison, and introduce a branch with a longer reach.  Lessee--now I have to count your line numbers...

 

 

 

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

TheTrueManHere wrote:
Loop: cpi r20,ef rjmp Go_up //error here !!!!!!!!! breq end

I don't think that is where the error is. 

 

1) Surely the RJMP is within reach.

2)  The BREQ line will never be reached.

2a)  Learn to use the AtmelStudio simulator to see what I mean.

 

Reversing the sense...

   CPI R20, ef

   BRNE NEARBY

   RJMP END ; "FAR AWAY"

NEARBY:    ;  INTRODUCE THE LABEL

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, finally it works

The Atmel shows the wrong line

Thanks a lot

Last Edited: Tue. Mar 26, 2019 - 03:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, it works.

The rearrange work is really important in assembly, haha

 

Last Edited: Tue. Mar 26, 2019 - 03:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

When I built the code Studio 7 said:

 

 

When I double-click either of those errors it takes me to:

 

 

and

 

 

So it seems to be an "out by one" error. It's the "breq" in each case.

 

As Lee says a common solution is:

    cpi r22,1   //error here !!!!!!!!!
    brne dont_goup 
    jmp goup
dont_goup:    
    rjmp godown

That is to change the sense of the branch from breq to brne then do a "long jump"

 

BTW the sequence:

Loop:

    cpi r20,ef
    rjmp Go_up  //error here !!!!!!!!!
    breq end

The breq here is AFTER the rjmp - it can never be reached !!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In general only use BREQ etc. for things “inside” the block you are working with.

In this case invert the branch use BRNE over the a rjmp (as cliff showed).

If rjmp can’t reach I will say that your program start to be too big for ASM.(it reach +-2K instructions)

That way you don't need to rearange anything when you add things.

 

If you have many jumps out from one variable, (where you would use a switch in C), then it could make sense to build up to use a ijmp.     

Last Edited: Tue. Mar 26, 2019 - 10:56 AM