開發(fā)環(huán)境:
MDK:Keil 5.30
開發(fā)板:GD32F207I-EVAL
MCU:GD32F207IK
Cortex-M的內(nèi)核中包含Systick定時(shí)器了,只要是Cortex-M系列的MCU就會(huì)有Systick,因此這是通用的,下面詳細(xì)分析。
1 Systick工作原理分析
SysTick 定時(shí)器被捆綁在 NVIC 中,用于產(chǎn)生 SysTick 異常(異常號(hào) :15)。在以前,操作系統(tǒng)和所有使用了時(shí)基的系統(tǒng)都必須有一個(gè)硬件定時(shí)器來(lái)產(chǎn)生需要的“滴答”中斷,作為整個(gè)系統(tǒng)的時(shí)基。滴答中斷對(duì)操作系統(tǒng)尤其重要。例如,操作系統(tǒng)可以為多個(gè)任務(wù)分配不同數(shù)目的時(shí)間片,確保沒(méi)有一個(gè)任務(wù)能霸占系統(tǒng) ;或者將每個(gè)定時(shí)器周期的某個(gè)時(shí)間范圍賜予特定的任務(wù)等,操作系統(tǒng)提供的各種定時(shí)功能都與這個(gè)滴答定時(shí)器有關(guān)。因此,需要一個(gè)定時(shí)器來(lái)產(chǎn)生周期性的中斷,而且最好還讓用戶程序不能隨意訪問(wèn)它的寄存器,以維持操作系統(tǒng)“心跳”的節(jié)律。
Cortex-M3 在內(nèi)核部分包含了一個(gè)簡(jiǎn)單的定時(shí)器——SysTick。因?yàn)樗械?CM3 芯片都帶有這個(gè)定時(shí)器,軟件在不同芯片生產(chǎn)廠商的 CM3 器件間的移植工作就得以簡(jiǎn)化。該定時(shí)器的時(shí)鐘源可以是內(nèi)部時(shí)鐘(FCLK,CM3 上的自由運(yùn)行時(shí)鐘),或者是外部時(shí)鐘。不過(guò),外部時(shí)鐘的具體來(lái)源則由芯片設(shè)計(jì)者決定,因此不同產(chǎn)品之間的時(shí)鐘頻率可能大不相同。因此,需要閱讀芯片的使用手冊(cè)來(lái)確定選擇什么作為時(shí)鐘源。在 GD32 中SysTick 以 HCLK(AHB 時(shí)鐘)或 HCLK/8 作為運(yùn)行時(shí)鐘,見上圖。
SysTick 定時(shí)器能產(chǎn)生中斷,CM3 為它專門開出一個(gè)異常類型,并且在向量表中有它的一席之地。它使操作系統(tǒng)和其他系統(tǒng)軟件在 CM3 器件間的移植變得簡(jiǎn)單多了,因?yàn)樵谒?CM3 產(chǎn)品間,SysTick 的處理方式都是相同的。SysTick 定時(shí)器除了能服務(wù)于操作系統(tǒng)之外,還能用于其他目的,如作為一個(gè)鬧鈴、用于測(cè)量時(shí)間等。 Systick 定時(shí)器屬于Cortex 內(nèi)核部件 ,可以參考《ARM Cortex-M3 權(quán)威指南》((英)JosephYiu 著,宋巖譯,北京航空航天大學(xué)出版社出版)來(lái)了解。
2 Systick寄存器分析
在傳統(tǒng)的嵌入式系統(tǒng)軟件按中通常實(shí)現(xiàn) Delay(N) 函數(shù)的方法為:
for(i = 0; i <= x; i ++);
x --- ;
對(duì)于GD32系列微處理器來(lái)說(shuō),執(zhí)行一條指令只有幾十個(gè) ns,進(jìn)行 for 循環(huán)時(shí),要實(shí)現(xiàn) N 毫秒的 x 值非常大,而且由于系統(tǒng)頻率的寬廣,很難計(jì)算出延時(shí) N 毫秒的精確值。針對(duì)GD32 微處理器,需要重新設(shè)計(jì)一個(gè)新的方法去實(shí)現(xiàn)該功能,以實(shí)現(xiàn)在程序中使用 Delay(N)。
Cortex-M3 的內(nèi)核中包含一個(gè) SysTick 時(shí)鐘。SysTick 為一個(gè) 24 位遞減計(jì)數(shù)器,SysTick 設(shè)定初值并使能后,每經(jīng)過(guò) 1 個(gè)系統(tǒng)時(shí)鐘周期,計(jì)數(shù)值就減 1。計(jì)數(shù)到 0 時(shí),SysTick 計(jì)數(shù)器自動(dòng)重裝初值并繼續(xù)計(jì)數(shù),同時(shí)內(nèi)部的 COUNTFLAG 標(biāo)志會(huì)置位,觸發(fā)中斷 (如果中斷使能情況下)。
在 GD32 的應(yīng)用中,使用 Cortex-M3 內(nèi)核的 SysTick 作為定時(shí)時(shí)鐘,設(shè)定每一毫秒產(chǎn)生一次中斷,在中斷處理函數(shù)里對(duì) N 減一,在Delay(N) 函數(shù)中循環(huán)檢測(cè) N 是否為 0,不為 0 則進(jìn)行循環(huán)等待;若為 0 則關(guān)閉 SysTick 時(shí)鐘,退出函數(shù)。
注: 全局變量 TimingDelay , 必須定義為 volatile 類型 , 延遲時(shí)間將不隨系統(tǒng)時(shí)鐘頻率改變。
Cortex-M3中的Systick部分內(nèi)容屬于NVIC控制部分,一共有4個(gè)寄存器,名稱和地址分別是:
STK_CTRL,0xE000E010--控制寄存器
第0位:ENABLE,Systick 使能位
(0:關(guān)閉Systick功能;1:開啟Systick功能)
第1位:TICKINT,Systick 中斷使能位
(0:關(guān)閉Systick中斷;1:開啟Systick中斷)
第2位:CLKSOURCE,Systick時(shí)鐘源選擇
(0:使用HCLK/8 作為Systick時(shí)鐘;1:使用HCLK作為Systick時(shí)鐘)
第16位:COUNTFLAG,Systick計(jì)數(shù)比較標(biāo)志,如果在上次讀取本寄存器后,SysTick 已經(jīng)數(shù)到了0,則該位為1。如果讀取該位,該位將自動(dòng)清零
STK_LOAD, 0xE000E014--重載寄存器
Systick是一個(gè)遞減的定時(shí)器,當(dāng)定時(shí)器遞減至0時(shí),重載寄存器中的值就會(huì)被重裝載,繼續(xù)開始遞減。STK_LOAD 重載寄存器是個(gè)24位的寄存器最大計(jì)數(shù)0xFFFFFF。
STK_VAL, 0xE000E018--當(dāng)前值寄存器
也是個(gè)24位的寄存器,讀取時(shí)返回當(dāng)前倒計(jì)數(shù)的值,寫它則使之清零,同時(shí)還會(huì)清除在SysTick控制及狀態(tài)寄存器中的COUNTFLAG標(biāo)志。
STK_CALRB, 0xE000E01C--校準(zhǔn)值寄存器
校準(zhǔn)值寄存器提供了這樣一個(gè)解決方案:它使系統(tǒng)即使在不同的CM3產(chǎn)品上運(yùn)行,也能產(chǎn)生恒定的SysTick中斷頻率。最簡(jiǎn)單的作法就是:直接把TENMS的值寫入重裝載寄存器,這樣一來(lái),只要沒(méi)突破系統(tǒng)極限,就能做到每10ms來(lái)一次 SysTick異常。如果需要其它的SysTick異常周期,則可以根據(jù)TENMS的值加以比例計(jì)算。只不過(guò),在少數(shù)情況下, CM3芯片可能無(wú)法準(zhǔn)確地提供TENMS的值(如, CM3的校準(zhǔn)輸入信號(hào)被拉低),所以為保險(xiǎn)起見,最好在使用TENMS前檢查器件的參考手冊(cè)。
SysTick定時(shí)器除了能服務(wù)于操作系統(tǒng)之外,還能用于其它目的:如作為一個(gè)鬧鈴,用于測(cè)量時(shí)間等。要注意的是,當(dāng)處理器在調(diào)試期間被喊停( halt)時(shí),則SysTick定時(shí)器亦將暫停運(yùn)作。
3 Systick定時(shí)器實(shí)現(xiàn)
SysTick屬于Cortex-M內(nèi)核的部分,因此其相關(guān)的定義在core_cm3.h文件中。
3.1 main文件分析
主函數(shù)如下:
/*
brief main function
param[in] none
param[out] none
retval none
*/
int main(void)
{
//systick init
sysTick_init();
/* configure LED1 GPIO port */
led_init(LED1);
/* configure LED2 GPIO port */
led_init(LED2);
/* configure LED3 GPIO port */
led_init(LED3);
/* configure LED4 GPIO port */
led_init(LED4);
while(1)
{
/* turn on LED1, turn off LED4 */
led_on(LED1);
led_off(LED4);
/*delay 500ms*/
delay_ms(500);
/* turn on LED2, turn off LED1 */
led_on(LED2);
led_off(LED1);
/*delay 500ms*/
delay_ms(500);
/* turn on LED3, turn off LED2 */
led_on(LED3);
led_off(LED2);
/*delay 500ms*/
delay_ms(500);
/* turn on LED4, turn off LED3 */
led_on(LED4);
led_off(LED3);
/*delay 500ms*/
delay_ms(500);
}
}
在 main 函數(shù)中,sysTick_init和 delay_us() 這兩個(gè)函數(shù)比較陌生,它們的功能分別是配置好 SysTick 定時(shí)器和進(jìn)行精確延時(shí)。整個(gè) main 函數(shù)的流程就是初始化 LED 及SysTick 定時(shí)器之后,就進(jìn)入死循環(huán),點(diǎn)亮LED的時(shí)間為精確的 500 ms。
3.2 gd32f207i_systick_eval.c文件分析
配置并啟動(dòng) SysTick
我們看一下systick_init()這個(gè)函數(shù),其功能是啟動(dòng)系統(tǒng)滴答定時(shí)器 SysTick。
/*
brief SysTick init
param[in] none
param[out] none
retval none
*/
void sysTick_init(void)
{
/* SystemFrequency / 1000 1ms中斷一次
* SystemFrequency / 100000 10us中斷一次
* SystemFrequency / 1000000 1us中斷一次
*/
/* setup systick timer for 1000Hz interrupts */
if(SysTick_Config(SystemCoreClock / 100000U)){
/* capture error */
while(1){
}
}
// 關(guān)閉滴答定時(shí)器
SysTick->CTRL &= ~ SysTick_CTRL_ENABLE_Msk;
/* configure the systick handler priority */
NVIC_SetPriority(SysTick_IRQn, 0x00U);
}
本函數(shù)實(shí)際上只是調(diào)用了 SysTick_Config() 函數(shù),它是屬于內(nèi)核層的 Cortex-M3 通用函數(shù),位于 core_cm3.h 文件中。若調(diào)用 SysTick_Config() 配置 SysTick 不成功,則進(jìn)入死循環(huán),初始化 SysTick 成功后,先關(guān)閉定時(shí)器,在需要的時(shí)候再開啟。SysTick_Config() 函數(shù)無(wú)法在GD32 外設(shè)固件庫(kù)文件中找到其使用方法。所以我們?cè)?Keil 環(huán)境下直接跟蹤這個(gè)函數(shù)到 core_cm3.h 文件,查看函數(shù)的定義。
/** \brief System Tick Configuration
The function initializes the System Timer and its interrupt, and starts the System Tick Timer.
Counter is in free running mode to generate periodic interrupts.
\param [in] ticks Number of ticks between two interrupts.
\return 0 Function succeeded.
\return 1 Function failed.
\note When the variable __Vendor_SysTickConfig is set to 1, then the
function SysTick_Config is not included. In this case, the file device.h
must contain a vendor-specific implementation of this function.
*/
__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
{
if ((ticks - 1) > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
SysTick->LOAD = ticks - 1; /* set reload register */
NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
SysTick->VAL = 0; /* Load the SysTick Counter Value */
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
SysTick_CTRL_TICKINT_Msk |
SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
return (0); /* Function successful */
}
在這個(gè)函數(shù)定義的前面有關(guān)于它的注釋,如果我們不想去研究它的具體實(shí)現(xiàn),可以根據(jù)這段注釋了解函數(shù)的功能 :這個(gè)函數(shù)啟動(dòng)了 SysTick ;并把它配置為計(jì)數(shù)至 0 時(shí)引起中斷 ;輸入的參數(shù) ticks 為兩個(gè)中斷之間的脈沖數(shù),即相隔 ticks 個(gè)時(shí)鐘周期會(huì)引起一次中斷 ;配置 SysTick 成功時(shí)返回 0,出錯(cuò)時(shí)返回 1。但是,這段注釋并沒(méi)有告訴我們它把 SysTick 的時(shí)鐘設(shè)置為 AHB 時(shí)鐘還是 AHB/8,這是一個(gè)十分關(guān)鍵的問(wèn)題,于是,我們將對(duì)這個(gè)函數(shù)的具體實(shí)現(xiàn)進(jìn)行分析,與大家再分享一下如何分析底層庫(kù)函數(shù)。分析底層庫(kù)函數(shù),要有 SysTick 定時(shí)器工作分析的知識(shí)準(zhǔn)備。
檢查輸入?yún)?shù)
SysTick_Config() 第 3 行代碼是檢查輸入?yún)?shù) ticks,因?yàn)?ticks 是脈沖計(jì)數(shù)值,要被保存到重載寄存器 STK_LOAD 寄存器中,再由硬件把 STK_LOAD 值加載到當(dāng)前計(jì)數(shù)值寄存器 STK_VAL 中使用,STK_LOAD 和 STK_VAL 都是 24 位的,所以當(dāng)輸入?yún)?shù) ticks 大于其可存儲(chǔ)的最大值時(shí),將由這行代碼檢查出錯(cuò)誤并返回。
位指示宏及位屏蔽宏
檢查 ticks 參數(shù)沒(méi)有錯(cuò)誤后,就稍稍處理一下把 ticks-1 賦值給 STK_LOAD 寄存器,要注意的是減 1,若 STK_VAL 從 ticks?1 向下計(jì)數(shù)至 0,實(shí)際上就經(jīng)過(guò)了 ticks 個(gè)脈沖。這句賦值代碼使用了宏 SysTick_LOAD_RELOAD_Msk,與其他庫(kù)函數(shù)類似,這個(gè)宏是用來(lái)指示寄存器的特定位置或進(jìn)行位屏蔽的。
/* SysTick Control / Status Register Definitions */
#define SysTick_CTRL_COUNTFLAG_Pos 16 /*!< SysTick CTRL: COUNTFLAG Position */
#define SysTick_CTRL_COUNTFLAG_Msk (1ul << SysTick_CTRL_COUNTFLAG_Pos) /*!< SysTick CTRL: COUNTFLAG Mask */
#define SysTick_CTRL_CLKSOURCE_Pos 2 /*!< SysTick CTRL: CLKSOURCE Position */
#define SysTick_CTRL_CLKSOURCE_Msk (1ul << SysTick_CTRL_CLKSOURCE_Pos) /*!< SysTick CTRL: CLKSOURCE Mask */
#define SysTick_CTRL_TICKINT_Pos 1 /*!< SysTick CTRL: TICKINT Position */
#define SysTick_CTRL_TICKINT_Msk (1ul << SysTick_CTRL_TICKINT_Pos) /*!< SysTick CTRL: TICKINT Mask */
#define SysTick_CTRL_ENABLE_Pos 0 /*!< SysTick CTRL: ENABLE Position */
#define SysTick_CTRL_ENABLE_Msk (1ul << SysTick_CTRL_ENABLE_Pos) /*!< SysTick CTRL: ENABLE Mask */
/* SysTick Reload Register Definitions */
#define SysTick_LOAD_RELOAD_Pos 0 /*!< SysTick LOAD: RELOAD Position */
上一篇:【技術(shù)分享】星空派GD32開發(fā)板LVGL移植經(jīng)驗(yàn)分享
下一篇:keil中GD32 MCU IAP中APP的存儲(chǔ)地址如何設(shè)置?
推薦閱讀最新更新時(shí)間:2025-06-26 18:47






