微內(nèi)核之多任務(wù)定時(shí)切換

/###################################################################

任務(wù)目標(biāo) :通過(guò)定時(shí)器產(chǎn)生任務(wù)切換,其中swi來(lái)實(shí)現(xiàn)多個(gè)任務(wù)之間切換

實(shí)驗(yàn)平臺(tái) : 本實(shí)驗(yàn)是基于S3C2440上實(shí)現(xiàn)

/####################################################################

工作原理 :

在運(yùn)行任務(wù)程序的時(shí)候通過(guò)定時(shí)器產(chǎn)生中斷,進(jìn)入任務(wù)優(yōu)先級(jí)調(diào)度课竣,選擇優(yōu)先級(jí)最高的任務(wù)去執(zhí)行;其中各個(gè)任務(wù)之間通過(guò)SWI軟中斷來(lái)實(shí)現(xiàn)相互切換膝晾。
難點(diǎn):在中斷模式和SVC模式下任務(wù)棧信息保存及恢復(fù),同時(shí)在SVC模式下把將要運(yùn)行的任務(wù)棧信息從該任務(wù)棧里恢復(fù)到寄存器中务冕,最后跳轉(zhuǎn)到用戶態(tài)執(zhí)行任務(wù)血当。
基本流程:

圖片.png

實(shí)現(xiàn)步驟:

請(qǐng)參考微內(nèi)核之任務(wù)切換。http://www.reibang.com/p/7792cdc4fd5f

增加與修改部分bug:

主要增加定時(shí)器中斷以及任務(wù)函數(shù)寄存器信息完整保存禀忆,使每次任務(wù)執(zhí)行時(shí)被中斷后能正確恢復(fù)該任務(wù)的信息臊旭,各個(gè)任務(wù)被中斷還能從中斷點(diǎn)繼續(xù)執(zhí)行。

1箩退、IRQ模式下任務(wù)棧信息保存

*IRQ模式中斷處理函數(shù)

/*#####################################################
 * IRQ中斷被監(jiān)測(cè)到离熏,則下面行為被執(zhí)行:
 * R14_irq = 將被執(zhí)行的下一條指令地址+4;
 * SPSR_irq = CPSR
 * CPSR[4:0] = 0b10010 ; Enter Supervisor mode 
 * CPSR[5] = 0         戴涝; Execute in ARM state 
 * CPSR[6] is unchanged 
 * CPSR[7] = 1         滋戳;Disable normal interrupts 
 * CPSR[8] = 1         ; Disable Imprecise Data Aborts (v6 only)
 * CPSR[9] = CP15_reg1_EEbit ; Endianness on exception entry 
 * 執(zhí)行irq處理函數(shù)后返回原程序啥刻,可以使用如下指令:
 * SUBS PC,R14,#4 ; SPSR_irq中的值自動(dòng)存儲(chǔ)到CPSR中
#######################################################*/    
HandleIRQ:

   SUB LR, LR, #4                             /*  計(jì)算返回地址,中斷模式LR保存被中斷指令的下一條指令 */
  
    STMDB   SP!,    { LR }                    /*  被中斷模式下的指令下一條指令 */
    STMDB   SP!,    { R0-R14}^                /* ^表示保存user模式下R0-R14奸鸯,只針對(duì)usr模式 */ 
                     
    LDR  R0,=IRQ_STACK          /* 保存irq模式下的SP棧,用于切換到SVC模式下*/
    STR SP, [R0]                        /*  恢復(fù)保存的寄存器值,用于調(diào)試  */

    LDR R0, =LR_VAR                     /*  保存IRQ模式下的LR郑什,用于調(diào)試  */
    STR R14, [R0]   

    LDR R0, =pCurTcb               /* 獲取當(dāng)前任務(wù)棧的起始地址 */
    LDR R2, [R0]        
    MRS R0, SPSR               
    STR R0,[R2],#4          /* SPSR存進(jìn)當(dāng)前任務(wù)棧里 */
    STR R0,[R2],#4          /* CPSR存進(jìn)當(dāng)前任務(wù)棧里 */ 

    MOV R1, SP
    MOV R3,#16              /* 把IRQ模式下保存寄存器數(shù)量R0-R14 */  
 
