閑來無事,作為第一次使用實時操作系統(tǒng)的小白想看看rtthread的調(diào)度方式。
總結(jié):
主要調(diào)度使用scheduler.c和context——gcc.s。
void rt_system_scheduler_start(void)
{
register struct rt_thread *to_thread;
rt_ubase_t highest_ready_priority;
to_thread = _get_highest_priority_thread(&highest_ready_priority);
rt_current_thread = to_thread;
rt_schedule_remove_thread(to_thread);
to_thread->stat = RT_THREAD_RUNNING;
rt_hw_context_switch_to((rt_ubase_t)&to_thread->sp);//跳轉(zhuǎn)至.s文件執(zhí)行
}
第一次會調(diào)用此函數(shù)用來執(zhí)行一個.s文件
c
rt_hw_context_switch_to:
LDR r1, =rt_interrupt_to_thread
STR r0, [r1] / 將rt_interrupt_to_thread寫入一個sp指針待會會用到 /
/* set interrupt flag to 1 /
LDR r1, =rt_thread_switch_interrupt_flag
MOV r0, #1
STR r0, [r1]
...
LDR r0, =NVIC_INT_CTRL / trigger the PendSV exception (causes context switch) /
LDR r1, =NVIC_PENDSVSET
STR r1, [r0] / NVIC_INT_CTRL為ICSR寄存器將28位置1會導(dǎo)致一個sv異常,任務(wù)切 換也在sv中進(jìn)行 /
/ restore MSP */
LDR r0, =SCB_VTOR / VTOR保存著內(nèi)存地址偏移,取出偏移值賦值給msp寄存器 /
LDR r0, [r0]
LDR r0, [r0]
NOP
MSR msp, r0
...
第一次觸發(fā)的sv異常
PendSV_Handler:
/* disable interrupt to protect context switch /
MRS r2, PRIMASK
CPSID I
/ get rt_thread_switch_interrupt_flag /
LDR r0, =rt_thread_switch_interrupt_flag
LDR r1, [r0]
CBZ r1, pendsv_exit / pendsv already handled /
/ clear rt_thread_switch_interrupt_flag to 0 /
MOV r1, #0x00
STR r1, [r0]
LDR r0, =rt_interrupt_from_thread / 第一次執(zhí)行所以此函數(shù)我們并沒有賦值所以會執(zhí)行跳轉(zhuǎn) /
LDR r1, [r0]
CBZ r1, switch_to_thread / skip register save at the first time /
MRS r1, psp / get from thread stack pointer /
STMFD r1!, {r4 - r11} / push r4 - r11 register /
LDR r0, [r0]
STR r1, [r0] / update from thread stack pointer /
switch_to_thread:
LDR r1, =rt_interrupt_to_thread / 獲取需要切換的任務(wù)的sp指針 /
LDR r1, [r1]
LDR r1, [r1] / load thread stack pointer /
LDMFD r1!, {r4 - r11} / pop r4 - r11 register /
MSR psp, r1 / update stack pointer /
/ 此時psp寄存器已指向我們目標(biāo)任務(wù)的sp /
pendsv_exit:
/ restore interrupt */
MSR PRIMASK, r2
ORR lr, lr, #0x04
BX lr
在后續(xù)的輪轉(zhuǎn)中我們會調(diào)用
void rt_schedule(void)
{
rt_base_t level;
struct rt_thread to_thread;
struct rt_thread from_thread;
/ disable interrupt /
level = rt_hw_interrupt_disable();
/ check the scheduler is enabled or not /
if (rt_scheduler_lock_nest == 0)
{
rt_ubase_t highest_ready_priority;
if (rt_thread_ready_priority_group != 0)
{
/ need_insert_from_thread: need to insert from_thread to ready queue /
int need_insert_from_thread = 0;
/ 獲取任務(wù)列表中優(yōu)先級最高的我們假設(shè)有比當(dāng)前任務(wù)更高的優(yōu)先級執(zhí)行39行,此時目標(biāo)任務(wù)為高優(yōu)先級任務(wù) /
to_thread = _get_highest_priority_thread(&highest_ready_priority);
...
if (to_thread != rt_current_thread)
{
/ if the destination thread is not the same as current thread /
/ 開始進(jìn)行轉(zhuǎn)換,首先將源任務(wù)設(shè)置為當(dāng)前任務(wù),再將當(dāng)前任務(wù)設(shè)置為目標(biāo)任務(wù) /
rt_current_priority = (rt_uint8_t)highest_ready_priority;
from_thread = rt_current_thread;
rt_current_thread = to_thread;
...
#ifdef RT_USING_OVERFLOW_CHECK
_rt_scheduler_stack_check(to_thread);
#endif
if (rt_interrupt_nest == 0)
{
extern void rt_thread_handle_sig(rt_bool_t clean_state);
/ 這句進(jìn)行任務(wù)切換 /
rt_hw_context_switch((rt_ubase_t)&from_thread->sp,
(rt_ubase_t)&to_thread->sp);
/ enable interrupt /
rt_hw_interrupt_enable(level);
goto __exit;
}
else
{
RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("switch in interruptn"));
rt_hw_context_switch_interrupt((rt_ubase_t)&from_thread->sp,
(rt_ubase_t)&to_thread->sp);
}
}
else
{
rt_schedule_remove_thread(rt_current_thread);
rt_current_thread->stat = RT_THREAD_RUNNING | (rt_current_thread->stat & ~RT_THREAD_STAT_MASK);
}
}
}
/ enable interrupt /
rt_hw_interrupt_enable(level);
__exit:
return;
}
rt_hw_context_switch:
/ set rt_thread_switch_interrupt_flag to 1 /
LDR r2, =rt_thread_switch_interrupt_flag
LDR r3, [r2]
CMP r3, #1
/ 沒有設(shè)置interrupt_flag跳過執(zhí)行 /
BEQ _reswitch
/ 再次置1用于sv異常 /
MOV r3, #1
STR r3, [r2]
/ 將源任務(wù)sp賦值給rt_interrupt_from_thread,此時from是有值的 /
LDR r2, =rt_interrupt_from_thread /* set rt_interrupt_from_thread /
STR r0, [r2]
_reswitch:
/ 將目標(biāo)任務(wù)sp賦值給rt_interrupt_to_thread*/
LDR r2, =rt_interrupt_to_thread /* set rt_interrupt_to_thread /
STR r1, [r2]
/ 再次進(jìn)入sv異常處理 /
LDR r0, =NVIC_INT_CTRL / trigger the PendSV exception (causes context switch) */
LDR r1, =NVIC_PENDSVSET
STR r1, [r0]
BX LR
此時sv處理與上次相比多了一個源任務(wù)的r4-r11的壓棧處理其他相同。
-
寄存器
+關(guān)注
關(guān)注
31文章
5322瀏覽量
120021 -
裸機
+關(guān)注
關(guān)注
0文章
39瀏覽量
6347 -
LDR
+關(guān)注
關(guān)注
0文章
99瀏覽量
7565 -
gcc編譯器
+關(guān)注
關(guān)注
0文章
78瀏覽量
3365 -
RTThread
+關(guān)注
關(guān)注
8文章
132瀏覽量
40811
發(fā)布評論請先 登錄
相關(guān)推薦
評論