2025-10-15 4:46 AM
Hi
I am using the function below to erase the flash, but am not able to do the same.
I have to erase from address 0x0803E000UL i.e. page 124
The function does basically
1. HAL_FLASH_Unlock
2. HAL_FLASHEx_Erase(&erase_init, &page_error) - where page is 124
3. reads the erased flash area
4. HAL_FLASH_Lock
Am I missing something? I would not prefer to run the function in ram
I have MCUboot running and my application running on slot 0 is based on FreeRTOS. I am trying to erase slot1.
#define SLOT1_BASE_ADDR 0x0803E000UL
void erase_slot1_flash(void)
{
HAL_StatusTypeDef status;
uint32_t page_error = 0;
FLASH_EraseInitTypeDef erase_init;
uint32_t page_index;
/* Determine actual flash size (in KB) from system memory register */
uint32_t flash_size_kb = *(uint16_t *)FLASHSIZE_BASE;
uint32_t flash_start = FLASH_BASE;
uint32_t flash_end_addr = FLASH_BASE + (flash_size_kb * 1024UL) - 1UL;
printf("SLOT1_BASE_ADDR = 0x%08lX\r\n", (unsigned long)SLOT1_BASE_ADDR);
printf("FLASH_BASE = 0x%08lX\r\n", (unsigned long)FLASH_BASE);
printf("FLASH_SIZE_KB = %lu\r\n", (unsigned long)flash_size_kb);
printf("FLASH_START_ADDR = 0x%08lX\r\n", (unsigned long)flash_start);
printf("FLASH_END_ADDR = 0x%08lX\r\n", (unsigned long)flash_end_addr);
/* Sanity check: make sure SLOT1 lies within flash */
if ((SLOT1_BASE_ADDR < flash_start) || (SLOT1_BASE_ADDR > flash_end_addr)) {
printf("Error: SLOT1_BASE_ADDR is outside internal flash range!\r\n");
return;
}
/* Compute which flash page the slot address belongs to */
page_index = (SLOT1_BASE_ADDR - FLASH_BASE) / FLASH_PAGE_SIZE;
HAL_FLASH_Unlock();
printf("Before erase: ");
for (uint8_t i = 0; i < 16; i++) {
uint8_t val = *(uint8_t *)(SLOT1_BASE_ADDR + i);
printf(" %02x", val);
}
printf("\n\r");
/* Prepare erase configuration */
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = page_index;
erase_init.NbPages = 1;
printf("Erasing page (index=%lu, address=0x%08lX)\r\n",
(unsigned long)page_index, (unsigned long)SLOT1_BASE_ADDR);
/* Optional: clear prior flash flags */
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR |
FLASH_FLAG_RDERR |
FLASH_FLAG_FASTERR |
FLASH_FLAG_MISERR |
FLASH_FLAG_PGSERR |
FLASH_FLAG_WRPERR |
FLASH_FLAG_PROGERR |
FLASH_FLAG_OPERR);
status = HAL_FLASHEx_Erase(&erase_init, &page_error);
if (status != HAL_OK) {
printf("Erase failed! HAL status=%d Flash error=%lu\r\n",
status, HAL_FLASH_GetError());
} else {
printf("Erase successful.\r\n");
}
printf("-After erase: ");
for (uint8_t i = 0; i < 16; i++) {
uint8_t val = *(uint8_t *)(SLOT1_BASE_ADDR + i);
printf(" %02x", val);
}
printf("\n\r");
HAL_FLASH_Lock();
}
Solved! Go to Solution.
2025-10-16 1:35 AM
Hi TDK
Honestly, I am lost in a pile of datasheets, which gives me a feeling I am chasing my own tail.
But thanks, for pointing me to the code, this helps.
As time, a factor which I cannot control, I am now planning to use a quick fix, I find that I can erase and write multiple times from flash location 0x08040000UL and store my new firmware at this location.
I configure MCUboot to use this location as slot1.
Do you see any problem for that?
Thanks for the support
2025-10-16 1:53 AM - edited 2025-10-16 1:55 AM
When you initialize a structure in its declaration, the fields which are not initialized explicitly are initialized to zeros. It's a common mistake in STM32 ecosystem to declare the structure without an initializer inside of a function, then to assign some fields - the remaining fields then have some random values, causing the call to fail or behave strangely. Unfortunately, many ST offcial examples suggest this to the programmers by setting the fields with a series of assignments instead of initializing them in the declaration.
If you consider ST documents and libraries to be of low quality, then you probably haven't seen their competitors' stuff.
ST reference manual are much better than others. Also, a big advantage of STM32 is that the errata is much smaller than the reference manual. ;)
2025-10-16 2:08 AM
Hi gbm
Thanks for pointing me out. But my assembler code generated was exactly the same. Also, this baffled me.
FLASH_EraseInitTypeDef erase_init = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Page = page_index,
.NbPages = 1
};I will have to erase around 50 pages. How do I do this? Should I make an array or 50 variables, initialize it statically and run one after another? Because the page_index will change in a loop
P.S.: I did not want to and will not point out on the quality of artifacts from a company which I have no control, or I have not developed In fact I have used ST products 15 years ago then I had to stop as I had to buy IAR license for the compiler. I am very happy to see the STM32CubeIDE and other products come alive. I am coming back to ST world and would like to apologize if my comment sounded offensive.
2025-10-16 2:21 AM - edited 2025-10-16 2:32 AM
@jo512 wrote:I will have to erase around 50 pages. How do I do this? Should I make an array or 50 variables, initialize it statically
You can re-use one structure.
@gbm's point was to ensure that there are no uninitialised fields in the structure.
PS:
As @TDK suggested, you can see the definition of the FLASH_EraseInitTypeDef in the source code.
It's also in the User Manual for the Firmware Pack:
via: https://www.st.com/en/embedded-software/stm32cubeg0.html#documentation
via: https://www.st.com/en/evaluation-tools/nucleo-g0b1re.html#tools-software
So, with your original code:
/* Prepare erase configuration */
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.Page = page_index;
erase_init.NbPages = 1;you leave the .Banks field uninitialised.
With this code:
FLASH_EraseInitTypeDef erase_init = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Page = page_index,
.NbPages = 1
};the the .Banks field at least gets initialised to zero - but that still may not be correct...
2025-10-16 6:17 AM
Did you try:
erase_init.Banks = FLASH_BANK_1;or
erase_init.Banks = FLASH_BANK_2;depending on where the page to be erased is.
Flash is 128 pages per bank. See "3.3.1 FLASH organization" in the reference manual.
STM32G0x1 advanced Arm<Sup>®</Sup>-based 32-bit MCUs - Reference manual
> P.S.: I have been advised multiple times by others not to use ST products, as the whole ecosystem and datasheet is a mess. I fear all these are leading me to the same path.
What alternative products have awesome documentation and ecosystems? Genuinely asking. I have used many different manufacturer's microcontrollers. They are all a mess in their own way. Maybe you could say Arduino is good here, but that's only because the software is very limiting.
2025-10-16 6:41 AM
@TDK wrote:What alternative products have awesome documentation and ecosystems?
Certainly not Atmel !
2025-10-16 8:32 AM
Hi All
I will not make this question a discussion of which company has the best product. This is my first project using ST after a couple of years. I did my research, should I chose NXP or ST, I decided to use STM32 just for the price perspective. I was advised against it by many.
Multiple manufactures provide Datasheets and ecosystems and I have been using them since 1996, for example
Currently, I am using ST just because it's the microcontroller with good price to feature ratio.
In the future, I would like to add ST also among my favorites.
2025-10-16 8:40 AM
So did properly setting erase_init.Banks help ?
2025-10-20 4:12 AM - edited 2025-10-20 4:15 AM
Hi All
As expected
FLASH_EraseInitTypeDef erase_init = {
.TypeErase = FLASH_TYPEERASE_PAGES,
.Page = page_index,
.NbPages = 1
};did not work, but setting the bank to 1
erase_init.Banks = FLASH_BANK_1;
seems to work
I have a question: Is there a method to identify which bank the code is executing and then choose the other bank?
2025-10-20 6:14 AM
The PC register points to the currently executing code. See if that's in bank 1 or bank 2.