/*  把IRQ模式下保存寄存器數(shù)量R0-R15復(fù)制到當(dāng)前任務(wù)棧里  */

IRQ_STACK_COPY:             

    LDR R0,[R1],#4      
    STR R0,[R2],#4      
    SUBS R3,R3,#1       
    BNE IRQ_STACK_COPY                      
        
    LDR LR, =int_return             /* 設(shè)置調(diào)用ISR即EINT_Handle函數(shù)后的返回地址 
    LDR PC, =ISR_Handle             /* 調(diào)用中斷服務(wù)函數(shù)府喳,在interrupt.c中 */

int_return:
   LDMIA   SP!,    { R0-R14 }^     /* ^表示把中斷模式下SP棧里寄存器恢復(fù)到usr模式下對(duì)應(yīng)的寄存器中 */
   LDMIA   SP!,    { PC }^         /* 中斷返回, ^表示將spsr的值復(fù)制到cpsr */

2、SVC模式下任務(wù)棧信息保存

*SVC模式中斷處理函數(shù)

/******************************************************************************
 * SWI中斷進(jìn)入到SVC(超級(jí)用戶模式)蘑拯,當(dāng)SWI被執(zhí)行時(shí)钝满,下面行為被執(zhí)行:
 * R14_svc = SWI指令的下一條指令;
 * SPSR_svc = CPSR
 * CPSR[4:0] = 0b10011 ; Enter Supervisor mode 
 * CPSR[5] = 0         申窘; Execute in ARM state 
 * CPSR[6] is unchanged 
 * CPSR[7] = 1         弯蚜;Disable normal interrupts 
 * CPSR[8] is unchanged 
 * CPSR[9] = CP15_reg1_EEbit ; Endianness on exception entry 
 * 執(zhí)行SWI函數(shù)后返回原程序剃法,可以使用如下指令:
 * MOVS PC,R14 ; SPSR_svc中的值自動(dòng)存儲(chǔ)到CPSR中
 ******************************************************************************/

