259: Update manifest/changelog for v1.0.0-alpha.3 release r=eldruin a=ryankurte
How do we feel about another alpha release now we've landed transactional SPI and I2C?
- Updated version in `Cargo.toml`
- Updated `CHANGELOG.md`
Note: create `v1.0.0-alpha.3` tag following merge
Co-authored-by: ryan <ryan@kurte.nz>
223: Add transactional I2C interface r=therealprof a=eldruin
An example where a transactional I2C interface would be an improvement is when facing the problem of sending an array of data where the first item is the destination address.
At the moment this requires copying the data into a bigger array and assigning the first item to the address. With a transactional I2C two `write` operations could be chained into one transaction so that it is possible to send the address and data without an extra copy.
This is specially problematic if the data length is unknown e.g. because it comes from the user.
You can see the problem [here in the eeprom24x driver](f75770c6fc/src/eeprom24x.rs (L220)). In this case I am lucky enough to have the page upper limit so that the copy workaround is possible.
With this PR a bunch of code and macros could be replaced by doing something similar to this:
```rust
let user_data = [0x12, 0x34, ...]; // defined somewhere else. length may be unknown.
let target_address = 0xAB;
let mut ops = [
Operation::Write(&[target_address]),
Operation::Write(&user_data),
];
i2cdev.try_exec(DEV_ADDR, &ops)
```
I added a PoC [here in linux-embedded-hal](7512dbcc09/src/lib.rs (L211)) including [an example](https://github.com/eldruin/linux-embedded-hal/blob/transactional-i2c/examples/transactional-i2c.rs) of a driver where a classical combined write/read is performed through the transactional interface.
Note: A default implementation of the `Transactional` trait like in #191 is not possible because STOPs would always be sent after each operation. What is possible is to do is the other way around. This includes an implementation of the `Write`, `Read` and `WriteRead` traits for `Transactional` implementers.
This is based on previous work from #178 by @ryankurte and it is similar to #191
TODO:
- [x] Add changelog entry
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
191: Added transactional SPI interface r=therealprof a=ryankurte
This PR adds a transactional interface for SPI devices (#94), compatible with linux spidev.
Split from #178 as I believe this is complete and useful, but that there is more experimentation required before (if?) the I2C component is landed, check there for previous reviews / discussion.
**Demonstrated in:**
- Linux embedded hal: https://github.com/rust-embedded/linux-embedded-hal/pull/35
- STM32F4xx-hal: https://github.com/stm32-rs/stm32f4xx-hal/pull/167
- embedded-spi driver abstraction (previously provided a polyfill for equivalent transactional functionality) https://github.com/ryankurte/rust-embedded-spi/pull/4/files#diff-74eea42f4e5e15399ac9184c8f2727a9R344
- sx128x radio driver: https://github.com/ryankurte/rust-radio-sx128x/pull/5
**Notes:**
- `Operation::Transfer` uses one buffer to allow polyfill using the existing `Transfer` trait (with the convenient side effect of reducing memory requirements)
- `W` has a static bound as it _should_ only ever be a type with static lifetime (u8, u16 etc., not a reference), and to differentiate this from `'a` which is the lifetime of the data in the object and only bound to the function
- `exec(.., &mut [Operation])` is chosen over `exec<O: AsMut<[Operation]>(..)` as the latter imposes limits on generic types using this trait (which i ran into, see [E0038](https://doc.rust-lang.org/error-index.html#E0038))
cc. @rust-embedded/hal folks, @eldruin, @RandomInsano, @rahix, @austinglaser for opinions / review
Co-authored-by: Ryan Kurte <ryankurte@gmail.com>
Co-authored-by: ryan <ryan@kurte.nz>
255: Release version 1.0.0-alpha.2 r=therealprof a=ryankurte
i forgot about bors and `cargo-release`'d this so, package is already live on crates.io :-/
(maybe it would be worth looking into releasing with tags via CI? but perhaps this is also more annoying)
related to #177
Co-authored-by: ryan <ryan@kurte.nz>
254: Remove futures examples r=therealprof a=eldruin
The `futures`-based examples are stuck on `futures` `0.1`, require nightly to run the tests and do not represent how asynchronous processing will be done in embedded any more.
In the `0.2.x` version these examples are still present. See [here](https://docs.rs/embedded-hal/0.2.4/embedded_hal/).
See [async/await on embedded Rust](https://ferrous-systems.com/blog/async-on-embedded/).
See #251
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
251: Update reference implementation implementation to stm32f1xx-hal and update examples r=therealprof a=eldruin
I think the `stm32f1xx-hal` is a good candidate for a reference implementation.
I have also updated the examples accordingly and modernized them a bit.
An additional possibility would be to remove the `futures` examples as well, since async handling will be different.
Closes#156
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
170: Remove unsupported examples for hal r=eldruin a=no111u3
Remove stm32f3 hal implementation as dependency and it's examples from runned doc tests.
Following the #156
Co-authored-by: Boris Vinogradov <no111u3@gmail.com>
120: Document implicit assumption in non-blocking spi trait r=therealprof a=david-sawatzke
It should only be able to read the data returned by the last write call. Otherwise the overflow handling isn't really possible when doing only write calls (at least on stm32f0). @therealprof and me came to this conclusion after chatting on irc that this is the intended usage of this api.
Co-authored-by: David Sawatzke <david-sawatzke@users.noreply.github.com>
Co-authored-by: David Sawatzke <d-git@sawatzke.dev>
Co-authored-by: david-sawatzke <david-sawatzke@users.noreply.github.com>
239: Add try_set_state method for OutputPin r=therealprof a=eldruin
This is an implementation of #200 to gather some opinions and so we can either accept it or close the issue.
This was earlier discussed at #44.
I added a conversion from `bool` following the usual convention as well as an `ops::Not` implementation as suggested in #200, which seemed appropriate.
I also added a default implementation for the `try_set_state` method. This bears the question whether a default implementation for `try_set_high()` / `try_set_low()` by using `try_set_state()` would be useful, so that potential implementors can choose to implement less methods.
It should be noted that adding a default implementation for all 3 methods has the somewhat amusing property of generating an endless loop if none is overwritten.
Closes#200
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
242: Make ADC Channel trait use a stateful method to get the IDs r=therealprof a=eldruin
Closes#110
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
238: Pwm: allow get_duty to return the old value for some time r=therealprof a=eldruin
This is #140 applied to the `Pwm` trait as well, since the same concerns apply. Follows up on #236.
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
PWM is often implemented in a buffered way to allow glitch-free
operation; as a result, implementing a strict "you get what you last
set" is not feasible for some implementations.
236: PwmPin: allow get_duty to return the old value for some time r=therealprof a=eldruin
This is #140 rebased to master.
However, I suppose the same thing applies to the `Pwm::try_get_duty()` method. Shouldn't the same note be added to that method as well?
Closes#140
Co-authored-by: chrysn <chrysn@fsfe.org>
PWM is often implemented in a buffered way to allow glitch-free
operation; as a result, implementing a strict "you get what you last
set" is not feasible for some implementations.
230: Make I2C compatible with multiple address sizes r=ryankurte a=eldruin
This adds I2C 7-bit and 10-bit address mode compatibility as roughly described [here](https://github.com/rust-embedded/embedded-hal/issues/147#issuecomment-511703503).
Discussion issue: #147
I have also added the `SevenBitAddress` as the default address mode to the traits so this is not even a breaking change.
Usage broken down per use case:
* **Device driver which only supports 7-bit addressing mode:**
The driver looks exactly the same as now since the default address mode is 7-bit.
```rust
impl<I2C, E> MyDriver<I2C>
where I2C: i2c::Write<Error = E> {
pub fn do_cool_stuff(&mut self) // ...
}
```
* **Device driver which only supports 10-bit addressing mode:**
The only difference to a 7-bit-address-only driver is one additional parameter in the I2C trait bound.
```rust
impl<I2C, E> MyDriver<I2C>
where I2C: i2c::Write<TenBitAddress, Error = E> {
pub fn do_cool_stuff(&mut self) // ...
}
```
* **Driver for device supporting both addressing modes:**
Complexity can be abstracted away into additional internal traits which can handle the addressing stuff. Driver code stays clean.
**This is nothing new**. We already do this on drivers for devices compatible with both I2C and SPI. No need for duplicated code.
Here a real example: [usage](3af5637f1d/src/device_impl.rs (L43)), [traits](https://github.com/eldruin/bmi160-rs/blob/master/src/interface.rs)
```rust
impl<DI, E> MyDriver<DI>
where DI: WriteData<Error = E> {
pub fn do_cool_stuff(&mut self) {} // ...
}
pub trait WriteData {
// ...
}
// it is also possible to just leave the `SevenBitAddress` type out here,
// since it is the default.
impl<I2C, E> WriteData for I2cInterface<I2C, SevenBitAddress>
where
I2C: i2c::Write<SevenBitAddress, Error = E>,
{
// ...
}
impl<I2C, E> WriteData for I2cInterface<I2C, TenBitAddress>
where
I2C: i2c::Write<TenBitAddress, Error = E>,
{
// ...
}
```
* **Bus controller impl supporting only 7-bit addressing mode:**
Code stays almost the same, just adding one addressing mode parameter. Additionally, _if desired_:
* 10-bit addressing can be software-emulated:
Emulate by extending and copying payload in separate `TenBitAddress` implementation. Total flexibility to do whatever is necessary in this case since the code is independent.
* 10-bit addressing cannot be software-emulated:
Implementation does not offer implementation for `TenBitAddress` variant. The user gets a compilation error and everything is clear.
* **Bus controller impl supporting both addressing modes:**
No problem. Two separate implementations guarantee as much flexibility as necessary. At the same time, sharing generic code is possible.
Additional benefits:
* No runtime performance cost
* No runtime switching, duplicated code or panics for unsupported modes.
* Consistent with what we do for code paths that can be determined statically by the compiler.
* To my taste elegant, simple and very descriptive.
See [here](https://github.com/rust-embedded/embedded-hal/issues/147#issuecomment-647157906) for a comparison to other alternatives.
I have also sealed the trait.
## Proof
* A HAL implementation of both modes: [bitbang-hal](https://github.com/eldruin/bitbang-hal/tree/i2c-multi-address-mode). [code changes](https://github.com/eldruin/bitbang-hal/compare/embedded-hal-1.0.0-alpha.1...eldruin:i2c-multi-address-mode)
* Drivers supporting only 7-bit addresses need **no changes**.
For demonstration purposes, explicitly including the `SevenBitAddress` would look like this: [OPT300x](https://github.com/eldruin/opt300x-rs/tree/i2c-multi-address-mode). [code changes](https://github.com/eldruin/opt300x-rs/compare/i2c-multi-address-mode).
This would be similar to the case of a 10-bit-only device driver.
Co-authored-by: Diego Barrios Romero <eldruin@gmail.com>
222: Improve watchdog API design using move semantics r=therealprof a=luojia65
This pull request improved watchdog API design. When starting watchdog, we may convert it into another type. We may implement different functions for this type. Or downstream developers can implement `Watchdog` for only an enabled type, to prevent feed to disabled watchdogs or forget to enable before feeding. If we are able to stop this watchdog, it can be converted into the former type.
If current design still need a same type after the watchdog is enabled, they may use `Target = Self`. In this way we create a fallback for earlier designs.
A simple proof of concept: [here](https://github.com/gd32v-rust/gd32vf103-hal/blob/new-watchdog-design/src/wdog.rs#L155-L169) (L120-L153 for its `Enable` implementation, and there is `Disable` implementation)
Related issue: https://github.com/rust-embedded/embedded-hal/issues/98
Earlier discussion: https://github.com/rust-embedded/embedded-hal/pull/76#issuecomment-417413406
Co-authored-by: luojia65 <me@luojia.cc>
Co-authored-by: Luo Jia <account@luojia.cc>