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: Brian Dean
Subject: Re: [avr-gcc-list] possible compiler bug?
Date: Wed, 28 Aug 2002 20:15:24 -0400
User-agent: Mutt/1.4i

On Wed, Aug 28, 2002 at 04:44:18PM -0700, Theodore A. Roth wrote:
> Brian,
> 
> Have tried using OCR1A instead of OCR1AL?

Yes, no change.

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

This is due to accessing the ports via the memory mapped I/O space,
i.e., you can access all the I/O ports using memory operations if you
add 0x20 to the I/O port value.

> 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.

Hmmm ... playing around here, the following small change to the code,
adding *pwmreg = pwmval; in main:

        #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(OCR1A);

          *pwmreg = pwmval;               /* <-------- this line */

          set_pwm(pwmreg, pwmval);
        }

The line above labeled "this line" seems to result in correct code
(see below) generation (high byte first, followed by low byte).  So
why doesn't it get generated correctly within the set_pwm() function?
Note that 'out' instructions are actually generated here, but 0x20 is
subtracted first (as is required).

I guess that within 'main()', the compiler "knows" the actual value in
the pointer and can take advantage of that knowledge, but within
'set_pwm()', there's no way the compiler can know what value is going
to be passed in and must treat it more generically.

I guess I still don't see why _all_ 16 bit writes can't be done high
byte first, unless someone knows of a case where, for a 16 bit write,
the _low_ byte must be written first for proper operation.  Does
anyone have an example from the Atmel datasheets of this "rule" being
violated?  I would think that Atmel would be consistant in this as all
AVR's share a nearly identical core.

-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 r24,Y+1
        ldd r25,Y+2
        out (74)+1-0x20,r25
        out 74-0x20,r24
        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 20 (14) */
        .size   main, .-main
/* File "bug.c": code   24 = 0x0018 (  17), prologues   4, epilogues   3 */
avr-gcc-list at http://avr1.org



reply via email to

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