新聞中心

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

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

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

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

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

 Systick配置:

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

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

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

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

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

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

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

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

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

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

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

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

下圖來(lái)自于list下生成的.map文件

再參考生成的bin文件和啟動(dòng)文件:

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

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

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

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

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

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

  中斷號(hào): 中斷號(hào)小 > 中斷號(hào)大

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

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

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

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

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

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

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

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

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

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



評(píng)論


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

關(guān)閉