Stuck in interrupt - determining in which?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

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.

0 Likes
1 Solution
Anonymous
Not applicable

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.

http://www.cypress.com/documentation/application-notes/an92584-designing-low-power-and-estimating-ba...

Thanks,

Ranjith

View solution in original post

0 Likes
7 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

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

0 Likes
Anonymous
Not applicable

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)?

0 Likes

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

0 Likes
Anonymous
Not applicable

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...

0 Likes

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

0 Likes
Anonymous
Not applicable

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...

0 Likes
Anonymous
Not applicable

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.

http://www.cypress.com/documentation/application-notes/an92584-designing-low-power-and-estimating-ba...

Thanks,

Ranjith

0 Likes