首页 > 解决方案 > 执行 pow(2, ((m - 69.0f) / 12.0f)) 时出现 DeepSleepLo​​ck 下溢错误 - MBed OS

问题描述

我在 NUCLEO_L432KC 和 MBed CLI 上使用 MBed OS 来编译、刷写和测试。使用 OpenOCD 和 gdb 进行调试。MBed 有自己的 GreenTea 测试自动化工具,用于在嵌入式硬件上进行单元测试,它使用 utest 和 Unity 测试框架。

当我使用 GreenTea 对这个函数进行单元测试时:

float Piano::midiNumToFrequency(uint8_t m)
{
    float exp = (m - 69.0f) / 12.0f;
    return pow(2, exp);
}

我收到 DeepSleepLo​​ck 下溢错误:

[1589410046.26][CONN][RXD] ++ MbedOS 错误信息 ++ [1589410046.30][CONN][RXD] 错误状态:0x80040124 代码:292 模块:4 [1589410046.35][CONN][RXD] 错误消息:DeepSleepLo​​ck 下溢( < 0) [1589410046.37][CONN][RXD] 位置:0x8003B09 [1589410046.40][CONN][RXD] 文件:mbed_power_mgmt.c+197 [1589410046.43][CONN][RXD] 错误值:0xFFFF [1589410046.53][CONN] [RXD] 当前线程:主 Id:0x20001200 条目:0x80044A7 StackSize:0x1000 StackMem:0x20001C18 SP:0x2000FF04 [1589410046.62][CONN][RXD] 更多信息,请访问: https ://mbed.com/s/error?error =0x80040124&tgt=NUCLEO_L432KC [1589410046.64][CONN][RXD] – MbedOS 错误信息 –</p>

然而,当我将功能更改为此:

float Piano::midiNumToFrequency(uint8_t m)
{
    float exp = (m - 69.0f);
    return pow(2, exp);
}

它可以正常工作并且测试良好。

MBed在这里有一个错误状态解码器,上面写着

使用报告的“位置”来找出导致错误的位置的地址,或者尝试构建一个启用了 MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED 配置的非发布版本,以捕获此错误源自的文件名和行号。

当我启用 MBED_CONF_PLATFORM_ERROR_FILENAME_CAPTURE_ENABLED 时,它说位置在 mbed_power_mgmt.c 第 197 行,这是函数:

/** Send the microcontroller to sleep
 *
 * @note This function can be a noop if not implemented by the platform.
 * @note This function will be a noop in debug mode (debug build profile when MBED_DEBUG is defined).
 * @note This function will be a noop if the following conditions are met:
 *   - The RTOS is present
 *   - The processor turn off the Systick clock during sleep
 *   - The target does not implement tickless mode
 *
 * The processor is setup ready for sleep, and sent to sleep using __WFI(). In this mode, the
 * system clock to the core is stopped until a reset or an interrupt occurs. This eliminates
 * dynamic power used by the processor, memory systems and buses. The processor, peripheral and
 * memory state are maintained, and the peripherals continue to work and can generate interrupts.
 *
 * The processor can be woken up by any internal peripheral interrupt or external pin interrupt.
 *
 * @note
 *  The mbed interface semihosting is disconnected as part of going to sleep, and can not be restored.
 * Flash re-programming and the USB serial port will remain active, but the mbed program will no longer be
 * able to access the LocalFileSystem
 */
static inline void sleep(void)
{
#if DEVICE_SLEEP
#if (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS)
    sleep_manager_sleep_auto();
#endif /* (MBED_CONF_RTOS_PRESENT == 0) || (DEVICE_SYSTICK_CLK_OFF_DURING_SLEEP == 0) || defined(MBED_TICKLESS) */
#endif /* DEVICE_SLEEP */
}

任何想法为什么会发生这种情况或如何进一步排除故障?

标签: embeddedmbedutestunity-test-framework

解决方案


这部分:

StackSize: 0x1000 
StackMem: 0x20001C18 
SP: 0x2000FF04

建议堆栈指针不再位于任务自己的堆栈中。

仅从发布的代码无法真正确定其原因,但报告的位置无关紧要;当函数从损坏的堆栈中弹出返回地址或使用损坏的堆栈指针时,程序计数器可能会在任何地方结束,也可能不在任何地方。

例如,您的测试线程可能没有足够的堆栈分配,并且溢出损坏了其他一些线程的堆栈或 TCB,然后崩溃。这种行为可能会导致您看到的错误,其中指示的代码与错误的来源无关。这纯粹是推测,但是还有其他错误机制,例如缓冲区溢出,可能会导致类似的非确定性行为。

要理解的关键是,仅仅因为修改这个函数似乎会影响结果并不意味着这个函数本身就有问题。


推荐阅读