-
Notifications
You must be signed in to change notification settings - Fork 174
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
RMT Onewire Peripheral #454
Conversation
test commit 2 next device asd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this !
I left a couple notes, though overall i think first try to convince the CI, to let the project build for every target. If you succeeded at that point we can go into more details.
You also get one additional cfg flag that you can use to gate the complete onewire bus implementation. When the remote component is included in the build system it will make the following available #[cfg(ESP_IDF_COMP_ESPRESSIF__ONEWIRE_BUS_ENABLED)] (in rust its all in lower case though ;D ) |
@Vollbrecht I think I need to also prevent the component from being included if the esp-idf version is 4, is there a flag for that? |
Remove references to the ds18b20 specific device. Add a feature flag `rmt-legacy` that, when enabled, will build the original rmt modules from v4 of the esp-idf. When disabled, the v5 rmt interface can be used for one wire applications. Implement the Iterator trait for a device search and use the Iterator in the example.
Struggling to get the v4 builds to go, I feel like it's an issue in the component inclusion that needs to be feature gated for versions <4, but I'm not 100% sure how to do that. I've gotten the v5 builds working across the board though, and I've tested the code is functioning locally on my |
The core problem is that the external onewire_bus crate does not support esp-idf v4. And that is fine as we already deprecated the usage of such, so a new API doesn't need to also work there. It just shouldn't break the usage of the crate. The problem arises duo to you directly adding the onewire_bus inside the Cargo.toml of esp-idf-hal, and thous telling the buildsystem to include it, though it can not work with that crate version. The solution to the problem looks as follows. You are already using the cfg flag that is generated when With the inclusion of the headers in esp-idf-sys a user also will only need to add this:
and not specify any headers himself. For the example its a bit annoying. To run it you would have to provide a modified Cargo.toml that includes it only for that example. Annoying but well i think without using something different than cargo itself unavoidable. You can add instructions in the doc header of the example how to run that example. It would look like TLDR:
|
@Vollbrecht unfortunately we need both includes. I've made a PR into esp-idf-sys. esp-rs/esp-idf-sys#325. It does work with the code not inside a module. Are you against namespacing inside the bindings? |
I have an issue now in that the old RMT examples will never get compiled and may actually be broken. Perhaps we should add a CI stage to test with the |
its broken, because of the problem i stated in my last post. For idf v4 the old driver is always used, and don't need a flag because v4 only has the old driver. You can't include the onewire_bus inside v4, That's why it need to be moved from the esp-idf-hal |
gj making the first milestone -> getting CI green ;D I am a bit busy right now, but will have a closer look at the weekend and hope to have some more feedback by then. |
@Vollbrecht @DaneSlattery This had been going on for quite some time. I'm not sure in the meantime - is this ready for merge, and what (if any) are the outstanding issues? |
Hi @ivmarkov The build works and the code is tested. The outstanding items are this:
|
src/onewire.rs
Outdated
/// | ||
/// The pin will be used as an open drain output. | ||
pub fn new( | ||
pin: impl Peripheral<P = impl crate::gpio::InputPin + crate::gpio::OutputPin> + 'd, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since internally the ESP IDF onewire driver uses the new RMT driver (a single channel for TX/RX) (plus the pin thst you already track) you need to somehow track the usage of the RMT channel peripheral, as it is still a peripheral - just like the pin which you track already.
If you don't track it, nothing major would happen because the old and the new RMT driver cannot co-exist, yet would still be good to follow the pattern established with the other drivers.
Now, some of the "new" (ESP IDF 5+) C drivers no longer take a peripheral "id"/"number". For example, the old RMT driver used to take a channel number, but the new C RMT driver doesn't as it internally manages what channel to be used. If you try to instantiate more driver instances than hardware channels you have available, it would likely return a runtime EspError
. So in a way - with the new RMT C driver you don't really know which concrete hardware channel peripheral will be used by that particular C driver instance.
With that said, nothing stops us from continuing the old way and passing to the driver a RMT "peripheral" (note that you don't need "new" RMT channel peripherals for the new C RMT driver, because the peripherals are ghost structures which however model actual hardware on the chip and not higher-level C driver concepts).
So what I suggest is to just enhance the new
constructor by passing an impl ... Channel ...
peripheral that you can copy from the old RMT driver wrapper. While there is no warranty that the C driver will use exactly the same channel that you pass to it - we don't care, as the channels are indistinguishable from each other. We just use - with the new C driver - the channels as a way of glorified "reference counting" of sorts.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Just mentioning that this comment ^^^ is still valid.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I had planned to look into this. It becomes quite problematic as you mentioned below because I ifdef the whole rmt module.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well I would not call it "quite problematic". #ifdef-ing only the driver inside rmt
module is hopefully not a rocket science. Easiest way to do it is what I suggested for the examples:
- Define a
mod driver {}
internal module (not public) - inside thermt
module itself. no need for a separate file, just an inline module. - Move all code except the
peripheral!
peripherals' definitions as well as the RMT peripheral traits (if any) inside the driver module - Put a
cfg
on top of thedriver
module - Put a cfg-ed
pub use driver::*
in thermt
module
No big deal?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No big deal. It's done.
I think at least a sketch of how the read/write API is needed - and I would say - as part of this PR rather than as a follow-up PR, because - depending how RW works (would you place the read/write methods on the "device" structure or on the "bus" structure?) this leads to one or another design. The other big problem is how dynamic are the devices on the bus. Are they somehow static or can they come and go (say - by physically removing the device from the wire)? Even if they can come and go, how often does that happen? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DaneSlattery I think we are getting there!
I've left a lot of comments, but these I hope would be quite easy to fix, as the latest approach seems solid.
My biggest request is to remove OWDevice
completely, as I continue to fail to understand what purpose it serves? Please let me know if I'm missing something.
src/lib.rs
Outdated
#[cfg(all(feature = "rmt-legacy", esp_idf_comp_espressif__onewire_bus_enabled))] | ||
compile_error!("the onewire component cannot be used with the legacy rmt peripheral"); | ||
|
||
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This cannot be done so simply. As discussed during the previous iteration, you do need the RMT peripherals which are defined by the esp_idf_hal::rmt
module. And you need to pass a RMT channel to OWDriver
in addition to the pin. So you can't just #ifNdef
the rmt
module when the rmt-legacy
feature is not defined. What you need to do instead is to leave the rmt
module here unconditionally, and then - inside the rmt
module - protect with an #ifdef
all of the driver code, but leave the peripheral definitions always defined and valid - even when the legacy RMT driver is #ifNdef
-ed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/peripherals.rs
Outdated
@@ -10,6 +10,7 @@ use crate::mac; | |||
use crate::modem; | |||
#[cfg(any(esp32, esp32s2, esp32s3, esp32c6))] | |||
use crate::pcnt; | |||
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per above, remove the cfg
line. The code in the esp_idf_hal::rmt
module should be changed so that the RMT peripherals are always defined. Even if the legacy RMT driver is #ifNdef
-ed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/peripherals.rs
Outdated
@@ -71,6 +72,7 @@ pub struct Peripherals { | |||
pub ledc: ledc::LEDC, | |||
#[cfg(esp32)] | |||
pub hledc: ledc::HLEDC, | |||
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
src/peripherals.rs
Outdated
@@ -168,6 +170,7 @@ impl Peripherals { | |||
ledc: ledc::LEDC::new(), | |||
#[cfg(esp32)] | |||
hledc: ledc::HLEDC::new(), | |||
#[cfg(any(feature = "rmt-legacy", esp_idf_version_major = "4"))] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@DaneSlattery Unrelated to the implementation chosen in this PR, but people do seem to use UART successfully as well to implement onewire in hardware: https://developer.electricimp.com/resources/onewire Interesting! |
@DaneSlattery No rush, but wondering if you still plan to fix the remaining issues? |
Shall I again re-review? I see you have marked with "Done" most (if not all) of the outstanding issues? |
Actually, no - there are still unaddressed outstanding issues... |
Hi Ivmarkov.
I am happy for you to mark as accepted the tasks that were |
Np - take your time. I just wasn't sure what is the status quo, and as mentioned I somehow did not receive notifications for the already addressed tasks.
I just did - thanks! |
Moves the RMT driver into a private `driver` module, which will only be compiled in rmt-legacy mode. Also reduce the number of cfg feature flags in examples by wrapping the implementation in a module.
Done! I somehow don't think this CI failure is exactly my fault, not sure what's happening. |
Thanks for continue working on this! Yeah currently they broke nightly for all users that are using the build-std feature though it seams a patch fixing it was already merged. So should hopefully working again tommorow :D |
Yes let's wait until tmr when we would hopefully have a clean CI, which would ensure the latest changes in this PR do not introduce build errors we have to fix post-merge. |
Greeen! |
Thank you for your persistence through this exercise. Merging. Post merge, I might exchange the order of |
#445 related