在上一次对Flash的操作,是在关闭总中断的情况下完成的。但是关闭总中断终归会造成系统响应时间延迟,而且在某些特殊的场合下,关闭总中断也容易造成丢失UART数据,或则SPI数据等现象。
解决的方法就是:既然在擦写Flash时不能进行Flash读操作,因此可以将NVIC的向量表重新映射到RAM,并且将中断响应函数也一并放入RAM中,这样的话,即使在擦写flash操作时有中断需要响应,因此也不会去读取Flash。原则上这样就避免了Flash擦写失败的情况。
硬件环境:G/TG STK
软件环境:将NVIC重新映射到RAM,并且将中断函数也映射到RAM中。由于以下的例子是基于IAR的,因此将函数映射到RAM的关键字是__ramfunc . 在例程中我们将systick的中断函数定义成了__ramfunc void SysTick_Handler(void)。 另外,需要注意一点的是,MSC_ErasePage() ,MSC_WriteWord()等函数在efm32_msc.h中也被定义成了__ramfuc类型。因此,在擦写Flash的时候,就不会再读取Flash的内容了。
例程:
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
#include "efm32.h"
#include "efm32_chip.h"
#include "efm32_cmu.h"
#include "efm32_msc.h"
//定义NVIC中断向量表,但是需要512字节对齐。ICCARM为IAR的编译器
#if defined (__ICCARM__)
#pragma location=0x20000000
__no_init uint32_t vectorTable[47];
#elif defined (__CC_ARM)
uint32_t vectorTable[47] __attribute__((at(0x20000000)));
#elif defined (__GNUC__)
uint32_t vectorTable[47] __attribute__((aligned(512)));
#else
#error Undefined toolkit, need to define alignment
#endif
volatile uint32_t msTicks;
const unsigned char ucWriteIn[8] = {'a','b','c','d','e','f','g','h',};
unsigned char ucReadOut[8];
__ramfunc void SysTick_Handler(void)
{
msTicks++;
}
/**************************************************************************
在RAM中创建一张NVIC的表格
*****************************************************************************/
void generateVectorTable(void)
{
vectorTable[SysTick_IRQn + 16] = (uint32_t) SysTick_Handler;
//vectorTable[RTC_IRQn + 16] = (uint32_t) RTC_IRQHandler;
SCB->VTOR = (uint32_t) vectorTable;
}
void main(void)
{
CHIP_Init();
/* Ensure core frequency has been updated */
SystemCoreClockUpdate();
generateVectorTable();//update the Vector table
//add a timer
if (SysTick_Config(SystemCoreClock / 1000)) while (1) ;
MSC_Init();//初始化MSC,并使能AUXHFRCO
//__disable_irq();
if(MSC_ErasePage((uint32_t *)0x0fe00000) == mscReturnOk)
{
MSC_WriteWord((uint32_t *)0x0fe00000,ucWriteIn,8);
}
MSC_Deinit();
unsigned char *Point = (unsigned char *)0x0fe00000;
for(unsigned char i = 0; i < 8; i++)
{
if(*(Point + i) == ucWriteIn[i])continue;
else
{
while(1); // error occur
}
}
//__enable_irq();
while(1);
}
截图如下: