0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從裸機(jī)到rtt任務(wù)切換有感

冬至子 ? 來源:陳再松 ? 作者:陳再松 ? 2023-10-13 11:31 ? 次閱讀

閑來無事,作為第一次使用實時操作系統(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的壓棧處理其他相同。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5301

    瀏覽量

    119866
  • 裸機(jī)
    +關(guān)注

    關(guān)注

    0

    文章

    39

    瀏覽量

    6331
  • LDR
    LDR
    +關(guān)注

    關(guān)注

    0

    文章

    98

    瀏覽量

    7552
  • gcc編譯器
    +關(guān)注

    關(guān)注

    0

    文章

    78

    瀏覽量

    3348
  • RTThread
    +關(guān)注

    關(guān)注

    7

    文章

    132

    瀏覽量

    40781
收藏 人收藏

    評論

    相關(guān)推薦

    ATmega128兩個任務(wù)切換不成功的問題

    寫了兩個任務(wù), 手動切換兩個任務(wù)的執(zhí)行。 但是切換有問題。高手幫忙看看。
    發(fā)表于 02-08 16:21

    請問uc/os任務(wù)切換問題該怎么解決?

    切換的時候,任務(wù)1的寄存器以及PC壓棧自己的任務(wù)堆棧,然后把任務(wù)2的任務(wù)堆棧內(nèi)容填寫到系統(tǒng)堆棧
    發(fā)表于 06-12 04:35

    請問ucos任務(wù)切換時先尋找優(yōu)先級高的任務(wù)任務(wù)切換有影響嗎?

    任務(wù)切換函數(shù)的本意是將正在運(yùn)行的任務(wù)的cpu寄存器內(nèi)容壓入堆棧,將優(yōu)先級高的任務(wù)堆棧的內(nèi)容存入cpu,但切換時要先尋找優(yōu)先級高的
    發(fā)表于 09-05 02:20

    請問UCOSIII中的任務(wù)調(diào)度和任務(wù)切換有什么區(qū)別?

    的現(xiàn)場當(dāng)前任務(wù)的堆棧中,主要是CPU寄存器值,然后恢復(fù)新的現(xiàn)場并且執(zhí)行新的任務(wù),這個過程就是任務(wù)切換。問題:1.他們的區(qū)別是
    發(fā)表于 05-25 07:27

    RTOS中的多任務(wù)切換的相關(guān)資料分享

    函數(shù)四.總流程五.結(jié)果六.后記(含代碼鏈接)一. 簡介??RTOS中的多任務(wù)切換是操作系統(tǒng)與裸機(jī)編程的一個非常大的區(qū)別,一般邏輯變成運(yùn)行在一個循環(huán)內(nèi),裸機(jī)編程很難實現(xiàn)兩個事件的并行(這
    發(fā)表于 12-06 07:08

    任務(wù)裸機(jī)系統(tǒng)與多任務(wù)系統(tǒng)的區(qū)別在哪

    總體概述與任務(wù)裸機(jī)系統(tǒng)與多任務(wù)系統(tǒng)的區(qū)別任務(wù)的定義與切換裸機(jī)系統(tǒng)與多
    發(fā)表于 02-18 07:03

    uCOS-III任務(wù)切換的實現(xiàn)

    uCOS-III任務(wù)切換的實現(xiàn)學(xué)習(xí)目的:熟悉uCOS-III任務(wù)切換實現(xiàn)原理在使用單片機(jī)做一些復(fù)雜的產(chǎn)品開發(fā)時,單純的裸機(jī)系統(tǒng)通常不能很
    發(fā)表于 02-18 06:16

    介紹一種嵌入式裸機(jī)任務(wù)切換方法

    一種嵌入式裸機(jī)任務(wù)切換方法有時候為了實現(xiàn)一些簡單的、對實時性要求不高的任務(wù),采用操作系統(tǒng)不僅增加了程序的復(fù)雜性,對低性能單片機(jī)的資源占用也是值得考慮的問題。這時候操作系統(tǒng)可能不是必要
    發(fā)表于 02-28 13:27

    RTT切換極限是1ms嗎?

    有一個任務(wù)每秒需要運(yùn)行兩千次,應(yīng)該怎么寫程序。RTT切換極限是1ms嗎?
    發(fā)表于 01-16 17:24

    RTT任務(wù)切換機(jī)制是如何實現(xiàn)的?

    RTT中如何實現(xiàn)任務(wù)切換機(jī)制
    發(fā)表于 11-02 06:28

    什么是CDMA軟切換?它與硬切換有什么分別?

    什么是CDMA軟切換?它與硬切換有什么分別? 移動通訊是建立在移動之中的。有了頻率的復(fù)用,必然帶來移動中的頻率切換問題,一個網(wǎng)絡(luò)質(zhì)量的
    發(fā)表于 06-01 20:27 ?928次閱讀

    什么是CDMA軟切換?它與硬切換有什么分別

    什么是CDMA軟切換?它與硬切換有什么分別 移動通訊是建立在移動之中的。有了頻率的復(fù)用,必然帶來移動中的頻率切換問題,一個網(wǎng)絡(luò)質(zhì)
    發(fā)表于 06-15 09:42 ?1278次閱讀

    淺談RTOS中的多任務(wù)切換(基于UC/OS iii)

    函數(shù)四.總流程五.結(jié)果六.后記(含代碼鏈接)一. 簡介??RTOS中的多任務(wù)切換是操作系統(tǒng)與裸機(jī)編程的一個非常大的區(qū)別,一般邏輯變成運(yùn)行在一個循環(huán)內(nèi),裸機(jī)編程很難實現(xiàn)兩個事件的并行(這
    發(fā)表于 11-23 18:06 ?25次下載
    淺談RTOS中的多<b class='flag-5'>任務(wù)</b><b class='flag-5'>切換</b>(基于UC/OS iii)

    3.小白初學(xué)UCosIII STM32F429 任務(wù)的定義與任務(wù)切換的實現(xiàn)1

    ,圖任務(wù)輪流切換波形圖 的波形圖的效果,并不是真正的多任務(wù)系統(tǒng)中任務(wù)切換的效果圖,這個效果其實可以完全由
    發(fā)表于 12-23 20:00 ?1次下載
    3.小白初學(xué)UCosIII STM32F429 <b class='flag-5'>任務(wù)</b>的定義與<b class='flag-5'>任務(wù)</b><b class='flag-5'>切換</b>的實現(xiàn)1

    ucosiii 任務(wù)切換

    uCOS-III任務(wù)切換的實現(xiàn)學(xué)習(xí)目的:熟悉uCOS-III任務(wù)切換實現(xiàn)原理在使用單片機(jī)做一些復(fù)雜的產(chǎn)品開發(fā)時,單純的裸機(jī)系統(tǒng)通常不能很
    發(fā)表于 12-23 20:02 ?1次下載
    ucosiii <b class='flag-5'>任務(wù)</b><b class='flag-5'>切換</b>