nu-lb-nuc140 RTX 流程 分析(一)

分析的程序源码:
https://download.csdn.net/download/wowocpp/10831727
运行环境 :nu-lb-nuc140 keil 5.25

1 系统编译

在这里插入图片描述
程序编译完毕之后,查看:
Nu_LB_NUC140_RTX_SRC\project\KEIL\lst\GPIO_OutputInput.map
在这里插入图片描述

2 系统上电 复位

在这里插入图片描述

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

单步执行之后,
这个时候 SP = MSP = 0x20000F18
注意 这个时候 LR 的值0x0000 0EE5 ,是 上面的反汇编语句:BL.W os_set_env 设置的
在这里插入图片描述
再次 单步执行:

3 MSR PSP,R0

在这里插入图片描述
继续单步执行:

4 os_flags的由来

Nu_LB_NUC140_RTX_SRC\project\KEIL\lst\GPIO_OutputInput.map
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
开始执行 :LDRB R0,[R0]
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
取得的 R0的值为:0x0000 0000

下一步执行:LSLS R0,#31

5 Z标志位 和 bne 指令

在这里插入图片描述
cmp:算数处理指令,用于把一个寄存器的内容和另一个寄存器的内容或立即数进行减法比较,
不存储结果, 但会更改标志位
  bne: 数据跳转指令,
  not equal 不相等跳转,相减不等于0 ,Z = 0 ,跳转到BNE后标签处
 
  beq: 数据跳转指令,标志寄存器中Z标志位等于1时, 跳转到BEQ后标签处

因为上一步执行结果为 0,Z =1

BNE PrivilegedE ; 不跳转

MOVS R0,#0x03 ; Unprivileged Thread mode, use PSP

在这里插入图片描述

6 MSR CONTROL,R0

在这里插入图片描述

注意 这个时候 LR 的值0x0000 0EE5 ,是 反汇编语句:BL.W os_set_env 设置的

7 执行BX LR

在这里插入图片描述

程序存储器 地址: 0x0000 0EE0中的 BL.W 跳转之后,会保存子函数返回的LR地址:0x0000 0EE5
执行BX LR 之后,跳转到0x0000 0EE4开始执行

8 源码 函数 存放地址

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
#define __SVC_0 __svc_indirect(0) // 位于 RTL.h中

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

在这里插入图片描述

在这里插入图片描述

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

#define os_sys_init(init) os_set_env();
_os_sys_init((U32)rt_sys_init,init,0,NULL)

init函数的地址为:0x0000 0DE1 ------F0C
rt_sys_init 函数的地址为: 0x0000 168D — F10

r12 中保存的是rt_sys_init 函数的地址 -----
r0 中保存的是init 函数的地址
r1 中保存的是 prio_stksz的值
在这里插入图片描述
r12 中保存的是p 函数的地址 -----
r0 中保存的是task 函数的地址
r1 中保存的是 prio_stksz的值
r2 中应该保存的是 stk的地址

9 执行SVC 0x00

在这里插入图片描述

查看 此时的 堆栈 :
在这里插入图片描述

执行 SVC 0x00
在这里插入图片描述

CPU 的执行模式 变为 handler
Stack 指针 使用的是MSP
PSP 指针 变为 0x2000 0EF8
LR指针 变为 0xFFFF FFFD

这个时候的内存:
在这里插入图片描述

10 取得SVC号码 原理:

在这里插入图片描述
其中的
LDR R1,[R0,#24] ; Read Saved PC from Stack
是 从栈保存的lr_SVC中获取 函数返回的时候的执行地址。

该地址是下面分析中的 0x2000 0F10 对应的数据:0x0000 0EF0
0x0000 0EF0 是执行 SVC 0 任务,返回之后去执行的下一条指令的地址。
SVC 0 指令和其下一条指令,之间 是间隔2个字节,所以减去2。
在这里插入图片描述
init函数的地址为:0x0000 0DE1 ------F0C
rt_sys_init 函数的地址为: 0x0000 168D — F10

r12 中保存的是rt_sys_init 函数的地址 -----
r0 中保存的是init 函数的地址
r1 中保存的是 prio_stksz的值
r2 中应该是 参数 stack = NULL的值
r3 0x0000 0010 这个值是干嘛的?系统启动之后就是这个值
看下面的定义 只用到了 prio_stksz和 stk两个参数
所以r3 空闲了
在这里插入图片描述

加2的原因

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203ic/Bgbcjggh.html
在这里插入图片描述

__svc_indirect 原型

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203ic/Bgbcjggh.html
在这里插入图片描述

10 取得SVC 号码

执行:
MRS R0,PSP ; Read PSP
LDR R1,[R0,#24] ; Read Saved PC from Stack
在这里插入图片描述

SUBS R1,R1,#2 ; Point to SVC Instruction
执行的原因是:
在这里插入图片描述
这个2 应该是和流水线有关,因为是16位指令,所以提前多取了2个字节

继续执行:
LDRB R1,[R1] ; Load SVC Number
看上图中的,
0x0000 0EEE DF00 SVC 0x00
其中0x0000 0EEE 是 存放在程序存储器中的地址
0xDF00 是存放在该地址中的内容。
0xDF00 的含义是 汇编代码 SVC 0x00 编译之后的机器码。
在这里插入图片描述

LDRB R1,[R1] 就是从程序存储器中取出低字节的数据0x00
在这里插入图片描述

11 CMP 指令 与 Z标志位

继续执行:
CMP R1,#0

    CMP 指令是 两个参数相减,结果为0 ,Z=1

在这里插入图片描述

    BNE     SVC_User                ; User SVC Number > 0    

由于 Z = 1, 所以 没有跳转到 SVC_User中去
继续执行:

    CMP     R1,#0
    BNE     SVC_User                ; User SVC Number > 0

    MOV     LR,R4

在这里插入图片描述

12 LDMIA 指令

继续执行:
LDMIA R0,{R0-R3,R4} ; Read R0-R3,R12 from stack
R0 = 0x2000 0EF8

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

13 调用 rt_sys_init 函数

执行到:
BLX R12 ; Call SVC Function
之前:
在这里插入图片描述

之后:
在这里插入图片描述

调用完 还会回来。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值