新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > SysTick系統(tǒng)時鐘滴答實(shí)驗(yàn)(stm32中斷入門)

SysTick系統(tǒng)時鐘滴答實(shí)驗(yàn)(stm32中斷入門)

作者: 時間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
 系統(tǒng)時鐘滴答實(shí)驗(yàn)很不難,我就在面簡單說下,但其中涉及到了STM32最復(fù)雜也是以后用途最廣的外設(shè)-NVIC,如果說RCC是實(shí)時性所必須考慮的部分,那么NVIC就是stm32功能性實(shí)現(xiàn)的基礎(chǔ),NVIC的難度并不高,但是理解起來還是比較復(fù)雜的,我會在本文中從實(shí)際應(yīng)用出發(fā)去說明,當(dāng)然最好去仔細(xì)研讀宋巖翻譯的第八章,注意這不是一本教你如何編寫STM32代碼的工具書,而是闡述Cortex-M3內(nèi)核原理的參考書,十分值得閱讀。

 SysTick系統(tǒng)時鐘的核心有兩個,外設(shè)初始化和Systick_Handle()中斷處理函數(shù)。

本文引用地址:http://m.butianyuan.cn/article/201611/318493.htm

 Systick配置:

static void SysTick_UserConfig(void){SysTick->CTRL &= 0xfffffffb;  //采用內(nèi)核外部時鐘,即SYSTICKSysTick->LOAD = 0x8;       //重裝值寄存器,VAL內(nèi)數(shù)值為0時重裝 SysTick->VAL = 0x00;          //SysTick當(dāng)前值寄存器 清零SysTick->CTRL = 0x03;         //SysTick定時器使能,中斷使能}

NVIC配置:

void NVIC_UserConfig(void){NVIC_SetVectorTable(NVIC_VectTab_FLASH,0x0);      //將指針指向flash中的中斷向量表}

中斷函數(shù):

void SysTick_Handler(void){static  uint32_t LED_Flag = 0;if(LED_Flag < 50){LED_1_ON();}if(LED_Flag >= 50){LED_1_OFF();}LED_Flag++;if(LED_Flag == 100){LED_Flag = 0;}}

 如此,就完成了簡單的SysTick滴答實(shí)驗(yàn),代碼請參考:http://files.cnblogs.com/files/zc110747/6.SysTick.7z

看到這是不是就結(jié)束了,不過記得當(dāng)時我寫完這個程序,疑問有以下幾點(diǎn):

1.向量表是如何定義的,重定位的操作有什么作用

2.為什么中斷函數(shù)名一定要是void SysTick_Handler(void),怎么確定的

3.中斷打亂了正常的程序流程,cpu怎么知道回到之前運(yùn)行的位置

4.中斷優(yōu)先級如何配置和理解

如何解決這些問題,這都需要從原理方面來解決了,了解過IAP和uC/os-ii的對這些問題應(yīng)該有一定認(rèn)知,下面我就系統(tǒng)的講解下我的想法:

1~2問題.當(dāng) CM3 內(nèi)核響應(yīng)了一個發(fā)生的異常后,對應(yīng)的異常服務(wù)例程(ESR)就會執(zhí)行。為了決定 ESR 的入口地址,這就是所謂的“向量表查表機(jī)制”。向量表其實(shí)是一個 WORD( 32 位整數(shù))數(shù)組,每個下標(biāo)對應(yīng)一種異常,該下標(biāo)元素的值則是該 ESR 的入口地址。如果細(xì)心查看startup_stm32f10x_cl.s,就會發(fā)現(xiàn)下面語句:

; Vector Table Mapped to Address 0 at ResetAREA    RESET, DATA, READONLYEXPORT  __VectorsEXPORT  __Vectors_EndEXPORT  __Vectors_Size__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset HandlerDCD     NMI_Handler                ; NMI HandlerDCD     HardFault_Handler          ; Hard Fault HandlerDCD     MemManage_Handler          ; MPU Fault HandlerDCD     BusFault_Handler           ; Bus Fault HandlerDCD     UsageFault_Handler         ; Usage Fault HandlerDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     SVC_Handler                ; SVCall HandlerDCD     DebugMon_Handler           ; Debug Monitor HandlerDCD     0                          ; ReservedDCD     PendSV_Handler             ; PendSV HandlerDCD     SysTick_Handler            ; SysTick Handler; External InterruptsDCD     WWDG_IRQHandler            ; Window Watchdog......DCD     OTG_FS_IRQHandler          ; USB OTG FS__Vectors_End__Vectors_Size  EQU  __Vectors_End - __VectorsAREA    .text, CODE, READONLY

  其中_Vectors既是所提到的WORD數(shù)組,這就是定義的向量表,如果了解過指向函數(shù)的指針,那么就可以知道,DCD的每一項(xiàng)就是定義的中斷服務(wù)例程,這樣我們就知道為什么Systick中斷的中斷服務(wù)例程是SysTick_Handler,當(dāng)然根據(jù)實(shí)際情況這個向量表只要和主函數(shù)代碼保持一致就可以實(shí)現(xiàn)中斷的查詢,例如uC/os-ii移植中修改PendSV_Handler。

  看到這解決了第二個問題,那么第一個問題,從上面可以看出來,向量表一直位于代碼的最頂端,也就是偏移量0x0的位置,為什么有時還需要重定位呢?如果看過IAP那篇,了解了啟動機(jī)制后,應(yīng)該明白上電后系統(tǒng)會默認(rèn)跳轉(zhuǎn)0x00(flash地址0x08映射),然后讀取向量表偏移寄存器,查詢向量表,因?yàn)榇藭r向量表的偏移量就是0x0,向量表就不需要重定義。而在IAP模式下,應(yīng)用代碼的起始地址并不是flash首地址,而是由偏移量0x8(假定值),從上面也可以簡單推出應(yīng)用代碼的向量表偏移量也是0x8,此時向量表偏移寄存器就需要重定義了。

下圖來自于list下生成的.map文件

再參考生成的bin文件和啟動文件:

可以很清晰證實(shí)上面的觀點(diǎn)。

3.了解M3芯片基礎(chǔ)的應(yīng)該知道,M3擁有通用寄存器組R0~R15,這些寄存器在程序運(yùn)行中保存著代碼流程的所有信息,包括當(dāng)前地址,正在修改的變量參數(shù)。因此在中斷觸發(fā)時,只要將R0~R15依次壓棧,中斷結(jié)束后出棧,代碼就會回到運(yùn)行之前的位置(uC/OS-ii正是模擬該過程實(shí)現(xiàn)任務(wù)切換的),當(dāng)然這只是最簡單的一種情況,因?yàn)閙3芯片本身支持中斷優(yōu)先級和中斷嵌套,實(shí)際復(fù)雜度遠(yuǎn)高于此.其實(shí)可以簡化為如下流程:

  主程序暫停 -〉相關(guān)位置和狀態(tài)參數(shù)入棧-〉中斷服務(wù)例程執(zhí)行-〉相關(guān)位置和狀態(tài)參數(shù)出棧-〉主程序恢復(fù)

