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章 异常和中断
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值