K_sleep from main function

Hi,

It seems like my system is crushing before going to deep sleep,

I have noticed that if I remove a k_sleep of 500 ms, just before going to deep sleep the system does not crush.

I was wondering if it is allowed to call k_sleep from main function. I know in other rtos is is not allowed since main is not running in a thread context. I would like to know if this the case in zephyr as well

Parents
  • Hi levijo,

    Calling k_sleep() in main() is fine. What kind of deep sleep are you talking about here? Do you have some code snippets?

    Hieu

  • Yes look below:

    The last k_sleep before sys_poweroff is the one I'm referring to

    enter_deep_sleep:
    
        if (exit_reason != SYSTEM_EXIT_CODE_RESTART_REQUIRED) {
            LOG_WRN("entering deep sleep ...");
    
            if (IS_ENABLED(CONFIG_APP_HAL_REGULATOR)) {
                hal_regulator_exit();
            }
    
    #if DT_NODE_HAS_STATUS(DT_INST(0, nordic_qspi_nor), okay)
            const struct device *const qspi_device = DEVICE_DT_GET(DT_INST(0, nordic_qspi_nor));
            if (device_is_ready(qspi_device)) {
                if (pm_device_action_run(qspi_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                    LOG_WRN("could not suspend nordic qspi");
                }
            }
    #endif
    
            if (IS_ENABLED(CONFIG_I2C)) {
                const struct device *const i2c_device = DEVICE_DT_GET(DT_NODELABEL(i2c1));
    
                if (device_is_ready(i2c_device)) {
                    if (pm_device_action_run(i2c_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                        LOG_WRN("could not suspend i2c1");
                    }
                }
            }
    
            if (IS_ENABLED(CONFIG_SERIAL)) {
                const struct device *const serial_device = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    
                if (device_is_ready(serial_device)) {
                    if (pm_device_action_run(serial_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                        LOG_WRN("could not suspend serial console");
                    }
                }
            }
    
            /* put the system in deep sleep */
            k_sleep(K_MSEC(500));
    
            sys_poweroff();
     

  • Could you please clarify how the system crashed? How is it different from if there is no k_sleep()?

    I have put device into System OFF right after k_sleep() before, and the system worked as expected. Right now, I unfortunately don't have access to a nRF5340 DK to try with, but I tried your code on a nRF54L15, and the system goes into System OFF, and wake up from that correctly.

    I am a little unclear about the purpose of the hal_regulator_exit() call. Could you please let me know what you aim to do here?

  • I realize that probably removing of the k_sleep() doesn't fix the problem but somehow avoid it.

    Here is some more information:

    before going to sleep I turned off the BLE, and get the following warnings:

    [00:01:00.899,749] <inf> led_module: got default LED state update event: 8
    [00:01:00.907,073] <inf> ble_nus_service: BLE TX thread terminating
    [00:01:00.913,757] <inf> ble_nus_service: BLE RX thread terminating
    [00metal: warning: tx_vq: freeing non-empty virtqueue
    metal: warning: rx_vq: freeing non-empty virtqueue
    [00:01:00.930,847] <inf> ble_nus_service: BLE service stopped
    [00:01:00.936,981] <wrn> main: entering deep sleep ...

    what does freeing non-emtpy virtqueue mean?

  • I have been trying to look into this error but find very few mentions and no meaningful lead so far.

    How did you turn off BLE? And what nRF Connect SDK version are you using?

  • Hi,

    I have found the root cause, it was a bug in our code,

    Thank you for your support,

Reply Children
  • It's great that you have it working. Records about that warning message is pretty scarce, so if you can, please share what you have found with the community.

  • The process of shutting down the system (entering deep sleep):

    enter_deep_sleep:
    
        if (exit_reason != SYSTEM_EXIT_CODE_RESTART_REQUIRED) {
            LOG_WRN("entering deep sleep ...");
    
            if (IS_ENABLED(CONFIG_APP_HAL_REGULATOR)) {
                hal_regulator_exit();
            }
    
    #if DT_NODE_HAS_STATUS(DT_INST(0, nordic_qspi_nor), okay)
            const struct device *const qspi_device = DEVICE_DT_GET(DT_INST(0, nordic_qspi_nor));
            if (device_is_ready(qspi_device)) {
                if (pm_device_action_run(qspi_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                    LOG_WRN("could not suspend nordic qspi");
                }
            }
    #endif
    
            if (IS_ENABLED(CONFIG_I2C)) {
                const struct device *const i2c_device = DEVICE_DT_GET(DT_NODELABEL(i2c1));
    
                if (device_is_ready(i2c_device)) {
                    if (pm_device_action_run(i2c_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                        LOG_WRN("could not suspend i2c1");
                    }
                }
            }
    
            if (IS_ENABLED(CONFIG_SERIAL)) {
                const struct device *const serial_device = DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
    
                if (device_is_ready(serial_device)) {
                    if (pm_device_action_run(serial_device, PM_DEVICE_ACTION_SUSPEND) < 0) {
                        LOG_WRN("could not suspend serial console");
                    }
                }
            }
    
            /* put the system in deep sleep */
            k_sleep(K_MSEC(500));
    
            sys_poweroff();

    1. suspending QSPI

    2. 500 ms delay

    3. another task tries to write to flash (using QSPI) - causing a crush

    I have moved the delay to be before suspending the QSPI and problem solved

Related