1. 程式人生 > >nu-lb-nuc140 RTX 流程 分析(三)

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章 異常和中斷
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

在這裡插入圖片描述
在這裡插入圖片描述