OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4316|回复: 4

vPortSVCHandler 函数的 前3行取地址 不理解

[复制链接]

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
发表于 2020-4-22 21:30:39 | 显示全部楼层 |阅读模式
5金钱
系统启动会先运行一次 vPortSVCHandler
__asm void vPortSVCHandler( void )
{
        PRESERVE8

        ldr        r3, =pxCurrentTCB        /* Restore the context. */
        ldr r1, [r3]                        /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
        ldr r0, [r1]                        /* The first item in pxCurrentTCB is the task top of stack. */
        ldmia r0!, {r4-r11}                /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
        msr psp, r0                                /* Restore the task stack pointer. */
        isb
        mov r0, #0
        msr        basepri, r0
        orr r14, #0xd
        bx r14
}


前3行取地址不太懂。
pxCurrentTCB        一个指针,指的是 当前任务, 也就是当前任务TCB的地址。
r3, =pxCurrentTCB  , 即 r3是当前任务TCB的地址。
ldr r1, [r3],即r1 = [r3] = 当前任务TCB的第一个4字节元素,也就是 volatile StackType_t        *pxTopOfStack;是一个指针,指向当前任务的栈顶,是个地址。
ldr r0, [r1]        ,即r0 = [r1] = 当前栈顶元素。

这样感觉不对了呀,
r0应该是栈地址才对啊。
这样才能执行 ldmia r0!, {r4-r11}才对。

怎么感觉多取了一次地址。





最佳答案

查看完整内容[请看2#楼]

你的问题是因为:第一行,你理解错了
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
743
金钱
743
注册时间
2018-9-1
在线时间
177 小时
发表于 2020-4-22 21:30:40 | 显示全部楼层
你的问题是因为:第一行,你理解错了
uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-23 19:47:26 | 显示全部楼层
ultraelec 发表于 2020-4-23 11:53
你的问题是因为:第一行,你理解错了


我之前在网上查了一下ldr的用法,是这么说的: 无标题.png

LDR r, label 和 LDR r, =label的区别:
LDR r, =label 会把label表示的值加载到寄存器中,而LDR r, label会把label当做地址,把label指向的地址中的值加载到寄存器中。
譬如 label的值是 0x8000, LDR r, =label会将 0x8000加载到寄存器中,而LDR r, label则会将内存0x8000处的值加载到寄存器中。

https://www.jianshu.com/p/66d801c85ee9



那我们第一行 取 ldr        r3, =pxCurrentTCB

是不是意思就是“把pxCurrentTCB表示的值加载到r3”,而pxCurrentTCB是指向当前任务的,pxCurrentTCB的值就是当前TCB的地址,
所以我觉得这句话就是说 “把TCB的地址赋值给r3”。




我感觉是有些问题,但是又不知道哪里错了。
无标题2.png
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

4

主题

82

帖子

0

精华

高级会员

Rank: 4

积分
743
金钱
743
注册时间
2018-9-1
在线时间
177 小时
发表于 2020-4-23 22:49:12 | 显示全部楼层
tao475824827 发表于 2020-4-23 19:47
我之前在网上查了一下ldr的用法,是这么说的:

LDR r, label 和 LDR r, =label的区别:

首先你要清楚一个事:
C代码中的pxCurrentTCB是变量。
而汇编中的pxCurrentTCB是一个label,可认为就是一个地址,它对应C中的pxCurrentTCB


ldr r3,=pxCurrentTCB # 读取<pxCurrentTCB变量的地址>到 r3
ldr r1,[r3]                    # 读取<pxCurrentTCB变量>到r1,即获取当前任务TCB地址
ldr r0,[r1]                    # 从<当前任务TCB>读取一个WORD大小到 r0,TCB首元素即任务栈顶

你查的资料说的也就是这么回事,你理解错了。

ldr rn, =label 是ldr伪指令,可以理解将label作为立即数加载到rn
ldr rn, label 不是伪指令,它通过间接寻址,把label作为地址,从这个地址中加载值到rn

你可能会想,按这个说法,SVC头两条不是脱裤子放屁吗
既然汇编中的pxCurrentTCB是C变量地址,为啥不直接
ldr r1,pxCurrentTCB
正好是间接寻址,拿到TCB指针。
这是因为ldr rn, label 这个指令是基于PC寻址,是有范围要求的,
对于C中的变量,由于是在链接时才能确定变量地址的,所以有可能会超了范围。
所以使用ldr rn,[rm]  。这个是基于rm的,不超过rm大小都可以。
uevip#126.com
回复

使用道具 举报

50

主题

385

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1126
金钱
1126
注册时间
2014-8-24
在线时间
146 小时
 楼主| 发表于 2020-4-23 23:16:01 | 显示全部楼层
看了一下,网上有不同的说法。
如果是 LDR rn = 一个变量,是把 变量的地址给rn,这样就说的通了。
找一份喜欢的工作,这样每天工作的8个小时是快乐的。 找一个喜欢的人,这样每天工作之外的16个小时也是快乐的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-22 22:35

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表