4.2 實現阻塞延時
4.3 systick 中斷服務
4.4 systick 初始化
4.5 案例
4.6 實驗現象
[野火®]《freertos 核心實現與應用開發實戰—基於stm32》在 rtos 中,任務需要延時時,不能再讓 cpu 空等來實現延時效果。
rtos 中的延時稱為阻塞延時,即任務需要延時的時候,任務會放棄 cpu 的使用權,cpu 可以去做其它的事情,當任務延時時間到,重新獲取 cpu 使用權,任務繼續執行,這樣就充分地利用了 cpu 的資源。
如果沒有其它任務可以執行,rtos 都會為 cpu 建立乙個空閒任務,這個時候 cpu 就執行空閒任務。
在 freertos 中,空閒任務是系統在初始化啟動排程器的時候建立的優先順序最低的任務,空閒任務主體主要是做一些系統記憶體的清理工作。
鑑於空閒任務的這種特性,在實際應用中,當系統進入空閒任務的時候,可在空閒任務中讓微控制器進入休眠或者低功耗等操作。
#define configminimal_stack_size ( ( unsigned short ) 128 )
stacktype_t idletaskstack[configminimal_stack_size]
;
tcb_t idletasktcb;
空閒任務在排程器啟動函式 vtaskstartscheduler() 中建立。
extern tcb_t idletasktcb;
void
( tcb_t *
*ppxidletasktcbbuffer,
stacktype_t *
*ppxidletaskstackbuffer,
uint32_t *pulidletaskstacksize )
;void
vtaskstartscheduler
(void
)}
獲取空閒任務的記憶體,即任務棧和任務tcb,該函式的實現如下。
void
( tcb_t *
*ppxidletasktcbbuffer,
stacktype_t *
*ppxidletaskstackbuffer,
uint32_t *pulidletaskstacksize )
阻塞延時的阻塞是指任務呼叫該延時函式後,任務會被剝離 cpu 使用權,然後進入阻塞狀態,直到延時結束,任務重新獲取 cpu 使用權才可以繼續執行。
在任務阻塞的這段時間,cpu 可以去執行其它的任務,如果其它的任務也在延時狀態,那麼 cpu 就將執行空閒任務。
void
vtaskdelay
(const ticktype_t xtickstodelay )
xtickstodelay 定義如下。
typedef
struct tsktaskcontrolblock
tsktcb;
typedef tsktcb tcb_t;
在任務上下文切換函式 vtaskswitchcontext () 中,會判斷每個任務的任務控制塊中的延時成員 xtickstodelay 的值是否為 0,如果為 0 就要將對應的任務就緒,如果不為 0 就繼續延時。
void
vtaskswitchcontext
(void
)else
if(task2tcb.xtickstodelay ==0)
else
}else
else
if(pxcurrenttcb->xtickstodelay !=0)
else
}else
if(pxcurrenttcb ==
&task2tcb)
else
if(pxcurrenttcb->xtickstodelay !=0)
else}}
}
在 freertos 中,延時阻塞的週期由 systick 中斷提供,作業系統裡面的最小的時間單位就是 systick 的中斷週期,稱之為乙個 tick,systick 中斷服務函式在 port.c 中實現。
void
xportsystickhandler
(void
)
void
xtaskincrementtick
(void)}
/* 任務切換 */
portyield()
;}
systick 的中斷服務函式要想被順利執行,則 systick 必須先初始化。
/* 配置 systick 需要用到的暫存器和巨集定義,在 port.c 中實現。*/
/* systick 控制暫存器 */
#define portnvic_systick_ctrl_reg (*((volatile uint32_t *) 0xe000e010 ))
/* systick 重裝載暫存器暫存器 */
#define portnvic_systick_load_reg (*((volatile uint32_t *) 0xe000e014 ))
#define configcpu_clock_hz (( unsigned long ) 25000000)
/* 系統時鐘的大小;*/
#define configtick_rate_hz (( ticktype_t ) 100)
/* systick 每秒中斷多少次,目前配置為 100,即每 10ms 中斷一次。*/
/* systick 時鐘源選擇 */
#ifndef configsystick_clock_hz
#define configsystick_clock_hz configcpu_clock_hz
/* 確保 systick 的時鐘與核心時鐘一致 */
#define portnvic_systick_clk_bit ( 1ul << 2ul )
#else
#define portnvic_systick_clk_bit ( 0 )
#endif
#define portnvic_systick_int_bit ( 1ul << 1ul )
#define portnvic_systick_enable_bit ( 1ul << 0ul )
void
vportsetuptimerinterrupt
(void
)
/* 任務1 */
void
task1_entry
(void
*p_arg )
}/* 任務2 */
void
task2_entry
(void
*p_arg )
}/* 定義空閒任務的棧和 tcb;*/
從邏輯分析儀中可以看到兩個任務的波形是完全同步,cpu 似乎在同時幹兩件事情。
flag1 和 flag2 的高電平的時間為(0.1802-0.1602)s,剛好等於阻塞延時的 20ms,所以實驗現象跟**要實現的功能是一致的。
FreeRtos 空閒任務與空閒任務鉤子函式
以下基礎知識 自正點原子pdf資料。前面例子中建立的任務大部份時間都處於阻塞態。這種狀態下所有的任務都不可執行,所以也不能被排程器選中。但處理器總是需要 來執行 所以至少要有乙個任務處於執行態。為了保證這 一點,當呼叫 vtaskstartscheduler 時,排程器會自動建立乙個空閒任務。空閒任...
FreeRTOS空閒任務
空閒任務在啟動排程器的時候被建立 啟動排程器 void vtaskstartscheduler void else endif if xreturn pdpass else else 空閒任務的作用包括 保證系統至少有乙個任務在執行 檢查等待終結列表中是否有任務並釋放它們。空閒任務 static p...
FreeRTOS 空閒任務與阻塞延遲實現
在裸機執行中,我們是使用軟體延時來實現延時的功能 delay 即是讓cpu空等來達到延時的目的。使用rtos的很大優勢就是榨乾cpu效能,永遠不讓他閒著,任務需要延時也就不需要讓cpu空等來實現延時的效果。rtos中的延時叫做阻塞延時,即任務需要延時的時候,任務會放棄cpu的使用權,cpu可以去幹其...