c-擦除从0x08000000地址开始的闪存页,在写保护禁用范围内,产生硬故障



我正试图从STM32F302RBT6中的闪存(2页2 KB,从地址0x08000000开始)中擦除所有引导程序,因为我的代码应用程序从0x08001000地址开始应该不会有问题。关键是,在擦除功能返回后,它会产生一个硬故障,由内存故障IACVIOL产生,并且永远不会达到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。我已经尝试了一些东西:

  1. 如果擦除两个以0x08003000开始的页面(不被应用程序),它运行良好,并且不会产生故障。

  2. 如果我一步一步地调试代码,问题就不会发生。这个代码到达while(1)。

  3. 我试着减少时钟并增加闪存延迟,但它没用。

  4. 如果我从主函数和将其放入APP_MEM_EraseBootloaderSectorInFlash函数中工作良好,不会产生故障。

这是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
}
}

故障报告

调用堆栈

STM系列闪存的第一部分可以映射到0x00000000,用作中断向量。

如果是这种情况,擦除部件将擦除中断矢量并阻止中断正常工作。

最新更新