我在这里写了一个空闲钩子
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中的调度程序滴答之外。在iar中的宏是
__bic_SR_register_on_exit(LPM3_bits); // Exit Interrupt as active CPU
但是,似乎将MCU置于睡眠状态会导致一些不规则的行为。 LED始终保持开启状态,但是当我调整范围时,当我通过其中一个中断(UART)唤醒MCU时,它将关闭几个指令周期,然后再重新打开。 如果我注释掉LPM3指令,事情就会按计划进行。 led大部分时间都处于关闭状态,只有在任务运行时才会亮起。
我使用的是MSP4f305438
有什么想法吗?
答案 0 :(得分: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