avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] possible compiler bug?


From: Theodore A. Roth
Subject: Re: [avr-gcc-list] possible compiler bug?
Date: Wed, 28 Aug 2002 16:44:18 -0700 (PDT)

Brian,

Have tried using OCR1A instead of OCR1AL?

>From the iom128.h file:

/* Timer/Counter1 Output Compare Register A */
#define OCR1A   _SFR_IO16(0x2A)
#define OCR1AL    _SFR_IO8(0x2A)
#define OCR1AH    _SFR_IO8(0x2B)

I wonder if you are confusing the compiler by telling it to make a pointer
out of an 8 bit register instead of a 16bit one.

While playing around, here's some various output from objdump:

  pwmreg = (uintptr_t *)OCR1AL;
  e2:   8a b5           in  r24, 0x2a   ; 42
  e4:   99 27           eor r25, r25

and

  pwmreg = (uintptr_t *)OCR1A;
  e2:   8a b5           in  r24, 0x2a   ; 42
  e4:   9b b5           in  r25, 0x2b   ; 43

This is a 16 bit read and the low byte was first, which matches the data
sheet (for m128).

And your original code generated this:

  pwmval = 512;
  da:   80 e0           ldi r24, 0x00   ; 0
  dc:   92 e0           ldi r25, 0x02   ; 2
  de:   89 83           std Y+1, r24    ; 0x01
  e0:   9a 83           std Y+2, r25    ; 0x02
  pwmreg = (uint16_t *)_SFR_ADDR(OCR1AL);

  set_pwm(pwmreg, pwmval);
  e2:   69 81           ldd r22, Y+1    ; 0x01
  e4:   7a 81           ldd r23, Y+2    ; 0x02
  e6:   8a e4           ldi r24, 0x4A   ; 74
  e8:   90 e0           ldi r25, 0x00   ; 0
  ea:   0e 94 65 00     call    0xca

Your code doesn't even generate any 'in' statements. ???

And just for grins, I tried a 16 write to see if high byte is frist:

  TCNT1 = 0xaa55;
  e2:   85 e5           ldi r24, 0x55   ; 85
  e4:   9a ea           ldi r25, 0xAA   ; 170
  e6:   9d bd           out 0x2d, r25   ; 45
  e8:   8c bd           out 0x2c, r24   ; 44

which looks good to me.

Ted Roth

On Wed, 28 Aug 2002, Brian Dean wrote:

:) Hi,
:)
:) I think there may be a bug in the code generation for writing 16 bit
:) values via a pointer.  Consider the following code:
:)
:)      #include <inttypes.h>
:)      #include <io.h>
:)
:)      void set_pwm(volatile uint16_t * pwmreg, uint16_t pwm)
:)      {
:)        *pwmreg = pwm;
:)      }
:)
:)
:)      int main(void)
:)      {
:)        volatile uint16_t * pwmreg, pwmval;
:)
:)        pwmval = 512;
:)        pwmreg = (uint16_t *)_SFR_ADDR(OCR1AL);
:)
:)        set_pwm(pwmreg, pwmval);
:)      }
:)
:) The generated assembler (below) appears to load the low byte first and
:) then the high byte.  However, the AVR data sheets state that when
:) accessing 16 bit registers such as the output compare registers, that
:) the high byte must be loaded first followed by the low byte.  I had an
:) elusive bug in a recent project that turned out to be due to this.
:) After I forced the high byte be written first, followed by the low
:) byte, my problems disappeared.
:)
:) While this shouldn't make any difference for writing to real RAM
:) locations, it makes a big difference when writing to memory mapped I/O
:) ports.
:)
:) The compiler version is:
:)
:)      Reading specs from /usr/local/lib/gcc-lib/avr/3.3/specs
:)      Configured with: ./configure --target=avr --prefix=/usr/local 
i386-portbld-freebsd4.6
:)      Thread model: single
:)      gcc version 3.3 20020812 (experimental)
:)
:) Thanks,
:) -Brian
:) --
:) Brian Dean                                   address@hidden
:)
:)         .file   "bug.c"
:)         .arch atmega163
:) __SREG__ = 0x3f
:) __SP_H__ = 0x3e
:) __SP_L__ = 0x3d
:) __tmp_reg__ = 0
:) __zero_reg__ = 1
:) _PC_ = 2
:)         .global __do_copy_data
:)         .global __do_clear_bss
:)         .text
:) ..global set_pwm
:)         .type   set_pwm, @function
:) set_pwm:
:) /* prologue: frame size=0 */
:) /* prologue end (size=0) */
:)         movw r30,r24
:)         st Z,r22
:)         std Z+1,r23
:) /* epilogue: frame size=0 */
:)         ret
:) /* epilogue end (size=1) */
:) /* function set_pwm size 4 (3) */
:)         .size   set_pwm, .-set_pwm
:) ..global main
:)         .type   main, @function
:) main:
:) /* prologue: frame size=2 */
:)         ldi r28,lo8(__stack - 2)
:)         ldi r29,hi8(__stack - 2)
:)         out __SP_H__,r29
:)         out __SP_L__,r28
:) /* prologue end (size=4) */
:)         ldi r24,lo8(512)
:)         ldi r25,hi8(512)
:)         std Y+1,r24
:)         std Y+2,r25
:)         ldd r22,Y+1
:)         ldd r23,Y+2
:)         ldi r24,lo8(74)
:)         ldi r25,hi8(74)
:)         call set_pwm
:) /* epilogue: frame size=2 */
:)         jmp exit
:) /* epilogue end (size=2) */
:) /* function main size 16 (10) */
:)         .size   main, .-main
:) /* File "bug.c": code   20 = 0x0014 (  13), prologues   4, epilogues   3 */
:) avr-gcc-list at http://avr1.org
:)

avr-gcc-list at http://avr1.org



reply via email to

[Prev in Thread] Current Thread [Next in Thread]