Flash read / write

We’re planning to use the flash memory to store data. Is there a writeup on doing this? I have searched through the firmware reference and seen write operations but I haven’t found any read.

Thanks in advance.

Jeff

@jeff There is no special function to read the flash… Just perform a read the same way you would read RAM.

2 Likes

@rvs
For the safe method to read the flash, there is an example.

void flash_cmd_read(uint32_t addr, flash_read_t* result)
{
//Wait until flash is idle
while (FLASH->IF_STATUS & FLASH_IF_BUSY);
// Disable interrupts while executing flash commmands
uint32_t intStatus = __get_PRIMASK();
uint32_t previousECC = FLASH->ECC_CTRL;
__set_PRIMASK(PRIMASK_DISABLE_INTERRUPTS);
FLASH->ECC_CTRL |= FLASH_CMD_ECC_ENABLE;
// Perform a CMD_READ with ECC enabled
FLASH->ADDR = addr;
FLASH->CMD_CTRL = CMD_READ;
while (FLASH->IF_STATUS & FLASH_IF_BUSY);
// Read data registers
result->data_ecc_on[0] = FLASH->DATA[0];
result->data_ecc_on[1] = FLASH->DATA[1];
// restore previous ECC configuration
FLASH->ECC_CTRL = previousECC;
// Enable interrupts and restore interrupt configuration
__set_PRIMASK(intStatus);
}

@martin.bela Thanks for this information. I feel like I’m missing a key document. I’m pouring over the FW ref and HW ref but I’m not seeing anything that connects the basics of working with this environment. Specifically, where would I formulate the answer you provided? I have many areas I’d like to get detailed operational information but I seem to be running into only partial information. For example the RW-BLE-GAP-IS_2mbps.pdf has all these defines but does not identify how they are used.

Thanks.

@jeff + @martin.bela I think performing flash read this way is heavy. A better solution is probably to activate ECC and enable FLASH_ECC_IRQn, so you can still read flash the way you would read RAM and rely on the flash ECC interrupt to catch errors.

1 Like

@rvs rvs @jeff
Yes. rvs suggestion is correct. Our example is for “safe method.”
Note:

Default ECC is enabled and ECC interrupt is disabled. (the example code can remove ECC enable part) . Enable ECC interrupt is correct. This can catch any flash error. (This is good idea, but this is not in read function and it could put in flash initialization function. )
Our example is just for “safe method”.
For example. The flash area for reading is code area not data area. We do need disable interrupt and enable interrupt, right?

// Perform a CMD_READ with ECC enabled flash memory
FLASH->ADDR = addr;
FLASH->CMD_CTRL = CMD_READ;
while (FLASH->IF_STATUS & FLASH_IF_BUSY);
// Read data registers
result->data_ecc_on[0] = FLASH->DATA[0];
result->data_ecc_on[1] = FLASH->DATA[1];

Each flash address cover 64-bit flash data.

Reading ECC enabled Flash memory has a bit of difference with reading RAM.

Can you explain the FLASH pointer you are using? I see FLASH_ADDR in the HW Ref but you’re using FLASH->ADDR. The FLASH_ADDR is defined as 0x4000053C.

Thanks in advance.

@jeff

FLASH_ADDR is defined as 0x4000053C. — This is register address.
We just set the read/write address into this FLASH_ADDR register.
For example,
We need read main flash address: 0x00100000.
FLASH->ADDR = 0x00100000;
In my board, I could have 0x20006000 and 0x00100159.

We can also use the J-Link commander to verify this.

or

Debugger

image

Hi @martin.bela ,

I have some trouble about writing and reading flash memory. Sometimes its work properly sometimes doesn’t. I have three function to read and write operation with RSL10SIP.

I am going to add this function. Do you see any wrong thing about that functions ?

Also Rsl10SIP Supply voltage is at 1.8V (VBAT AND VDDIO)…

This is write enable function to flash memory.

void FLASH_MAIN_HIGH_WriteEnable(bool enable)
{

    FLASH->MAIN_CTRL= MAIN_HIGH_W_ENABLE;
    FLASH->MAIN_WRITE_UNLOCK = enable ? FLASH_MAIN_KEY : 0;

    bool MAIN_HIGH_W_unlocked = (FLASH->IF_STATUS & 0x04) == 0x04;

    if (MAIN_HIGH_W_unlocked != enable){

    Sys_NVIC_DisableAllInt();
    Sys_NVIC_ClearAllPendingInt();

    while(1) asm("nop");
  }

}

