cgcclinkerembedded

Forcing const arrays of pointers to const arrays into read-only memory with gcc? ('causes a section type conflict')


#include <stdio.h>
__attribute__ ((section(".text"))) static const int one[2] = { 1, 2 };
__attribute__ ((section(".text"))) static const int two[2] = { 3, 4 };

static const int* parent[2] = { one, two };

If I place the array 'parent' above in .text I get this error:

sections.c:5:54: error: parent causes a section type conflict with one

This appears to be because the addresses of one and two, although known at link time, are being considered as if they were variables - and therefore parent is being initialised at run time, which means it is placed in RAM. However the system I am compiling for is a small 8-bit micro with very little RAM and so I need to put not only simple const arrays in ROM (actual literal EPROM), but also arrays of arrays, where the elements are the base addresses of the simpler arrays which were successfully placed in a ROM segment.

Programs for this environment execute at a fixed address so there are no complicating issues such as relocatable code or a linking loader that may put code at some random address - the code in EPROM is fixed at address 0000.

What can I do to force these const arrays of const arrays to be placed in read-only memory?

Although the target system is a 6809 micro, I'm relatively confident you do not need to look for a 6809-specific explanation or workaround - it's a generic gcc problem and I believe a solution that would work on i686 or arm linux would work just as well for my environment (which is the Vectrex video game console).

I have looked at other answers here concerning the 'causes a section type conflict' error, but none offered an answer relevant to the problem of initialising const arrays with data that the compiler/linker ought to know the address of. If I compile without the section attribute, it does compile but it places those specific arrays in RAM and the linker warns ?ASlink-Warning-Size limit exceeded in bank ram and of course it fails at runtime.

int main(int argc, char **argv) {
  int i, j, k=0;
  for (i = 0; i < 2; i++) {
    for (j = 0; j < 2; j++) {
      k += parent[i][j];
    }
  }
  fprintf(stderr, "tot = %d\n", k);
  return 0;
}

Solution

  • The normal way to do it on most compilers is to declare the variable to be allocated in ROM as a read-only variable. With pointers, that is done like this:

    static const int* const parent[2] = { one, two };
    

    However, if you are short on flash/eeprom then this is probably not the best idea since the addresses in the array will take up extra space - and for what gain? You really should consider allocating a 2D array instead, if possible.