BLE interferes with IPC during deep sleep

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

cross mob
lock attach
Attachments are accessible only for community members.
JeHu_3414236
Level 5
Level 5
10 likes received First like received

I am using the BLE Pioneer Kit and the attached test program.  CM0 inits BLE and goes to deep sleep. CM4 sends an IPC pipe message after 1s. I do not get the interrupt for IPC in the myAcquireCallback() function. CM0 can receive the IPC message if I make any of these changes:

     1. use regular sleep instead of deep sleep

     2. don't register a dummy deep sleep PM callback that always returns success

     3. don't use WCO for Clk_LF

Does anyone know what is the problem?

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MeenakshiR_71
Employee
Employee
100 likes received 50 likes received 25 likes received

Seems like there is a corner case bug in our SysPm PDL's Cy_SysPm_ExecuteCallback() API. Because of the bug, the order in which the callbacks are registered are important. When ble_init is executed first, BLE deep sleep callback is registered first and then your callbacks. Since your callback executes on BEFORE_TRANSITION mode, it is remembered as the LastCallback in the Cy_SysPm_ExecuteCallback API before entering deep sleep. And after wake-up, the callbacks are executed from LastCallback to RootCallback. Since you deep sleep API was already registered as the last callback, the code works fine. However, when your callback is registered first, the code breaks as the LastCallback is your callback and that is the RootCallback too - the BLE deep sleep callbacks never get executed.

I am still not sure how this relates to the IPC interrupt - during my debug, I saw the interrupt getting triggered and showing up in the Pending state and never moving to the active state to execute the handler (which calls the IPC callback). Will do more investigation later.

For now, can you try the attached cy_syspm.c file and see if that fixes your issue?

View solution in original post

0 Likes
6 Replies
MeenakshiR_71
Employee
Employee
100 likes received 50 likes received 25 likes received

Hello Jefferson,

I was able to notice the issue and I am not really sure what is causing the issue but moving the "ble_init()" to before the first Cy_SysPm_RegisterCallback fixed the issue. I will investigate further and update - let me know if this fixes the issue at your end too.

Regards,

Meenakshi Sundaram R

0 Likes
lock attach
Attachments are accessible only for community members.
MeenakshiR_71
Employee
Employee
100 likes received 50 likes received 25 likes received

Seems like there is a corner case bug in our SysPm PDL's Cy_SysPm_ExecuteCallback() API. Because of the bug, the order in which the callbacks are registered are important. When ble_init is executed first, BLE deep sleep callback is registered first and then your callbacks. Since your callback executes on BEFORE_TRANSITION mode, it is remembered as the LastCallback in the Cy_SysPm_ExecuteCallback API before entering deep sleep. And after wake-up, the callbacks are executed from LastCallback to RootCallback. Since you deep sleep API was already registered as the last callback, the code works fine. However, when your callback is registered first, the code breaks as the LastCallback is your callback and that is the RootCallback too - the BLE deep sleep callbacks never get executed.

I am still not sure how this relates to the IPC interrupt - during my debug, I saw the interrupt getting triggered and showing up in the Pending state and never moving to the active state to execute the handler (which calls the IPC callback). Will do more investigation later.

For now, can you try the attached cy_syspm.c file and see if that fixes your issue?

0 Likes

Thanks.  This change fixed the problem.  I have another problem related to BLE and sleep.  In my app I set flags inside ISR and handle them in main loop.  I register sleep callbacks that check these flags.  If they are set in the CY_SYSPM_CHECK_READY event, I return CY_SYSPM_FAIL.  This method does not work with the current PM system.  The CY_SYSPM_CHECK_READY is done outside a critical section.  There can be many callbacks to make like BLE and UART and the interrupt can happen after my check was done.  Also the BLE callback seems to assume that it is the only PM callback that will ever be used.  It enters deep sleep at CY_SYSPM_CHECK_READY.  What about the other callbacks that can fail and abort deep sleep?  The BLE callback must be the last one called for it to work.

0 Likes

If you want the code in your callback to not get impacted by interrupts, then use the BEFORE_TRANSITION case. This case is after the DeepSleep API enters Critical section and no interrupts should be serviced during this.

BLE callback will put the BLESS to deep sleep or low power mode (if the BLESS is not active - like transmitting bytes) and that should not impact other code. The BLESS comes out of LPM automatically on a BLESS interrupt. In the DeepSleep API, even if one callback returns fail, the deep sleep will be aborted and callbacks that need to process that can use the FAIL case. BLESS does not need to process that as it puts only itself to LPM mode.

0 Likes

The BEFORE_TRANSITION case does not care about the return value so it will go to sleep afterwards even if my interrupt flag is set and I want to abort sleep.  I don't want to do all my processing with interrupts disabled because it can take a long time.  Does this mean I have to force trigger some interrupt in the callback to wake up immediately?

0 Likes

I see your issue. It seems like in this case, you will need to force trigger an interrupt in BEFORE_TRANSITION to wake up immediately. I will put this request to our SysPm driver dev team and will let you know what we can do in the future rev of the driver.

Regards,

Meenakshi Sundaram R

0 Likes