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

ports/esp32/machine_timer.c: Solves #4078, ESP32 timer reinitilization error #4811

Conversation

dybber
Copy link
Contributor

@dybber dybber commented May 24, 2019

Solves the problem where multiple calls to machine.Timer.init() causes an OSError 261 on ESP32 boards.

The fix is explained here: espressif/arduino-esp32#1869 (comment)

Solves issue #4078.

@dpgeorge
Copy link
Member

Thanks for the patch, but I'm not sure it's the right way to solve that issue of error 261. Active timers are put on a linked list (on the MicroPython side) and if you create a timer twice then it'll be placed twice on this list. I think it would be better to check for an existing timer on the list when creating one, and reuse it if found.

@dybber
Copy link
Contributor Author

dybber commented May 25, 2019

Oh yes, didn't actually think of that! But now when checking the code, I don't believe that's the case.

The init function calls machine_timer_disable which removes the existing timer from the list, before changing parameters and reenabling it.

https://github.com/micropython/micropython/blob/master/ports/esp32/machine_timer.c#L179

@dpgeorge
Copy link
Member

The init function calls machine_timer_disable which removes the existing timer from the list, before changing parameters and reenabling it.

But that doesn't stop there being multiple instances of Timer all pointing to the same underlying hardware resource, because these multiple Timer instances are distinct pointers to the MicroPython heap.

@dybber
Copy link
Contributor Author

dybber commented May 27, 2019

Okay, I see. I can implement a reference counting solution. Just as a sanity check before I start, do you think the following would be a suitable solution:

  • Timer's are added to the list already in the Timer constructor, not by the .init() method, if added twice reference counter is increased and the existing timer returned.
  • Timer's are stopped started by .init() / .deinit() method, but does not alter the list
  • Timer's are removed from the list in __del__ (or -1 ref count)

Btw. I still believe the flags in the patch are necessary though, to solve the problem that occurs in programs such as this, which also raises OSError 261:

timer0 = Timer(0)
timer0.init(period=1000, mode=Timer.PERIODIC, callback=my_callback)
timer0.deinit()
timer0.init(period=1000, mode=Timer.PERIODIC, callback=my_callback)

@dpgeorge
Copy link
Member

I can implement a reference counting solution.

I don't think it needs that. There are only 4 timers in total so just keeping them in the link list forever after creation is fine (until soft reset, via machine_timer_deinit_all()). Adding them to the list in the constructor sounds good.

I still believe the flags in the patch are necessary though, to solve the problem that occurs in programs such as this, which also raises OSError 261

That particular code runs fine for me, no error.

The patch solves the problem where multiple Timer
objects (e.g. multiple Timer(0) instances) could initialize multiple
handles to the same internal timer. The list of timers is now
maintained not for "active" timers (where init is called), but for all
timers created. The timers are only removed from the list of timers on
soft-reset (machine_timer_deinit_all).
@dybber
Copy link
Contributor Author

dybber commented May 28, 2019

Okay, check the latest commit.

You are right, the flags are not necessary. The example raising OSError 261 above only appeared when re-executing the code after a soft-reboot, however, it works now without the flags.

@dpgeorge
Copy link
Member

Thank you! Merged in de76f73

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.

None yet

2 participants