- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
We have a PSoC4BLE based device that is mostly sleeping, but waking up once a second for RTC time update and a few more times due to BLE advertisement.
"Sporadically" (after a few hours/days and only on selected devices), the device stopped responding (BLE was still advertising, but our code stopped executing). We increased the watchdog interrupt priority and were able to detect this state and do a software reset.
Although this prevents the device from staying in not-responding state, the cause for the problem is not fixed.
Since the interrupt priority change resulted in the ability to catch the state, we assume that the CPU stays in one of the interrupts (due to higher priority, WDT interrupt is nested and gets executed).
Now the question - how to determine which interrupt resulted in this stuck state. In Cortex-M3 one can check the NVIC's active interrupts mask, but M0 doesn't support it.
Solved! Go to Solution.
- Labels:
-
BLE
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Matevz,
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.
Thanks,
Ranjith
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So no other choice remaining: Poor man's debugging.
But:
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.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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)
{
CySysPmDeepSleep();
}
}
else
{
if (blessState != CYBLE_BLESS_STATE_EVENT_CLOSE)
{
CySysPmSleep();
}
}
The intriguing question is why this is happening to selected devices only and how this can be resolved...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Matevz,
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.
Thanks,
Ranjith