interruptible sleep

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

cross mob
NiLe_4630071
Level 1
Level 1
First like given

I have code that needs to run on a timer. Running with a fixed sleep in between won't be accurate enough, the timer is necessary. I've set up a "Timer Counter" on the schematic to fire on an interrupt which is handled by CM0+. The problem is that the code I need to run can't run correctly inside an interrupt handler. Instead, I wrote

Cy_SysPm_Sleep (CY_SYSPM_WAIT_FOR_INTERRUPT);

and put my code after it, but this function call never returns. If I add debug code in the interrupt handler, that fires, but not code after Cy_SysPm_Sleep. I've also tried not installing any handler for the interrupt, no difference.

How do I sleep CM0+ until an interrupt fires, but otherwise ignore the interrupt or have no handler for it?

0 Likes
1 Solution

My TCPWM is named Counter_1 and I'm using the generated utility functions. Simply changing my call to be "Counter_1_ClearInterrupt(TCY_TCPWM_INT_ON_TC);" resolved the issue.

Thank you!

View solution in original post

0 Likes
4 Replies
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi,

Please note that Cy_SysPm_Sleep is a blocking function. It will not return until the CPU comes out of sleep. You can use the following firmware logic:

void timer_isr()

{

   Cy_tcpwm_clearinterupt();

   interrupt_flag==1;

}

for (;;)

{

   if(interrupt_flag ==1)

   {

       //Your code

       //interrupt_flag=0;

   }

   if(interrupt_flag ==0)

   {

        Cy_SysPm_Sleep (CY_SYSPM_WAIT_FOR_INTERRUPT);  

   }

}

Hope this helps. Kindly update if you have further queries.

Thanks

Ganesh

0 Likes

Hi Ganesh! I'm afraid this isn't working for me yet:

void timer_isr() {

  Cy_SCB_UART_PutArrayBlocking(UART_DEBUG_HW, "X", 1);

  Counter_1_ClearInterrupt(0);  // what's the meaning of this 0 anyway?
}

// in main:

while (1) {

  Cy_SCB_UART_PutArrayBlocking(UART_DEBUG_HW, "A", 1);

  Cy_SysPm_Sleep(CY_SYSPM_WAIT_FOR_INTERRUPT);

  Cy_SCB_UART_PutArrayBlocking(UART_DEBUG_HW, "B", 1);

}

I see tons of 'X' over the UART, but never* 'B'. I've slowed down the timer so that the timer is firing at a rate of around 1/10th of a second, slow enough for the UART to keep up. Even if I comment out the print of "X", the "B" never prints. I've tried calling __WFI() instead of the sleep function and it makes no difference. I've put a debugger breakpoint on the "B" printing line and indeed it's not being reached, even though "X" is being printed. It doesn't sleep if I step through the WFI with the debugger, but I assume that's because the debugger necessarily wakes up the core.

As far as I can tell, interrupts cause the ISR to run while Sleep() continues to block. That's not the behaviour I expected, and it seems like it's not what you expected either, given your answer? Is there something else I can do to debug this?

* when run as part of a larger program with BLE on CM4 (only on CM4, not dual-core), I do see a "BA" printout after a GATTS notify event. I don't know why that happens. It's not correlated with my interrupt timing so I'm assuming it's an SEV somewhere in the BLE stack? I can't easily see from the debugger why CM0+ was woken up.

0 Likes

Hi Nick,

From your explanation I think the timer interrupt is not getting cleared and that is why the code execution stays always in the ISR. When interrupt is never cleared, the code execution will never return even if the device is in sleep mode or not in sleep mode.

That is why it is printing 'X' everytime when you write this line in the ISR " Cy_SCB_UART_PutArrayBlocking(UART_DEBUG_HW, "X", 1);" and not printing anything when you remove this line.

The proper way of clearing a TCPWM interrupt is to use the following API:

Cy_TCPWM_ClearInterrupt(Timer_HW, Timer_CNT_NUM, CY_TCPWM_INT_ON_TC); (the mask value should be set accordingly).

Please refer PDL section --> TCPWM  --> Common --> Functions --> Cy_TCPWM_ClearInterrupt() for more details. You can also refer the code example for proper way of clearing the timer interrupt.

https://www.cypress.com/documentation/code-examples/ce220169-psoc-6-mcu-periodic-interrupt-using-tcp...

Please check the above solution and let us know if it doesn't work.

"* when run as part of a larger program with BLE on CM4 (only on CM4, not dual-core), I do see a "BA" printout after a GATTS notify event. I don't know why that happens. It's not correlated with my interrupt timing so I'm assuming it's an SEV somewhere in the BLE stack? I can't easily see from the debugger why CM0+ was woken up."

--> Kindly attach your project to understand the reason for this behavior.

Thanks and regards

Ganesh

My TCPWM is named Counter_1 and I'm using the generated utility functions. Simply changing my call to be "Counter_1_ClearInterrupt(TCY_TCPWM_INT_ON_TC);" resolved the issue.

Thank you!

0 Likes