HandleSWI:

    STMDB   sp!,    {R14}           /* svc模式下R14(LR)保存user模式下的下一條指令地址PC; */
    LDR R0, =LR_VAR                 /* 保存SVC模式下的LR碎捺,用于調(diào)試 */
    STR R14, [R0]
    
    STMDB   sp!,    { r0-r14}^      /* ^表示user模式下的R0-R14到SVC模式的SP中,只針對(duì)user模式 */                 

    MRS     R0, SPSR                /* 不同模式之間切換贷洲,cpsr被保存在SPSR中 */    
    STMDB   sp!, {R0}               /* CPSR位置 */    
    STMDB   sp!, {R0}               /* SPSR位置 */    


    LDR R0, =SVC_STACK              /* 保存SVC模式下的SP棧收厨,用于恢復(fù)和調(diào)試 */
    STR sp, [R0]


    /******************************************************************************
    * 下面代碼用于監(jiān)測(cè)irq中斷觸發(fā)的SWI中斷,以便跳轉(zhuǎn)到taskSched函數(shù)執(zhí)行最高優(yōu)先級(jí)任務(wù)
    ******************************************************************************/

    sub  R0, R14, #4                 /* lr -4 為指令SWI XXX的地址,低24位是軟件中斷號(hào) */
    nop
    ldr  R1,[R0,#0]                  /* lr -4 為指令SWI XXX的地址,低24位是軟件中斷號(hào) */
    nop
    bic  R1,R1,#0XFF000000           /* 取得arm指令的低24位立即數(shù) */
    cmp  R1,#255                     /* 判斷24位立即數(shù)优构,如果是255诵叁,調(diào)用timer0_taskSched函數(shù) */
    beq  timer0_taskSched

    /******************************************************************************
    * 把寄存器值保存到當(dāng)前任務(wù)棧里,把SVC模式下保存的當(dāng)前任務(wù)棧信息保存到當(dāng)前任務(wù)棧
    * tasknTcb中钦椭。以備下次調(diào)用時(shí)在恢復(fù)該任務(wù)的棧信息,是否可以直接存在棧里呢?
    ******************************************************************************/

    LDR   R0, =pCurTcb            /* 獲取當(dāng)前任務(wù)棧的起始地址 */
    LDR   R1, [R0] 

    CMP   R1,#0                     /* 把pCurTcb值==0拧额;說(shuō)明是taskStart函數(shù);跳轉(zhuǎn)到taskBefore處執(zhí)行 */
    BEQ   taskBefore
    
    LDR   R0,=SVC_STACK             /* 恢復(fù)異常時(shí)保存SVC模式下的SP棧指針到R2 */
    LDR   R2,[R0] 
    
    MOV   R3,#18                    /* 把SVC模式下棧信息保存到當(dāng)前任務(wù)棧地址彪腔,保存SPSR/CPSR/R0-R14寄存器 */    
STACK_COPY: 
    LDR   R0,[R2],#4 
    STR   R0,[R1],#4 
    SUBS  R3,R3,#1 
    BNE   STACK_COPY 
    
taskBefore:

    sub lr, lr, #4                  /* lr -4 為指令SWI XXX的地址,低24位是軟件中斷號(hào) */
    ldr R3,[lr,#0]                  /* lr -4 為指令SWI XXX的地址,低24位是軟件中斷號(hào) */
    bic R3,R3,#0XFF000000           /* 取得arm指令的低24位立即數(shù) */
    
    cmp R3,#0                       /* 判斷24位立即數(shù)侥锦,如果是0,調(diào)用usrModeSpSetup函數(shù) */
    beq  usrModeSpSetup

    cmp R3,#1                       /* 判斷24位立即數(shù)德挣,如果是1恭垦,調(diào)用task1Tcb函數(shù) */
    ldr R0,=task1Tcb
    ldr R0,[R0]
    beq  taskTcbSwitch

    cmp R3,#2                       /* 判斷24位立即數(shù),如果是2格嗅,調(diào)用task2Tcb函數(shù) */
    ldr R0,=task2Tcb
    ldr R0,[R0]
    beq  taskTcbSwitch

    cmp R3,#3                       /* 判斷24位立即數(shù)番挺,如果是3,調(diào)用task3Tcb函數(shù) */
    ldr R0,=task3Tcb
    ldr R0,[R0]
    beq  taskTcbSwitch

    bne  END 
taskTcbSwitch:
    ldr pc, =taskSwitch

/******************************************************************************
* 建立用戶模式椔鸷疲空間
******************************************************************************/
usrModeSpSetup:
    mrs R0, CPSR                    /* Read the CPSR */
    bic R0, R0, #0xdF               /* Clear the mode irq fiq bits  */
    orr R0, R0, #0x10               /* Set the mode bits to FIQ mode */
    msr cpsr_c, R0                  /* 進(jìn)入用戶態(tài)建芙,并設(shè)置用戶態(tài)的SP,使能中斷 */
    ldr sp, =0x33e00000             /* 設(shè)置用戶棧指針起始值 */
    ldr R0, =USER_STACK                 /* 保存IRQ模式下的LR,用于調(diào)試 */
    str sp, [R0]

    ldr pc, =rootTask               /* rootTask開(kāi)始用戶模式 */

timer0_taskSched:
    ldr pc, =taskSched              /* 在SVC模式下進(jìn)入taskSched函數(shù)調(diào)度函數(shù) */
            
END:
    
    movne R0, #-1                   /* 沒(méi)有該軟中斷對(duì)應(yīng)函數(shù)懂扼,出錯(cuò)返回-1 */


3禁荸、任務(wù)切換函數(shù)taskswitch修改


/***********************************************************************************
函數(shù)功能: 實(shí)現(xiàn)任務(wù)切換,調(diào)用新得任務(wù)執(zhí)行阀湿,并把控制權(quán)交給新任務(wù).
入口參數(shù): pTcb: 即將運(yùn)行的任務(wù)的TCB指針.
返 回 值: none.
***********************************************************************************/


int taskSwitch(TCB * pTcb)
{

    /****************************************************************************** 
    * 即將運(yùn)行任務(wù)的寄存器組地址, 匯編語(yǔ)言通過(guò)這個(gè)變量恢復(fù)寄存器 
    ******************************************************************************/
    nextTaskSp = &pTcb->strStackReg;

    /* 即將運(yùn)行任務(wù)的TCB指針 */
    pCurTcb = pTcb;
    __asm__(

    /******************************************************************************
    * 獲取將要運(yùn)行任務(wù)的棧信息并運(yùn)行新任務(wù)
    ******************************************************************************/
    " LDR    R0, =nextTaskSp \n\t"
    " LDR    R1, [R0] \n\t"

    " LDMIA  R1!, {R0} \n\t"      /* Spsr位置 */
    " MSR    SPSR, R0  \n\t"
    " LDMIA  R1!, {R0} \n\t"      /* cpsr位置 */

    " MOV  R13, R1 \n\t"          /* 開(kāi)始恢復(fù)原用戶態(tài)任務(wù)棧信息 */

    " LDMIA  R13!, {R0-R12}^ \n\t"  /* ^表示把任務(wù)棧里R0-R14恢復(fù)到user模式下的R0-R14中赶熟,只針對(duì)用戶模式哦 */
    " ADD R13,R13,#0x4 \n\t"        /* 跳過(guò)恢復(fù)用戶態(tài)的R13  */
    
    " LDMIA  R13!, {R14}^ \n\t"     /* ^表示把任務(wù)棧里R0-R14恢復(fù)到user模式下的R0-R14中,只針對(duì)用戶模式哦 */

    " nop \n\t"
    " LDMIA  R13!, {R14} \n\t"      /* ^表示把任務(wù)棧里R15恢復(fù)到SVC模式下的R14中陷嘴,只針對(duì)用戶模式哦 */
    " nop \n\t"

    " LDR R13, =SVC_STACK \n\t"     /* 保存SVC模式下的SP棧映砖,用于恢復(fù)和調(diào)試 */  
    " LDR R13, [R13] \n\t"  
    " ADD R13,R13,#0x48 \n\t"       /* 恢復(fù)SVC模式下的SP棧;這里可以釋放掉SVC模式SP棧,因?yàn)橐接脩裟J?*/

    " MOVS   R15,  R14 \n\t"        /* 進(jìn)入用戶模式, SVC模式下的SPSR值恢復(fù)到USR模式下的CPSR中 */
 
);
    return 0;
}


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灾挨,一起剝皮案震驚了整個(gè)濱河市邑退,隨后出現(xiàn)的幾起案子竹宋,更是在濱河造成了極大的恐慌,老刑警劉巖地技,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蜈七,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡莫矗,警方通過(guò)查閱死者的電腦和手機(jī)飒硅,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)作谚,“玉大人三娩,你說(shuō)我怎么就攤上這事∶美粒” “怎么了雀监?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)彬伦。 經(jīng)常有香客問(wèn)我滔悉,道長(zhǎng),這世上最難降的妖魔是什么单绑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任回官,我火速辦了婚禮,結(jié)果婚禮上搂橙,老公的妹妹穿的比我還像新娘歉提。我一直安慰自己,他們只是感情好区转,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布苔巨。 她就那樣靜靜地躺著,像睡著了一般废离。 火紅的嫁衣襯著肌膚如雪侄泽。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天蜻韭,我揣著相機(jī)與錄音悼尾,去河邊找鬼。 笑死肖方,一個(gè)胖子當(dāng)著我的面吹牛闺魏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俯画,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼析桥,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起泡仗,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤埋虹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后沮焕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體吨岭,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拉宗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年峦树,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片旦事。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡魁巩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出姐浮,到底是詐尸還是另有隱情谷遂,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布卖鲤,位于F島的核電站肾扰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏蛋逾。R本人自食惡果不足惜集晚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望区匣。 院中可真熱鬧偷拔,春花似錦、人聲如沸亏钩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)姑丑。三九已至蛤签,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栅哀,已是汗流浹背震肮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留昌屉,地道東北人钙蒙。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像间驮,于是被迫代替她去往敵國(guó)和親躬厌。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容