4.Cortex-M3支持最多240個可配置中斷,中斷優(yōu)先級的數(shù)目3~8位,也就是支持8~256個優(yōu)先級,而事實(shí)上一般并沒有支持那么多,如8,16,32級,其中最多支持128個搶占級。arm中斷及復(fù)位控制寄存器中的3~8位設(shè)定優(yōu)先級的部分,通過配置可將其分割為兩部分,前面為搶占級,后面為亞優(yōu)先級,并且亞優(yōu)先級至少為1位,分組是可以從保留的優(yōu)先級組開始的。一個中斷的優(yōu)先級可通過以下順序判斷,優(yōu)先級依此降低。

  優(yōu)先級組:搶占級 > 亞優(yōu)先級

  優(yōu)先級: 數(shù)值小 > 數(shù)值大

  中斷號: 中斷號小 > 中斷號大

搶占級和亞優(yōu)先級的區(qū)別:

  搶占級是在發(fā)生在中斷嵌套的基礎(chǔ),上面提到了中斷打斷了線程的流程,但是如果有搶占級的加入,中斷本身也會被優(yōu)先級更高的中斷打斷,具體流程如下:

  主程序暫停 -〉低優(yōu)先級中斷 -〉高優(yōu)先級中斷-〉低優(yōu)先級中斷-〉主程序恢復(fù)

  亞優(yōu)先級表示沒有發(fā)生中斷的嵌套,一個中斷只有在它結(jié)束后另一個亞優(yōu)先級的中斷才會響應(yīng),即不會發(fā)生中斷嵌套。

此外為了加快中斷執(zhí)行的流程,Cortex-M3提供了基于優(yōu)先級的四種動作:

  1.占先:主要發(fā)生在搶占級中,即高優(yōu)先級中斷低優(yōu)先級執(zhí)行,發(fā)生中斷嵌套

  2.末尾連鎖:若占先發(fā)生上一個中斷的末尾出棧之前,則打斷出棧動作,直接執(zhí)行高優(yōu)先級中斷,結(jié)束后如果沒有發(fā)生搶占,才執(zhí)行出棧

  3.遲來 若占先發(fā)生在中斷的開始入棧階段,則繼續(xù)入棧,低優(yōu)先級中斷掛起。

  4.返回 出棧過程,如果收到高優(yōu)先級中斷則停止并產(chǎn)生末尾連鎖

  從上面可以看出,中斷優(yōu)先級和中斷嵌套在加上ARM基于優(yōu)先級機(jī)制的優(yōu)化,可以讓中斷中高優(yōu)先級任務(wù)更快執(zhí)行,正是優(yōu)先級設(shè)定的意義。



評論


技術(shù)專區(qū)

關(guān)閉