This actually write function to flash memory.

void Write_FlashMem(){

    FLASH_MAIN_HIGH_WriteEnable(true);
    __set_PRIMASK(PRIMASK_DISABLE_INTERRUPTS);

    FLASH_IF_CTRL ->LP_MODE_BYTE = CMD_SET_LOW_POWER;

    for (int i = 0; i < SAVED_NUMBERS_VARIABLE; i++) {

        FLASH -> ADDR = FLASHMEM_SAVE_BASE_ADDR + 8*i;
        FLASH ->CMD_CTRL = CMD_SECTOR_ERASE;
    }

    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> ADDR = FLASHMEM_SAVE_BASE_ADDR;

    FLASH -> DATA[0] = variable;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable1;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable2;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable3;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY);


    __set_PRIMASK(PRIMASK_ENABLE_INTERRUPTS);
    FLASH_MAIN_HIGH_WriteEnable(false);

}

This is read function to flash memory.

void Read_FlashMem(){

    while (FLASH->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH_IF_CTRL ->LP_MODE_BYTE = CMD_SET_LOW_POWER;

    uint32_t previousECC = FLASH->ECC_CTRL;
    __set_PRIMASK(PRIMASK_DISABLE_INTERRUPTS);

    FLASH->ECC_CTRL |= FLASH_CMD_ECC_ENABLE;

    FLASH->ADDR = FLASHMEM_SAVE_BASE_ADDR;
    FLASH->CMD_CTRL = CMD_READ;
    while (FLASH->IF_STATUS & FLASH_IF_BUSY) ;
    variable = (uint8_t) FLASH->DATA[0];

    FLASH->CMD_CTRL = CMD_READ;
    while (FLASH->IF_STATUS & FLASH_IF_BUSY) ;
    variable1 = (uint8_t) FLASH->DATA[0];

    FLASH->CMD_CTRL = CMD_READ;
    while (FLASH->IF_STATUS & FLASH_IF_BUSY) Sys_Watchdog_Refresh();
    variable2 = (uint8_t) FLASH->DATA[0];

    FLASH->CMD_CTRL = CMD_READ;
    while (FLASH->IF_STATUS & FLASH_IF_BUSY);
    variable3 = (uint8_t) FLASH->DATA[0];


    FLASH->ECC_CTRL = previousECC;
    __set_PRIMASK(PRIMASK_ENABLE_INTERRUPTS);

}

@karuf

Would you please try this code in below and let us know if it is working ?

void Write_FlashMem(){

    FLASH_MAIN_HIGH_WriteEnable(true);
//    __set_PRIMASK(PRIMASK_DISABLE_INTERRUPTS);
    __disable_irq();
    FLASH_IF_CTRL ->LP_MODE_BYTE = CMD_SET_LOW_POWER;

    for (int i = 0; i < SAVED_NUMBERS_VARIABLE; i++) {

        FLASH -> ADDR = FLASHMEM_SAVE_BASE_ADDR + 8*i;
        FLASH ->CMD_CTRL = CMD_SECTOR_ERASE;
    }

    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> ADDR = FLASHMEM_SAVE_BASE_ADDR;

    FLASH -> DATA[0] = variable;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable1;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable2;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY) ;

    FLASH -> DATA[0] = variable3;
    FLASH -> CMD_CTRL = CMD_PROGRAM_NOSEQ;
    while(FLASH ->IF_STATUS & FLASH_IF_BUSY);

//    __set_PRIMASK(PRIMASK_ENABLE_INTERRUPTS);
     __enable_irq();
    FLASH_MAIN_HIGH_WriteEnable(false);

}
1 Like

Hi @martin.bela ,

Thanks for your reply.

I guess ı fixed this problem . It was about low power mode of flash memory. I have been trying for 2 days and everything seems okey. If something goes wrong ı will inform you.

This line has to change with below…

FLASH_IF_CTRL ->LP_MODE_BYTE = CMD_SET_LOW_POWER;

FLASH_IF_CTRL ->LP_MODE_BYTE = FLASH_LOW_POWER_ENABLE;
Sys_Delay_ProgramROM(SystemCoreClock/1000);
FLASH->CMD_CTRL = CMD_SET_LOW_POWER;
1 Like