Operating system 臂皮质m4 xPSR在分支时发生变化

Operating system 臂皮质m4 xPSR在分支时发生变化,operating-system,arm,embedded,Operating System,Arm,Embedded,我正在写一个操作系统。。。我正在研究上下文转换 .. 我可以将内核切换到用户程序并返回。但SVC调用似乎不起作用 syscall: svc SYSCALL_SVC_NUMBER bx lr 当调用svc it trigger interrupt时,我可以看到控制流返回内核。当它返回到用户程序时,就会出现硬故障 在这附近 -->bx-lr 我已经检查了所有寄存器是否正确加载,除了xPSR缺少thumb位。这就是为什么会出现严重的错误 但是我不知道为什么xPSR是零 .global

我正在写一个操作系统。。。我正在研究上下文转换 .. 我可以将内核切换到用户程序并返回。但SVC调用似乎不起作用

syscall:
    svc SYSCALL_SVC_NUMBER
    bx lr
当调用svc it trigger interrupt时,我可以看到控制流返回内核。当它返回到用户程序时,就会出现硬故障

在这附近 -->bx-lr

我已经检查了所有寄存器是否正确加载,除了xPSR缺少thumb位。这就是为什么会出现严重的错误

但是我不知道为什么xPSR是零

.global activate
activate:
/* save kernel state in ip register */
mrs ip, psr
push {r4, r5, r6, r7, r8, r9, r10, r11, ip, lr}

/* switch to process stack */
msr psp, r0

mov ip, #2
msr control, ip

