PSoC 6 CPU Sleep

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

cross mob
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Hi.

I'm trying to use the HAL System Power Management library to put the CM4 to sleep. So far, I've had no luck, and as I have found too many times, there is very little documentation available, and no examples. What documentation exists (e.g. Architecture TRM) is unclear, even suggesting that only masked interrupts can wake up a sleeping CPU.

Here's the environment:

  • PSoC 63 with BLE in a custom board.
    • MTB 2.3.0 
    • BSP 2.3.0
    • PDL 2.3.0
    • HAL 2.1.0
  • CM4 and CM0+ running FreeRTOS
  • Several peripherals in use (BLE, I2C, UART, SPI, RTC, TWPCM, etc.)
  1. I registered four callbacks using cyhal_syspm_register_callback(). 
  2. I call cyhal_syspm_sleep().
  3. The four callbacks are called with state set to CYHAL_SYSPM_CB_CPU_SLEEP and mode set to CYHAL_SYSPM_CHECK_READY. All callbacks return true.
  4. The four callbacks are called again with state set to CYHAL_SYSPM_CB_CPU_SLEEP, but this time mode set to CYHAL_SYSPM_BEFORE_TRANSITION.
  5. The four callbacks are immediately called a third time with state set to CYHAL_SYSPM_CB_CPU_SLEEP, but this time mode set to CYHAL_SYSPM_AFTER_TRANSITION.

The first problem is that the CPU either doesn't sleep, or wakes up immediately. I disable the RTOS SysTick interrupt in one of the callbacks. I also disable several other peripheral interrupts, and turn off the BLE stack, none of which has made a difference. It's likely that some interrupt is firing, but I can't think of a good way to determine which is the culprit.

The second problem is that the stated behavior, namely that the callbacks are called on wakeup (CYHAL_SYSPM_AFTER_TRANSITION) in the reverse of the order in which they are called on sleep (CYHAL_SYSPM_CB_CPU_SLEEP) does not match the observed behavior.
Callbacks are always called in the same order, even when one of the callbacks returns false in response to CYHAL_SYSPM_CHECK_READY.

Has anyone successfully used cyhal_syspm_sleep() to put one of the CPUs to sleep?

Thanks,

-Nick

0 Likes
1 Solution

Hi @NiBu_4687336 ,

This is one disadvantage of HAL where it makes the developers life simple by taking away granular control which PDL provides  as it is a generic interface that can be used across multiple product families.
The best recommendation here is to use PDL for complex project like yours which involves a plethora of peripherals so that we have granular and precise control over them.

The HAL library is a wrapper which in the backend uses PDL libraries as shown in the below image:

AlenAn14_0-1655357018728.png


HAL is useful for beginners who would like to easily prototype with some basic peripherals but when going more advanced,  its best to use PDL for better control.

For example, in the definition cyhal_uart_init() routine you can see interrupts being set up in the same .

So you will have to take into account these HAL based SCB's as well.
 
Documentation for HAL is provided here.

Warm Regards
Alen

View solution in original post

0 Likes
21 Replies
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Here's another (or perhaps a clearer) question:

I'm trying to prevent interrupts from waking up my CPU. Absent any guidance from the HAL or PDL documentation, I'm doing that by disabling them in the NVIC, by calling NVIC_DisableIRQ(). That means the peripherals may still raise interrupts, but they will not be propagated to the CPU.

This may or may not be enough to prevent the CPU from waking up from sleep mode. Anybody care to guess?

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Okay, on one seems interested in answering general questions. Here are some more specific ones.

How can I prevent the ARM CM4 SysInt exception from waking the CM4 from sleep mode?

Currently I'm using 

portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;

Where portNVIC_SYSTICK_CTRL_REG = 0xe000e010 and portNVIC_SYSTICK_ENABLE_BIT = 1. That's equivalent to the CMSIS

SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Next question:

How can I prevent a HAL-managed SCB UART from waking the CM4?

Currently I'm using 

cyhal_uart_enable_event( &cyhal_uart_obj, CYHAL_UART_IRQ_TX_DONE | CYHAL_UART_IRQ_RX_NOT_EMPTY, IrqPriority_UART, false );

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Next question:

