Search code examples
gccavratmegaavr-gcc

avr-gcc ATmega4809 problem with `.rodata` section


(This is a follow up of this question)

The following program doesn't work (in ATmega4809)

#include <avr/io.h>


void f(const char str[])
{
    if (str[0] == 'a')  // <-- here is the problem. The program thinks that str[0] != 'a'
        PORTC.OUT |= PIN0_bm;
    
     else 
        PORTC.OUT &= ~PIN0_bm;
   
}

const char str[] = "abc"; // this string the compiler stores in the .rodata section

int main()
{
    PORTC.DIR |= PIN0_bm;

    while (1) { f(str); }
}

The problem is that the compiler writes str in the .rodata section.

If I change the definition of str forcing the compiler to write it in the .data section:

const char str[] __attribute__((section(".data")))  = "abc";

the program works.

(You can see all the details in my previous question)

My questions are:

  1. How can I force the compiler to write all the const strings into the .data section so my programs work?

  2. is this a bug in avr-gcc 13.3.0?


Solution

  • How can I force the compiler to write all the const strings into the .data section so my programs work?

    This is the wrong question for the wrong solution. The problem is somewhere else, for example you are uploading .text and .data to the device but are missing .rodata. When I

    $ avr-gcc-13 x.c -mmcu=atmega4809 -o x.elf && avr-objdump -h x.elf && avr-objdump -P mem-usage x.elf
    
    x.elf:     file format elf32-avr
    
    Sections:
    Idx Name          Size      VMA       LMA       File off  Algn
      0 .data         00000000  00802800  00000130  000001c4  2**0
                      CONTENTS, ALLOC, LOAD, DATA
      1 .text         0000012c  00000000  00000000  00000094  2**1
                      CONTENTS, ALLOC, LOAD, READONLY, CODE
      2 .rodata       00000004  0000412c  0000012c  000001c0  2**0
                      CONTENTS, ALLOC, LOAD, READONLY, DATA
      3 .comment      0000001b  00000000  00000000  000001c4  2**0
                      CONTENTS, READONLY
      4 .note.gnu.avr.deviceinfo 00000040  00000000  00000000  000001e0  2**2
                      CONTENTS, READONLY, OCTETS
    ...
    
     x.elf:     file format elf32-avr
    AVR Memory Usage
    ----------------
    Device: atmega4809
    
    Program:     304 bytes (0.6% Full)
    (.text + .data + .rodata + .bootloader)
    
    Data:          0 bytes (0.0% Full)
    (.data + .bss + .noinit)
    

    So your problem is how are you uploading the binary, or how are you building the binary, or both.

    • Make sure that you are specifying -mmcu=atmega4809 when linking (provided you do a separate link invokation). Flash loaders like avrdude understand ELF; this is often easier and less error prone than building a HEX file.
    • Make sure that you are uploading .rodata to the target. In the example above, (at least) 304 bytes have to be uploaded according to avr-objdump -P mem-usage. Notice that .rodata display is a relatively new addition, see PR31687: Output of avr-objdump -P mem-usage missing .rodata, fixed in Binutils v2.43.