Stuck waiting for BB low power clock when entering sleep

Hello!

I have an application that is mostly working with Bluetooth and sleep mode, however, sometimes the BB fails to switch over to the low power clock and is stuck in Sys_PowerModes_Sleep() function until some kind of watchdog restarts the system after ~30s:

    /* Wait until the baseband has switched to the low power clock */
    while (BBIF_STATUS->CLK_STATUS_ALIAS == MASTER_CLK_BITBAND);

This function is called from BLE_Power_Mode_Enter().

The sleep is working fine for some hours, the device periodically wakes up to send advertisements and do other app specific function, but then it gets stuck. I have based my project on peripheral_server_hrp_fota_sleep example code.

If I read/write BLE characteristics continuously (from a script) I it gets stuck here after only few minutes of operation.

1 Like

Hello,

Thanks for reaching out to us! I will take a look into that function to see if I can find any clues. If you would like to share your project I can take a closer look at what is happening in your case.

Hi!
Unfortunately I am not able to share our project. I will try to isolate the problem to a smaller shareable project that runs on a devkit.

In the meantime, could you please describe the events/dependencies, that are preventing the BB to switch over to the low power clock? Perhaps there are BB/BBIF register values that are worth sharing?

Hello,
Not a problem, feel free to share only what you are comfortable with.
If you take a look at our sample code “peripheral_server_sleep”, we have included this check before attempting to power down the device.

        /* If not in the middle of a period measurement for RSOSC, allow the
         * application to go to sleep power mode. */
        if (low_power_clk_param.low_power_enable ||
            (RTC_CLK_SRC == RTC_CLK_SRC_XTAL32K))
        {
            Sys_DIO_Config(LED_DIO, DIO_MODE_GPIO_OUT_0);

            GLOBAL_INT_DISABLE();
            BLE_Power_Mode_Enter(&sleep_mode_env, POWER_MODE_SLEEP);
            GLOBAL_INT_RESTORE();
        }

Did you include this in your code?

Hi,
No, I do not have this check, because I only use 32kHz external crystal for RTC. It reports working fine when the problem occurs:
image

Hi Gotlaufs,
The only dependency I can find related to the Sys_PowerModes_Sleep()is to ensure that DMA0 is available and ready, so the BB settings can be stored there during sleep. However, this should be covered by the line of code just above where you are getting stuck;

    /* Wait until DMA is completed */
    while (DMA_CTRL0->ENABLE_ALIAS);

Do you have any peripherals that are using DMA0 during wake-time? If so, you may need to take efforts to disable it before going to sleep.

Hi,
No I am not using any DMAs in my application.

I noticed, that when the hang occurs, the SYSCLK source is already RC osc and the radio is already disabled (RF_POWER_DISABLE). That implies that the system is sometimes not executing wakeup code.

If I insert something like:

    /* Wait for interrupt */
    SYS_WAIT_FOR_INTERRUPT;
    while (stayHere) {
        __NOP();
    }

in rsl10_sys_power_modes.c at the end of Sys_PowerModes_Sleep(), it is reached after some minutes of heavy BLE operation.

I have tried manually checking RF state (if it enabled) right after enter_sleep_asm():

        enter_sleep_asm();
        if(SYSCTRL_RF_POWER_CFG->RF_POWER_ALIAS == RF_POWER_DISABLE_BITBAND) {
          // Looks like wakeup routine was not called properly
          Wakeup_From_Sleep_Application();
        }

This (hack) appears to solve my problem.

What can cause the CPU to not power down properly and return from Sys_PowerModes_Sleep()?

I am happy to hear you were able to find a suitable workaround!
Were you able to create a shareable version of your project? It would help me to know what areas to focus on when looking into the root issue. I would love to try and re-create the issue if possible.

Unfortunately I do not have the time right now to create a shareable project.

I will try to do it next week

Please let me know, and I will be happy to take a look at it.

Hello!
While experimenting I think I’ve found the root cause of this issue. My application uses peripherals with interrupts and some of the interrupt lines were left enabled or pending when entering sleep. The Cortex-M CPU may not go into sleep on such condition. When I disabled and cleared pending status from all interrupts I no longer can reproduce the problem.

I also noticed, that all of the BLE interrupts remain enabled in the example applications with sleep. Is there some “special” handling procedure that they do not cause issues with sleep?

It would be very helpful if the sleep enter routine would either refuse to enter sleep with pending/enabled interrupts or recover if WFI instruction is not executed, because now the FW will crash, because all the BLE HW is deinitialized just before entering sleep.

3 Likes

That is great news!
I will take a look at our sleep application example. It sounds like it could be missing a check before entering sleep, but your suggestion is a good solution that would make that unnecessary.
Thank you for taking the time to let us know.

1 Like

Hello!

I don’t see this message on the forum, so I’m replying here.

I have based the project on ble_peripheral_server_hrp_fota_sleep example, but it is since heavily modified.

I have custom sleep enter/exit routines that enable returning in place instead of calling MainLoop() function and the problem was that I did not disable all (app) interrupt sources.

It would be nice if there was a check in sleep entry function for enabled interrupts.

1 Like

Hi Gotlaufs,
Sorry for the confusion, I deleted my last question after I re-read your initial comment and saw you had already mentioned it.
I reviewed the example with our design team, and It doesn’t look like anything is missing in this case. This example doesn’t include any external interrupts, so we did not need to included any way to handle them.
Because this issue is not unique to the sleep function, they feel it isn’t necessary to add a check to it.
Thank you again for your excellent feedback.

1 Like

Hello!

What I meant by It would be nice if there was a check in sleep entry function for enabled interrupts. was that this check could be included in the HAL code, perhaps in BLE_Power_Mode_Enter() function.

Understood. Thank you for your feedback!