OS Tick API CMSIS-RTOS2 API
在裝置不可知的 RTOS 實作和特定的周期性定時器功能之間提供低級 API 。更多...
函數 | |
int32_t | OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) |
建立 OS Tick 。更多... | |
void | OS_Tick_Enable (void) |
啟用 OS Tick 。更多... | |
void | OS_Tick_Disable (void) |
禁用 OS Tick 。更多... | |
void | OS_Tick_AcknowledgeIRQ (void) |
确認 OS Tick IRQ 。更多... | |
int32_t | OS_Tick_GetIRQn (void) |
擷取 OS Tick IRQ 編号。更多... | |
uint32_t | OS_Tick_GetClock (void) |
擷取 OS Tick 時鐘。更多... | |
uint32_t | OS_Tick_GetInterval (void) |
擷取 OS Tick 間隔。更多... | |
uint32_t | OS_Tick_GetCount (void) |
擷取 OS Tick 計數值。更多... | |
uint32_t | OS_Tick_GetOverflow (void) |
擷取 OS Tick 溢出狀态。更多... | |
描述
CMSIS OS Tick API 可以被任意 RTOS 實作使用,以便在各種各樣的控制器中輕松使用。
Cortex-M 器件共享一個通用系統節拍定時器,用于 RTOS 定時目的。Cortex-A 器件沒有常見的系統節拍定時器,但是有各種供應商特定的解決方案。為了使 RTOS(如 RTX5)更容易支援多種 Cortex 微控制器,OS Tick API 用于封裝裝置特定的定時器實作。
Cortex-M 系統滴答定時器的預設實作可以在 os_systick.c 中找到。
- 注意
- 預設的實作被定義為弱,是以可以很容易地被替代的使用者實作覆寫。
#include "os_tick.h" //lint -emacro((923,9078),SCB,SysTick) "cast from unsigned long to pointer" #include "RTE_Components.h" #include CMSIS_device_header #ifdef SysTick #ifndef SYSTICK_IRQ_PRIORITY #define SYSTICK_IRQ_PRIORITY 0xFFU #endif static uint8_t PendST; // Setup OS Tick. __WEAK int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) { uint32_t load; (void)handler; if (freq == 0U) { //lint -e{904} "Return statement before end of function" return (-1); } load = (SystemCoreClock / freq) - 1U; if (load > 0x00FFFFFFU) { //lint -e{904} "Return statement before end of function" return (-1); } // Set SysTick Interrupt Priority #if ((defined(__ARM_ARCH_8M_MAIN__) && (__ARM_ARCH_8M_MAIN__ != 0)) || \ (defined(__CORTEX_M) && (__CORTEX_M == 7U))) SCB->SHPR[11] = SYSTICK_IRQ_PRIORITY; #elif (defined(__ARM_ARCH_8M_BASE__) && (__ARM_ARCH_8M_BASE__ != 0)) SCB->SHPR[1] |= ((uint32_t)SYSTICK_IRQ_PRIORITY << 24); #elif ((defined(__ARM_ARCH_7M__) && (__ARM_ARCH_7M__ != 0)) || \ (defined(__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ != 0))) SCB->SHP[11] = SYSTICK_IRQ_PRIORITY; #elif (defined(__ARM_ARCH_6M__) && (__ARM_ARCH_6M__ != 0)) SCB->SHP[1] |= ((uint32_t)SYSTICK_IRQ_PRIORITY << 24); #else #error "Unknown ARM Core!" #endif SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk; SysTick->LOAD = load; SysTick->VAL = 0U; PendST = 0U; return (0); } /// Enable OS Tick. __WEAK void OS_Tick_Enable ( void) { if (PendST != 0U) { PendST = 0U; SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; } SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; } /// Disable OS Tick. __WEAK void OS_Tick_Disable ( void) { SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U) { SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; PendST = 1U; } } // Acknowledge OS Tick IRQ. __WEAK void OS_Tick_AcknowledgeIRQ ( void) { (void)SysTick->CTRL; } // Get OS Tick IRQ number. __WEAK int32_t OS_Tick_GetIRQn ( void) { return ((int32_t)SysTick_IRQn); } // Get OS Tick clock. __WEAK uint32_t OS_Tick_GetClock ( void) { return (SystemCoreClock); } // Get OS Tick interval. __WEAK uint32_t OS_Tick_GetInterval ( void) { return (SysTick->LOAD + 1U); } // Get OS Tick count value. __WEAK uint32_t OS_Tick_GetCount ( void) { uint32_t load = SysTick->LOAD; return (load - SysTick->VAL); } // Get OS Tick overflow status. __WEAK uint32_t OS_Tick_GetOverflow ( void) { return ((SysTick->CTRL >> 16) & 1U); } #endif // SysTick
函數文檔
int32_t OS_Tick_Setup | ( | uint32_t | freq, |
IRQHandler_t | handler | ||
) |
- 參數
-
[in] freq 滴答頻率,機關為 Hz [in] handler 滴答 IRQ 處理程式
- 傳回
- 成功時為 0 ,錯誤時為 -1 。
設定一個硬體時間,用于為 RTOS 産生周期性的滴答中斷。
定時器應該配置為在給定頻率下産生中斷。給定的回調應該用作中斷處理程式。
定時器隻應該被初始化并相應地配置。在調用 OS_Tick_Enable 之前,它不能啟動也不能建立中斷。
對于使用内置 SystemTick 定時器的簡單 Cortex-M 裝置,預設實作如下例所示:
#ifndef SYSTICK_IRQ_PRIORITY #define SYSTICK_IRQ_PRIORITY 0xFFU #endif static uint8_t PendST; int32_t OS_Tick_Setup (uint32_t freq, IRQHandler_t handler) { (void)handler; uint32_t load; if (freq == 0U) { return (-1); } load = (SystemCoreClock / freq) - 1U; if (load > 0x00FFFFFFU) { return (-1); } NVIC_SetPriority(SysTick_IRQn, SYSTICK_IRQ_PRIORITY); SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk; SysTick->LOAD = load; SysTick->VAL = 0U; PendST = 0U; return (0); }
int32_t OS_Tick_Enable | ( | void | ) |
啟動定時器來計數并啟用周期性中斷的生成。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
int32_t OS_Tick_Enable ( void) { if (PendST != 0U) { PendST = 0U; SCB->ICSR = SCB_ICSR_PENDSTSET_Msk; } SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk; return (0); }
int32_t OS_Tick_Disable | ( | void | ) |
停止定時器計數并禁止生成周期性中斷。
在調用這個函數之後,定時器不能産生任何進一步的中斷。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
int32_t OS_Tick_Disable ( void) { SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk; if ((SCB->ICSR & SCB_ICSR_PENDSTSET_Msk) != 0U) { SCB->ICSR = SCB_ICSR_PENDSTCLR_Msk; PendST = 1U; } return (0); }
int32_t OS_Tick_AcknowledgeIRQ | ( | void | ) |
确認待處理的滴答中斷,即通過清除挂起标志。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
int32_t OS_Tick_AcknowledgeIRQ ( void) { (void)SysTick->CTRL; return (0); }
int32_t OS_Tick_GetIRQn | ( | void | ) |
- 傳回
- OS Tick IRQ 編号。
傳回實際的數值來辨別定時器使用的中斷。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
int32_t OS_Tick_GetIRQn ( void) { return (SysTick_IRQn); }
uint32_t OS_Tick_GetClock | ( | void | ) |
- 傳回
- OS Tick 時鐘,機關為 Hz 。
傳回定時器工作的時鐘頻率,即給定内部計數器值的增量。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
uint32_t OS_Tick_GetClock ( void) { return (SystemCoreClock); }
uint32_t OS_Tick_GetInterval | ( | void | ) |
- 傳回
- OS Tick 間隔。
将連續滴答中斷之間的内部計數器值的實際計數間隔傳回。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
uint32_t OS_Tick_GetInterval ( void) { return (SysTick->LOAD + 1U); }
uint32_t OS_Tick_GetCount | ( | void | ) |
- 傳回
- OS Tick 計數值。
傳回 0 到 OS_Tick_GetInterval() - 1 之間的内部計數器的目前值。
如果需要更高的時間分辨率,則使用此值計算子标記,即 OS_Tick_GetCount()/ OS_Tick_GetInterval()。
- 注意
- 如果硬體是一個遞減計數器(例如 Cortex-M 系統節拍定時器),則必須計算相應的遞增計數器值。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
uint32_t OS_Tick_GetCount ( void) { uint32_t load = SysTick->LOAD; return (load - SysTick->VAL); }
OS_Tick_GetOverflow | ( | void | ) |
- 傳回
- OS Tick 溢出狀态(1 - 溢出,0 - 無溢出)。
傳回溢出信号的目前狀态,即定時器中斷等待位。
這個資訊可以用來計算一個中間的(但是正确的)滴答值,而滴答中斷正在挂起但被阻塞。
對于使用内置 SystemTick 計時器的簡單 Cortex-M 裝置,預設實作如下例所示:
uint32_t OS_Tick_GetOverflow ( void) { return ((SysTick->CTRL >> 16) & 1U); }