views:

231

answers:

2

I've spent a good while getting my AVR development system set up with the full GCC tool chain (everything is the most recent current stable version) and I have solved most issues with it but one.

This following code gives me an error which I just don't get. The AVR assembly manual states that the sbi instruction can accept 0-7 as a constant expression but it still errors out on me. Can anyone shed some light onto why it does this please?

  #ifndef __AVR_ATmega168__
      #define __AVR_ATmega168__
  #endif

  #include <avr/io.h>

      rjmp Init

  Init:

      ser r16
      out DDRB, r16
      out DDRD, r16

      clr r16

      out PORTB, r16
      out PORTD, r16

  Start:

      sbi PORTB, 0
      rjmp Start

The line in question is sbi PORTB, 0.

Compiled / assembled with:

avr-gcc ledon.S -mmcu=atmega168

+2  A: 

I think it's complaining about PORTB rather than the bit number (0). How have you defined PORTB ? It needs to be in the range 0..31. You may need to subtract 32 from PORTB if your ports are defined in the range 32..63 ?

Paul R
Thanks for the help but PORTB is defined in <avr/io.h> (indirectly - io.h includes iom168.h which then includes iomx8.h which actually defines it) as 0x05 so that should not be the problem either.
Simon
Just as an experiment try changing: `sbi PORTB, 0` to `sbi 5, 0` to see if you get the same error.
Paul R
Thanks for the help. That got me on the right track to fixing the problem, see my comment to the other answer if you are interested.
Simon
+3  A: 

If you comment out the offending line and just compile the rest, you can take a look at the resulting object file with avr-objdump -D ledon.o.

That will show you that the value of PORTB is actually 0x25, and thus out of range for sbi like Paul suggested.

00000002 <Init>:
   2:   0f ef           ldi     r16, 0xFF       ; 255
   4:   04 bd           out     0x24, r16       ; 36
   6:   0a bd           out     0x2a, r16       ; 42
   8:   00 27           eor     r16, r16
   a:   05 bd           out     0x25, r16       ; 37
   c:   0b bd           out     0x2b, r16       ; 43
ndim
Well, I'll be damned. Thanks for that. That lead me to find the fix for the this annoying problem. Alas I can't mark both as the correct answer even though you both helped.Anyway it turns out the problem was that the AVR libc sets defines __SFR_OFFSET internally if you don't manually define it as 0x20 which results in the problem shown above. If you need to use the header files then you need to define it yourself as 0 before you include them in order to remain compatible.
Simon
I'm pretty sure you can't sbi a port number on any avr, and by changing the libc (!), you are probably making the sbi work on r6.
Jens Björnhager
@Jens - actually the comments in the header file in question state that you should define __SFR_OFFSET yourself if you are using something that does not make use of the offset (well my assembly code doesn't and neither do any of the examples in the book I am working from). So unless this book is fundamentally wrong then I have to assume that you can sbi a port.
Simon
@Jens: On this 644 I am working with `PORTD ` is translated into `5e 98 cbi 0x0b, 6`, so there *are* AVRs on which you can `cbi`/`sti` a port directly. For some strange reason, if I run this command through gcc with `-mmcu=atmega164p`, I get the same machine code as for the 644. So the __SFR_OFFSET automatically being defined to 0x20 is a little strange, to say the least.
ndim
Whoops, I have been reading sbi as subi all along.
Jens Björnhager
@Jens: That explains a few things. :-)
ndim