SysTick的優先級是高還是低 原 薦

SysTick系統嘀嗒定時器並非STM32獨有的,它是Cortex內核的部分,CM3爲它專門開出一個異常類型,並且在中斷向量表中佔有一席之地(異常號15)。這樣它可以很方便的移植到不同廠商出CM3內核的芯片上,尤其對於有實時操作系統的軟件,它一般會作爲整個系統的時基,所以這個對操作系統非常重要。

但在STM32開發手冊中對它的介紹卻很少,幾乎到一筆帶過的程度。有關SysTick的詳細介紹可參考《Cortex-M3權威指南》第133 頁第八章及第179頁第十三章。

剛接觸SysTick時,因它屬於內核中斷優先級,我一直有個疑問,它是比所有的可屏蔽中斷優先級都高呢還是都低,或是處在等同設置地位 ?
最初我自以爲內核中斷優先級要比所有可屏蔽中斷優先級高,當認真查閱資料與做實驗後,發覺並非如此。

SysTick總共有四個寄存器:
1、

此寄存器在系統代碼中由 SysTick->CTRL變量表示;

2、

此寄存器在系統代碼中由 SysTick-> LOAD變量表示;

3、

此寄存器在系統代碼中由 SysTick-> VAL變量表示;

4、

此寄存器在系統代碼中由SysTick-> CALIB 變量表示,沒有用過,也不常用,暫不作介紹。


這幾個寄存器的偏移量如下圖所示:


上面寄存器結構體的定義在 \CMSIS\CM3\CoreSupport  core_cm3.h中如下所示:

/
**@addtogroup CMSIS_CM3_SysTick CMSIS CM3 SysTick
  memory mapped structure for SysTick
  @{
  */
typedef struct
{
    __IO uint32_t CTRL; /*!< Offset: 0x00 SysTick Control and Status Register */
    __IO uint32_t LOAD; /*!< Offset: 0x04 SysTick Reload Value Register */
    __IO uint32_t VAL; /*!< Offset: 0x08 SysTick Current Value Register */
    __I uint32_t CALIB; /*!< Offset: 0x0C SysTick Calibration Register */
} SysTick_Type;

SysTick 是一個24 位的定時器,即一次最多可以計數 224個時鐘脈衝,這個脈衝計數值被保存到SysTick->VAL 當前計數值寄存器中,它只能向下計數,每接收到一個時鐘脈衝SysTick->VAL 的值就向下減 1,直至0,然後由硬件自動把重載寄存器SysTick->LOAD 中的值到SysTick->VAL重新計數,並且當SysTick->VAL值計數到0時,觸發異常,調用void SysTick_Handler(void)函數,可以在此中斷服務函數中處理定時中斷事件了,一般是對設定值進行遞減計數操作。只要不把它在SysTick控制及狀態寄存器SysTick->CTRL中的第0位使能位清除,就永不停息。

它屬於系統異常,是內核級中斷,並且優先級是可以設置的,具體設置也是在  core_cm3.h中代碼如下:

/**
 * @brief Initialize and start the SysTick counter and its interrupt.
 *
 * @param ticks number of ticks between two interrupts
 * @return 1 = failed, 0 = successful
 *
 * Initialise the system tick timer and its interrupt and start the
 * system tick timer / counter in free running mode to generate 
 * periodical interrupts.
 */
static __INLINE uint32_t SysTick_Config(uint32_t ticks)
{ 
    if (ticks > SysTick_LOAD_RELOAD_Msk) return (1); /* Reload value impossible */
    SysTick->LOAD = (ticks & SysTick_LOAD_RELOAD_Msk) - 1; /* set reload register */
    NVIC_SetPriority (SysTick_IRQn, (1<<__NVIC_PRIO_BITS) - 1); 
    SysTick->VAL = 0; 
    SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | 
        SysTick_CTRL_TICKINT_Msk | 
        SysTick_CTRL_ENABLE_Msk; 
    return (0); /* Function successful */
}

在此段代碼中,優先級的設置是通過NVIC_SetPriority()函數實現,此函數對內核中斷優先級和外部中斷優先級設置都可以,比較強大,但需要手動算出來搶佔和從優先級,不太方便,當跳進此函數,我們可以算出Systick默認優先是最低的(效果相當於SCB->SHP[11] = 0xF0,如果你推算下,SHP[11] 正好對應於Systick優先級的設置);對於可屏蔽中斷,優先級的設置一般通過 NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)函數來實現,具體應用可參考下面的示例代碼。

當介紹完了理論後,發現還是沒有搞清楚最初的疑惑!現在就做實現來揭示真相。

先設置一事件中斷,把優先級設置高一些,

void Exti_Config(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    EXTI_InitStructure.EXTI_Line = EXTI_Line1;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}


注:中斷分組我在實驗中,最初初始化設置爲如下:

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

設爲第二組。

在系統滴答中斷裏觸發外部中斷事件,並點亮LED1 :

void SysTick_Handler(void)
{ 
    EXTI_GenerateSWInterrupt(EXTI_SWIER_SWIER1); 
    LED_1 = ON;
    Delay();
}

外部中斷處理函數中點亮LED0,如下:

void EXTI1_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line1) != RESET) 
    {
        EXTI_ClearITPendingBit(EXTI_Line1); 
        LED_0 = ON;
        Delay();
    }
}

當外部中斷優先級比較高時,它可以搶佔Systick中斷先執行,以上代碼實驗結果爲,LED0先點亮後,再回到LED1再點亮。

但當把外部中斷設置爲與systick相同的優先級時,則systick優先級就會相對較高,例如把上面的優先級改爲:

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; 
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;

則會LED1先亮,執行完SysTick_Handle函數後才輪到EXTI1_IRQHandler執行。

由以上實驗可得出,當優先級相同時,內核級中斷要優先於外部可屏蔽中斷執行,但設置外部可屏蔽中斷優先級大於內核級中斷時,它是可搶佔內核中斷的。

另外,個人認爲,若要實現systick精確延時,最好把systick優先級設置高一些,如 NVIC_SetPriority (SysTick_IRQn, 0);
即把SCB->SHP[11] = 0x00;則可達到systick優先級高於任合外部中斷的效果,此時延時會更少被其它中斷干擾,會更加精準。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章