[Bug c/20288] New: AVR assignment of a value through a 16 bit pointer generates out of order code

2005-03-02 Thread bob dot paddock at gmail dot com
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


[Bug target/20288] AVR assignment of a value through a 16 bit pointer generates out of order code

2005-03-03 Thread bob dot paddock at gmail dot com

--- Additional Comments From bob dot paddock at gmail dot com  2005-03-03 
13:13 ---
(In reply to comment #5)

>Personally see no problem.  The quote above has specifically to do with how to
>write a logical 16-bit timer/counter value into a pair of otherwise distinct
>8-bit registers, which controls a specific peripheral function which presumes a
>specific write sequence to maintainthe logical integrety of that specific
timer/counter value; it has nothing to with 16-bit pointers,
>the sequencing of multi-byte logical data type transactions, or the compiler in
>general.

It is specific to the pointer case because the correct order of operations is
generated in all other cases.  Due to the limited Flash space of the AVR it is
common to have structures of pointers pointing to the hardware registers, so
that the same code will work with both Output Compare One, and Output Compare
Three for example.

The Input Capture and Output Compare registers are truly 16-bits in length,
they are not distinct 8-bit registers.  They are accessed 8-bits at a time.

To access the 16-bit registers 8-bits at a time without use of the hardware
latching mechanism would require that interrupts be disabled.  In many embedded
applications this is unacceptable, hence the hardware is provided to deal with
this problem.

By not disabling interrupts and not using the hardware latching mechanism the
embedded device, be it a Cruse Control or Phase Control System, is going to
have outputs that are off by a factor of 256 at apparently "random" times.

If the complier can not be made to generate correct code for this case then the
compile should fail.  Consider that if the the order of 16-bit operations I/O
was wrong in all cases then the GCC would not be usable on the AVR.

"Asynchronous Hardware/Firmware" by Jack Ganssle at
http://www.ganssle.com/articles/asynchf.htm goes into the gory details of why
this type of failure in a embedded device is down right dangerous.


-- 


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