snakeemail 发表于 2021-1-4 14:39:10

arm cortex硬件出栈PC,会将出栈的PC值自动加1?


1.1 问题来源发现freertos第一次代码模拟压栈,放入PC的函数指针,最低位必须是0.   1.2 问题资料说: 手动写pc,必须把最低位设1,告诉mcu此时是thumb状态。 但freertos的代码把最低位强行变0了。 这不是矛盾吗?1.3 我的猜测资料说读PC,值最低位总是0,所以代码里面模拟硬件压栈,PC的bit要求为0,因为PC肯定是硬件读出来放到栈里面,只要读PC的bit必须为0.硬件自动出栈给pc的时候,自动给出栈给pc的值加1?1.4 freerots源码StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ){        /* Simulate the stack frame as it would be created by a context switch         interrupt. */        pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */        *pxTopOfStack = portINITIAL_XPSR;        /* xPSR */        pxTopOfStack--;        *pxTopOfStack = ( ( StackType_t ) pxCode ) & 0xfffffffeUL;        /* PC */ 不理解此处为什么要把bit0变为0        pxTopOfStack--;        *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS;        /* LR */        pxTopOfStack -= 5;        /* R12, R3, R2 and R1. */        *pxTopOfStack = ( StackType_t ) pvParameters;        /* R0 */        pxTopOfStack -= 8;        /* R11, R10, R9, R8, R7, R6, R5 and R4. */         return pxTopOfStack;}



李益达 发表于 2021-1-4 16:55:20

我找了半天也不知道“资料说: 手动写pc,必须把最低位设1,告诉mcu此时是thumb状态。”这个资料的来源,能否出示资料来源? 我记得切换ARM Thumb状态的是cpsr(xPSR portINITIAL_XPSR bit24 为1)寄存器T位决定的。 *pxTopOfStack = ( ( StackType_t ) pxCode ) & 0xfffffffeUL;   此处这么操作不能单一理解未想要把bit0变为0,如果是thumb状态,则是16位,如果是arm32 状态则为32位,所以这里bit0是想要半字对齐或字对齐(如果使用的是cortex-m,则只有thumb-2指令集,半字节对齐)。不知道这样解释对不对。

eric2013 发表于 2021-1-4 17:51:32

这个在使用分支或者内存读取指令来更新PC的时候才需要强制PC的BIT0 = 1,否则会触发硬件异常,其它不用。

另外对于T标志,CM内核永远是1


snakeemail 发表于 2021-1-5 11:42:57

本帖最后由 snakeemail 于 2021-1-5 12:09 编辑

@李益达   我用的是cortex,所以直接写PC,最低位一定要是1。 资料是看的 ARM cortex-M3 权威指南。见下图。
@eric2013 太对了。最后我的看法就是,只要是代码写PC(不论是pop, ldr),一定要求LSB一定为1,表示branch后为thumb状态。 而当MCU硬件自动出栈,把栈里面的值给PC,那就不属于代码写的,这个时候又需要强制最低位为0. 但这个地方真的是很拧巴。
我看ucos这一块没有干任何事情,直接把函数指针放到栈里面。以前的freertos代码也是这样,到了9.0加上的,估计要看看github的记录才行。






页: [1]
查看完整版本: arm cortex硬件出栈PC,会将出栈的PC值自动加1?