新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 移植ucosII到STM32F103ZE(五)

移植ucosII到STM32F103ZE(五)

作者: 時(shí)間:2016-11-25 來源:網(wǎng)絡(luò) 收藏
os_cpu_a.asm
這個(gè)文件包含著必須用匯編寫的代碼。
EXTERN OSRunning ; External references
EXTERN OSPrioCur
EXTERN OSPrioHighRdy
EXTERN OSTCBCur
EXTERN OSTCBHighRdy
EXTERN OSIntNesting
EXTERN OSIntExit
EXTERN OSTaskSwHook
申明這些變量是在其他文件定義的,本文件只做引用(有幾個(gè)好像并未引用,不過沒有關(guān)系)。
EXPORT OS_CPU_SR_Save ; Functions declared in this file
EXPORT OS_CPU_SR_Restore
EXPORT OSStartHighRdy
EXPORT OSCtxSw
EXPORT OSIntCtxSw
EXPORT OS_CPU_PendSVHandler ; #0
#0這里 OS_CPU_PendSVHandler 要替換為PendSV_Handler;如下圖:

替換后的 PPendSV中斷
聲明這些函數(shù)是在本文件中定義的。EXPORT這個(gè)關(guān)鍵字是跟編譯器有關(guān)的,能被keil識別,但不能被IAR 識別。
NVIC_INT_CTTRL EQU 0xE000ED04 ;中斷控制及狀態(tài)寄存器 ICSR 的地址
NVIC_SYSPRI14 EQU 0xE000ED22 ;PendSV優(yōu)先級寄存器的地址
NVIC_PENDSV_PRI EQU 00xFF ; PendSV 中斷的優(yōu)先級為 255(最低)
NVIC_PENDSVSET EQU 0x10000000 ; 位 28 為 1
;定義幾個(gè)常量,類似 C 語言中的#define預(yù)處理指令。
S_CPU_SR_Save
MRS R0, PRIMASK ;讀取 PRIMASK 到R0 中,R0 為返回值
CPSID I ;PRIMASK=1,關(guān)中斷(NMI 和硬 fault 可以響應(yīng))
BX LR ;返回

OS_CPU_SR_Restore
MSR PRIMASK, R0 ;讀取 R0 到PRIMASK 中,R0 為參數(shù)
BX LR ;返回

