gnu arm cortex m4上的C ++异常处理程序,带有freertos

时间:2016-09-13 11:07:27

标签: c++ arm embedded freertos cortex-m

更新2016-12 现在还有一个这种行为的最小示例:https://community.nxp.com/message/862676

我正在使用ARM Cortex M4和freertos使用freescales自由Kinetis IDE(gnu arm工具链)。问题是那个

try {
    throw 4; // old scenario also not working: throw std::runtime_error("wut");
} catch (...) {
}

导致在尝试之后暂停CPU和代码,或者在执行catch处理程序时(在添加一些代码时)没有执行。

可在此处找到装配:https://gist.github.com/Superlokkus/3c4201893b4c51e154e2a0afdf78fef0

我认为这会导致SVC中断,我很抱歉我弄错了,Freertos欺骗了我,因为当我扔东西时它会在DefaultISR中停止。

throw indeeds跳转到 __ cxa_throw然后从那里跳到___Unwind_RaiseException __gnu_Unwind_RaiseException __cxa_begin_catch>  < _ZSt9terminatev> 因此看起来std::terminate被调用,但是catch all块不应该允许这样。或者我的假设是错误的,这种行为是因为gcc C ++运行时异常支持是一个总是调用terminate的存根?!

更新2016-09 :因为我看到rand()尝试使用malloc(),我还定义了一个工作的malloc()/ freeRTOS函数和etvoilà:__ cxa_allocate_exception使用malloc(我想知道工具链如何期望我处理bad_alloc案例)。 所以现在,它仍然崩溃,但在异常分配后(我认为): 执行路径是:

(throwing function after exception allocation)
__cxa_throw
   ...                        //(some intructions in __cxa_throw)
   __cxa_begin_catch  //I guess something went wrong here
    _ZSt9terminatev // Immediately after __cxa_begin_catch
        _ZN10__cxxabiv111__terminateEPFvvE:
         00016dfc: push {r3, lr}
         00016dfe: blx r0  //Goes directly to WDOG_EWM_IRQHandler or hard fault handler
         00016e00: bl 0x194ac <abort>

如果您想知道或者它可能会有所帮助:我的调试器说它的WDOG_EWM_IRQHandler崩溃了,如果我没有定义hard_fault处理程序和自己的默认处理程序。

所以我想在堆栈展开时出现了问题,因为我在_throw的名称中通过一些带有“完成堆栈展开”的符号,但是我没有抓住我在一个对象的析构函数中设置的断点。应该已经清理干净了。这似乎促使__cxa_begin_catch调用abort或其他东西。

(Kinetis Design Studio 3.2.0 GNU ARM C / C ++交叉编译器 版本:1.12.1.201502281154 为了我们 FRDM-KV31F)

3 个答案:

答案 0 :(得分:8)

由于错误,大多数异常都将执行默认处理程序,因此您需要做的第一件事就是确定实际执行的异常。您可以看到&#34;确定哪个异常处理程序正在执行&#34;以下页面中的部分:http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

我猜,因为你没有在你的代码中使用外围设备,它将是一个故障处理程序,可能是硬故障。同一页面(参见上面的链接)也提供了有关调试的说明。

除此之外 - 确保执行正常的FreeRTOS调试,例如确保定义了configASSERT(),并确保有堆栈溢出检查。有关这些主题的信息,请参见此页面:http://www.freertos.org/FAQHelp.html

答案 1 :(得分:7)

从RTOS方面来看,C ++异常只是一个美化的跳跃。只要他们从您的代码的一位跳到另一位,他们就不会干扰RTOS。所以你可以写一个try { } catch(std::exception) { }

当有 no C ++处理程序时,RTOS确实必须介入,因为C ++代码停止运行。

答案 2 :(得分:2)

在freescales Kinetis和asking the same problem on the nxp community成功创建了一个默认设置的空白项目后,恩智浦工程师Alice_Yang(以恩智浦徽章为准)告诉我答案:

By default new projects link to newlib-nano which has it exception support disabled.

  

The libstdc++ built along with newlib-nano have exception handling disabled.

所以解决方案是简单地链接到newlib。这可以通过简单地删除“其他链接器标志”中的“-specs = nano.specs”行来完成,并确保也禁用添加相同选项的复选框。 然后一切都按预期工作。只有代码在ROM /文本大小上增加了27 kB,在RAM /数据中增加了2kB。 enter image description here