Systick是什麼?
關于Systick,在Context-M3權威指南中如此描述:
SysTick定時器被捆綁在NVIC中,用于産生SYSTICK異常(異常号: 15)。在以前,大多作業系統需要一個硬體定時器來産生作業系統需要的滴答中斷,作為整個系統的時基。例如,為多個任務許以不同數目的時間片,確定沒有一個任務能霸占系統;或者把每個定時器周期的某個時間範圍賜予特定的任務等,還有作業系統提供的各種定時功能,都與這個滴答定時器有關。是以,需要一個定時器來産生周期性的中斷,而且最好還讓使用者程式不能随意通路它的寄存器,以維持作業系統“心跳”的節律。
SysTick定時器能産生中斷, CM3為它專門開出一個異常類型,并且在向量表中有它的一席之地。它使作業系統和其它系統軟體在CM3器件間的移植變得簡單多了,因為在所有CM3産品間對其處理都是相同的。
SysTick 是一個 24 位的倒計數定時器,當計到 0 時,将從 RELOAD 寄存器中自動重裝載定時初值。隻要不把它在 SysTick 控制及狀态寄存器中的使能位清除, 就永不停息,圖 13.1 中小結了 SysTick的相關寄存器。
這是定義在core_cm3.h中的結構體:
SysTick 的最大使命,就是定期地産生異常請求,作為系統的時基。 OS 都需要這種“滴答” 來推動任務和時間的管理。 如欲使能 SysTick 異常, 則把 STCSR.TICKINT 置位。 另外, 如果向量表被重定位到 SRAM 中,還需要為 SysTick 異常建立向量,提供其服務例程的入口位址。
Systick如何使用?
前面說了那麼多,Systick到底是什麼,小夥伴們是不是已經明白了呢?其實,簡單一句話,就是“心跳”,CPU以心跳為依據配置設定要做的事情,嘀哒...嘀哒...嘀哒...
cubemx配置Systick
來來來,實踐是檢驗真理的唯一标準,沒有實踐的理論就是耍流氓~~
Systick是系統的“心跳”,為系統提供着時基來源,cubemx中是已經為我們勾選了的,預設的時基是來源于Systick
當然了,條條大路通羅馬,Systick可以作為時基,但卻不是唯一的,不信你看,實際上有這麼多的定時器都可以用來作為時基來源的,移植過作業系統的小夥伴一定不陌生,本次,我們隻介紹關于Systick的功能~
- 時鐘配置
關于時鐘配置的詳細講解,請參看:CubeMX的正确打開方式 一文
- 序列槽配置
關于序列槽配置的詳細解釋,請參看:CubeMX的正确打開方式 一文
- Systick中斷
可以看到,Systick的中斷是預設已經開啟了的,直接使用即可
Systick代碼詳細解析
結合生成的工程,來看看Systick的時鐘配置以及工作流程,systick首先在HAL_Init()函數中被提到,被cue來幹嘛呢,接下來跟進去看看
從英文解釋中(别說看不懂哈),Systick被配置為系統時基,并且被配置為了1ms,做技術,要有刨根問底的精神,奧利給,繼續跟進去看看
這段英文解釋很重要,外設中斷程序調用HAL_Delay的時候,要特别注意中斷的優先級問題,如果systick的中斷優先級低于外設中斷優先級,會導緻一直在外設中斷中阻塞,如果外設中調用了HAL_Delay(),一定要保證Systick的中斷優先級高于外設中斷優先級,但是,小飛哥是極其不建議在中斷中調用HAL_Delay()函數的
明明是在說Systick的事情,怎麼牽扯到HAL_Delay()函數了呢,那就再來看看,HAL_Delay()是如何實作的呢?打開HAL_Delay(),可以看到,實際上是通過uWTick這個全局變量不斷增加,比較來實作的延時,那麼uWTick是在哪裡增加的呢?
好家夥,轉了十萬八千裡,最終還是在Systick中斷中進行增加的,預設配置的是Systick 1ms中斷,這下知道了我們調用的HAL_Delay(),為什麼是1ms了吧,繞了那麼一大圈,是不是有點想打人呢~
預設配置的是1ms中斷周期,那我們HAL_Delay()的最小機關是1ms,如果想獲得1us的中斷周期,該如何調整呢?且往下看,這是我們自定義的systick周期配置函數,一步一步來看
先來看systick的時鐘來源,時鐘來源為HCLK或者是HCLK的8分頻,小飛哥實驗選擇的是HCLK,72MHZ,确定了systick的時鐘源,接下來配置systick的中斷周期
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
再來看這個函數,分析之前,我們先來看看systick的中斷周期時間是怎麼計算的,T=ReloadValue10001/72000000ms
這是預設的配置1ms,主頻是72MHZ,uwTickFreq預設是1KHZ,根據上面的分析計算,算下來T = (72MHZ/1000)1/72MHZ=1000/72MHZ(1/72MHZ)=1/1000s=1ms,你看懂了嗎?
HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)
根據上面的分析,我們想要1us、10ms、100ms....的中斷周期怎麼辦,那就根據上面的計算公式算吧,那這麼修改後,HAL_Delay不就可以實作us延時了嘛,實作當然是能實作,但中斷是不是過于頻繁了呢,1us一個中斷诶,那怎麼實作呢,請檢視,關于HAL庫us延時的3種實作方式
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); //1ms
到此,關于systick的工作流程就算是介紹差不多了,還有最後一步,Systick中斷回調函數需要添加到中斷回調句柄中
可以看到systick中斷回調函數依然是_weak修飾符,意思就是我們自己一個一樣名字的函數,不會報錯
我們自己重新定義回調函數,進行中斷事務,好的程式設計習慣,中斷置标志,所有的邏輯處理放在中斷外處理,建議這樣做
while中不斷查詢标志
測試結果
間隔100ms,列印systick test,測試OK,over
關于Embeded-party
歡迎加入群聊Embeded-party,這裡有一群可愛的人兒,很多有意思的設計,等着你的加入哦
資料擷取
公衆号背景回複,systick,即可獲得源碼哦~