关于freeRtos中操作pxCurrentTCB部分汇编指令的理解
__asm void vPortSVCHandler( void )
{
/* *INDENT-OFF* */
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
/* *INDENT-ON* */
}
一直对于这些指令莫名的脑袋浆糊,后来用stm32中freertos的demo代码中keil5中做简单的调试,对此感觉有了一点理解,做一下记录,代码还是要动手操练。
ldr r3, = pxCurrentTCB /* Restore the context. */
pxCurrentTCB 是个全局的结构体指针变量,这个指令的意思是取 指针变量的地址赋值给 r3
在c语言中,定义一个指针变量,直接对这个指针变量赋值操作,实际编译成汇编文件怎么处理的也不懂,但是在汇编语言中,ldr指令获取的是这个变量的链接地址。
ldr r1, [ r3 ] /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */
获取pxCurrentTCB的值,比如定义一个int *p, a=100,这条指令意思相当于p=&a
ldr r0, [ r1 ] /* The first item in pxCurrentTCB is the task top of stack. */
pxCurrentTCB 是一个结构体指针,r0的值就是获取pxCurrentTCB指向的结构体的第一个元素,即栈顶指针pxTopOfStack,相当于获取*p的值,对于一个结构体变量就是第一项的值。
struct Test{
int a;
int b;
int c;
}
struct Test test;
struct Test *ptest=NULL;
void fun(void)
{
ptest = &test;
test.a = 1;
test b = 2;
test c = 3;
}
ldr r3, = pxCurrentTCB /* */
ldr r1, [ r3 ] /* 上面一步取的是pxCurrentTCB指针变量的地址,这两步相于 ptest = &test; */
ldr r0, [ r1 ] /* 结构体变量中第一个元素的值,即test.a 的值 */
xPortPendSVHandler中的任务切换的实现
__asm void xPortPendSVHandler( void )
{
extern uxCriticalNesting;
extern pxCurrentTCB;
extern vTaskSwitchContext;
PRESERVE8
mrs r0, psp
isb
ldr r3, =pxCurrentTCB
ldr r2, [ r3 ]
stmdb r0 !, { r4 - r11 }
str r0, [ r2 ]
stmdb sp !, { r3, r14 }
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0
dsb
isb
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp !, { r3, r14 }
ldr r1, [ r3 ]
ldr r0, [ r1 ]
ldmia r0 !, { r4 - r11 }
msr psp, r0
isb
bx r14
nop
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)