1. 程式人生 > >EFM32片內外設--MSC之不關總中斷

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);
}

截圖如下: