This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi,
We are using Z-Stack v.2.5.1 (or 2.6.0.3) in a very low power sensor.
I am trying to start an event from a hardware interrupt service. The system uses POWER_SAVING and can be in sleep state tens of seconds. A HW interrupt wakes up the system, and its ISR is executed ok. The problem is, that I have one task (initialised etc.) and I would like to set an event to the task inside the ISR, that would get executed after a small time or immediately after exiting the ISR. I can not make this work; the set event in the ISR is served only after one next previously and potentially unrelated timed event is served. I.e. it looks like the system goes to sleep mode after the ISR, and wakes up only to the previously set timed task, not to the one set in the ISR.
In other words; there are several timed events handled in multiple tasks. If I try to use in the ISR e.g. osal_set_event(MyTaskID,MYEVENT) or a timed event osal_start_timerEx( MyTaskID, MYEVENT,100), then the MYEVENT in the MyTaskID gets processed only after some other, previously set timed event executes, which may happen after a long time. So, it looks like the system goes to sleep after ISR exit, and the updated list of expiring tasks does not get actually processed until the previously set another event is executed first.
There is only a couple of workarounds that I have figured: If I set a dummy MY_DUMMY_EVENT in MyTaskID, that is periodically executed for examply once a second, then the event set in the ISR gets executed once the MY_DUMMY_EVENT is executed next time. Also if the MyTaskID is set to PWRMGR_HOLD state with osal_pwrmgr_task_state() makes the event set in the ISR to be processed immediately. However both solutions are really bad as they require excess power. In fact it voids the benefits of using the HW ISR, since effectively it would be the same to use polling instead of interrupt...
Is there a neat and simple solution to this?
Thanks,
Ilkka
it looks like the system goes to sleep mode after the ISR,
Did you include code in your ISR to exit the low power mode? The MSP430 will restore the previous mode on the return from interrupt unless you have done something to change that. Like include "LPM4_EXIT". (aka "__bic_SR_register_on_exit(LPM4_bits)")
Ilkka,
I'm not sure how Z-stack has been implemented here as we have no support for MSP430 on Z-stack as that solution is made for our zigbee enabled devices. So there may be fundamental issues with using Z-stack here that would cause you inefficiencies on MSP430.
I went back utilising the ready made Port2 interrupt handler in io_pins.c and there is the __low_power_mode_off_on_exit() which should clear the SR register bits, thus disabling the low power mode in ISR exit, as far as I understand. (It's a bit misleading that in the IoPins_SetIntFunction() comments it says " * \param lowPower - if true, low_power_mode_on_exit() is called in interrupt" while I think that the opposite is true, i.e. when called with lowPower=true, it actually means that when exiting from the ISR, the clocks should be running).
Anyway, while it would make sense that the lower power mode was kept active, if I make a timed event with osal_start_timerEx() to be started e.g. after one second, shouldn't that event be started even if the low power mode was kept active when exiting the ISR? I can see with osal_next_timeout() that the next timeout gets updated, but perhaps something else is needed as well (?). Calling the osal_adjust_timers() doesn't seem to make a difference. The issued event gets executed seemingly after a random time.
Worth noting is that I have one HW interrupt in Port1, it utilises the ISR handler in io_pins.c in a same manner, and it seems to work ok. In Port2, I have two interrupt pins, and the problem seems to be occur only with those. I use IAR C/C++ compiler, and the code using Port1 is written (compiled) in C, while the problematic Port2 interrupts are combined with some C++ code (.cpp source). I wonder if the IAR compiler makes something funny here...(?)
I can see that the entry and exit with the ISR work precisely as such, actually combined with some TimerB HW interrupt code. Also, the task - event machine works (combined with C++) as it should, that is; when the events are not started from the ISR itself.
**Attention** This is a public forum