How can I prevent a HAL-managed SCB I2C controller from waking the CM4?

Currently I'm using 

cyhal_i2c_enable_event( &cyhal_i2c_obj, CYHAL_I2C_MASTER_WR_CMPLT_EVENT |  CYHAL_I2C_MASTER_RD_CMPLT_EVENT | CYHAL_I2C_MASTER_ERR_EVENT, IrqPriority_I2c, false );

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

And...

I have an external signal connected via a digital input pin to the "Capture Signal" of a TCPWM that is configured as a counter/timer. The TCPWM's "Interrupt Source" is connected as a CM4 interrupt source using Cy_SysInt().

How can I prevent this configuration from waking the CM4?

Currently I'm using NVIC_DisableIRQ() to disable the interrupt from the TCPWM. Is that sufficient, or will the capture signal to the TCPWM wake the CM4 as well?

-Nick

0 Likes
Gautami_12
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi @NiBu_4687336,

sorry for the delay in replying.
Can you please refer to the below link for the first question related to PSoC 6 CPU SLEEP:-
https://github.com/Infineon/Community-Code-Examples/blob/master/mtb_training/session05/mtb_05_ex03_u...
This code example helps to solve your issue.

 

 please refer to the below link:-
https://community.infineon.com/t5/ModusToolbox-Blog/Session-5-Introduction-to-Low-Power-Modes-in-PSo...
This is a training program video based on Low power modes that solve the issues you are facing on CPU sleep, interrupts, etc.

please refer to https://www.infineon.com/dgdl/Infineon-AN219528_PSoC_6_MCU_Low-Power_Modes_and_Power_Reduction_Te...
this has information about disabling unused blocks .this can be used to disable I2C and UART blocks while not using them.

Please let us know if you have any more queries

Warm Regards,
Gautami J

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Hi @Gautami_12.

Thanks for the reply. Unfortunately, none of the links you provided address my questions. The code examples represent trivial cases with basically no interrupt sources. Nothing in any of the linked documents sheds any light on what is required to prevent the CPU from being awakened by a specific interrupt.

As I described in my initial post, I am able to put the CM4 CPU into sleep mode - at least the API functions report success - but the CPU then wakes up immediately.

Please see my specific questions above.

Thanks again,

-Nick

0 Likes

Hi,

Can you please try implementing a callback handler for each block to know which block is making the CPU wake up?

Please refer to Snippet 2: Interrupt on UART event in the link provided below to know how to implement the callback handler for each block.

CALL_HANDLER_FOR_BLOCKS

please refer to the screenshot below for more reference:-

Gautami_12_0-1651836812656.png

Can please you confirm if you are observing the issue when you program and run the code or if it is present while debugging?

If possible, can you please share with us a sample project of your code where you are observing this issue so that we can try to debug the error on our end?

Warm Regards,
Gautami J

0 Likes

Hi @Gautami_12.

Sorry to take so long to reply - I had to switch tasks as I was making no progress on this one.

I use four SCBs:

  1. SCB 1 - Console UART
  2. SCB 2 - SPI I/F to off-chip ADC, "masked" to CM0+ only
  3. SCB 5 - SPI I/F to off-chip CAN controller and SPI-mode SD card
  4. SCB 6 - I2C I/F to off-chip GNSS (unpopulated)

Of the four SCBs, only two should affect the CM4; SCB 1 and SCB 5. SCB 2 is not "masked" to the CM4 and the GNSS module associated with SCB 6 is not installed on my development board, hence the I2C I/F is not used.

I have event callbacks for both SCB 1 and SCB 5. I disable events for both before switching to low-power mode, so neither will be called, regardless of whether or not the associated interrupt awakened the CM4.

The behavior is the same whether or not the debugger is attached.

I have captured the state of several registers immediately on return from the call to __WFI() in the Cy_SysPm_CpuEnterSleep() function in cy_syspm.c. Here is what I see:

