rtthread
鏈表
初始化雙向鏈表
rt_inline void rt_list_init(rt_list_t *l) {l->next = l->prev = l; }插入
rt_inline void rt_list_insert_after(rt_list_t *l, rt_list_t *n) {l->next->prev = n;n->next = l->next;l->next = n;n->prev = l; }
在NODE1后面插入節(jié)點n,可以理解為:NODE3的前一個結(jié)點為n,n的后一個節(jié)點為NODE3,NODE3即l->next
刪除
rt_inline void rt_list_remove(rt_list_t *n) {n->next->prev = n->prev;n->prev->next = n->next;n->next = n->prev = n; }就緒列表
就是一個rt_list_t類型的數(shù)組。
/* 線程就緒列表 */ rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];每個線程控制塊都有一個成員tlist,類型為rt_list_t.我們將線程插入到就緒列表里面,就是通過將線程控制塊的 tlist 這個節(jié)點插入到就緒列表中來實現(xiàn)的。
/* 初始化線程 */ rt_thread_init( &rt_flag1_thread, /* 線程控制塊 */flag1_thread_entry, /* 線程入口地址 */RT_NULL, /* 線程形參 */&rt_flag1_thread_stack[0], /* 線程棧起始地址 */sizeof(rt_flag1_thread_stack) ); /* 線程棧大小,單位為字節(jié) */ /* 將線程插入到就緒列表 */ rt_list_insert_before( &(rt_thread_priority_table[0]),&(rt_flag1_thread.tlist) );系統(tǒng)調(diào)度初始化
/*** @ingroup SystemInit* This function will initialize the system scheduler*/ void rt_system_scheduler_init(void) {register rt_base_t offset;/* 線程就緒列表初始化 */for (offset = 0; offset < RT_THREAD_PRIORITY_MAX; offset ++){rt_list_init(&rt_thread_priority_table[offset]);}/* 初始化當(dāng)前線程控制塊指針 */rt_current_thread = RT_NULL; }此時的鏈表為空
啟動調(diào)度器
/*** @ingroup SystemInit* This function will startup scheduler. It will select one thread* with the highest priority level, then switch to it.*/ void rt_system_scheduler_start(void) {register struct rt_thread *to_thread;register rt_ubase_t highest_ready_priority;#if RT_THREAD_PRIORITY_MAX > 32register rt_ubase_t number;number = __rt_ffs(rt_thread_ready_priority_group) - 1;highest_ready_priority = (number << 3) + __rt_ffs(rt_thread_ready_table[number]) - 1; #elsehighest_ready_priority = __rt_ffs(rt_thread_ready_priority_group) - 1; #endif/* get switch to thread */to_thread = rt_list_entry(rt_thread_priority_table[highest_ready_priority].next,struct rt_thread,tlist);rt_current_thread = to_thread;/* switch to new thread */rt_hw_context_switch_to((rt_uint32_t)&to_thread->sp);/* never come back */ }臨界段保護(hù)
PRIMASK寄存器
這個寄存器只有一個位,置1后,將關(guān)閉所有可屏蔽中斷的異常,只剩NMI和硬fault,默認(rèn)值為0
;/* ; * rt_base_t rt_hw_interrupt_disable(); ; */ rt_hw_interrupt_disable PROCEXPORT rt_hw_interrupt_disableMRS r0, PRIMASKCPSID IBX LRENDP;/* ; * void rt_hw_interrupt_enable(rt_base_t level); ; */ rt_hw_interrupt_enable PROCEXPORT rt_hw_interrupt_enableMSR PRIMASK, r0BX LRENDP為什么不直接這樣寫?
;/* ; * void rt_hw_interrupt_disable(); ; */ rt_hw_interrupt_disable PROC EXPORT rt_hw_interrupt_disable CPSID I BX LR ENDP;/* ; * void rt_hw_interrupt_enable(void); ; */ rt_hw_interrupt_enable PROC EXPORT rt_hw_interrupt_enable CPSIE I BX LR ENDP避免在嵌套的臨界段失效,如下所示
/* 臨界段代碼 */ {/* 臨界段 1 開始 */rt_hw_interrupt_disable(); /* 關(guān)中斷,PRIMASK = 1 */{/* 臨界段 2 */rt_hw_interrupt_disable(); /* 關(guān)中斷,PRIMASK = 1 */{}rt_hw_interrupt_enable(); /* 開中斷,PRIMASK = 0 */ //(注意)}/* 這里已經(jīng)開啟了中斷,而臨界段1還未結(jié)束 *//* 臨界段 1 結(jié)束 */rt_hw_interrupt_enable(); /* 開中斷,PRIMASK = 0 */ }正確做法如下:
PRIMASK = 0; /* PRIMASK 初始值為 0,表示沒有關(guān)中斷 */ rt_base_t level1; rt_base_t level2;/* 臨界段代碼 */ {/* 臨界段 1 開始 */level1 = rt_hw_interrupt_disable(); /* 關(guān)中斷,level1=0,PRIMASK=1 */{/* 臨界段 2 */level2 = rt_hw_interrupt_disable(); /* 關(guān)中斷,level2=1,PRIMASK=1 */ {}rt_hw_interrupt_enable(level2); /* 開中斷,level2=1,PRIMASK=1 */}/* 臨界段 1 結(jié)束 */rt_hw_interrupt_enable(level1); /* 開中斷,level1=0,PRIMASK=0 */ }對象
軟件定時器
總結(jié)
- 上一篇: 编译google绘图框架skia
- 下一篇: Hardening Linux