LowPowerLab Forum

Hardware support => Moteino => Topic started by: kni on October 13, 2017, 01:32:00 PM

Title: One solution to moteino failure to return from sleep
Post by: kni on October 13, 2017, 01:32:00 PM
I thought I'd document an issue I've been chewing on for a couple months now, and what recently solved the problem for me.

I had a couple moteino's, which were using interrupts, that would intermittently fail to come out of sleep.

The symptoms, and the steps I took to troubleshoot, were very similar to this thread:
https://lowpowerlab.com/forum/low-power-techniques/moteino-weathernode-won't-wake-up

Base on that discussion, I hypothesized my code was allowing the sleep function to be called before interrupts we re-enabled. It turns out this hypothesis was incorrect. The real culprit turned out to be calling flash.sleep when the flash chip was already asleep. The problem was intermittent because the condition for this to occur, requires radio.receiveDone to return false.

Let's walk through the code, common to many of the example sketches, to explain this more clearly...

When setup is called, the flash is initialized and immediately put to sleep:
Code: [Select]
if (flash.initialize()) flash.sleep();

When running the through the normal loop, the flash chip is only woken up if radio.receiveDone returns true:
Code: [Select]
if (radio.receiveDone())
{
...
flash.wakeup();
...
}

Once the loop completes the task it was programmed to do (read temp, check motion, etc.), the device is put to sleep:
Code: [Select]
flash.sleep();
radio.sleep();
LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF);

flash.sleep is called unconditionally here, which results in an unresponsive moteino, if the flash chip was never woken up to check for a received message.

I was able to consistently demonstrate this issue by commenting out the entire if (radio.receiveDone()) block, while leaving in the final call to flash.sleep.

What I did not do is investigate why radio.receiveDone returned false. I did not need the flash chip for the project I was working on, so I just commented out both radio.receiveDone and the final call to flash.sleep. The problem is completely gone now.

The following thread was what pointed me to this solution:
https://lowpowerlab.com/forum/general-topics/spiflash-initialise()-hangs-intermittently-running-on-moteino/new/

If I read this right, commit 7885ef3 on Aug 4, should fix this, so just update your spiflash library. Alternatively, make sure one's code does not try to put to sleep a flash chip that is already sleeping.




Title: Re: One solution to moteino failure to return from sleep
Post by: Tony Weil on October 17, 2017, 06:35:01 PM
I think you are onto something!

1) I was also able to consistently duplicate what you did and demonstrate this issue by commenting out the entire if (radio.receiveDone()) block, while leaving in the final call to flash.sleep.

2) I was then able to consistently solve the problem by commenting out the entire if (radio.receiveDone()) block and removing the final call to flash.sleep.

3) Unfortunately, after updating the SPIFlash from commit 7885ef3 on Aug 4, I was still able to cause the issue in #1 above. I tried all sorts of things including deleting the library cache files, rebooting, etc.

4) As an experiment, I also tried leaving the if (radio.receiveDone()) block and then adding a second flash.sleep, right after the first one prior to the LowPower.powerDown statement. I expected it to cause the issue in #1 above, but it didn't.

For now, since I don't need the flash or OTA programming, I'll just try #2 above for a while and see how long it lasts.

Thanks,
Tony

Title: Re: One solution to moteino failure to return from sleep
Post by: Uncle Buzz on October 30, 2017, 12:29:02 PM
I was in front of same issue, but without using radio, so  if (radio.receiveDone()) statement.

If you check datasheet of the winbond flash, you can read :
Quote
While in the power-down state only the Release Power-down /
Device ID (ABh) instruction, which restores the device to normal operation, will be recognized. All other
instructions  are  ignored.  This  includes  the  Read  Status  Register  instruction
,  which  is  always  available
during normal operation. Ignoring all but one instruction makes the Power Down state a useful condition
for securing maximum write protection. The device always powers-up  in the normal operation  with  the
standby current of ICC1.

So, with code previous to commit 7885ef3, the loop
Code: [Select]
while(busy());
in command function, even for wakeup, wasn't able to read status register of flash.

I'm still not sure what will happend if you send another command during power-down mode, has you could be stuck in the same loop.