The CM4 NVIC "pending" register (base address 0xE000E200) contains a "1" bit corresponding to each of the follow interrupt sources (and "0" for all others):

  • ioss_interrupt_gpio_IRQn
  • cpuss_interrupts_ipc_0_IRQn
  • cpuss_interrupts_ipc_3_IRQn
  • cpuss_interrupts_ipc_8_IRQn
  • tcpwm_0_interrupts_0_IRQn

Additionally, 

  • Register IPC_INTR_STRUCT0_INTR_MASKED (base address 0x40231000) has a value of 0.
  • Register IPC_INTR_STRUCT3_INTR_MASKED (base address 0x40231060) has a value of 0.
  • Register IPC_INTR_STRUCT8_INTR_MASKED (base address 0x40231100) has a value of 0.
  • Register TCPWM0_CNT0_INTR_MASKED (base address 0x40380130) has a value of 0.

It would be infeasible to provide a sample project, as it would necessarily have to run on our custom board.

Thanks,

-Nick

0 Likes

Hi @NiBu_4687336 ,

You have mentioned that you are using interrupts only for 4 SCB blocks but as per the interrupt sources that you mentioned which trigger the interrupt pending register in  0xE000E200 that you have shared, it seems like the interrupts are triggered by a GPIO, a timer and 3 IPC (Inter Process Communication) structures.
You can decode the device that is triggering the interrupt by checking for it in device configurator as shown below (Example)

AlenAn14_0-1653548046695.png

For instance, the tcpwm_0_interrupts_0_IRQn you have shared in the above reply seems to be triggered by TCPWM 0 Counter 0.

Please try and isolate these interrupt sources to understand the root cause of the interrupt that is preventing your system from entering sleep.

Also please check if any IPC communications are happening between CM0+ and CM4 cores as well which also trigger the interrupt for the cores.

If required, you can also try disabling the interrupts that you don't want your device to wake up from by using the Interrupt Clear-enable Registers (0XE000E180) before calling the Sleep API.

This way only the SCB interrupts can cause the device to wakeup and not the other interrupt sources that you mentioned in your previous thread.

Make sure to enable the interrupts you disabled before going to sleep after the wakeup else the respective interrupts will remain disabled.

Warm Regards
Alen

 

0 Likes

Hi @AlenAn14.

Thanks for the reply. My comments about SCB interrupts were in the context of a discussion of SCBs. As you noted, I have more interrupt sources than just the SCBs. 

There will be active interrupt sources while the CM4 is supposed to be sleeping; however, none of them are "masked to" the CM4:

  • IPC_INTR_STRUCT0_INTR_MASKED is 0.
  • IPC_INTR_STRUCT3_INTR_MASKED is 0.
  • IPC_INTR_STRUCT8_INTR_MASKED is 0.
  • TCPWM0_CNT0_INTR_MASKED is 0.

Section 6.2.2 of the PSoC 6 MCU: CY8C63x6, CY8C63x7 Architecture Technical Reference Manual (TRM) states:

"IPC_INTR_STRUCTx_INTR_MASK: The bit in this register masks the interrupt sources. Only the interrupt sources with their masks enabled can trigger the interrupt."

And

"IPC_INTR_STRUCTx_INTR_MASKED: This register provides the instantaneous value of the interrupts after they are masked."

If we accept that this is accurate, then it is clear that none of the IPC interrupts can have awakened the CM4. The same analysis holds for the TWPCM interrupt.

Is the TRM is wrong? Am I misinterpreting it? Is there some other bit of information that I'm overlooking?

Is there a reliable way to identify what awakened the CM4?

Thanks again,

-Nick

0 Likes

Hi @NiBu_4687336 ,

Can you please let me know what is the state of IPC_INTR_STRUCTx_INTR_MASK for IPC_STRUCT0/3/8 ?

For the TCPWM 0 as well, you have to clear the corresponding bit in the TCPWM0_CNTx_INTR_MASK register to disable the interrupt for the timer.

 

The IPC_INTR_STRUCTx_INTR_MASKED register is an AND of the INTR and the MASK register. Can you confirm if IPC_INTR_STRUCTx_INTR_MASK register is also 0?

