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.

Compiler/MSP432E401Y: #pragma DATA_SECTION requiring my variable be declared as constant

Part Number: MSP432E401Y

Tool/software: TI C/C++ Compiler

I am placing an array in the Flash memory block but when I declare my variable it needs to be declared as a const otherwise at runtime the program aborts.

Here is what I'm doing:

#pragma DATA_SECTION(myArray, .mySection)

myArray[1024]; //This causes abort

const myArray[1024] = {0}; //does not cause issues but I would like to see if I can keep this location non-volatile so I was trying not to initialize.

my linker command file looks as such:

MEMORY
{
FLASH (RX) : origin = 0x00000000, length = 0x000F0000
myFLASH(RW) : origin = 0x000F0000, length = 0x00010000
SRAM (RWX) : origin = 0x20000000, length = 0x00040000
}

/* Section allocation in memory */

SECTIONS
{
.text : > FLASH
.const : > FLASH
.cinit : > FLASH
.pinit : > FLASH
.init_array : > FLASH

.mySection : > myFLASH

.

.

.

  • Sean_ said:
    myArray[1024]; //This causes abort

    The compiler will zero-initialise the myArray during startup.

    On a MSP432E attempts to write addresses in the flash range result in a bus fault. This is because flash must be modified using the Flash Memory Address (FMA), Flash Memory Data (FMD), and Flash Memory Control (FMC) registers.

    Sean_ said:
    I would like to see if I can keep this location non-volatile so I was trying not to initialize.

    The NOINIT and PERSISTENT Pragmas should help. Not sure if you need to give an initial value when the program is first programmed.

  • Hi Chester,

    Thanks for your reply. 

    I was looking at the NOINIT and PERSISTENT Pragmas and have some additional questions. 

    It states the PERSISTENT Pragma is used on statically initialized variables.  My ultimate goal is to calculate a number of values at run time and store it in the FLASH section of the memory as non-volatile.  I would like to only calculate and write these once during load time as PERSISTENT pragma allows.  The only issue is the PERSISTENT Pragma requires a static initialization.  Is there a way to do this if I would calculate these values during run time?

    Thanks.

  • As Chester pointed out, a DATA_SECTION in flash is anomalous since the CPU can't write directly to flash through C-level assignments -- only indirectly through the flash registers.

    PERSISTENT initializes the data at program-download time, but not at every MCU reset. (The downloader knows how to write to flash.) This allows you to detect when you need to (re-)populate the data, but it still doesn't get you out of writing through the flash registers.

    NOINIT sets aside the space but doesn't ever initialize it. This allows your data to survive a program-download, but leaves it up to you to figure out when you need to (re-)populate the data. (Since things can move on a download, LOCATION is particularly valuable here.) And you still have to write through the flash registers.

    This is less cumbersome on FRAM-based devices since the CPU can write directly to FRAM (with perhaps a little fiddling on the sidelines).

    Have you considered using the EEPROM? That survives both MCU resets and program-downloads.

    [Edit: Minor clarification]

    [More Edit: Sorry, I forgot you can't write 0->1 in flash. That makes LOCATION (so you can erase it) even more important, and increases the attraction of EEPROM.]

  • Thanks Bruce.

    EEPROM will not work as 6KB is not enough space.

    I left out some information that I should have included. 

    I am using the "FlashErase" and "FlashProgram" functions from the driverlib to erase and write to flash.  My assumption is that these functions are using the flash registers.

    I tried the NOINIT option along with the LOCATION as such:

    In linker command file:

    TI.noinit :> myFlash

    In .c file:

    #pragma NOINIT(myArray)
    #pragma LOCATION(myArray, 0x000F0000)
    
    uint32_t tempArray[1024];
    
    for(i=0;i<1024;++i)
    
    tempArray[1024] = i*(some formula);
    
    FlashErase(0x000F0000);
    
    FlashProgram(tempArray, 0x000F0000, 1024*4);

    When I initially download the program and execute I see my values in the Flash memory.  The next time I download, I'm seeing that the Flash is already been erased to all F's (0xFF).

    My understanding was that NOINIT will not initialize this memory location but it seems to be resetting(erasing) the flash memory. 

  • Try setting "Properties->Debug->Flash Settings->Erase and download necessary segments only". That prevents the downloader from issuing a mass-erase. It's what I did back in the Ancient Days. (I still do, actually, though there may be a more delicate method.) 

**Attention** This is a public forum