2025-04-11 1:10 AM - edited 2025-04-11 3:28 AM
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?
2025-04-11 5:32 AM
Are you erasing the flash before writing?
Perhaps simplify the example to write only a single double word.
2025-04-11 5:52 AM
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.
2025-04-11 6:11 AM
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.
2025-04-11 6:26 AM
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."
2025-04-11 6:50 AM
"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.
2025-04-11 12:09 PM - edited 2025-04-11 12:09 PM
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
2025-04-11 1:29 PM
> 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.