OSStartHighRdy()由 OSStart()調(diào)用,用來啟動最高優(yōu)先級任務(wù),當(dāng)然任務(wù)必須在OSStart()前已被創(chuàng)建。
OSStartHighRdy
;設(shè)置 PendSV 中斷的優(yōu)先級 #1
LDR R0, =NVIC_SYSPRI14 ;R0 = NVIC_SYSPRI14
LDR R1, =NVIC_PENDSV_PRI ;R1 = NVIC_PENDSV_PRI
STRB R1, [R0] ; *(uint8_t *)NVIC_SYSPRI14 = NVIC_PENDSV_PRI
;設(shè)置 PSP 為0 #2
MOVS R0, #0 ;R0 = 0
MSR PSP, R0 ;PSP = R0
;設(shè)置 OSRunning 為TRUE
LDR R0, =OSRunning ;R0 = OSRunning
MOVS R1, #1 ;R1 = 1
STRB R1, [R0] ;OSRunning = 1
;觸發(fā) PendSV 中斷 #3
LDR R0, =NVIC_INT_CTRL ;R0 = NVIC_INT_CTRL
LDR R1, =NVIC_PENDSVSET ;R1 = NVIC_PENDSVSET
STR R1, [R0] ; *(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET
CPSIE I ;開中斷
OSStartHang
;死循環(huán),應(yīng)該不會到這里
B OSStartHang
#1.PendSV 中斷的優(yōu)先級應(yīng)該為最低優(yōu)先級,原因在<>的 7.6 節(jié)已有說明。
#2.PSP 設(shè)置為 0,是告訴具體的任務(wù)切換程序(OS_CPU_PendSVHandler()),這是第一次任務(wù)切換。做過切換后 PSP 就不會為0了,后面會看到。
#3.往中斷控制及狀態(tài)寄存器 ICSR(0xE000ED04)第 28 位寫 1 即可產(chǎn)生 PendSV 中斷。這個(gè)<>8.4.5 其它異常的配置寄存器有說明。
當(dāng)一個(gè)任務(wù)放棄 cpu 的使用權(quán),就會調(diào)用OS_TASK_SW()宏,而 OS_TASK_SW()就是 OSCtxSw()。OSCtxSw()應(yīng)該做任務(wù)切換。但是在 CM3 中,所有任務(wù)切換都被放到PendSV 的中斷處理函數(shù)中去做了,因此 OSCtxSw() 只需簡單的觸發(fā) PendSV中斷即可。OS_TASK_SW()是由OS_Sched()調(diào)用。
void OS_Sched (void)
{
# if OS_CRITICAL_METHOD==3
OS_CPU_SR cpu_sr = 0;
#endif
OS_ENTER_CRITICAL();

if (OSIntNesting ==0) {
if (OSLockNesting == 0) {
OS_SchedNew();
if (OSPrioHighRdy != OSPrioCur)
{
OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy];
#if OS_TASK_PROFILE_EN > 0
OSTCBHighRdy->OSTCBCtxSwCtr++;
#endif
OSCtxSwCtr++;
OS_TASK_SW();
}
}
}

OS_EXIT_CRITICAL();
}

OSCtxSw ;觸發(fā)PendSV 中斷
LDR R0, =NVIC_INT_CTRL ;R0 = NVIC_INT_CTRL
LDR R1, =NVIC_PENDSVSET ;R1 = NVIC_PENDSVSET
STR R1, [R0] ;*(uint32_t *)NVIC_INT_CTRL = NVIC_PENDSVSET
BX LR ;返回
當(dāng)一個(gè)中斷處理函數(shù)退出時(shí),OSIntExit()會被調(diào)用來決定是否有優(yōu)先級更高的任務(wù)需要執(zhí)行。如果有
OSIntExit()對調(diào)用 OSIntCtxSw()做任務(wù)切換。
OSIntCtxSw ;觸發(fā) PendSV 中斷
LDR R0, =NVIC_INT_CTRL
LDR R1, =NVIC_PENDSVSET
STR R1, [R0]
BX LR
看到這里有人可能奇怪怎么 OSCtxSw()和OSIntCtxSw()完全一樣,事實(shí)上,這兩個(gè)函數(shù)的意義是不一樣的,OSCtxSw()做的是任務(wù)之間的切換,如任務(wù) A 因?yàn)榈却硞€(gè)資源或是做延時(shí)切換到任務(wù) B,而
OSIntCtxSw()則是中斷退出時(shí),由中斷狀態(tài)切換到另一個(gè)任務(wù)。由中斷切換到任務(wù)時(shí),CPU 寄存器入棧的工作已經(jīng)做完了,所以無需做第二次了(參考邵老師書的 3.10 節(jié))。這里只不過由于 CM3 的特殊機(jī)制導(dǎo)致了在這兩個(gè)函數(shù)中只要做觸發(fā) PendSV中斷即可,具體切換由 PendSV 中斷來處理。
前面已經(jīng)說過真正的任務(wù)切換是在 PendSV 中斷處理函數(shù)里做的,由于 CM3 在中斷時(shí)會有一半的寄存器自動保存到任務(wù)堆棧里,所以在 PendSV 中斷處理函數(shù)中只需保存 R4-R11并調(diào)節(jié)堆棧指針即可。

上一頁 1 2 下一頁

關(guān)鍵詞: 移植ucosIISTM32F103Z

評論


技術(shù)專區(qū)

關(guān)閉