Skip to main content
Visitor II
September 24, 2024
Solved

HardFault on "HAL_FLASHEx_Erase" & "HAL_FLASH_Program" while USART is on

  • September 24, 2024
  • 2 replies
  • 1347 views

Hello,

I have made several tries but non of them could possible solve my problem.

In an STM32F030K Series, so Single Bank Flash memory, I am trying to have Flash Operation and UART module works together under the same build.

I know that Interrupts during Flash Erase-Write operation are creating troubles to the stability and creating HardFault Error for sure.

In order to avoid this behavior I have tried all the following methods in order to prevent HardFault Error BUT non of them worked.

Method 1:

 

 

	HAL_UART_DeInit(&huart1);
	__disable_irq();	/* Disable Global Interrupts */
	HAL_FLASH_Unlock();										/* Unlock the Flash to enable the flash control register access */

	Flash_ErasePage(FLASH_USER_START_ADDR);					/* Erase 1 complete memory page */

	Flash_ProgramPage(FLASH_USER_START_ADDR,EE_CacheTable);	/* Program 1 complete memory page */

	HAL_FLASH_Lock();										/* Lock the Flash to disable the flash control register access */
	__enable_irq();	/* Disable Global Interrupts */
	 MX_USART1_UART_Init();

 

 

 

Method 2: USART Interrupt runs in RAM 

 

 

#define RAMFUNC __attribute__ ((section (".ramfunctions")))
RAMFUNC void USART1_IRQHandler(void)
{
 /* USER CODE BEGIN USART1_IRQn 0 */
	
	/* USER CODE END USART1_IRQn 0 */
	 HAL_UART_IRQHandler(&huart1);
	 /* USER CODE BEGIN USART1_IRQn 1 */

 /* USER CODE END USART1_IRQn 1 */
}

 

 

 

 

Important information

  • USART Init is the following:

 

void MX_USART1_UART_Init(void)
{

 /* USER CODE BEGIN USART1_Init 0 */

 /* USER CODE END USART1_Init 0 */

 /* USER CODE BEGIN USART1_Init 1 */

 /* USER CODE END USART1_Init 1 */
 huart1.Instance = USART1;
 huart1.Init.BaudRate = 9600;
 huart1.Init.WordLength = UART_WORDLENGTH_8B;
 huart1.Init.StopBits = UART_STOPBITS_1;
 huart1.Init.Parity = UART_PARITY_NONE;
 huart1.Init.Mode = UART_MODE_TX_RX;
 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 huart1.Init.OverSampling = UART_OVERSAMPLING_16;
 huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
 huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
 if (HAL_UART_Init(&huart1) != HAL_OK)
 {
 Error_Handler();
 }
 HAL_UART_Receive_IT(&huart1,&data_rx,1);
 /* USER CODE BEGIN USART1_Init 2 */
 /* USER CODE END USART1_Init 2 */

}​

 

 

  • USART Callback is the following:

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	RX_DATA[j++]=data_rx;
	if(j>255)j=0;
	uart_receive_input(data_rx);
	HAL_UART_Receive_IT(&huart1,&data_rx,1);
}​

 

 

  • Program make use the following interrupts:
    SYSTICK Interrupt -  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
    USART -                   HAL_NVIC_SetPriority(USART1_IRQn, 1, 0);
    TIM1 Interrupt -         HAL_NVIC_SetPriority(TIM1_BRK_UP_TRG_COM_IRQn, 2, 0);
  • Flash Operation is not executed into any kind of Interrupt.
    It is just called during normal operation time in While Loop.
  • The problem insist to appear only when USART module is never called during initial Call during initialization.
    This topic has been closed for replies.
    Best answer by TDK

    There's no reason you can't use UART and also modify the flash, so the error must be due to something else. I don't think there is an error in the portion of the code you are showing, but we only see portions of it. What is the nature of the hard fault?

    2 replies

    Super User
    September 24, 2024

    If you're erasing code that the interrupt uses, and replacing it with new code, you'll need to update the vector table with the pointer to the new code.

    If you are erasing code that the program uses, it's going to hard fault. The update procedure needs to be run entirely from RAM.

    Unclear which of these is happening. Perhaps lay out your memory usage and explain what role the page at FLASH_USER_START_ADDR has in your program.

    Typically, if you are performing an in-application update, you would reset the chip after doing so and let it boot up normally.

    PelekisAuthor
    Visitor II
    September 25, 2024

    Hello,

    I am erasing 1 Page of Flash named
    "FLASH_USER_START_ADDR" = ADDR_FLASH_PAGE_31 ((uint32_t)0x08007C00) /* Base @ of Page 31,1 Kbyte*/

    I also save the parameters that i want in the same area within a function called during "while loop".
    For example:

     

    void SE_FactoryReset(void){
    	SE_FlushMemory(0,1024);
    	SE_SavePameter(P_C1_MODE,0,1);
    	SE_SavePameter(P_C2_MODE,0,1);
    	SE_SavePameter(P_C3_MODE,0,1);
    	SE_SavePameter(P_C4_MODE,0,1);
    	SE_SavePameter(P_C5_MODE,0,1);
    	SE_SavePameter(P_C6_MODE,0,1);
    	SE_SavePameter(P_C7_MODE,0,1);
    	SE_SavePameter(P_C8_MODE,0,1);
    	SE_SavePameter(P_C9_MODE,0,1);
    	SE_SavePameter(P_C1_TIME,5,1);
    	SE_SavePameter(P_C2_TIME,5,1);
    	SE_SavePameter(P_C3_TIME,5,1);
    	SE_SavePameter(P_C4_TIME,5,1);
    	SE_SavePameter(P_C5_TIME,5,1);
    	SE_SavePameter(P_C6_TIME,5,1);
    	SE_SavePameter(P_C7_TIME,5,1);
    	SE_SavePameter(P_C8_TIME,5,1);
    	SE_SavePameter(P_C9_TIME,5,1);
    
    
    	SE_SavePameter(P_SIREN_TIME,5,1);
    	SE_SavePameter(P_DOOR_TIME,5,1);
    
    
    }

     

     

    I am not able to reset the MCU every time I store data to flash.

    I am using this method on the same MCU Series for more than 20 project and never faced any kind of problem.

    BUT in non of them project I have ever use the Interrupts of UART in the past.
    In opposite within all project, that I have tried the exact same Flash Operation Functions, there used to be plenty of interrupts that were working, but with just disabling and enabling the IRQs right before and right after the flash operation had never problems in the past.

     

    	__disable_irq();	/* Disable Global Interrupts */
    	HAL_FLASH_Unlock();										/* Unlock the Flash to enable the flash control register access */
    
    	Flash_ErasePage(FLASH_USER_START_ADDR);					/* Erase 1 complete memory page */
    
    	Flash_ProgramPage(FLASH_USER_START_ADDR,EE_CacheTable);	/* Program 1 complete memory page */
    
    	HAL_FLASH_Lock();										/* Lock the Flash to disable the flash control register access */
    	__enable_irq();	/* Disable Global Interrupts */

     

     

    So please let me know whats the difference with the UART since I only face this kind of problem when UART module is enabled and only when UART module work on Interrupt mode.

     

    As for the information you asked me!

    The parameters that I am saving in the flash are dedicated bytes that program need in order to work according the user needs.

    So for example the "SE_SavePameter(P_C1_MODE,5,1);" would save in 1 byte with value 5 on flash location ((uint32_t)0x08007C00)+2 and so on for the rest of the parameters that I save in my program.

    Also the following code will give me back the value of the Flash saved memory in order to make use of it in my program:

     

    #define MEM2PTR(x)				(FLASH_USER_START_ADDR + (2 * x))
    #define MEM2DATA(x) 			*((unsigned int *)MEM2PTR(x))

     

     

     

    Best Regards

     

     

     

    TDKAnswer
    Super User
    September 25, 2024

    There's no reason you can't use UART and also modify the flash, so the error must be due to something else. I don't think there is an error in the portion of the code you are showing, but we only see portions of it. What is the nature of the hard fault?

    Super User
    September 25, 2024

    Try to debug it as usually with HardFaults, i.e. start from address in stacked PC and look at instructions in disasm before that address (sometimes several instructions before that) together with registers content to find out which of them caused the fault, and then relate that instruction with your (and by that I mean also Cube/HAL) source code.

    JW