This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MCU-PLUS-SDK-AM243X: 在R5的核上进入异常中断后怎么获取进入异常前的PC指针

Part Number: MCU-PLUS-SDK-AM243X


在R5的核上跑freertos的操作系统,进入异常中断后怎么获取进入异常前的PC指针?主要是想知道进入异常的时候程序运行到了哪里。该怎么实现?是不是下图中的R14_USER寄存器就存储了进入异常前的PC指针?如果是的话,怎么获取R14_USER寄存器?

  • 在R5的核上跑freertos的操作系统,进入异常中断后怎么获取进入异常前的PC指针?

    通过读取特定的寄存器。

    主要是想知道进入异常的时候程序运行到了哪里。该怎么实现?

    读取特定的寄存器来获取进入异常前的PC指针。

    怎么获取R14_USER寄存器?

    用汇编指令

    MRS r0, R14_USER

  • 我用内嵌汇编和纯汇编编译都没通过,这个问题和之前问的如何获取psp是一样的问题,报的错都是"invalid operand for instruction",如图 ,所以到底应该怎么获取psp和R14_USER这些特殊寄存器的值?

  • 个人理解R14_USER寄存器应该是用户模式下的链接寄存器,存储跳转到当前函数返回地址。发生异常时,LR值会被保存堆栈中

    我画了个R5异常堆栈结构示意简图:
    +-----------------------------+
    | Exception Stack Frame |
    +-----------------------------+
    | R0 |
    +-----------------------------+
    | R1 |
    +-----------------------------+
    | R2 |
    +-----------------------------+
    | R3 |
    +-----------------------------+
    | R12 |
    +-----------------------------+
    | LR (R14_USER) |
    +-----------------------------+
    | PC (R15) |
    +-----------------------------+
    | xPSR |
    +-----------------------------+
    | S0 |
    | |
    | ... |
    | |
    | |
    +-----------------------------+

    在这个堆栈帧中,LR(R14_USER)的偏移量为4,因此可以通过读取堆栈中R14_USER的偏移地址来获取进入异常前的PC指针。

    然后我自己写一个示例,您试一下使用这个方式获取R14_USER的值看是否可行,:

    void exception_handler(void)
    {
    // Get the LR (R14_USER) value from the stack
    uint32_t* stack_ptr = (uint32_t*)__get_PSP(); // or __get_MSP() depending on the stack used
    uint32_t lr_value = stack_ptr[6]; // Assuming R14_USER is at offset 6 in the stack frame
    
    // Now lr_value contains the value of LR (R14_USER) before the exception
    // You can use it to determine where the exception occurred
    }

    `__get_PSP()`和`__get_MSP()`是CMSIS提供的宏,获取当前任务的堆栈指针。

    如上述方法不行,您再试一下内嵌汇编或者纯汇编,我写了一段示例代码,供您参考下:

    获取PSP

    内嵌汇编:

    uint32_t get_PSP(void)
    {
    uint32_t psp_value;
    __asm volatile("MRS %0, PSP" : "=r" (psp_value));
    return psp_value;
    }

    纯汇编:

    get_PSP:
    MRS r0, PSP
    BX lr

    获取R14_USER(LR)

    内嵌汇编:

    uint32_t get_LR(void)
    {
    uint32_t lr_value;
    __asm volatile("MOV %0, LR" : "=r" (lr_value));
    return lr_value;
    }

    纯汇编:

    get_LR:
    MOV r0, LR
    BX lr


  • 你提到的内联汇编和纯汇编获取psp的方法都不行,报的就是invalid operand for instruction的错,所以我一直在追问的就是获取psp的正确方法是什么?感觉编译器不认psp

  • 那应该就是不认了

  • 所以要怎么得到psp,是不是应该有别的指令方法?

  • MRS R0, PSP ; 将当前进程堆栈指针(PSP)的值读取到 R0 中

    上述指令将当前进程堆栈指针(PSP)的值读取到通用寄存器 R0 中。

    如果您希望在异常处理例程中获取进入异常前的 PSP 值,可以在异常入口处保存 PSP 的值,然后在异常处理例程中使用。例如:

    在异常入口处保存 PSP 值:

    MRS R1, PSP ; 保存当前进程堆栈指针(PSP)的值到 R1 中