cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_FLASH_Program doesn't work at very beginning of firmware application?

carleslsregner
Associate III

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. 

 

 

3 REPLIES 3
KnarfB
Super User

So what HAL error do you get? Have you stepped into the HAL sources and checked what exactly fails?

hth

KnarfB 

Good point. 

I am diving into the function FLASH_WaitForLastOperation. The error code is 160 and it returns HAL_ERROR.

/**
  * @brief  Wait for a FLASH operation to complete.
  *   Timeout maximum flash operation timeout
  * @retval HAL_StatusTypeDef HAL Status
  */
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
{
  uint32_t error;
  uint32_t tickstart = HAL_GetTick();

  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
     Even if the FLASH operation fails, the BUSY flag will be reset and an error
     flag will be set */

#if defined(FLASH_DBANK_SUPPORT)
  error = (FLASH_SR_BSY1 | FLASH_SR_BSY2);
#else
  error = FLASH_SR_BSY1;
#endif /* FLASH_DBANK_SUPPORT */

  while ((FLASH->SR & error) != 0x00U)
  {
    if(Timeout != HAL_MAX_DELAY)
    {
      if ((HAL_GetTick() - tickstart) >= Timeout)
      {
        return HAL_TIMEOUT;
      }
    }
  }

  /* check flash errors */
  error = (FLASH->SR & FLASH_SR_ERRORS);

  /* Clear SR register */
  FLASH->SR = FLASH_SR_CLEAR;

  if (error != 0x00U)
  {
    /*Save the error code*/
    pFlash.ErrorCode = error;
    return HAL_ERROR;
  }

  /* Wait for control register to be written */
  while ((FLASH->SR & FLASH_SR_CFGBSY) != 0x00U)
  {
    if(Timeout != HAL_MAX_DELAY)
    {
      if ((HAL_GetTick() - tickstart) >= Timeout)
      {
        return HAL_TIMEOUT;
      }
    }
  }

  return HAL_OK;
}

 

I am going to check what is this 160 error code. 

TDK
Super User

Calling HAL_FLASH_Program at the start of the program can interfere with the debugging process. When you upload a new program, it resets a few times before the debugger starts. Otherwise, it works as described.

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