esp-rs / esp32-hal

A hardware abstraction layer for the esp32 written in Rust.
Apache License 2.0
192 stars 28 forks source link

Added clock control and serial modules #11

Closed arjanmels closed 4 years ago

arjanmels commented 4 years ago

This pull request includes a clock_control, dport and serial peripheral. Also included are two examples (basic serial, and clock control).

In its current state it allows switching clock frequency on the esp32 between Xtal, PLL and internal 8.5MHz clock. Also calculates the CPU, APB, Ref clock and source.

For clock switching the approach used by esp-idf is followed and both locking mechanism (for Dynamic Clock Switching and callbacks are implemented).

It support serial input and output at programmable baudrate.

jeandudey commented 4 years ago

I thought about the clock switching too, it's hard to get it right. My thinking about it was that peripherals (and sometimes user code) needs to be informed about clock changes.

Callback mechanism: when clocks change a callback in peripheral drivers is called, allowing them to update state

This introduces another problem for example I2C, that to calculate frequency there are higher and lower bounds for the APB frequency, an update could result in an invalid setting or defaulting to another frequency (min or max) without the user of the HAL getting knowledge of it.

A locking mechanism like used in the esp-idf: when a peripheral needs a fixed clock it acquires a lock . When no locks are acquired the clocks can be dynamically scaled for lower power consumption

This might be a good alternative, since when the peripheral ends using the fixed clock it needs, the clock can go back to the previous configuration.


I haven't tested the code yet on real hardware, I'm trying to get a working rustc for Xtensa. This is really good work.

jeandudey commented 4 years ago

What about splitting the PR into smaller chunks? For example, the watchdog module seems like a pretty good candidate, and might get tested and merged more easily.

arjanmels commented 4 years ago

@jeandudey You confirm my thinking on the clock, so as primary measure a locking mechanism it will be. I probably still will implement a callback for good measure. This will take me some time, because I am still learning rust and finding a good way to have things work with the borrow system (safe, but still usable), is still a struggle for me.

I will first work on getting the PLL started, just because this is good fun.

Once these are done, I will indeed start thinking of how to subdivide the commits. Splitting of the watchdog is currently none trivial, because it is create by clock_control. My current proposal would be: 1) clock_control + watchdog, 2) serial 3) examples. Again feedback is welcome.

BTW I do my testing on Adafruit Huzzah32 board, but I also have some TTGO cheap chinese boards. For rustc I simply followed the instructions on: https://github.com/MabezDev/rust-xtensa for linux, worked like a breeze for me (after I increased Memory on my VM to 16GB form 4GB that is).

arjanmels commented 4 years ago

Ok, got the PLL running. At the moment still using a call into a ROM routine to send some commands on an internal I2C bus. (planning to reimplement this in rust). Also improved structure of initializing and getting the various structures, but this is work in progress towards outline for dynamic frequency switching.

arjanmels commented 4 years ago

I tried (see comments on rom.rs), but was not able to get it working. Hence this workaround. However I intend to reimplement the rom routine in rust anyway, so then this can be removed again.

Gasper commented 4 years ago

Just FYI, I've been using Serial from your feature-uart branch for about a week now on both, some simple aliexpress board as well as QEMU. I'll try these latest changes when I get the chance. I could only get UART0 working so far, but I assume this is expected?

arjanmels commented 4 years ago

@Gasper Thanks for the feedback. I was indeed focusing on uart0. The most recent commits, should also support uart1 & 2 on the default pins, but I have not tested this.

arjanmels commented 4 years ago

Dynamic Frequency Shifting is working! Callbacks are working, but require function/closure with static lifetime, so limited flexibility. Help from somebody with more experience in rust is welcome here.

Next is a bit of cleanup and then need to think how to divide this up in manageable pull requests. @MabezDev @jeandudey your thoughts on this are welcome. What is you preference? One big pull request (easiest for me), or a couple of separate ones. What I propose: 1) updated flash script, license and README.md 2) clock_control +dport module 3) serial module 4) examples.

Gasper commented 4 years ago

@arjanmels I tested the latest code today, the serial example, as it is, but I couldn't get it to print anything human-readable... should it be working at the moment? It is clear that it is printing something, and I played with various baud rates and other properties, but no luck. The version that I've been using so far (ccdcbcd) is working as usual. I can poke around a little bit, do a git bisect maybe, but wanted to check with you first that this current version is fine

I'm looking forward for this to get merged!

arjanmels commented 4 years ago

Still WIP, so could be broken, will checkin tested version this weekend. (At the moment i an mainly using Uber rtccntrl sample)

arjanmels commented 4 years ago

I think this is ready for review and merge. I merged the latest baseline changes and all 3 examples are working for me (after modifying the pin to which the led is connected).

Review, testing and then merging would be much appreciated.

arjanmels commented 4 years ago

Option to override the xtal frequency was missing.

Gasper commented 4 years ago

That's awesome, I was playing with it yesterday, and everything I tried worked fine. I haven't reviewed the code though, I'm hoping someone who is expert at Rust/embedded will find time... otherwise I can try to dig into it, but it will take a bit

arjanmels commented 4 years ago

I found out I needed to fix/improve 8MHz clock enable/disable when playing with using the default esp-idf bootloader.

MabezDev commented 4 years ago

Just nitpicking, haven't tested yet, my machine blows when trying to compile rustc

@jeandudey what OS? If you're running linux, I could send you an already built toolchain, if you'd like?

jeandudey commented 4 years ago

@MabezDev Ubuntu 18.04, x86_64, would love to test :raised_hands:

arjanmels commented 4 years ago

@jeandudey. I packaged my built on ubuntu 19.10 x86_64. Not certain this works, but you might give it a try: https://drive.google.com/open?id=1tkoS_m5QQfi9FJrtilvXr3wvINIgN9Ff https://drive.google.com/open?id=1IK0xZ_vITsR_BoNgOzdAn-kAFmd04pxw

arjanmels commented 4 years ago

Added suppression of warnings so library builds cleanly (which are there because of TODO's in follow up pulls to extend functionality).

MabezDev commented 4 years ago

Thanks for the awesome work @arjanmels! And thanks for the testing and reviews @jeandudey & @Gasper. Very excited to see this merged!