【问题标题】:UsageFault when branching to a function pointer on Cortex-M0跳转到 Cortex-M0 上的函数指针时出现 UsageFault
【发布时间】:2017-02-24 16:59:22
【问题描述】:

我在 STM32F0 (ARM Cortex-M0) 上运行代码。我定义了一个指向nested function的函数指针:

void My_Async_Func(void *handle, void (*complete)(bool success)) {
    /* 
     *  \/ A nested function \/
     */
    void receiveHandler(void) {
        // This function lies at an even-numbered address
    }
    /* ... */
    uart->rxDoneHandler = &receiveHandler;
    Go(uart);
}

嵌套函数似乎搞砸了。稍后当我调用 rxDoneHandler 指针时,它会尝试分支到 0x8c0c6c0c 并且我得到一个 UsageFault。根据ARM docs,这是因为我在仅支持 Thumb 指令集的处理器上跳转到 偶数 地址,这需要您只跳转到 odd-编号的地址。

我正在使用 GCC arm-none-eabi 4.9.3。我的 CFLAGS 是:

arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -mfloat-abi=soft -O0 -g3 -Wall -fmessage-length=0 -ffunction-sections -c -MMD -MP 

我尝试过的事情

我尝试按照here 的建议使用-mthumb-interwork 调用gcc。结果一样。

我尝试使用类似

的属性手动设置函数的对齐方式
__attribute__((aligned(16))) void receiveHandler(void) {

}

同样的结果。

当我调用它时,我尝试手动将 1 添加到指针

(uart->rxDoneHandler + 1)();

同样的结果。

是我做错了什么,还是编译器中的错误?

【问题讨论】:

    标签: pointers gcc arm cortex-m thumb


    【解决方案1】:

    嵌套函数必须不能从封闭函数的外部调用,除非你仍然“逻辑上”在该函数内部;来自嵌套函数的 GCC 页面(重点是我的):

    可以通过存储其地址或将地址传递给另一个函数来从其名称范围之外调用嵌套函数:

     hack (int *array, int size)
     {
       void store (int index, int value)
         { array[index] = value; }
    
       intermediate (store, size);
     }
    

    这里,中间函数接收store的地址作为参数。如果中间调用存储,则给存储的参数用于存储到数组中。 但这种技术只有在包含函数(本例中为 hack)不退出时才有效。

    我的猜测是您将uart->rxDoneHandler 注册为中断服务例程(或从 ISR 中调用的东西)。你不能那样做。

    【讨论】:

    • 嗯。是啊,你说得对。在My_Async_Func 的末尾添加WFI 指令使其工作,大概是通过阻止函数返回。
    • 仍然不应该在 ISR 中使用来自不同范围的嵌套函数。我真的无法想象这是编译器设计者曾经考虑过的他们应该支持的用法
    • ISR 为什么重要?
    • 因为它是进入函数的“横向”方式。您实际上不在同一个堆栈层次结构中。
    猜你喜欢
    • 1970-01-01
    • 2015-08-23
    • 2021-12-07
    • 2020-03-22
    • 1970-01-01
    • 2015-10-01
    • 2015-09-15
    • 1970-01-01
    • 2021-07-04
    相关资源
    最近更新 更多