Closed japaric closed 4 years ago
I can probably help porting some NRF51/NRF52 drivers from TockOS that I have been involved in. I think the BLE driver could be interesting to have in a separate crate.
Let me know if you think it is a good idea!
I'm going to look at my Raspberry Pi SenseHat crate and my LM4F120 chip crate, as used by the Stellaris Launchpad, as soon as I can.
If TockOS starts using this HAL internally then new chip support should be easier to add in the future. I found the LM4F120 port fairly hard going.
If I find time I could try to do a DS18B20 (dallas one-wire) temperature sensor driver implementation.
Current stumbling blocks so far (I'm developing on the LPC11UXX):
(In both cases, what @rnestler wrote)
I've tons of devices at hand and I might write drivers for them but first I need to get the device crates and HALs up to snuff.
Apart from the usual Serial/I2C/SPI suspects what I'd like to see is whether the HAL approach is also viable for bit-banged GPIO, potentially even timing critical devices, some of which are also in @japaric's list, like the Neopixels. Something that would be really killer to have is support for multiplexed and charlieplexed LED matrices.
If TockOS starts using this HAL internally then new chip support should be easier to add in the future. I found the LM4F120 port fairly hard going.
I'd personally be highly supportive of that, but would need some convincing that it would fit the capsule architecture (that hasn't seemed to be the case for previous iterations). Perhaps @niklasad1 can report some insights if he ports his BLE stack from Tock.
@japaric Is there going to be a registry for embedded stuff and especially drivers? crates.io is becoming more and more useless to find interesting crates...
The LM4F120 crate now implements embedded_hal::serial::{Read, Write}
. It was pretty straightforward.
@niklasad1
Let me know if you think it is a good idea!
More drivers is a good idea, IMO. :-)
porting some NRF51/NRF52 drivers
Just to clarify: Is this driver about interfacing an external pre-flashed nRF5x device, or is it some BleRadio
trait on top of which a generic BLE stack con be built? In the later case you implement the BleRadio
trait for, say, a nrf51
device crate and you get a BLE stack for free (ideally).
@therealprof
I'd like to see is whether the HAL approach is also viable for bit-banged GPIO
At the very least we'll want to add a digital::OutputPort
trait whose API changes the state of a whole port (8 or 16 pins) atomically (single register op). And maybe another trait to change the state of N pins that belong to the same port atomically.
potentially even timing critical devices, ..., like the Neopixels
The words Neopixels and bit banging reminded me of an Arduino library I saw. It implemented the protocol using assembly and was fully blocking (nop
delays) to meet the timing constraints. I hope that our neopixels driver provides a DMA based (asynchronous) mode, apart from a bit banged mode.
Is there going to be a registry for embedded stuff and especially drivers?
I meant to include this in the issue description: I'm using the embedded-hal keyword for my driver crates. That makes them easier to find. Perhaps we can just use crates.io and keywords instead of creating another registry / list. We can bikeshed the keywords to use in this thread: perhaps embedded-hal
(or embedded-hal-driver
) for the driver crates, embedded-hal-impl
for the HAL impl crates, like the stm32f30x-hal crate, and svd2rust
for the svd2rust generated device crates?
@japaric
Just to clarify: Is this driver about interfacing an external pre-flashed nRF5x device, or is it some BleRadio trait on top of which a generic BLE stack con be built? In the later case you implement the BleRadio trait for, say, a nrf51 device crate and you get a BLE stack for free (ideally).
Coincidentally I'm working on a micro:bit crate (which is based on the NRF51822, as I'm pretty sure you're aware of 😉). I planned on adapting the BLE code from the Zephyr project, since Nordic is quite active there providing a BLE implementation for their devices without the humongous softdevice blob.
It's not quite ready for primetime yet since the documentation is somewhat lacking and reversing Zephyr somewhat time consuming due to the many layers of abstraction and indirection.
But your recent work and post kind of beat me to adapting what I have to the new singleton approach and also use the embedded-hal (which I previously haven't), so I'm trying to put some more time in.
At the very least we'll want to add a digital::OutputPort trait whose API changes the state of a whole port (8 or 16 pins) atomically (single register op). And maybe another trait to change the state of N pins that belong to the same port atomically.
Yeah, that's going to be interesting. But the reason I mentioned this is that there somehow (and I'm not sure what this will might look like just yet) should be a way to facility the required high speed updates.
The words Neopixels and bit banging reminded me of an Arduino library I saw. It implemented the protocol using assembly and was fully blocking (nop delays) to meet the timing constraints. I hope that our neopixels driver provides a DMA based (asynchronous) mode, apart from a bit banged mode.
Some of those WS controllers can be driven by abused SPI peripherals provided by some MCUs but that can't be taken for granted. AFAIR that doesn't work on the RasPi and that one also cannot do the required timing via bitbanging the GPIOs.
I meant to include this in the issue description: I'm using the embedded-hal keyword for my driver crates. That makes them easier to find. Perhaps we can just use crates.io and keywords instead of creating another registry / list. We can bikeshed the keywords to use in this thread: perhaps embedded-hal (or embedded-hal-driver) for the driver crates, embedded-hal-impl for the HAL impl crates, like the stm32f30x-hal crate, and svd2rust for the svd2rust generated device crates?
That might work but has quite a number of disadvantages:
crates.io is okay for larger std crates but for the hundreds or even thousands of embedded crates we're going to have, this is going nowhere fast... Originally I was counting on japaric.io or rust-embedded becoming the authoritative source for everything embedded in Rust but somehow this didn't quite happen. ;)
My hopes are still that we can establish a lively community around those topics, with a comprehensive catalog of relevant crates (architectural, register mapping, MCU HAL, peripheral HAL, BSP and specific implementations), articles on the use of any of that and general development topics, guides for embedded Rust development and support (development tools and debugging software/hardware to use) and potentially even general MCU howtos (selecting and connecting peripherals to an MCU, developing your own hardware...)...
Greetings,
Another open source nrf ble stack to check out is mynewt's nimble, which is the rtos im currently using in my daily work. https://github.com/apache/mynewt-core/tree/master/net/nimble
Im hoping to try out rust for the first time, and ble on the microbit would be a great reason for me to finally dig in as 'full' functionality (bootloading over ble mainly) on nrf51822 devices is tough to come by with every other rtos out there due to the low memory. Curious how rust could stand up.
This is much futher out there, but the bootloader zephyr and mynewt team are collaborating on is called mcuboot. It would be pretty cool to support that, allowing people to transition devices away from zephyr/mynewt into a rust rtos. https://github.com/runtimeco/mcuboot/
For now Im quietly lurking and watching you all. Keep up the great work
On Thu, Jan 18, 2018 at 6:03 PM, Daniel Egger notifications@github.com wrote:
@japaric https://github.com/japaric
Just to clarify: Is this driver about interfacing an external pre-flashed nRF5x device, or is it some BleRadio trait on top of which a generic BLE stack con be built? In the later case you implement the BleRadio trait for, say, a nrf51 device crate and you get a BLE stack for free (ideally).
Coincidentally I'm working on a micro:bit crate (which is based on the NRF51822, as I'm pretty sure you're aware of 😉). I planned on adapting the BLE code from the Zephyr project, since Nordic is quite active there providing a BLE implementation for their devices without the humongous softdevice blob.
It's not quite ready for primetime yet since the documentation is somewhat lacking and reversing Zephyr somewhat time consuming due to the many layers of abstraction and indirection.
But your recent work and post kind of beat me to adapting what I have to the new singleton approach and also use the embedded-hal (which I previously haven't), so I'm trying to put some more time in.
At the very least we'll want to add a digital::OutputPort trait whose API changes the state of a whole port (8 or 16 pins) atomically (single register op). And maybe another trait to change the state of N pins that belong to the same port atomically.
Yeah, that's going to be interesting. But the reason I mentioned this is that there somehow (and I'm not sure what this will might look like just yet) should be a way to facility the required high speed updates.
The words Neopixels and bit banging reminded me of an Arduino library I saw. It implemented the protocol using assembly and was fully blocking (nop delays) to meet the timing constraints. I hope that our neopixels driver provides a DMA based (asynchronous) mode, apart from a bit banged mode.
Some of those WS controllers can be driven by abused SPI peripherals provided by some MCUs but that can't be taken for granted. AFAIR that doesn't work on the RasPi and that one also cannot do the required timing via bitbanging the GPIOs.
I meant to include this in the issue description: I'm using the embedded-hal keyword for my driver crates. That makes them easier to find. Perhaps we can just use crates.io and keywords instead of creating another registry / list. We can bikeshed the keywords to use in this thread: perhaps embedded-hal (or embedded-hal-driver) for the driver crates, embedded-hal-impl for the HAL impl crates, like the stm32f30x-hal crate, and svd2rust for the svd2rust generated device crates?
That might work but has quite a number of disadvantages:
- It relies on people knowing how to correctly tag the crates and actually do it
- crates.io doesn't tracking of crates so one doesn't get notified about new crates of interest or updates
- The quality of the entries varies a lot and investigating potentially relevant crates consumes a lot of time with a strong tendency to becoming even worse
- The amount of search results is often overwhelming and there's virtually no support narrow down the search. Just for fun I just tried this query https://crates.io/search?q=embedded&sort= and I didn't find the result very encouraging...
crates.io is okay for larger std crates but for the hundreds or even thousands of embedded crates we're going to have, this is going nowhere fast... Originally I was counting on japaric.io http://blog.japaric.io/ or rust-embedded http://www.rust-embedded.org/ becoming the authoritative source for everything embedded in Rust but somehow this didn't quite happen. ;)
My hopes are still that we can establish a lively community around those topics, with a comprehensive catalog of relevant crates (architectural, register mapping, MCU HAL, peripheral HAL, BSP and specific implementations), articles on the use of any of that and general development topics, guides for embedded Rust development and support (development tools and debugging software/hardware to use) and potentially even general MCU howtos (selecting and connecting peripherals to an MCU, developing your own hardware...)...
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/rust-embedded/rfcs/issues/39#issuecomment-358833981, or mute the thread https://github.com/notifications/unsubscribe-auth/AAb0dPHuDDZgZCXBl3-PWRaJb2VPGVj_ks5tL-nugaJpZM4RiLZg .
@jacobrosenthal
Another open source nrf ble stack to check out is mynewt's nimble, which is the rtos im currently using in my daily work. https://github.com/apache/mynewt-core/tree/master/net/nimble
I am aware, I tried everything I could find for that MCU, including (but not limited to) Mynewt, RIOT and Zephyr. Most ecosystems rely on the softdevice while some others provide their own (but often very limited) BLE stack. The Zephyr stack is written by the vendor Nordic themself and has been certified so it is known to be feature complete and (somewhat) correct.
Im hoping to try out rust for the first time, and ble on the microbit would be a great reason for me to finally dig in as 'full' functionality (bootloading over ble mainly) on nrf51822 devices is tough to come by with every other rtos out there due to the low memory. Curious how rust could stand up.
Rust allows for ridiculously small firmwares on those MCUs (compared to other ecosystems that is) so I'm confident that there won't be any space issues per se. Of course if you add a BLE capable bootloader for DFU that whole situation changes a good deal because that will take a sizeable amount of flash by itself. I wouldn't hold my breath for that to materialize. ;)
Bootloaders don't have a very high priority for me at the moment but adding support for mcuboot might be straight forward. Question is what the benefits would be, especially on the micro:bit but I'll have a look, thanks.
Rust allows for ridiculously small firmwares on those MCUs (compared to other ecosystems that is) so I'm confident that there won't be any space issues per se.
Is that really true? The generated format!
code is very bloated, for example, with its myriad of vtables, tables, floating point...
@whitequark
Is that really true? The generated format! code is very bloated, for example, with its myriad of vtables, tables, floating point...
That's true, format!
is relatively expensive due to the incapability to properly see the used types and monomorphize; however (unless there's another bug I'm not aware of, not using format!
too much in my code) it should be a one-time overhead which is comparable to printf()
formatting in C and no-one forces you to use formatters; outputting strings using write_str()
as well as "manually" formatting numbers e.g. using the NumToA crate.
Here I have an example rendering a counter triggered by USART input onto an I2C driven SSD1306 OLED display:
File .text Size Name 0.2% 28.4% 604B USART1 0.2% 26.5% 564B main 0.1% 17.9% 380B [41 Others] 0.1% 11.3% 240B compiler_builtins::int::udiv::udivsi3 0.0% 5.5% 116B i2c_ssd1306::ssd1306_print_bytes 0.0% 3.9% 84B stm32f042::peripherals::i2c::write_data 0.0% 3.0% 64B cortex_m_rt::reset_handler 0.0% 1.4% 30B udivmodsi4 0.0% 0.8% 18B aeabi_memcpy 0.0% 0.8% 18B aeabi_uidivmod 0.0% 0.5% 10B __aeabi_uidiv 0.7% 100.0% 2.1KiB .text section size, the file size is 310.9KiB
This (a bit older example) includes write_str
use and an implementation on the serial port and an somewhat similar implementation for the display rendering...
I have both an HC05 and HC06 pair and a tricolour e-ink display. I should be able to start work on these pretty soon.
I already have (incomplete) PN532
Rust implementation based on i2cdev
crate. I'd love to adapt it to HAL, but I don't expect to have time soon. In case anyone else wants to do it, I'm willing to help.
@whitequark, @therealprof check out fast_fmt
crate. It was specifically designed to avoid this overhead.
@Kixunil any documentation would be helpful.
would be great to have USB support, i.e. some library interfacing for instance FTDI chips. seems like tock os got some generic USB code.
@mneumann Not sure I follow. Why would you use an USB<->Serial interface? Some MCUs have USB peripherals built-in but providing an HAL for creating an USB endpoint is a somewhat complex and very specific.
@therealprof : if the MCU has a built-in USB peripheral then I'd of course use that, given that it's easy to use from Rust ;-). But those devices I have at hand, need an external USB chip. Regardless of whether it's on or off-chip, I'd love to be able to use USB from Rust. This is just the last (big) missing piece to make use of Rust on embedded for me.
@mneumann There's a couple of posts about implementing USB Serial in Rust here, but the series is unfinished.
I have created a separate issue for tracking progress on a generic USB stack: #40. Please continue USB discussions over there; let's keep this thread focused on drivers built on top of embedded-hal. (I'm of the opinion that USB is complex and specialized enough that it should go into its own crate separate from embedded-hal.)
@whitequark what exactly are you missing?
DHT22 - temperature + humidity sensor (1-wire)
I already had the DHT22 working with Rust at some point, although not in the form of a reusable driver library. If anyone is interested, I can dig up the code. Caveats: It's messy code, integrated into an application, built on top of other messy unpublished code. I'm not sure how useful it's going to be, but as a starting point, it may be better than nothing.
@japaric
I meant to include this in the issue description: I'm using the embedded-hal keyword for my driver crates. That makes them easier to find. Perhaps we can just use crates.io and keywords instead of creating another registry / list. We can bikeshed the keywords to use in this thread: perhaps
embedded-hal
(orembedded-hal-driver
) for the driver crates,embedded-hal-impl
for the HAL impl crates, like the stm32f30x-hal crate, and svd2rust for thesvd2rust
generated device crates?
I'm in full agreement. Not sure what the best keywords would be, but we should have them. I'm already using the svd2rust
keyword for lpc82x.
@therealprof
That might work but has quite a number of disadvantages: [...]
I think your points are valid, and I would love to see a community resource like the one you describe. However, someone has to build this, and it's going to be a lot of work. crates.io is already here, and we can start using the suggested tags to ease the problems that it has right now.
I'm gonna have a go at building something for a HD44780-style (S6A0069 in my case) 16x2 LCD. @japaric I see you mention an LCD in the context of an IO expander: would a potential IO expander API expose digital::OutputPin
s such that the LCD module could operate generically over either the uC's pins or the expander's?
@hannobraun
I think your points are valid, and I would love to see a community resource like the one you describe. However, someone has to build this, and it's going to be a lot of work. crates.io is already here, and we can start using the suggested tags to ease the problems that it has right now.
I totally agree. One doesn't preclude the other. I fully expect that crates.io will remain the official source for all crates, including embedded ones. I was hoping we could at least get something like https://github.com/brson/stdx up.
@JJJollyjim: clerk might be of interest for you. Here are some tickets from embedded-hal https://github.com/japaric/embedded-hal/issues/29 https://github.com/japaric/embedded-hal/issues/30
@JJJollyjim
I see you mention an LCD in the context of an IO expander
It's just that the LCD I have has an I2C port expander attached to it and the only interface that the module exposes in I2C. But ideally the port expander driver, say PCF8574<I2C>
itself would implement the digital::*
traits and then you be able to plug that in the LCD driver, say LCD<PCF8574<I2C1>>
, but an LCD abstraction right on top of I2C would still be a good start.
For HD44780 compatible LCDs, there are mainly two I²C port expanders used: The PCF8574 and the MCP23008.
In case it helps, here's my Python driver for those LCDs: https://github.com/dbrgn/RPLCD/blob/master/RPLCD/i2c.py
@JJJollyjim @japaric: My current Display
implementation is abstract over the underlying protocol, currently there are two impls for either 4 or 8 data line parallel mode, but it should be possible to impl the traits for I2C, too, but maybe it would need some refactoring with the new HAL traits in mind.
Thanks, this "switch to a stable embedded-hal release" fixes lots of things I was fighting with in the previous version. As soon as the blue-pill crate is updated I'll port my working "1-Wire" driver on this new version (with a 18B20 example, device enumeration). I also have a work in progress CAN driver (that is not an easy one).
@tib888 ok, if you already have a working DS18B20 driver I won't start with writing another one :)
Are there plans to implement a generic display driver, and then device specific crates that implement that abstraction? There are so many different variations of each display type (Eg 128x64, 128x32, monochrome, yellow/blue in those AdaFruit OLED displays alone) that there is a lot of deduplication to be done.
@tib888 FYI: the blue-pill
crate has been replaced by the stm32f103xx-hal
crate, which implements the embedded-hal traits for the whole STM32F103XX family.
Are there plans to implement a generic display driver, and then device specific crates that implement that abstraction?
I just want to note I have extensive experience in this area. There are a number of LCD types in terms of striping and colour depth, as you note. You also need tooling for building static filesystems containing bitmaps (or bitmap maps, such as fonts) in the correct stripe format for quick rendering.
I would love to see something but it's quite a lot of work. A generic framebuffer abstraction over some pixel format P is probably a good start, although it might be better to wait for numeric generics.
@thejpster: Maybe you want have a look at the RFCs and already implemented stuff of the embedded-hal trait and add some comments with suggestions or even new feature request for things that will be needed to implement such drivers.
I'm currently working on a driver for the Si7021 humidity/temperature sensor (I2C). WIP driver code: Si7021
Some other sensors I'll probably tackle later:
I also have a couple of SSD1306 based OLEDs in different sizes (96x32, 128x64). I think at some point we will need something like embedded-gfx
which holds things like the ones @thejpster mentioned. I'm thinking of traits like MonochromeDisplay
, ColorDisplay
, DoubleBuffered
, ... and generic functions to draw a line or print some text on either of those.
@wose I've some old and crusty Rust code for the SSD1306 in here: https://github.com/therealprof/stm32f042/blob/master/examples/i2c_ssd1306.rs
I've just released a driver for the NXP MAG3110 magnetometer here.
I've just released a driver for the NXP MAG3110 magnetometer here.
@therealprof neat. Want to do a small writeup about your driver covering what it does and how to use it?
@japaric Well, to be honest. I can tell you how to use it but I have no idea what a possible application might be and how to implement it since the datasheet is somewhat lacking. You can detect proximity to magnets and (so I would guess) with a bit of calibration sense and calculate the orientation in the room and cardinal direction. I just needed something to test the nrf51 I2C driver with and this on-board sensor on the micro:bit is far easier to use than the MMA8653FC accelerometer, which I'm working on now.
NB: I still haven't figured out how to use multiple sensors on the I2C bus at the same time... 😉
I would love to help with this and create a driver for the NEO-M8 series of GPS receivers, but I will need help. I've already written a driver for them in C++, so I know the chips and the protocols (and have some known-working M8Ts on hand to test with), but I'm still at the "blink an LED" phase when it comes to embedded rust (have lost momentum due to not doing random-thing-I-don't-know-about which makes it a PITA to flash new code to the board). Would anyone here be interested in being PM and/or code-reviewer for me (I promise I won't take much bandwidth)?
I have a WIP Si5351 clock generator driver here: https://github.com/ilya-epifanov/si5351
I've added the WIP drivers that people have reported to the issue description. If yours is missing let me know!
I've also send a PR / RFC to the embedded-hal repo that establishes a process for adding new
traits to it. If you would like to suggest a tweak to the proposed process leave a comment over
there. In that PR I'm also calling for collaborators that will help me put the proposed process in
practice. Finally, that PR is also adding a list of embedded-hal
drivers (like the one we have
here) and a list embedded-hal
implementations (which didn't previously exist) to the README; if
you'd like your crate to be listed there feel free to send a follow up PR.
While playing around with rust on the 'Black Pill' (stm32f103xx device like blue pill), I've created a very basic MAX7219 driver, which when development is completed should have a very similar feel to the LedControl library for Arduino.
It's still a WIP, but I've uploaded the code I currently have to: https://github.com/maikelwever/max7219
When I fix the TODOs outlined in the readme there, I'll probably push it to crates.io as well.
I've also tried a early revision on an OrangePI which also seemed to work fairly well.
I published a blog post about the l3gd20
and lsm303dlhc
drivers, which are already on crates.io, so I have move them to the list of "Released" drivers. Two driver released; 50 more to go!
I've been thinking that it may not be necessary to do a blog post about the driver to consider it released. I think we can move to the released list if it has been published on crates.io and you have let the Rust community know about it via any means: a blog post, twitter, u.r-l.o post, etc.
Do let me know when you consider your driver as being "released to the community" so I can update the lists and the count!
@maikelwever That's a bit banged implementation of SPI, right? I was just thinking that we could provide generic bit banged implementations of SPI and maybe i2C in the embedded-hal
crate. I think that would be a good place for them. Then others can use those implementations instead of writing a new implementation.
Not sure about this. The RFC proposes to open a new issue for each stage of trait design. I worry it might lead to confusion from having so many issues.
I did a little writeup "Let's write an embedded-hal-driver" as part of the WIP driver for AT24C32/64 like EEPROMs. I'll finish and release it to crates.io within the next few days.
Some other WIP drivers:
@wose Neat! If you (or any one else) want me to retweet your blog post feel free to @ me on Twitter (japaricious).
Added the MCP3008 driver by @pcein to the list of released drivers.
There's now a HAL published on crates.io:
embedded-hal
(Introduction blog post). :tada:To put it to test and to expand the crates.io ecosystem I'm starting the weekly driver initiative.
The goal is to release a new no_std, generic,
embedded-hal
based driver crate every one or two weeks. Driver crate here means a library crate that lets you interface an external component like a digital sensor or a wireless transceiver. A driver release consists of (a) publishing a library crate on crates.io (*) and (b) presenting your driver to the community via any means: a blog post, a tweet, a reddit post, au.r-l.ohttps://users.rust-lang.org post, etc.(*) Make sure you tag your crate with the
embedded-hal-driver
keyword!If you'd like to participate leave a comment here stating the driver you'll be working on. If you can post a link to the repo where the (WIP) driver code is or will be, even better! If you don't have a personal blog to present your driver to the community you can do a guest post on my blog.
For a list of released and WIP drivers check the awesome-embedded-rust list. If you'd like your crate to be added to that list simply send a PR to that repo!
TODO (potentially):
These are components that @japaric has at hand:
ENC28J60 - ethernet controller (SPI)L298N - Motor driver