cancel
Showing results for 
Search instead for 
Did you mean: 

Problem writing to Flash - Function returns success but memory remains 0xFF

JR2963
Senior II

Hi,

I'm working with STM32WB (with BLE) and trying to write to Flash in a custom section (contains version info, flags, etc.). The target flash memory initially contains 0xFFFFFFFFFFFFFFFF (confirmed in debugger), and I’m trying to write a uint64_t value like 0x0000000000000000. I'm using a function FD_WriteData(...), which internally calls HAL_FLASH_Program(...) via FD_WriteSingleData(...).

Here is the FD_WriteData() function:

uint32_t FD_WriteData(uint32_t DestAddress, uint64_t * pSrcBuffer, uint32_t NbrOfData)
{
    uint32_t loop_flash;
    uint32_t return_value;
    SingleFlashOperationStatus_t single_flash_operation_status = SINGLE_FLASH_OPERATION_DONE;

    // Take semaphore (dual-core STM32WB)
    while (LL_HSEM_1StepLock(HSEM, CFG_HW_FLASH_SEMID));

    HAL_FLASH_Unlock();

    for (loop_flash = 0; (loop_flash < NbrOfData) &&
         (single_flash_operation_status == SINGLE_FLASH_OPERATION_DONE); loop_flash++)
    {
        single_flash_operation_status = FD_WriteSingleData(DestAddress + (8 * loop_flash),
                                                           *(pSrcBuffer + loop_flash));
    }

    if (single_flash_operation_status != SINGLE_FLASH_OPERATION_DONE)
    {
        return_value = NbrOfData - loop_flash + 1;
    }
    else
    {
        HAL_FLASH_Lock();
        LL_HSEM_ReleaseLock(HSEM, CFG_HW_FLASH_SEMID, 0);
        return_value = 0;
    }

    return return_value;
}

I call this function with a valid flash address (aligned to 8 bytes), and the function returns 0 (success), but when I inspect flash memory afterward (in debugger or memory view), the values are still 0xFFFFFFFFFFFFFFFF.

I'm trying to write into a "metadata" area that looks like this in the .ld file:

My app is in region  FLASH_APP1, and the area I want to write is FLASH_METADATA_APP1.

/* Specify the memory areas */
MEMORY
{
   /* Bootloader region */
    FLASH_BOOTLOADER(rx) : ORIGIN = 0x08000000, LENGTH = 32K

    /* METADATA region for App1 */
    FLASH_METADATA_APP1 (rx) : ORIGIN = 0x08008000, LENGTH = 1K 

    /* Application 1 region */
    FLASH_APP1 (rx) : ORIGIN = 0x08008400, LENGTH = 363K
 

This area holds a group of const variables, like this:

SECTIONS
{

  .metadata :
  {
      . = ALIGN(4);
      KEEP(*(.metadata.FLASH_CONTENT))
      KEEP(*(.metadata.TARGET_PROJECT))
      KEEP(*(.metadata.SW_VERSION_MAJOR))
      KEEP(*(.metadata.SW_VERSION_MINOR))
      KEEP(*(.metadata.SW_VERSION_PATCH))
      KEEP(*(.metadata.FW_FIRST_BOOT_FLAG))
      KEEP(*(.metadata.RUNABLE_FLAGS))
      . = ALIGN(4);
  } >FLASH_METADATA_APP1
...
 .metadata1 :
  {
    _start_of_metadata_1 = ORIGIN(FLASH_METADATA_APP1);  
    KEEP(*(.metadata1))
    _end_of_metadata_1 = ORIGIN(FLASH_METADATA_APP1) + LENGTH(FLASH_METADATA_APP1);  
    . = ALIGN(4);
  } >FLASH_METADATA_APP1

and in the app_data.c:

const uint32_t SW_VERSION_PATCH __attribute__((section(".metadata.SW_VERSION_PATCH"))) = ...;
const uint64_t FW_FIRST_BOOT_FLAG __attribute__((section(".metadata.FW_FIRST_BOOT_FLAG"))) __attribute__((aligned(8))) = 0xFFFFFFFFFFFFFFFF;

Flash content is unchanged — it still reads as 0xFF FF FF FF FF FF FF FF after the write 0x0

 

IMPORTANT: I can write to address which is in FLASH_APP1 region without problem! What does it mean?

7 REPLIES 7
TDK
Guru

Are you erasing the flash before writing?

Perhaps simplify the example to write only a single double word.

If you feel a post has answered your question, please click "Accept as Solution".

I can not erase it, in the section are another important data. I just want to write to address 0x8008018  one double word (0x0). This place is filled with 0xFF from default.

If 0xFF (or anything else) has been written to it after erasing, you cannot change the value again. Doing so will yield an ECC error which may or may not be getting detected by the functions you're using.

If you feel a post has answered your question, please click "Accept as Solution".

I'm not sure if we understand each other. I'm uploading both the APP_META_DATA and APP area using Segger — via debug. Then, in the application, when I try to write to a place filled with FF, it only works if that place is in the APP1 area, but not if it's in the APP_META_DATA area. This should be a one-time write for the application's lifetime — the area I want to write to is like a "one-write EEPROM."

"A place filled with FF" does not necessarily mean that section is erased. Does your ELF file or whatever file you are flashing include data at 0x8008018? Include your ELF file here if you are not sure.

If you feel a post has answered your question, please click "Accept as Solution".

In the .map file the address is visible – I have it pre-filled in the code as 0xFF. Is that wrong? What’s the solution? Should I not define this address anywhere in code?

const uint64_t __attribute__((section(".metadata.FW_FIRST_BOOT_FLAG"))) __attribute__((aligned(8))) FW_FIRST_BOOT_FLAG = (uint64_t)UINT64_MAX; // 0xFFFFFFFF => have not booted yet

map file:

.metadata.FW_FIRST_BOOT_FLAG
  0x08008018        0x8 ...
  0x08008018                FW_FIRST_BOOT_FLAG

 

> What’s the solution? Should I not define this address anywhere in code?

Mark the section as NOLOAD in the linker script to prevent it from being loaded during programming. You shouldn't assign it a value, as the compiler/linker will want to initialize it to that value. Not sure if you'll get a warning.

Since your current structure has some loaded and some not loaded sections, you may need to refactor. Consider just using a pointer to an address to check rather than an actual variable.

Should still compare it against the uninitialized value (all 0xFF) to see if it's been written or not.

You shouldn't be declaring it "const" as your program modifies the value.

If you feel a post has answered your question, please click "Accept as Solution".