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.

MSPM0G3507: How to store data in flash?

Part Number: MSPM0G3507
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi experts,

I need to use some storage from flash memory, ~126 KB to 127 KB (1KB), to store my data (calibration values, customer data, etc.). Still, I cannot configure that. Could you please help me with this?

Thanks for your help.

  • Hey Kaushika,

    You would want to first edit your linker file and reserve a region of the flash for your data to ensure no other data is stored there. Then, in your program, you can use MSP DriverLib functions to protect, unprotect, read from, and write to your reserved memory region. If you haven't already, I'd recommend looking at the following resources:

    Best,

    Daniel

  • Thank you, Daniel.

    I will follow these resources.

  • Can you help me edit or replace the driver_linker.cmd. When rebuilding, everything changes. If I turn off rebuilding, so many errors occur. Can I replace the original driver_linker.cmd to partition the Flash?

  • Did you make sure to disable the Linker File Generation option in sysconfig under Project Configuration?

  • Yes. I did it. Now I do not know my driver_linker.cmd is correct or not? I have separated 1KB from the original flash. Still, I am in a testing period. I need to write some data into the desired address in my FLASH2. Then, I need to ensure that data must be available when changing the code. I mean this data should be permanent until I erase it.

    -uinterruptVectors
    --stack_size=512
    
    MEMORY
    {
        FLASH           (RX)  : origin = 0x00000000, length = 0x0001FC00   /* 127KB for app */
        FLASH2          (RX)  : origin = 0x0001FC00, length = 0x00000400  /* 1KB for BSL */
        SRAM            (RWX) : origin = 0x20000000, length = 0x00001000
        BCR_CONFIG      (R)   : origin = 0x41C00000, length = 0x00000080
        BSL_CONFIG      (R)   : origin = 0x41C00100, length = 0x00000080
    
    }
    
    SECTIONS
    {
        .intvecs       : > 0x00000000
        .text          : palign(8) {} > FLASH
        .const         : palign(8) {} > FLASH
        .cinit         : palign(8) {} > FLASH
        .pinit         : palign(8) {} > FLASH
        .rodata        : palign(8) {} > FLASH
        .ARM.exidx     : palign(8) {} > FLASH
        .init_array    : palign(8) {} > FLASH
        .binit         : palign(8) {} > FLASH
        .TI.ramfunc    : load = FLASH, palign(8), run=SRAM, table(BINIT)
    
        .user_data 	   : {} > FLASH2
    
        .vtable :   > SRAM
        .args   :   > SRAM
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM (HIGH)
    
        .BCRConfig  : {} > BCR_CONFIG
        .BSLConfig  : {} > BSL_CONFIG
    }
    

    First, I unselect the diver_linker.cmd generation option and edit the .cmd file. After that, I re-select that option. Then the driver_linker.cmd survived.

    This is my .c code.

    #include "ti_msp_dl_config.h"
    
    // Define 4 sector-aligned flash addresses (must match flash sector boundaries, e.g. 1KB-aligned)
    #define USER_FLASH_BASE_1  0x0001F000
    #define USER_FLASH_BASE_2  0x0001F400
    #define USER_FLASH_BASE_3  0x0001F800
    #define USER_FLASH_BASE_4  0x0001FC00
    
    // Data blocks to write (2 x 32-bit = 64-bit each block)
    uint32_t userData[4][2] = {
        {0xAAAA1111, 0xBBBB2222},   // Data for address 1
        {0xCCCC3333, 0xDDDD4444},   // Data for address 2
        {0xEEEE5555, 0xFFFF6666},   // Data for address 3
        {0x12345678, 0x9ABCDEF0}    // Data for address 4
    };
    
    // Corresponding flash addresses for each data block
    uint32_t flashAddresses[4] = {
        USER_FLASH_BASE_1,
        USER_FLASH_BASE_2,
        USER_FLASH_BASE_3,
        USER_FLASH_BASE_4
    };
    
    // Flash write function for each 64-bit data block
    void write_flash_block(uint32_t address, uint32_t *data)
    {
        // Unprotect sector
        DL_FlashCTL_unprotectSector(FLASHCTL, address, DL_FLASHCTL_REGION_SELECT_MAIN);
    
        // Erase sector before writing
        DL_FLASHCTL_COMMAND_STATUS status;
        status = DL_FlashCTL_eraseMemoryFromRAM(FLASHCTL, address, DL_FLASHCTL_COMMAND_SIZE_SECTOR);
        if (status != DL_FLASHCTL_COMMAND_STATUS_PASSED) {
            while (1); // Erase failed
        }
    
        // Program 64-bit (2 x 32-bit) word with ECC auto-generated
        status = DL_FlashCTL_programMemoryBlockingFromRAM64WithECCGenerated(
            FLASHCTL,
            address,
            data,
            2,
            DL_FLASHCTL_REGION_SELECT_MAIN
        );
        if (status != DL_FLASHCTL_COMMAND_STATUS_PASSED) {
            while (1); // Write failed
        }
    }
    
    int main(void)
    {
        SYSCFG_DL_init();
    
        // Write each data block to corresponding flash sector
        for (int i = 0; i < 4; i++) {
            write_flash_block(flashAddresses[i], userData[i]);
        }
    
        // Toggle LED to show success
        while (1) {
            DL_GPIO_togglePins(GPIO_LEDS_PORT, GPIO_LEDS_USER_LED_1_PIN);
            delay_cycles(16000000);
        }
    }
    

    Then I check the address through debugging, 

    The data values are present, but when I flash new code, they are no longer there. All erased.
    Am I wrong? Can you help me do this the right way? 

    At the final, I need to save some configuration on flash permanently. Still, I am testing at ground level.

    Really appreciate your assistance.

    Thank you.

  • Keep "Linker File Generation" off and add the modified linker file directly into your project. Also, ensure that the addresses you are writing to in your c code are within the bounds that you set for your user data (FLASH2).

  • I tried several time to save custom Linker file to project. But I couldn't do it. Can you give me the steps for that. And what commands should I use to write data in Flash.

  • Uncheck "Linker File Generation" and place your custom linker file directly into your project directory. I believe your problem with the memory being rewritten is due to your project configuration within CCS. Right-click on your project folder, then navigate to Properties -> Debug -> Category -> MSPM0 Flash Settings -> Erase Configuration. Here you can adjust what memory is erased, and the default is most likely set to erase all of MAIN memory. Select "Erase MAIN memory sectors by range" and then specify the range you want to erase in the fields below. 

  • Okay. Thank you, Daniel. I passed this step. 
    I encountered another error when flashing the code.

    [ERROR] CORTEX_M0P: Flash Programmer: Error in image size. Length of block is 260, but it should be divisible by 8 since Flash Programmer writes in 64-bits

    #include "ti_msp_dl_config.h"
    
    /* Address in main memory to write to */
    #define MAIN_BASE_ADDRESS (0x0001FC00)
    
    /* Array to write 64-bits to flash. Data must be loaded 32-bits at a time,
     * but a single word program is executed. */
    uint32_t gDataArray64[] = {0xABCDEF00, 0x12345678};
    
    /*
     * 8-bit ECC code array that corresponds with the data in
     * gDataArray64MultipleWords1
     */
    uint8_t gECCArray[] = {0x67, 0xF9, 0xF6, 0x68, 0xEB};
    
    volatile DL_FLASHCTL_COMMAND_STATUS gCmdStatus;
    
    /* Codes to understand where error occured */
    #define NO_ERROR 0
    #define ERROR_ERASE 1
    #define ERROR_64BIT_W 2
    
    volatile uint8_t gErrorType = NO_ERROR;
    
    int main(void)
    {
        SYSCFG_DL_init();
    
        /* Erase sector in main memory */
        DL_FlashCTL_unprotectSector(
            FLASHCTL, MAIN_BASE_ADDRESS, DL_FLASHCTL_REGION_SELECT_MAIN);
        gCmdStatus = DL_FlashCTL_eraseMemoryFromRAM(
            FLASHCTL, MAIN_BASE_ADDRESS, DL_FLASHCTL_COMMAND_SIZE_SECTOR);
        if (gCmdStatus != DL_FLASHCTL_COMMAND_STATUS_PASSED) {
            /* If command did not pass, set error flag */
            gErrorType = ERROR_ERASE;
        }
    
    
        if (gErrorType == NO_ERROR) {
            /*
            * Program single flash word (64-bit data) write to flash in main memory
            * with ECC enabled. Data must be loaded 32-bits at a time, but a single
            * word program is executed. The flash controller hardware will handle
            * generating the 8-bit ECC code.
            */
            DL_FlashCTL_unprotectSector(
                FLASHCTL, MAIN_BASE_ADDRESS, DL_FLASHCTL_REGION_SELECT_MAIN);
            gCmdStatus = DL_FlashCTL_programMemoryFromRAM64WithECCGenerated(
                FLASHCTL, (MAIN_BASE_ADDRESS), &gDataArray64[0]);
            if (gCmdStatus != DL_FLASHCTL_COMMAND_STATUS_PASSED) {
                /* If command did not pass, set error flag */
                gErrorType = ERROR_64BIT_W;
            }
        }
    
        /*
         * Signal to check the contents of MAIN_BASE_ADDRESS:
         * DE AD BE EF
         * CA FE BA BE
         * DE AD BE EF
         * CA FE BA BE
         * DE AD BE EF
         * CA FE BA BE
         * DE AD BE EF
         * CA FE BA BE
         * DE AD BE EF
         * CA FE BA BE
         */
    
        /* Set Breakpoint if error status exists on completion */
        if (gErrorType != NO_ERROR) {
            __BKPT(0);
        }
        /* After completion, toggle LED */
        while (1) {
            DL_GPIO_togglePins(GPIO_LEDS_PORT,
                GPIO_LEDS_USER_LED_1_PIN | GPIO_LEDS_USER_TEST_PIN);
            delay_cycles(16000000);
        }
    }
    
    -u _c_int00
    --stack_size=0x800
    
    MEMORY
    {
        FLASH        (RX)  : origin = 0x00000000, length = 0x0001FC00
        NV_FLASH     (RWX) : origin = 0x0001FC00, length = 0x00000400
        SRAM         (RWX) : origin = 0x20200000, length = 0x00008000
        BCR_CONFIG   (R)   : origin = 0x41C00000, length = 0x00000080
        BSL_CONFIG   (R)   : origin = 0x41C00100, length = 0x00000080
    }
    
    SECTIONS
    {
        .intvecs        :   > FLASH
        .text           :   > FLASH
        .const          :   > FLASH
        .cinit          :   > FLASH
        .pinit          :   > FLASH
        .rodata         :   > FLASH
        .ARM.exidx      :   > FLASH
        .init_array     :   > FLASH
        .TI.ramfunc     :   load = FLASH, run = SRAM, table(BINIT), palign(8)
        .binit          :   > FLASH
    
        .data           :   > SRAM
        .bss            :   > SRAM
        .sysmem         :   > SRAM
        .vtable         :   > SRAM
        .stack          :   > SRAM (HIGH)
    
        .BCRConfig      :   > BCR_CONFIG
        .BSLConfig      :   > BSL_CONFIG
    
    
    }

    Are there any mistakes in the code? Please, can you guide me?

  • Make sure to retain the alignment for your sections and set .intvecs to start at 0x00000000.

    -uinterruptVectors
    --stack_size=512
    
    MEMORY
    {
        FLASH        (RX)  : origin = 0x00000000, length = 0x0001FC00
        NV_FLASH     (RX) : origin = 0x0001FC00, length = 0x00000400
        SRAM         (RWX) : origin = 0x20200000, length = 0x00008000
        BCR_CONFIG   (R)   : origin = 0x41C00000, length = 0x00000080
        BSL_CONFIG   (R)   : origin = 0x41C00100, length = 0x00000080
    }
    
    SECTIONS
    {
        .intvecs        :   > 0x00000000
        .text           :   palign(8) {} > FLASH
        .const          :   palign(8) {} > FLASH
        .cinit          :   palign(8) {} > FLASH
        .pinit          :   palign(8) {} > FLASH
        .rodata         :   palign(8) {} > FLASH
        .ARM.exidx      :   palign(8) {} > FLASH
        .init_array     :   palign(8) {} > FLASH
        .TI.ramfunc     :   load = FLASH, run = SRAM, table(BINIT), palign(8)
        .binit          :   palign(8) {} > FLASH
    
        .data           :   > SRAM
        .bss            :   > SRAM
        .sysmem         :   > SRAM
        .vtable         :   > SRAM
        .stack          :   > SRAM (HIGH)
    
        .BCRConfig      :   > BCR_CONFIG
        .BSLConfig      :   > BSL_CONFIG
    }

  • Thank you, Daniel !!