2025-07-03 6:52 AM
Hello,
I am developing a RAM-based bootloader on STM32H5, to update my firmware application.
Application and bootloader resides on different flash areas, and the bootloader code is copied into RAM at startup.
[0x8000000 - 0x801FFFF] bootloader
[0x8020000 - 0x803FFFF] reserved
[0x8040000 - 0x80FFFFF] application
First, the bootloader erases all the application sectors.
Then the bootloader receives code fragments via fieldbus, and program the flash memory 16 bytes (flash-word) at time, at correctly aligned addresses:
int16_t HW_FLASH_Program(uint32_t addr, int32_t len, uint8_t *buff_p)
{
HAL_StatusTypeDef status;
uint8_t flash_word[FLASH_WORD_LEN];
uint32_t aligned_addr;
uint32_t offset;
uint32_t chunk;
HAL_FLASH_Unlock();
while (len > 0)
{
// back-align the address to 16 bytes
aligned_addr = addr & ~(FLASH_WORD_LEN - 1);
if ((addr == aligned_addr) && (len >= FLASH_WORD_LEN))
{
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, addr, (uint32_t)buff_p);
LL_ICACHE_Invalidate();
if (status != HAL_OK)
{
HAL_FLASH_Lock();
return -1;
}
addr += FLASH_WORD_LEN;
buff_p += FLASH_WORD_LEN;
len -= FLASH_WORD_LEN;
}
else
{
// address not aligned or length less than 16 bytes
// read the current contents of the flash word
for (uint32_t i = 0; i < FLASH_WORD_LEN; i++)
{
flash_word[i] = *((__IO uint8_t *)(aligned_addr + i));
}
// overwite only the affected part
offset = addr - aligned_addr;
chunk = FLASH_WORD_LEN - offset;
if (chunk > len)
{
chunk = len;
}
for (uint32_t i = 0; i < chunk; i++)
{
flash_word[offset + i] = buff_p[i];
}
// write the flash word
status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_QUADWORD, aligned_addr, (uint32_t) flash_word);
LL_ICACHE_Invalidate();
if (status != HAL_OK)
{
HAL_FLASH_Lock();
return -2;
}
addr += chunk;
buff_p += chunk;
len -= chunk;
}
}
HAL_FLASH_Lock();
return 0;
}
I can perform erase and program operations correctly, but I have an NMI exception during the verify operations, when trying to read back a particular flash location, due to an ECCD event.
I checked that the flash content is the same whether the applicaton is programmed via JTAG/SWD or bootloader, but in the first case I don't have the problem.
In particular, at 0x08040400 is placed the application CRC (0x9968) and the exception occours when reading the address 0x08040402 where are placed the padding at zero, as higlighted in bold, below:
[0x08040400 - 0x0804040F]: 68 99 00 00 | FF FF FF FF | 56 2E 31 30 | 31 00 00 00
MEMORY
{
...
CRC (r) : ORIGIN = 0x8040400, LENGTH = 0x00008
...
}
.crc :
{
. = ALIGN(4);
KEEP(*(.crc))
. = ALIGN(4);
} >CRC
const uint16_t crc __attribute__((section(".crc"))) = {0x9968};
In particular, I have seen that the .crc section code is received by the bootloader as 4 byte segment, that being shorter than the 16 byte flash-word, activates the following read-modify-write procedure:
1. Read 16 bytes flash-word at address 0x08040400 in a buffer.
2. Overwrite the first 4 location of the buffer, with the CRC + padding.
3. Write back the 16 bytes buffer to flash at address 0x08040400.
Thank you,
Carlo
Solved! Go to Solution.
2025-07-21 5:23 AM
Hello @Dor_RH,
the problem was with my program function, which allowed to program the same 16 byte flash-word in two steps rather than in a single step.
Even if during the second step I paid attention to reiterate the value of the bytes written in the first step, the ECC for the same flash word is calculated two times, and the second time it won't be programmed correctly, as it is not at 0xFF any longer.
This problem was difficoult to investigate because the HAL_FLASH_Program() won't signal any error when it fails to program the ECC.
Regards,
Carlo
2025-07-17 3:28 AM
Hello @CTabo.1,
NMIs during verify operations can be caused by hardware issues such as voltage drops or instability.
They can also result from memory access violations, such as when the code tries to read or write to protected or invalid memory areas.
To read/write data from/to flash memory with HAL functions, I advise you to get inspired from an available example such as FLASH_FastProgram under STM32CubeH5
This example can help you to understand and use the FLASH HAL API to erase and fast program the internal Flash.
I hope my answer has helped you. When your question is answered, please select this topic as the solution that answered you, as it will help others find that answer faster.
Thanks for your contribution.
Dor_RH
2025-07-21 5:23 AM
Hello @Dor_RH,
the problem was with my program function, which allowed to program the same 16 byte flash-word in two steps rather than in a single step.
Even if during the second step I paid attention to reiterate the value of the bytes written in the first step, the ECC for the same flash word is calculated two times, and the second time it won't be programmed correctly, as it is not at 0xFF any longer.
This problem was difficoult to investigate because the HAL_FLASH_Program() won't signal any error when it fails to program the ECC.
Regards,
Carlo