If so then the IPC registers and the TCPWM should not trigger the interrupts. 
In which case your interrupts may be triggered by some other factor.

Can you check the NVIC set-enable register of Cortex M0 and Cortex M4 CPUs and see if any other interrupts are enabled ?

Can you isolate /figure out who uses those interrupts and disable the same before going to sleep using the Interrupt Clear-enable Registers (0XE000E180) ?

Warm Regards
Alen

 

 

0 Likes

 

Hi @AlenAn14.

What can be learned from the state of the MASK register? Since the relevant MASKED bits are 0, either no interrupt occurred, or an interrupt occurred, but it was not masked to the CM4 processor. In either event, the CM4 should not wake up.

The CM0+ does not sleep when the CM4 does. It continues to run, including servicing interrupts.

From the Architecture TRM:

"Any peripheral interrupt, masked to the CPU, will wake the CPU to Active mode. Only
the CPU(s) with the interrupt masked will wake."

Before I put the CM4 into sleep mode, I disable all SCB interrupts that are to be handled by the CM4, as well as GPIO interrupts.

I use HAL for at least some of the SCB code. The HAL functions don't expose interrupt control directly. Is there any documentation on how to disable interrupts for SCBs that are under the control of HAL constructs?

Thanks,

-Nick

0 Likes

Hi @NiBu_4687336 ,

This is one disadvantage of HAL where it makes the developers life simple by taking away granular control which PDL provides  as it is a generic interface that can be used across multiple product families.
The best recommendation here is to use PDL for complex project like yours which involves a plethora of peripherals so that we have granular and precise control over them.

The HAL library is a wrapper which in the backend uses PDL libraries as shown in the below image:

AlenAn14_0-1655357018728.png


HAL is useful for beginners who would like to easily prototype with some basic peripherals but when going more advanced,  its best to use PDL for better control.

For example, in the definition cyhal_uart_init() routine you can see interrupts being set up in the same .

So you will have to take into account these HAL based SCB's as well.
 
Documentation for HAL is provided here.

Warm Regards
Alen

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Okay, since no one is interested in answering those questions, here's another one.

Is it possible to put the CM4 into sleep mode, while using a GPIO pin as an interrupt that is serviced by the CM0+, without waking the CM4?

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Just keeping the thread alive...

0 Likes
lock attach
Attachments are accessible only for community members.
Gautami_12
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi @NiBu_4687336,

Sorry for the delay.

yes, it is possible to put the CM4 into sleep mode, while using a GPIO pin as an interrupt that is serviced by the CM0+, without waking the CM4.
please refer to the project attached below. It demonstrates the proof for the same.

In this project, the interrupt in CM0+ is created by making pin 9[0] low (in falling edge) accordingly user-led toggles. In CM4 - toggling of the RGB red led code is implemented but when CM4 is kept in sleep mode RGB led does not toggle.
As a result, even when interrupts occur in CM0+  it does not wake up the CM4 hence RGB led does not toggle.

Please create a new thread for any other issues. We will be happy to help you in resolving your issues.

Warm Regards,
Gautami J

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Hi @Gautami_12.

Thanks, but you may have missed the point. Low-power operation doesn't work. My question about GPIO pins was just one attempt to elicit some kind of response from Cypress or anyone else. Knowing that it should be possible to use a GPIO interrupt is useful, but doesn't go very far toward explaining why my CM4 won't go to sleep.

I provided detailed information about the state of pending interrupts in response to your previous question. Does any of that suggest a direction for further investigation?

-Nick

0 Likes
NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Poking to keep the thread alive...

NiBu_4687336
Level 5
Level 5
5 solutions authored 50 replies posted 25 replies posted

Poking to keep the thread alive...

Gautami_12
Moderator
Moderator
Moderator
50 likes received 100 solutions authored 250 replies posted

Hi @NiBu_4687336 ,

The thread was locked due to inactivity for long time, you can continue the discussion on the topic by opening a new thread with reference to the locked one. The continuous discussion in an inactive thread may mostly be unattended by community users.

Thanks and Regards,
Gautami J
Cypress Semiconductor Corporation
An Infineon Technologies Company

0 Likes