You could analyze the stack. This requres having access to debugging capabilities which will not work in deep-sleep.
Does disabling the deep sleep mode change the behaveour?
Can you please post your complete project so that we all can have a look at all of your settings. To do so, use
Creator->File->Create Workspace Bundle (minimal)
and attach the resulting file.
Unfortunately, changing the project sometimes results in the issue not appearing at all... Inserting a delay of 5 ms before sleep "fixes" the issue, as well as turning on LED via GPIO before going to sleep... It is really bizzare situation to me.
Debugging is out of question since this issue appears in deep sleep after prolonged runtime... Based on information we gathered, it gets stuck in one of the interupts that are handled by auto-generated code in PSoC Creator.
Unfortunately, the project code can not be shared.
Is there any information on how to capture and decode the call stack? Is it even possible to do without having all debugger info (especially information on the ISR function stack size (for local variables)?
So no other choice remaining: Poor man's debugging.
Keep in mind that there are quite a lot PSoCs out there. So it might be very probable that you might have made an error. This might be caused by clobbering the stack, bad pointer, overwriting variables, forgotten "volatile" and some more. Check for all of those. Many of these errors get captured by a non-maskable interrupt. You may replace that with your own handler to get some infos. Have a deep look into "Cortex M0 Devices Generic User Guide" from ARM website.
The NVIC's ISER and ISPR registers are saved to dedicated 'failure status' RAM before executing the software reset.
It appears that 3 interrupts are enabled (3 bits set in ISER):
- IRQ1 (GPIO 1): ok, digital input for wake-up
- IRQ8 (WDT): ok, RTC timer
- IRQ12 (BLE): ok, BLE subsystem
However, when the watchdog kicks-in due to thread code not being executed anymore, the IRQ12 has the pending bit set.
The IRQ1 interrupt doesn't cause the problem since we monitor its execution and is not active during hang.
The IRQ8 interrupt is the WDT interrupt that is handling the issue and issues software reset.
The IRQ12 interrupt is inacessible to us and has the pending bit set - it surely looks like this is the one that is causing the issue.
The sleep is entered by calling the CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP) first, then checking both the return value and the actual BLE state (CyBle_GetBleSsState).
lpMode = CyBle_EnterLPM(CYBLE_BLESS_DEEPSLEEP);
blessState = CyBle_GetBleSsState();
if(lpMode == CYBLE_BLESS_DEEPSLEEP)
if (blessState == CYBLE_BLESS_STATE_ECO_ON || blessState == CYBLE_BLESS_STATE_DEEPSLEEP)
if (blessState != CYBLE_BLESS_STATE_EVENT_CLOSE)
The intriguing question is why this is happening to selected devices only and how this can be resolved...
Maybe it helps saving the Interrupt Program Status Register value which reflects the currently handled interrupt.
IRQ12 is reserved, but I am not sure if this is true for the PSoC4 BLE
IPSR wouldn't really bring any value since the 'stuck' handler is in fact a WDT interrupt (IRQ8). Somehow, we need to pull the data from the stack and try resolving the stacked register set... I guess some digging in the listings files is needed...
Please ensure to have the entry/exit from deepsleep in the critical section as recommended in our application note below.
This will ensure the entry/wakeup to deepsleep is not interrupted.