2

我写了一个这里显示的空闲钩子

void vApplicationIdleHook( void )
{
    asm("nop");
    P1OUT &= ~0x01;//go to sleep lights off!
    LPM3;// LPM Mode -  remove to make debug a little easier...
    asm("nop");
}

这应该会导致 LED 关闭,并且 MSP430 在无事可做时进入睡眠状态。我在某些任务期间打开 LED。

我还确保在退出任何可能唤醒 MCU 的中断时修改 SR 中的睡眠模式位(portext.s43 中的调度程序滴答 isr 除外。iar 中的宏是

__bic_SR_register_on_exit(LPM3_bits);   // Exit Interrupt as active CPU

然而,似乎让 MCU 进入睡眠状态会导致一些异常行为。LED 始终保持打开状态,尽管当我确定它时,当我通过其中一个中断(UART)唤醒 mcu 时,它会关闭几个指令周期,然后重新打开。如果我注释掉 LPM3 指令,事情就会按计划进行。LED 灯大部分时间保持关闭状态,仅在任务运行时亮起。

我正在使用 MSP4f305438

有任何想法吗?

4

1 回答 1

3

也许问题在于调用 __bic_SR_register_on_exit(LPM3_bits)。该宏更改了堆栈SR中的 LPM 位,因此它必须知道在堆栈中的何处可以找到已保存的 SR。我相信 __bic_SR_register_on_exit() 是为您使用 __interrupt 指令时编译器生成的标准中断堆栈帧而设计的。但是,抢占式 RTOS(如 FreeRTOS)使用自己的堆栈帧,通常比编译器生成的堆栈帧大,因为 RTOS 必须存储完整的上下文。在这种情况下,从 ISR 调用的 __bic_SR_register_on_exit() 可能无法在堆栈上找到 SR。更糟糕的是,它可能会破坏堆栈上其他一些已保存的寄存器值。

对于抢占式内核,我不会从 ISR 调用 __bic_SR_register_on_exit() 。结果是空闲回调只被调用一次,并且再也不会被调用,因为每次 RTOS 执行上下文切换回空闲任务时,副作用是在 LPM 位打开的情况下恢复 SR。这会导致睡眠模式(这是您想要的),但您的 LED 不会切换。

Miro Samek state-machine.com

于 2010-03-16T13:22:02.387 回答