ldr ip, [sp, #0x38]
msr psr_nzcvq, ip

/* load user state */
pop {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, lr}
add sp, #0x8
ldr ip, [sp, #-0x8]
/* this line can branch correctly */
bx ip

啊,是的,你是对的,但是你不需要同时修改任何东西

例如,使用此代码

mov r1,#0x22
mov r2,#0x33
mov r3,#0x44
mov r0,#0x55
mov r12,r0
mov r0,#0x66
mov r14,r0
mov r0,#0x11
svc #1
堆栈在命中svc处理程序时如下所示

相当肯定这是有文件记录的

20000FD4 FFFFFFF9     return address                                                                        
20000FD8 00000011     r0                                                                        
20000FDC 00000022     r1                                                                        
20000FE0 00000033     r2                                                                        
20000FE4 00000044     r3                                                                        
20000FE8 00000055     r12                                                                        
20000FEC 00000066     r14                                                                        
20000FF0 0100009E     r15                                                                        
20000FF4 21000000     xPSR
在cortex-m上出现异常时,它们在硬件中的行为方式可以根据调用约定直接调用C函数。了解程序计数器本身的lsbit为0,lsbit为1的东西用于BX、BLX和POP,这些指令使用它来确定ARM或THUMB模式,该位被剥离,然后用作PC

SVC的返回值可以/应该与上面的类似。如果要使用svc或任何其他中断来进行上下文切换,则需要构建匹配的堆栈

当然,这里有一点鸡和蛋的问题,对于每一个线程,您都会像上面那样构建一个堆栈图像

20000FD4 FFFFFFF9                                                                             
20000FD8 00000011                                                                             
20000FDC 00000022                                                                             
20000FE0 00000033                                                                             
20000FE4 00000044                                                                             
20000FE8 00000055                                                                             
20000FEC 00000066                                                                             
20000FF0 01001234                                                                         
20000FF4 21000000 
但是你可以把不在乎放在寄存器中,除了你设置为线程入口点的pc。没有设置lsbit。此外,您还需要一些结构来保存其他寄存器的状态

然后,当您切换上下文时,您将上述以外的寄存器保存在某个结构中,该结构包括sp,然后从下一个线程(包括其sp)中填充这些寄存器。然后,您将返回bx lr

还有更多的内容,请参阅atomthreads或chibios或其他开源、功能性操作系统


您可以更正被中断的地址,或者在本例中,svc(程序计数器)之后的地址位于堆栈上,没有设置lsbit,但同时也是正确的。用于从异常(svc或定时器中断或其他)返回的实际lr是特殊的0xFFFFxxxx,它设置了lsbit。

啊,是的,您是对的,但您不需要同时修改任何内容

例如,使用此代码

mov r1,#0x22
mov r2,#0x33
mov r3,#0x44
mov r0,#0x55
mov r12,r0
mov r0,#0x66
mov r14,r0
mov r0,#0x11
svc #1
堆栈在命中svc处理程序时如下所示

相当肯定这是有文件记录的

20000FD4 FFFFFFF9     return address                                                                        
20000FD8 00000011     r0                                                                        
20000FDC 00000022     r1                                                                        
20000FE0 00000033     r2                                                                        
20000FE4 00000044     r3                                                                        
20000FE8 00000055     r12                                                                        
20000FEC 00000066     r14                                                                        
20000FF0 0100009E     r15                                                                        
20000FF4 21000000     xPSR
在cortex-m上出现异常时,它们在硬件中的行为方式可以根据调用约定直接调用C函数。了解程序计数器本身的lsbit为0,lsbit为1的东西用于BX、BLX和POP,这些指令使用它来确定ARM或THUMB模式,该位被剥离,然后用作PC

SVC的返回值可以/应该与上面的类似。如果要使用svc或任何其他中断来进行上下文切换,则需要构建匹配的堆栈

当然,这里有一点鸡和蛋的问题,对于每一个线程,您都会像上面那样构建一个堆栈图像

20000FD4 FFFFFFF9                                                                             
20000FD8 00000011                                                                             
20000FDC 00000022                                                                             
20000FE0 00000033                                                                             
20000FE4 00000044                                                                             
20000FE8 00000055                                                                             
20000FEC 00000066                                                                             
20000FF0 01001234                                                                         
20000FF4 21000000 
但是你可以把不在乎放在寄存器中,除了你设置为线程入口点的pc。没有设置lsbit。此外,您还需要一些结构来保存其他寄存器的状态

然后,当您切换上下文时,您将上述以外的寄存器保存在某个结构中,该结构包括sp,然后从下一个线程(包括其sp)中填充这些寄存器。然后,您将返回bx lr

还有更多的内容,请参阅atomthreads或chibios或其他开源、功能性操作系统


您可以更正被中断的地址,或者在本例中,svc(程序计数器)之后的地址位于堆栈上,没有设置lsbit,但同时也是正确的。用于从异常(svc或定时器中断或其他)返回的实际lr是特殊的0xFFFFxxxx,它设置了lsbit。

激活函数的输入是指向用户堆栈顶部的指针,该文档说分支可以清除T位,但为什么?文档说明了众所周知的BX,设计驱动T位的BLX和POP可以修改T位,因为它就是这样设计的。若BX、BLX或POP将T位设为零,请阅读下面三行:当T位为0时尝试执行指令会导致故障或锁定。我得到了它,谢谢,当分支到偶数地址时,我是否应该显式加1?您应该使用
LR
中的一个特殊“异常返回”值,并通过
bx-lr
指令返回线程模式。要求您正确设置堆栈帧。激活函数的输入是指向用户堆栈顶部的指针。该文档说明分支可能会清除T位,但原因是什么?该文档说明了众所周知的BX、BLX和POP,通过设计驱动T位可以修改T位,因为这就是T位的设计方式。若BX、BLX或POP将T位设为零,请阅读下面三行:当T位为0时尝试执行指令会导致故障或锁定。我得到了它,谢谢,当分支到偶数地址时,我是否应该显式加1?您应该使用
LR
中的一个特殊“异常返回”值,并通过
bx-lr
指令返回线程模式。要求您正确设置堆栈帧。基本上就像Turbo J在评论中所说的。我现在找不到它,但我非常确定至少有一个堆栈指针是可配置的选项。不明白,现在,mpu是可配置的,所以可能有一个没有。我把堆栈指针弄乱了,发现这是一件非常痛苦的事情,没有保护,不管怎样,svc处理程序可以使用主堆栈和/或在输入自己的st时设置堆栈指针