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 ""
# 1 ""
# 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=800UL -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