Zephyr Power Management PM_STATE_SOFT_OFF

I am having trouble figuring out how to put system in PM_STATE_SOFT_OFF from inside workqueue. If I put system to sleep inside workqueue it does't go to sleep, looks like execution continues. How should I approach this problem?

void power_down(void) {
    pm_state_force(0u, &(struct pm_state_info){PM_STATE_SOFT_OFF, 0, 0});
    k_sleep(K_SECONDS(2U));
}

static void work_handler(struct k_work *work) {
    power_down();
}

void main(void) {
    k_work_init(&work, work_handler);
    k_work_submit(&work);
    while(1) {
		printk("Loop...\r\n");
	}
}

In current example the loop continues. If I replace k_work_submit with just direct power_down call then system goes to sleep and any execution stops.

Parents
  • Hello,

    Running a workqueue thread is not like just calling a function. It is spawning a separate thread. I would recommend reading the documentation about Workqueque Threads (and maybe threads in zephyr in general).

    The main() thread by default has the highest priority. More about that HERE
    Your workqueue thread will have lower priority and that's why it will not work.

    If you suspend the main thread, for example by running k_sleep(K_FOREVER); then your workqueue thread will run properly.
    You could also let the main() return.

    Also, the k_sleep in power_down will not work when run properly, since it happens after switching the state to PM_STATE_SOFT_OFF which equals to the SYSTEM OFF mode.

    Best regards,

    Michal

  • OK, I understand that, I have a battery gauge thats periodically checking battery level and if battery is low I need to shut down the system. Per driver documentation its best to have any trigger return through a workqueue. But it will never shut down. Should I just avoid using workqueue in driver trigger implementation then?

    As far as k_sleep in power_down, I am not sure why its there, thats how it is written in the SDK example so I figured it needs to be there.

Reply
  • OK, I understand that, I have a battery gauge thats periodically checking battery level and if battery is low I need to shut down the system. Per driver documentation its best to have any trigger return through a workqueue. But it will never shut down. Should I just avoid using workqueue in driver trigger implementation then?

    As far as k_sleep in power_down, I am not sure why its there, thats how it is written in the SDK example so I figured it needs to be there.

Children
Related