On the AVR when one makes an assignment of a value through a 16 bit pointer,
avr-gcc is assigning the low byte, then high byte.  However, many uses of a
pointer like this are for situations such as pointing at 16-bit registers.  In
such cases, the assignment should be made high byte first, then low byte, as
per Atmel data-sheets due to the sequence of the latching mechanism.

[The follow emphasis is Atmel's from the data-sheet]:

"On the AVR to do a 16-bit write, *THE HIGH BYTE MUST BE WRITTEN BEFORE THE LOW
BYTE*. For a 16-bit read, THE LOW BYTE MUST BE READ BEFORE THE HIGH BYTE."

This applies to all internal 16 bit I/O registers.
 
The following example generates incorrect code if the pointer points to 16-bit
I/O register mapped into SRAM (outside of I/O space):

main.i:
# 1 "main.c"
# 1 "C:\\BKU\\Projects\\SC200\\SourceCode\\GCCTests//"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "main.c"
# 28 "main.c"
volatile unsigned short *ptr_u16;

int main( void )
{
    ptr_u16 = (unsigned short *) (*(volatile unsigned short *)0x0086);

    *ptr_u16 = 0x1234;
}

Bad output:

  34                    .LM3:
  35 0018 84E3                  ldi r24,lo8(4660)
  36 001a 92E1                  ldi r25,hi8(4660)
  37 001c 8083                  st Z,r24 <----- low byte assigned first 
[INCORRECT]
  38 001e 9183                  std Z+1,r25

Command Line:
avr-gcc -c -mmcu=atmega162 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -funsigned-char
-funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes
-Wa,-adhlns=main.lst  -std=gnu99 -v --save-temps -MD -MP -MF .dep/main.o.d
main.c -o main.o 

Build specs:

Reading specs from C:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/specs
Configured with: ../gcc-3.4.3/configure --prefix=m:/WinAVR --build=mingw32
--host=mingw32 --target=avr --enable-languages=c,c++ --with-dwarf2
Thread model: single
gcc version 3.4.3
 C:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/../../../../avr/bin/ld.exe -m avr5 -Tdata
0x800100 -o main.elf
C:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5/crtm162.o
-LC:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/avr5
-LC:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3 -LC:/WINAVR~2/BIN/../lib/gcc
-LC:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5
-LC:/WINAVR~2/BIN/../lib/gcc/avr/3.4.3/../../../../avr/lib main.o -Map=main.map
--cref -lm -lgcc -lc -lgcc

-- 
           Summary: AVR assignment of a value through a 16 bit pointer
                    generates out of order code
           Product: gcc
           Version: 3.4.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: bob dot paddock at gmail dot com
                CC: ericw at evcohs dot com,gcc-bugs at gcc dot gnu dot org
GCC target triplet: AVR


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20288

Reply via email to