設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦
- 單片機(jī)應(yīng)用編程技巧解析
- 基于89C52的教室智能節(jié)能照明系統(tǒng)設(shè)計(jì)
- 一種新型的雨量光照傳感器的設(shè)計(jì)
- 智能護(hù)眼臺(tái)燈設(shè)計(jì)
- 蓄電池高能脈沖充電系統(tǒng)設(shè)計(jì)
- 基于51單片機(jī)定時(shí)器的電子時(shí)鐘設(shè)計(jì)方案
- 瑞薩電子推出面向單電機(jī)應(yīng)用優(yōu)化的卓越MCU, 涵蓋電動(dòng)工具、家用電器等廣泛應(yīng)用場(chǎng)景
- 基于單片機(jī)的LED自適應(yīng)調(diào)光系統(tǒng)
- 智能小車主控系統(tǒng)電路設(shè)計(jì)
- LTC3772EDDB 演示板,550kHz 降壓型 DC/DC 轉(zhuǎn)換器,VIN = 2.75V-8V,VOUT = 3.3V @ 2A
- 用于大功率通用離線電源的 NCP1379 準(zhǔn)諧振電流模式控制器的典型應(yīng)用
- 用于 CRT 顯示器的 92W、-15V、5V、6.3V、15V、80V、200V AC 到 DC 多輸出電源
- 來(lái)自多個(gè)輸入源的 LTC3622EDE-23/5 雙路輸出降壓型穩(wěn)壓器的典型應(yīng)用電路
- AKD4644-B,帶有內(nèi)置 MIC/HP/RCV 放大器的 AK4644 立體聲編解碼器評(píng)估板
- 使用 Analog Devices 的 AD8033AKS 的參考設(shè)計(jì)
- LT6657BHMS8-1.25 負(fù)分流模式基準(zhǔn)的典型應(yīng)用電路
- CN0130
- 用于便攜式的 12 位 8 通道 DAC
- 使用 ROHM Semiconductor 的 BD12IA5WEFJ 的參考設(shè)計(jì)
- 比亞迪宣布實(shí)現(xiàn)媲美L4級(jí)智能泊車,承諾為安全兜底
- GW2208:同星智能以太網(wǎng)/CANFD/LIN網(wǎng)關(guān)設(shè)備來(lái)襲
- 在中國(guó)市場(chǎng),恩智浦繼續(xù)“上強(qiáng)度”
- 越疆機(jī)器人正式發(fā)布六足仿生機(jī)器狗
- BMW新世代融合獨(dú)創(chuàng)駕控超級(jí)大腦 重塑智能極致駕趣標(biāo)桿
- 2025年1-5月智能座艙供應(yīng)商裝機(jī)量排行榜:本土勢(shì)力多領(lǐng)域突圍,德賽西威持續(xù)霸榜
- 座艙車載聲學(xué)裝機(jī)量分析:多數(shù)量揚(yáng)聲器逐漸向下普及
- Lumissil Microsystems推出高側(cè)線性LED驅(qū)動(dòng)器系列 擴(kuò)展汽車照明產(chǎn)品組合
- Elaphe推出用于高性能電動(dòng)汽車的Sonic X輪轂電機(jī)平臺(tái)
- Aigtek高壓放大器在軟體機(jī)器人研究中的應(yīng)用
- 羅德施瓦茨成立大中華區(qū),羅杉博士任總裁
- 博世與蔚來(lái)正式成為“好基友”
- 羅德與施瓦茨任命羅杉博士為全球副總裁兼大中華區(qū)總裁
- 如何打造中國(guó)“芯”硅谷?
- Mobileye 和英偉達(dá):兩巨頭終將殊途同歸?
- Cognitive Pilot研發(fā)牙簽尺寸雷達(dá)傳感器 可用于自動(dòng)駕駛汽車
- 石墨負(fù)極密集投產(chǎn) 硅碳助力突破300Wh/kg比能量
- Sensata發(fā)布新型低噪聲固態(tài)繼電器
- Gumstix推出多款基于Jetson的開發(fā)板
- 鼎充新能源三大充電場(chǎng)站順利通過(guò)海口市聯(lián)合驗(yàn)收小組現(xiàn)場(chǎng)檢測(cè)
- 新產(chǎn)品快遞High-Side Current Monitors Simplify Measurement at High Voltage
- Modbus Plus 網(wǎng)絡(luò)在大型捏合機(jī)控制系統(tǒng)中的應(yīng)用
- 請(qǐng)幫忙分析TL431電路
- TI store“Cyber Monday”大促銷,所有開發(fā)工具九折+全場(chǎng)包郵!
- evc 4.0 下 調(diào)用軟件盤
- 2440 nandflash 啟動(dòng)問(wèn)題
- 親手制作漂亮的電子雜志(轉(zhuǎn))
- 讓我教你做數(shù)控放大器
- MOS管 場(chǎng)效應(yīng)管百科
- 求D773的數(shù)據(jù)手冊(cè)