nu-lb-nuc140 RTX 流程 分析(三)
nu-lb-nuc140 RTX 流程 分析(三)
開始解析如下的部分:
__asm void SVC_Handler (void)
當前的暫存器:
讀取os_tsk
typedef struct OS_TSK { P_TCB run; /* Current running task */ P_TCB new; /* Scheduled task to run */ } *P_TSK; struct OS_TSK os_tsk;
os_tsk 0x20000058 Data 8 rt_task.o(.data)
0x20000060 - 8 = 0x20000058
R1 = 0x20000AE0 ----> run
R2 = 0x20000078 -----> new
R3 = 0x20000058
R0 = 0x00000001
執行指令:LDMIA R3!,{R1,R2} ; os_tsk.run, os_tsk.new
這一段的含義就是:
如果os_tsk.run 等於os_tsk.new ,那麼 就跳轉到SVC_Exit中去
如果os_tsk.run不等於os_tsk.new,那麼 繼續往下執行
SUBS R3,#8
0x20000060 - 8 = 0x20000058 R3 還是指向os_tsk的開頭
CMP R1,#0 ; Runtask deleted?
os_idle_TCB 0x20000ae0 Data 56 rt_task.o(.bss)
r1 = os_tsk.run 如果os_tsk.run = 0 那麼 就跳轉到 SVC_Restore
這裡 r1 = 0x20000ae0
繼續往下執行:
PUSH {R2,R3}
這一段程式碼的含義是:
os_tsk.run->ret_upd =1
MRS R3,PSP ; Read PSP
當前的 sp指標 指向 0x2000 0F10
之前 sp指標 指向的是 0x2000 0F18 因為存放了 R2和 R3的值
執行之後:
這個時候,R3 = 0x2000 02F0
然後繼續執行:
STR R3,[R1,#TCB_TSTACK-32] ; Update os_tsk.run->tsk_stack
R3 = 0x200002D0
R1 = 0x20000B00
os_tsk.run->tsk_stack = R3 = 0x200002D0
R3 = 0x2000 02D0
R4 = 0x50004080
R5 = 0x00002000
R6 = 0x00001BA4
R7 = 0x0000168D
R3 = 0x2000 02E0
執行到:
STMIA R3!,{R4-R7} ; Save old context (R8-R11)
執行之後:
BL rt_stk_check ; Check for Stack overflow
執行
執行:
STR R2,[R3] ; os_tsk.run = os_tsk.new
R2 = 0x2000 0078
R3 = 0x2000 0058
R3 = 0xFFFFFFFD
BX R3
之後 壓棧 儲存現場 和 出棧 恢復現場 同時進行。
p_BM->free = 0x2000 0210
p_BM->end = 0x2000 0A10
p_BM->blk_size = 0x0000 0100
next_block = 0x2000 0210 – task1
next_block = 0x2000 0310 – task2
next_block = 0x2000 0410 – task3
next_block = 0x2000 0510 – task4
next_block = 0x2000 0610 – task5
next_block = 0x2000 0710 – task6
next_block = 0x2000 0810 – task7
next_block = 0x2000 0910
next_block = 0x2000 0A10
init函式的地址為:0x0000 0DE1 ------F0C
之前是 0x2000 03F0 ,之後是 0x2000 0410
0x 0x2000 0410 - 0x2000 03F0 = 0x20 = 32
0xFFFFFFFD 表示中斷返回時從PSP堆疊恢復暫存器值,中斷返回後進入執行緒模式,使用PSP堆疊(這是常見的,OS處理完中斷後返回使用者程式)。
#define TCB_RETUPD 38 /* ‘ret_upd’ offset */
struct OS_TCB os_idle_TCB;
init函式的地址為:0x0000 0DE1 ------F0C
BX 0xFFFF FFFD 解析
記一次STM32中HardFault問題的除錯解決(INVPC, LR 0xFFFFFFF5)
https://blog.csdn.net/_xiao/article/details/78475195
EXC_RETURN是用於程式從異常中斷中返回的。
根據Cortex-M3的異常處理流程,當發生異常時,CPU先將核心暫存器壓入當前堆疊(如果當前是執行緒模式,則壓入PSP堆疊,如果當前是Handler模式,則壓入MSP堆疊),然後CPU會將LR設定為一個特殊的值,比如0xFFFFFFFD,然後切換到Handler模式,切換成MSP堆疊,最後進入異常處理例程(異常處理例程總是使用MSP堆疊)。在異常處理例程完成後需要從中斷返回時,就將LR的值載入到PC中(通常是BX LR指令,也可以是MOV PC,LR指令,或者POP {…, PC}等指令,只要能將LR賦給PC即可),由於LR的值是0xFFFFFFFD,CPU檢測到向PC中載入的是這個特殊值時,就知道是中斷返回,於是做中斷返回的動作(與壓入動作相反:從堆疊中彈出核心暫存器的值,恢復到執行緒模式或Handler模式等)。
這裡這個特殊的值(0xFFFFFFFD)就是EXC_RETURN,它的特點是高28位全部是1,只有低4位可變化,不同的低4位表示不同的中斷返回動作。
這個值是CPU在進入異常處理前自動設定的,只有3個值是合法的:
0xFFFFFFF1 表示中斷返回時從MSP堆疊恢復暫存器值,中斷返回後進入Handler模式,使用MSP堆疊,(相當於從中斷返回到另一箇中斷)。
0xFFFFFFF9 表示中斷返回時從MSP堆疊恢復暫存器值,中斷返回後進入執行緒模式,使用MSP堆疊(這種用於不使用PSP只使用MSP堆疊的情況)。
0xFFFFFFFD 表示中斷返回時從PSP堆疊恢復暫存器值,中斷返回後進入執行緒模式,使用PSP堆疊(這是常見的,OS處理完中斷後返回使用者程式)。
可以看到,中斷返回依賴於LR中的值,在此專案中,LR的值變成了0xFFFFFFF5,顯然也是一個EXC_RETURN值,但這個值與上面3個都不同,是非法的,所以引起了INVPC錯誤。
具體解析
請參考<ARM Cortex-M0權威指南(中文) 高清掃描版.pdf>
第10章 <支援作業系統的特性>
中斷的情況呢?
參考 第8章 異常和中斷