This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

#pragma DATA_SECTION and .cinit

Hello all,

Hopefully just a quick question.  I would like to pragma some initialized data into RAM and not have an entry generated in the .cinit table, but instead load the data from a different region in flash.  Is this possible?

For example:

#pragma DATA_SECTION(test_var, ".test_var_section");

unsigned int test_var[100] = {0,1,2,3,4...99};

.test_var_section LOAD = FLASH, RUN = RAM

{

   *(.test_var_section)

The above statements will generate a .cinit entry and allocate the data in ram.

What I would like to do is RUN the data from RAM and initialize it from a different region of flash as specified in the Linker Command File.

The problem comes during linking, when the LOAD rule is ignored becuase the .test_var_section has been created as an un-initalized section.

Looking at the assemlbly, a .cinit section has been created to hold the initialized values and a un-initialize section has been used to instantiate the data.  This causes a problem when trying to move the data with the above pragma.

Is there any way ,other than writing assembly code, to bypass the creation of the .cinit entry used for initialization, and instead use the flash region specified in the Linker Command File.

Thanks,

Paul

  • Could the data be treated as const?  If so, declare the array as const and it will not participate in .cinit.

  • Thank for the reply.

    We have tried this and marking that data as "const" will not work, as the data is really not const.

    The compiler will error with "const unsigned int *"  is incompatible with parameter of type "unsigned int *".

    We have found that if we declare the data as "const" in the *.c file and do not mark the data extern as "const" in the *.h it works...but this is dirty and not recommended (plus also probably violates some C standard) and will confuse future developers.

    Thanks,

    Paul

  • Declare the array "const".  Put it in a section you name with the DATA_SECTION pragma.  Allocate it to flash for loading and RAM for execution.  The copy from flash to RAM has to be explicitly performed before the data can be accessed.  Use the copy tables described in this app note to make that step easy.

    Thanks and regards,

    -George

  • Thank all of you for the replies.

    The problem with marking the array const is that the values cannot be changed during runtime, technically.  As a matter of fact, the compiler will not allow you to do this and produces an error indicating as such. The error being "expression must be a modifiable lvalue."  which makes complete sense.

    The real issue here is that moving data with a #pragma statement should prevent the data from ending up in the ".cinit" section, and it should be the users responsibility  to take care of the initialization of any data that has been specifically relocated to a different section.

    Thanks,

    Paul

  • Paul P. (P Squared) said:
    The problem with marking the array const is that the values cannot be changed during runtime

    You made that point earlier.  Sorry I overlooked it.

    Paul P. (P Squared) said:
    The real issue here is that moving data with a #pragma statement should prevent the data from ending up in the ".cinit" section

    Such is not the case.  The initialization records contained within .cinit can initialize data that resides in any uninitialized section, anywhere in memory.  This is the only mechanism the compiler has for initializing global variables.  Note .cinit is a read-only section.  Thus it can be placed in flash.

    If you still want the initialization of your #pragma DATA_SECTION array to be done outside of .cinit, then I suggest this ... Do not initialize the array at all.  Define yet another array called "for_init".  Mark it const, and use #pragma DATA_SECTION on it.  Initialize for_init with the initial values for your array.  In the link command file, place the for_init section in flash.  At the appropriate time, use memcpy to initialize your array with the contents of for_init.

    Thanks and regards,

    -George

  • In Standard C, "const" really means "read only", not "constant".  You can use the "const" qualifier in the "definition" of the data object, preferably in a translation unit (source file) separate from any that may refere to the object; this will affect which section the compiler will assign it to, and .cinit should not include it.  Then, the declaration(s) of the object (probably in a header file) can be non-"const"-qualified, so the code that accesses the object will not be seen to be in conflict with the not-currently-visible elsewhere-const-specification.  There would be a genuine violation of the *semantic* specification in the C standard only if in fact the object was not modifiable (e.g. its run-time location is in ROM and an attempt is made to modify its contents).

    In my opinion, the .cinit mechanism is insufficiently flexible.  For example, I'd really like to be able to easily specify appending an entry to the .cinit table saying that a designated ROM section should be copied to a designated RAM section, not involving named variables.  That way, the normal _c_int00 running out of ROM (after being called by the RESET vector) could boot-load the entire part of the application that has been built to load into ROM but run out of RAM.  There would be no need for a separate boot-loader as such.