I'm trying to erase all bootloader from flash (2 pages of 2 KB, starting from address 0x08000000) in STM32F302RBT6, and as my code app starts from the 0x08001000 address should not be a problem to do it. The point is, after the erasing function returns, a hard fault it's generated with a memory fault IACCVIOL and never reaches the while(1).
public int main (void)
{
HAL_Init();
ClockInit();
APP_MEM_EraseBootloaderSectorInFlash();
while(1);
}
unsigned char APP_MEM_EraseBootloaderSectorInFlash(void)
{
unsigned char result = 0;
__disable_irq();
HAL_FLASH_Unlock();
result = ErasePageinFlash(0x08000000);
result = ErasePageinFlash(0x08000800);
HAL_FLASH_Lock();
__enable_irq();
return result;
}
static unsigned char ErasePageinFlash(uint32_t page_address)
{
unsigned char result = 0;
uint32_t page_error;
FLASH_EraseInitTypeDef erase_init;
erase_init.TypeErase = FLASH_TYPEERASE_PAGES;
erase_init.NbPages = 1u;
erase_init.PageAddress = page_address;
if (HAL_FLASHEx_Erase(&erase_init, &page_error) == HAL_OK)
{
result = 1;
}
return result;
}
PS. I've Already tried some things:
If I erase two pages starting in 0x08003000 (not used by the application), it works fine, and no fault is generated.
If I debug the code step by step, the problem doesn't occur. The code reaches the while(1).
I've tried to reduce the clock and increment flash latency, but it didn't work.
If I change the position of the while(1) from the main function and put it inside the APP_MEM_EraseBootloaderSectorInFlash function, it works fine, and no fault is generated.
This is the code of ClockInit:
static void ClockInit(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
//RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16;
while (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
// TODO :: Fault behaviour
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
while (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
// TODO :: Fault behaviour
}
}
The first part of flash memory of STM series may be mapped to 0x00000000, which is used as the interrupt vector.
If this is the case, erasing the part will erase the interrupt vector and prevent interrupts from work correctly.