Bez tytułu

z Aqua Kitten, 4 tygodnie temu, napisane w Plain Text, wyświetlone 62 razy.
URL https://pastebin.k4be.pl/view/2f7f901a Udostępnij
Pobierz wklejkę lub Pokaż surowy tekst
  1. avr-gcc -Os: __flash disregarded for some struct array accesses
  2.  
  3. At -Os, avr-gcc generates a plain ld (RAM load) instead of lpm (flash load) for the first field of a const __flash-qualified struct array element, while correctly emitting lpm for the second field of the same element. The struct's first field ends up reading garbage off RAM space instead of the intended flash-resident constant.
  4.  
  5. Reproduced with:
  6. - avr-gcc (Gentoo 15.2.1_p20260214 p5) 15.2.1
  7. - avr-gcc 13.2.1
  8. - git revision b6825a7ce698b65657e952e437ab9edd655fe5a5 (2026-07-06)
  9.  
  10. Not reproduced with -O0, -O1, -O2, only -Os.
  11.  
  12. Bug not present in a 2020 build (unknown avr-gcc version).
  13.  
  14. Minimal reproduction
  15.  
  16. #include <avr/io.h>
  17.  
  18. struct pair { unsigned char data; unsigned char cmd; };
  19. const __flash struct pair table[] = { {0x11, 1}, {0x33, 0}, {0x55,1} };
  20.  
  21. void write_data(unsigned char d);
  22. void write_cmd(unsigned char c);
  23.  
  24. void test(void){
  25.     unsigned char i;
  26.     for(i=0; i<3; i++){
  27.         if(table[i].cmd) write_data(table[i].data); else write_cmd(table[i].data);
  28.     }
  29. }
  30.  
  31. Build:
  32. avr-gcc -Os -mmcu=atmega8 -I/usr/avr/include -S -o test.s test.c
  33.  
  34. Relevant output (-Os):
  35. test:
  36.     push r28
  37.     push r29
  38.     ldi r28,lo8(table)
  39.     ldi r29,hi8(table)
  40. .L4:
  41.     movw r30,r28
  42.     ld r24,Z+          ; <-- BUG: reads table[i].data from DATA SPACE (SRAM), not flash
  43.     lpm r25,Z           ; correct: reads table[i].cmd from flash
  44.     cpi r25,lo8(0)
  45.     breq .L2
  46.     rcall write_data    ; called with garbage r24 (SRAM byte at address `table`), not 0x11/0x33/0x55
  47. .L3:
  48.     adiw r28,2
  49.     ldi r24,hi8(table+6)
  50.     cpi r28,lo8(table+6)
  51.     cpc r29,r24
  52.     brne .L4
  53.     pop r29
  54.     pop r28
  55.     ret
  56. .L2:
  57.     rcall write_cmd
  58.     rjmp .L3
  59.  
  60. A single, non-looping access to the same kind of struct correctly uses lpm at every optimization level tested, so this may be specific to the loop/pointer-increment shape above, not __flash struct access in general:
  61.  
  62. struct pair { unsigned char a; unsigned char b; };
  63. const __flash struct pair table[] = { {0x11, 0x22}, {0x33, 0x44} };
  64.  
  65. unsigned char out;
  66. void test(unsigned char i){
  67.     out = table[i].a;   // correctly compiles to lpm at -Os
  68. }
  69.  
  70. Workaround: replace const __flash with PROGMEM, use pgm_read_* for access.

odpowiedź "Bez tytułu"

Tutaj możesz odpowiedzieć na wklejkę z góry

captcha