2026-01-02 4:18 AM - last edited on 2026-01-02 4:58 AM by Andrew Neil
I have one question regarding the HAL_FLASH_Program function. I use the HAL_FLASH_Program many times during the runtime of the firmware. I use it to store log, warnings and errors in the several flash pages. When the page is full and I must write into it I erase the page, obviously.
However, at the very begining I also want to store the "reset cause" (an entry in the flash pages) of the last power cycle (switch on off). Was it a BOR, WWDOG, IWOG, PINRST, etc, etc,..?
Unfortunately, I am unable to successfully use HAL_FLASH_Program with a HAL_OK. It seems as if HAL_FLASH_Program does not work at the very beginning of the firmware application... does it sound crazy? Could it be that this function needs some time to work.
/**
* @brief The function's role is to save the log data into the log page/s.
*/
mid_error_t flash_program_loop_2(const uint8_t * data_in)
{
HAL_FLASH_Unlock();
/**
* first we check if the next position to write is valid.
* If it is not valid, we need to erase the page and start from the beginning.
*/
if (flash_next_i_log > flash_end_i_log)
{
flash_next_i_log = flash_start_i_log;
}
if (flash_read_data(flash_next_i_log) != 0xFFFFFFFF)
{
flash_erase_page_by_address(flash_next_i_log);
// we need to erase the page before writing
flash_counter_log = flash_counter_log - (FLASH_PAGE_SIZE/size_of_log_struct_in_flash); // we are removing the logs that were in that page);
}
/**
* now we write the data.
*/
for (uint8_t f_i = 0; f_i < size_of_log_struct_in_flash; f_i += 8)
{
uint8_t auxdata[8] = { 0 };
/**
* if the writing is urgent.
*/
memcpy(auxdata, &(data_in[f_i]),8*sizeof(uint8_t));
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
(uint32_t)flash_next_i_log + (uint32_t)f_i,
(uint64_t) auxdata[0] | ((uint64_t) auxdata[1] << 8)
| ((uint64_t) auxdata[2] << 16)
| ((uint64_t) auxdata[3] << 24)
| ((uint64_t) auxdata[4] << 32)
| ((uint64_t) auxdata[5] << 40)
| ((uint64_t) auxdata[6] << 48)
| ((uint64_t) auxdata[7] << 56)) != HAL_OK)
{
return MID_ERROR_GENERAL ;
}
}
flash_last_i_log = flash_next_i_log; // updating last log position
flash_next_i_log += size_of_log_struct_in_flash;
if (flash_next_i_log > flash_end_i_log)
{
flash_next_i_log = flash_start_i_log;
}
flash_counter_log++; // we are adding one more log
flash_counter_log_aux2++;
return MID_ERROR_OK; // everything went ok
}
I thought that with HAL_init, SystemClock_config and Mx_GPIO_Init was enough...
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();What do you think?
Thanks for all.
Sorry for the trouble.
Merry Christmas and Happy New Year 2026.
Solved! Go to Solution.
2026-01-07 2:02 AM
I will try to run it without debbuging it.
2026-01-07 4:06 AM
0xa0 according to the pFlash.ErrorCode
Programming Alignment Error (PGAERR) and Programming Sequence Error (PGSERR)
#define FLASH_SR_PGAERR_Pos (5U)
#define FLASH_SR_PGAERR_Msk (0x1UL << FLASH_SR_PGAERR_Pos) /*!< 0x00000020 */
#define FLASH_SR_PGAERR FLASH_SR_PGAERR_Msk
#define FLASH_SR_PGSERR_Pos (7U)
#define FLASH_SR_PGSERR_Msk (0x1UL << FLASH_SR_PGSERR_Pos) /*!< 0x00000080 */
#define FLASH_SR_PGSERR
2026-01-07 6:11 AM
Put HAL_Delay(500) before doing any flash operation. That will satisfy the debugger connecting process.
2026-01-07 7:45 PM
Try to find the source of those errors (when PGA and PGS flag appeared). Possibly, there is a writing into flash addresses without FLASH_Unlock. But anyway, FLASH_WaitForLastOperation should settle everything (waits for BSY, clears error flags), one just have to properly handle erroneous cases.
2026-01-07 7:53 PM
0.5 sec delay is way TOO much. It is enough to wait until BSY is gone. And according to my experience, flash operations don't interfere with debugging. At least while starting under reset.
2026-01-08 11:01 PM
I found several problems and the solutions to them.
-> always use unlock/lock no matter if it is program the flash or erasing it.
->clear flash error flag
-> disable and enable the interruptions before and after programing the flash
-> wait for any operations to end.
mid_error_t flash_save_loop_1(const uint8_t * data_in, bool urgent)
{
assert_param(size_of_occurrence_struct_in_flash % 8 == 0);
/**
* first we check if the next position to write is valid.
* If it is not valid, we need to erase the page and start from the beginning.
*/
if (flash_next_i_occurrence > flash_end_i_occurrence)
{
flash_next_i_occurrence = flash_start_i_occurrence;
}
else if (flash_read_data(flash_next_i_occurrence) != 0xFFFFFFFF)
{
flash_erase_page_by_address(flash_next_i_occurrence);
}
HAL_FLASH_Unlock();
__disable_irq();
FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
/* Clear error flags */
__HAL_FLASH_CLEAR_FLAG( FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );
for (uint32_t f_i = 0; f_i < size_of_occurrence_struct_in_flash; f_i += 8)
{
uint64_t auxdata = 0xFFFFFFFFFFFFFFFFULL;
memcpy(&auxdata, &data_in[f_i], (8 > size_of_occurrence_struct_in_flash - f_i)?(size_of_occurrence_struct_in_flash - f_i):8);
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_next_i_occurrence + f_i, auxdata) != HAL_OK)
{
__enable_irq();
HAL_FLASH_Lock();
return MID_ERROR_GENERAL;
}
}
__enable_irq();
HAL_FLASH_Lock();
flash_next_i_occurrence += size_of_occurrence_struct_in_flash;
if (flash_next_i_occurrence > flash_end_i_occurrence)
{
flash_next_i_occurrence = flash_start_i_occurrence;
}
return MID_ERROR_OK; // everything went ok
}