Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix racing issue for SAMD when executing WFI #2956

Merged
merged 1 commit into from
May 26, 2020

Conversation

hathach
Copy link
Member

@hathach hathach commented May 25, 2020

fix #2912 and/or other "slow responses" with USB after low power PR. It is basically the same as #2868 for nRF. There is lots of discussion there, I will sum it up here. Following is the racing.

  1. USB Interrupt handler is complete and submitted to the event queue of TinyUSB task
  2. WFI happens
  3. Since tud_task() isn't called yet to response, there is no more USB event. CPU has a good full sleep of N seconds.
  4. WFI end, tud_task() is called to handle usb events

It is the racing between usb isr -> event queue -> tud_task() handling and WFI.
Note: this is NOT what we want to do, we don't want to sleep while there are USB events in the queue and host is waiting --> therefore we must make sure all the usb events in the queue task are processed before executing WFI. That's way when there is a new request (IN/OUT) from host, we could wake up and handle.

Following is reference to other platform implementation of WFI, disabling interrupt and DSB is mostly required.

Yeah, I did a bit of research it is advisable prat to disable the interrupt before WFI() to avoid race condition. WFI() doesn't require interrupt enabled to wake CPU. It is best practice to also all DSB() before WFI() as well according to ARM docs. Here is the implementation of zephyr

https://github.com/zephyrproject-rtos/zephyr/blob/master/arch/arm/core/aarch32/cpu_idle.S#L75

another reference from freeRTOS tickless mode, which do the same as this function
https://github.com/FreeRTOS/FreeRTOS-Kernel/blob/master/portable/GCC/ARM_CM4F/port.c#L510

There is a other useful doc from mbed as well.
https://os.mbed.com/media/uploads/pateshian/wfi_wake_up_from_sleep_11_17_2016_.pdf (D_SLEEP_VERSION == 2)

Originally posted by @hathach in https://github.com/_render_node/MDIzOlB1bGxSZXF1ZXN0UmV2aWV3VGhyZWFkMjY2MTQxNzg4OnYy/pull_request_review_threads/discussion

@hathach hathach requested review from tannewt and dhalbert May 25, 2020 14:13
@@ -496,7 +497,12 @@ void port_sleep_until_interrupt(void) {
(void) __get_FPSCR();
}
#endif
__WFI();
common_hal_mcu_disable_interrupts();
if (!tud_task_event_ready()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tannewt Are there more cases here when we wouldn't want to go into WFI? Other pending tasks? This relates to trying to redo the background task stuff to add flags to indicate pending work.

But I think this is a good change for now to get things working better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not that I can think of immediately. We should rethink it with the background work.

Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the fix! We should make sure and update other ports too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

time.sleep() in code.py prevents USB from working
3 participants