EFM32片內外設--MSC之不關總中斷
在上一次對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);
}
截圖如下: