cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030 Cortex-M0 HardFault Error on "HAL_FLASHEx_Erase" and "HAL_FLASH_Program" while USART is on

Pelekis
Associate II

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.
1 ACCEPTED SOLUTION

Accepted Solutions

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?

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

View solution in original post

5 REPLIES 5
TDK
Guru

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.

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

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

 

 

 

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

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?

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

Hello,

Yes you are correct the error had nothing to do with the UART combination with Flash Operations.

The actual problem was that UART had been set on Interrupt mode for Every 1 byte it was receiving.

So with the UART RX was issuing new interrupt while the prior UART RX interrupt was not pr-emptied.

Thanks A lot!