aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-10 00:03:44 +0000
committerGitHub <[email protected]>2022-07-10 00:03:44 +0000
commit5f43c1d37e9db847c7861fe0bd821db62edba9f6 (patch)
treeab7064865dc499f0999a2a2a67c539e7ad5b82a8
parent921bc4d97ba290045e026389d7ab68399bb1ceab (diff)
parentc9b58561538b5fb3e5702744c9f5653d039f8c98 (diff)
Merge #850
850: Shared buses with SetConfig r=Dirbaio a=kalkyl Addresses issue #830 Co-authored-by: Henrik Alsér <[email protected]>
-rw-r--r--embassy-embedded-hal/Cargo.toml6
-rw-r--r--embassy-embedded-hal/src/lib.rs10
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/i2c.rs (renamed from embassy-embedded-hal/src/shared_bus/i2c.rs)96
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/mod.rs3
-rw-r--r--embassy-embedded-hal/src/shared_bus/asynch/spi.rs (renamed from embassy-embedded-hal/src/shared_bus/spi.rs)81
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/i2c.rs87
-rw-r--r--embassy-embedded-hal/src/shared_bus/blocking/spi.rs52
-rw-r--r--embassy-embedded-hal/src/shared_bus/mod.rs46
-rw-r--r--embassy-nrf/Cargo.toml3
-rw-r--r--embassy-nrf/src/spim.rs44
-rw-r--r--embassy-nrf/src/twim.rs11
-rw-r--r--embassy-rp/Cargo.toml3
-rw-r--r--embassy-rp/src/spi.rs18
-rw-r--r--embassy-stm32/Cargo.toml3
-rw-r--r--embassy-stm32/src/i2c/v1.rs21
-rw-r--r--embassy-stm32/src/i2c/v2.rs17
-rw-r--r--embassy-stm32/src/spi/mod.rs8
17 files changed, 461 insertions, 48 deletions
diff --git a/embassy-embedded-hal/Cargo.toml b/embassy-embedded-hal/Cargo.toml
index d1b9f3ea4..d2606d264 100644
--- a/embassy-embedded-hal/Cargo.toml
+++ b/embassy-embedded-hal/Cargo.toml
@@ -5,12 +5,14 @@ edition = "2021"
5 5
6[features] 6[features]
7std = [] 7std = []
8# Enable nightly-only features
9nightly = ["embedded-hal-async", "embedded-storage-async"]
8 10
9[dependencies] 11[dependencies]
10embassy = { version = "0.1.0", path = "../embassy" } 12embassy = { version = "0.1.0", path = "../embassy" }
11embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 13embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
12embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" } 14embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.8" }
13embedded-hal-async = { version = "0.1.0-alpha.1" } 15embedded-hal-async = { version = "0.1.0-alpha.1", optional = true }
14embedded-storage = "0.3.0" 16embedded-storage = "0.3.0"
15embedded-storage-async = "0.3.0" 17embedded-storage-async = { version = "0.3.0", optional = true }
16nb = "1.0.0" \ No newline at end of file 18nb = "1.0.0" \ No newline at end of file
diff --git a/embassy-embedded-hal/src/lib.rs b/embassy-embedded-hal/src/lib.rs
index 27ffa7421..d77c2d635 100644
--- a/embassy-embedded-hal/src/lib.rs
+++ b/embassy-embedded-hal/src/lib.rs
@@ -1,6 +1,12 @@
1#![cfg_attr(not(feature = "std"), no_std)] 1#![cfg_attr(not(feature = "std"), no_std)]
2#![feature(generic_associated_types)] 2#![cfg_attr(feature = "nightly", feature(generic_associated_types, type_alias_impl_trait))]
3#![feature(type_alias_impl_trait)]
4 3
4#[cfg(feature = "nightly")]
5pub mod adapter; 5pub mod adapter;
6
6pub mod shared_bus; 7pub mod shared_bus;
8
9pub trait SetConfig {
10 type Config;
11 fn set_config(&mut self, config: &Self::Config);
12}
diff --git a/embassy-embedded-hal/src/shared_bus/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
index e8131288a..136117920 100644
--- a/embassy-embedded-hal/src/shared_bus/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs
@@ -22,28 +22,14 @@
22//! let i2c_dev2 = I2cBusDevice::new(i2c_bus); 22//! let i2c_dev2 = I2cBusDevice::new(i2c_bus);
23//! let mpu = Mpu6050::new(i2c_dev2); 23//! let mpu = Mpu6050::new(i2c_dev2);
24//! ``` 24//! ```
25use core::fmt::Debug;
26use core::future::Future; 25use core::future::Future;
27 26
28use embassy::blocking_mutex::raw::RawMutex; 27use embassy::blocking_mutex::raw::RawMutex;
29use embassy::mutex::Mutex; 28use embassy::mutex::Mutex;
30use embedded_hal_async::i2c; 29use embedded_hal_async::i2c;
31 30
32#[derive(Copy, Clone, Eq, PartialEq, Debug)] 31use crate::shared_bus::I2cBusDeviceError;
33pub enum I2cBusDeviceError<BUS> { 32use crate::SetConfig;
34 I2c(BUS),
35}
36
37impl<BUS> i2c::Error for I2cBusDeviceError<BUS>
38where
39 BUS: i2c::Error + Debug,
40{
41 fn kind(&self) -> i2c::ErrorKind {
42 match self {
43 Self::I2c(e) => e.kind(),
44 }
45 }
46}
47 33
48pub struct I2cBusDevice<'a, M: RawMutex, BUS> { 34pub struct I2cBusDevice<'a, M: RawMutex, BUS> {
49 bus: &'a Mutex<M, BUS>, 35 bus: &'a Mutex<M, BUS>,
@@ -116,3 +102,81 @@ where
116 async move { todo!() } 102 async move { todo!() }
117 } 103 }
118} 104}
105
106pub struct I2cBusDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig> {
107 bus: &'a Mutex<M, BUS>,
108 config: BUS::Config,
109}
110
111impl<'a, M: RawMutex, BUS: SetConfig> I2cBusDeviceWithConfig<'a, M, BUS> {
112 pub fn new(bus: &'a Mutex<M, BUS>, config: BUS::Config) -> Self {
113 Self { bus, config }
114 }
115}
116
117impl<'a, M, BUS> i2c::ErrorType for I2cBusDeviceWithConfig<'a, M, BUS>
118where
119 BUS: i2c::ErrorType,
120 M: RawMutex,
121 BUS: SetConfig,
122{
123 type Error = I2cBusDeviceError<BUS::Error>;
124}
125
126impl<M, BUS> i2c::I2c for I2cBusDeviceWithConfig<'_, M, BUS>
127where
128 M: RawMutex + 'static,
129 BUS: i2c::I2c + SetConfig + 'static,
130{
131 type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
132
133 fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
134 async move {
135 let mut bus = self.bus.lock().await;
136 bus.set_config(&self.config);
137 bus.read(address, buffer).await.map_err(I2cBusDeviceError::I2c)?;
138 Ok(())
139 }
140 }
141
142 type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
143
144 fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
145 async move {
146 let mut bus = self.bus.lock().await;
147 bus.set_config(&self.config);
148 bus.write(address, bytes).await.map_err(I2cBusDeviceError::I2c)?;
149 Ok(())
150 }
151 }
152
153 type WriteReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a;
154
155 fn write_read<'a>(
156 &'a mut self,
157 address: u8,
158 wr_buffer: &'a [u8],
159 rd_buffer: &'a mut [u8],
160 ) -> Self::WriteReadFuture<'a> {
161 async move {
162 let mut bus = self.bus.lock().await;
163 bus.set_config(&self.config);
164 bus.write_read(address, wr_buffer, rd_buffer)
165 .await
166 .map_err(I2cBusDeviceError::I2c)?;
167 Ok(())
168 }
169 }
170
171 type TransactionFuture<'a, 'b> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a, 'b: 'a;
172
173 fn transaction<'a, 'b>(
174 &'a mut self,
175 address: u8,
176 operations: &'a mut [embedded_hal_async::i2c::Operation<'b>],
177 ) -> Self::TransactionFuture<'a, 'b> {
178 let _ = address;
179 let _ = operations;
180 async move { todo!() }
181 }
182}
diff --git a/embassy-embedded-hal/src/shared_bus/asynch/mod.rs b/embassy-embedded-hal/src/shared_bus/asynch/mod.rs
new file mode 100644
index 000000000..2e660b724
--- /dev/null
+++ b/embassy-embedded-hal/src/shared_bus/asynch/mod.rs
@@ -0,0 +1,3 @@
1//! Asynchronous shared bus implementations for embedded-hal-async
2pub mod i2c;
3pub mod spi;
diff --git a/embassy-embedded-hal/src/shared_bus/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
index fd4b6d565..8034c90b5 100644
--- a/embassy-embedded-hal/src/shared_bus/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs
@@ -25,7 +25,6 @@
25//! let spi_dev2 = SpiBusDevice::new(spi_bus, cs_pin2); 25//! let spi_dev2 = SpiBusDevice::new(spi_bus, cs_pin2);
26//! let display2 = ST7735::new(spi_dev2, dc2, rst2, Default::default(), 160, 128); 26//! let display2 = ST7735::new(spi_dev2, dc2, rst2, Default::default(), 160, 128);
27//! ``` 27//! ```
28use core::fmt::Debug;
29use core::future::Future; 28use core::future::Future;
30 29
31use embassy::blocking_mutex::raw::RawMutex; 30use embassy::blocking_mutex::raw::RawMutex;
@@ -34,24 +33,8 @@ use embedded_hal_1::digital::blocking::OutputPin;
34use embedded_hal_1::spi::ErrorType; 33use embedded_hal_1::spi::ErrorType;
35use embedded_hal_async::spi; 34use embedded_hal_async::spi;
36 35
37#[derive(Copy, Clone, Eq, PartialEq, Debug)] 36use crate::shared_bus::SpiBusDeviceError;
38pub enum SpiBusDeviceError<BUS, CS> { 37use crate::SetConfig;
39 Spi(BUS),
40 Cs(CS),
41}
42
43impl<BUS, CS> spi::Error for SpiBusDeviceError<BUS, CS>
44where
45 BUS: spi::Error + Debug,
46 CS: Debug,
47{
48 fn kind(&self) -> spi::ErrorKind {
49 match self {
50 Self::Spi(e) => e.kind(),
51 Self::Cs(_) => spi::ErrorKind::Other,
52 }
53 }
54}
55 38
56pub struct SpiBusDevice<'a, M: RawMutex, BUS, CS> { 39pub struct SpiBusDevice<'a, M: RawMutex, BUS, CS> {
57 bus: &'a Mutex<M, BUS>, 40 bus: &'a Mutex<M, BUS>,
@@ -109,3 +92,63 @@ where
109 } 92 }
110 } 93 }
111} 94}
95
96pub struct SpiBusDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig, CS> {
97 bus: &'a Mutex<M, BUS>,
98 cs: CS,
99 config: BUS::Config,
100}
101
102impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiBusDeviceWithConfig<'a, M, BUS, CS> {
103 pub fn new(bus: &'a Mutex<M, BUS>, cs: CS, config: BUS::Config) -> Self {
104 Self { bus, cs, config }
105 }
106}
107
108impl<'a, M, BUS, CS> spi::ErrorType for SpiBusDeviceWithConfig<'a, M, BUS, CS>
109where
110 BUS: spi::ErrorType + SetConfig,
111 CS: OutputPin,
112 M: RawMutex,
113{
114 type Error = SpiBusDeviceError<BUS::Error, CS::Error>;
115}
116
117impl<M, BUS, CS> spi::SpiDevice for SpiBusDeviceWithConfig<'_, M, BUS, CS>
118where
119 M: RawMutex + 'static,
120 BUS: spi::SpiBusFlush + SetConfig + 'static,
121 CS: OutputPin,
122{
123 type Bus = BUS;
124
125 type TransactionFuture<'a, R, F, Fut> = impl Future<Output = Result<R, Self::Error>> + 'a
126 where
127 Self: 'a, R: 'a, F: FnOnce(*mut Self::Bus) -> Fut + 'a,
128 Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>> + 'a;
129
130 fn transaction<'a, R, F, Fut>(&'a mut self, f: F) -> Self::TransactionFuture<'a, R, F, Fut>
131 where
132 R: 'a,
133 F: FnOnce(*mut Self::Bus) -> Fut + 'a,
134 Fut: Future<Output = Result<R, <Self::Bus as ErrorType>::Error>> + 'a,
135 {
136 async move {
137 let mut bus = self.bus.lock().await;
138 bus.set_config(&self.config);
139 self.cs.set_low().map_err(SpiBusDeviceError::Cs)?;
140
141 let f_res = f(&mut *bus).await;
142
143 // On failure, it's important to still flush and deassert CS.
144 let flush_res = bus.flush().await;
145 let cs_res = self.cs.set_high();
146
147 let f_res = f_res.map_err(SpiBusDeviceError::Spi)?;
148 flush_res.map_err(SpiBusDeviceError::Spi)?;
149 cs_res.map_err(SpiBusDeviceError::Cs)?;
150
151 Ok(f_res)
152 }
153 }
154}
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
index bfbcb6c2e..ac361a786 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs
@@ -23,7 +23,8 @@ use embassy::blocking_mutex::Mutex;
23use embedded_hal_1::i2c::blocking::{I2c, Operation}; 23use embedded_hal_1::i2c::blocking::{I2c, Operation};
24use embedded_hal_1::i2c::ErrorType; 24use embedded_hal_1::i2c::ErrorType;
25 25
26use crate::shared_bus::i2c::I2cBusDeviceError; 26use crate::shared_bus::I2cBusDeviceError;
27use crate::SetConfig;
27 28
28pub struct I2cBusDevice<'a, M: RawMutex, BUS> { 29pub struct I2cBusDevice<'a, M: RawMutex, BUS> {
29 bus: &'a Mutex<M, RefCell<BUS>>, 30 bus: &'a Mutex<M, RefCell<BUS>>,
@@ -141,3 +142,87 @@ where
141 }) 142 })
142 } 143 }
143} 144}
145
146pub struct I2cBusDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig> {
147 bus: &'a Mutex<M, RefCell<BUS>>,
148 config: BUS::Config,
149}
150
151impl<'a, M: RawMutex, BUS: SetConfig> I2cBusDeviceWithConfig<'a, M, BUS> {
152 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, config: BUS::Config) -> Self {
153 Self { bus, config }
154 }
155}
156
157impl<'a, M, BUS> ErrorType for I2cBusDeviceWithConfig<'a, M, BUS>
158where
159 M: RawMutex,
160 BUS: ErrorType + SetConfig,
161{
162 type Error = I2cBusDeviceError<BUS::Error>;
163}
164
165impl<M, BUS> I2c for I2cBusDeviceWithConfig<'_, M, BUS>
166where
167 M: RawMutex,
168 BUS: I2c + SetConfig,
169{
170 fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
171 self.bus.lock(|bus| {
172 let mut bus = bus.borrow_mut();
173 bus.set_config(&self.config);
174 bus.read(address, buffer).map_err(I2cBusDeviceError::I2c)
175 })
176 }
177
178 fn write(&mut self, address: u8, bytes: &[u8]) -> Result<(), Self::Error> {
179 self.bus.lock(|bus| {
180 let mut bus = bus.borrow_mut();
181 bus.set_config(&self.config);
182 bus.write(address, bytes).map_err(I2cBusDeviceError::I2c)
183 })
184 }
185
186 fn write_read(&mut self, address: u8, wr_buffer: &[u8], rd_buffer: &mut [u8]) -> Result<(), Self::Error> {
187 self.bus.lock(|bus| {
188 let mut bus = bus.borrow_mut();
189 bus.set_config(&self.config);
190 bus.write_read(address, wr_buffer, rd_buffer)
191 .map_err(I2cBusDeviceError::I2c)
192 })
193 }
194
195 fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> {
196 let _ = address;
197 let _ = operations;
198 todo!()
199 }
200
201 fn write_iter<B: IntoIterator<Item = u8>>(&mut self, addr: u8, bytes: B) -> Result<(), Self::Error> {
202 let _ = addr;
203 let _ = bytes;
204 todo!()
205 }
206
207 fn write_iter_read<B: IntoIterator<Item = u8>>(
208 &mut self,
209 addr: u8,
210 bytes: B,
211 buffer: &mut [u8],
212 ) -> Result<(), Self::Error> {
213 let _ = addr;
214 let _ = bytes;
215 let _ = buffer;
216 todo!()
217 }
218
219 fn transaction_iter<'a, O: IntoIterator<Item = Operation<'a>>>(
220 &mut self,
221 address: u8,
222 operations: O,
223 ) -> Result<(), Self::Error> {
224 let _ = address;
225 let _ = operations;
226 todo!()
227 }
228}
diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
index 81cf97457..704858cdb 100644
--- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
+++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs
@@ -26,7 +26,8 @@ use embedded_hal_1::digital::blocking::OutputPin;
26use embedded_hal_1::spi; 26use embedded_hal_1::spi;
27use embedded_hal_1::spi::blocking::{SpiBusFlush, SpiDevice}; 27use embedded_hal_1::spi::blocking::{SpiBusFlush, SpiDevice};
28 28
29use crate::shared_bus::spi::SpiBusDeviceError; 29use crate::shared_bus::SpiBusDeviceError;
30use crate::SetConfig;
30 31
31pub struct SpiBusDevice<'a, M: RawMutex, BUS, CS> { 32pub struct SpiBusDevice<'a, M: RawMutex, BUS, CS> {
32 bus: &'a Mutex<M, RefCell<BUS>>, 33 bus: &'a Mutex<M, RefCell<BUS>>,
@@ -115,3 +116,52 @@ where
115 }) 116 })
116 } 117 }
117} 118}
119
120pub struct SpiBusDeviceWithConfig<'a, M: RawMutex, BUS: SetConfig, CS> {
121 bus: &'a Mutex<M, RefCell<BUS>>,
122 cs: CS,
123 config: BUS::Config,
124}
125
126impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiBusDeviceWithConfig<'a, M, BUS, CS> {
127 pub fn new(bus: &'a Mutex<M, RefCell<BUS>>, cs: CS, config: BUS::Config) -> Self {
128 Self { bus, cs, config }
129 }
130}
131
132impl<'a, M, BUS, CS> spi::ErrorType for SpiBusDeviceWithConfig<'a, M, BUS, CS>
133where
134 M: RawMutex,
135 BUS: spi::ErrorType + SetConfig,
136 CS: OutputPin,
137{
138 type Error = SpiBusDeviceError<BUS::Error, CS::Error>;
139}
140
141impl<BUS, M, CS> SpiDevice for SpiBusDeviceWithConfig<'_, M, BUS, CS>
142where
143 M: RawMutex,
144 BUS: SpiBusFlush + SetConfig,
145 CS: OutputPin,
146{
147 type Bus = BUS;
148
149 fn transaction<R>(&mut self, f: impl FnOnce(&mut Self::Bus) -> Result<R, BUS::Error>) -> Result<R, Self::Error> {
150 self.bus.lock(|bus| {
151 let mut bus = bus.borrow_mut();
152 bus.set_config(&self.config);
153 self.cs.set_low().map_err(SpiBusDeviceError::Cs)?;
154
155 let f_res = f(&mut bus);
156
157 // On failure, it's important to still flush and deassert CS.
158 let flush_res = bus.flush();
159 let cs_res = self.cs.set_high();
160
161 let f_res = f_res.map_err(SpiBusDeviceError::Spi)?;
162 flush_res.map_err(SpiBusDeviceError::Spi)?;
163 cs_res.map_err(SpiBusDeviceError::Cs)?;
164 Ok(f_res)
165 })
166 }
167}
diff --git a/embassy-embedded-hal/src/shared_bus/mod.rs b/embassy-embedded-hal/src/shared_bus/mod.rs
index cd748cac8..61200443d 100644
--- a/embassy-embedded-hal/src/shared_bus/mod.rs
+++ b/embassy-embedded-hal/src/shared_bus/mod.rs
@@ -1,6 +1,44 @@
1//! Shared bus implementations 1//! Shared bus implementations
2use core::fmt::Debug;
3
4use embedded_hal_1::{i2c, spi};
5
6#[cfg(feature = "nightly")]
7pub mod asynch;
8
2pub mod blocking; 9pub mod blocking;
3/// Shared i2c bus implementation for embedded-hal-async 10
4pub mod i2c; 11#[derive(Copy, Clone, Eq, PartialEq, Debug)]
5/// Shared SPI bus implementation for embedded-hal-async 12pub enum I2cBusDeviceError<BUS> {
6pub mod spi; 13 I2c(BUS),
14}
15
16impl<BUS> i2c::Error for I2cBusDeviceError<BUS>
17where
18 BUS: i2c::Error + Debug,
19{
20 fn kind(&self) -> i2c::ErrorKind {
21 match self {
22 Self::I2c(e) => e.kind(),
23 }
24 }
25}
26
27#[derive(Copy, Clone, Eq, PartialEq, Debug)]
28pub enum SpiBusDeviceError<BUS, CS> {
29 Spi(BUS),
30 Cs(CS),
31}
32
33impl<BUS, CS> spi::Error for SpiBusDeviceError<BUS, CS>
34where
35 BUS: spi::Error + Debug,
36 CS: Debug,
37{
38 fn kind(&self) -> spi::ErrorKind {
39 match self {
40 Self::Spi(e) => e.kind(),
41 Self::Cs(_) => spi::ErrorKind::Other,
42 }
43 }
44}
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index 887ea1bd2..3569a70c6 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -21,7 +21,7 @@ time = ["embassy/time"]
21defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt", "embedded-io?/defmt"] 21defmt = ["dep:defmt", "embassy/defmt", "embassy-usb?/defmt", "embedded-io?/defmt"]
22 22
23# Enable nightly-only features 23# Enable nightly-only features
24nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io"] 24nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async", "dep:embedded-io", "embassy-embedded-hal/nightly"]
25 25
26# Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. 26# Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`.
27# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. 27# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version.
@@ -68,6 +68,7 @@ embassy = { version = "0.1.0", path = "../embassy" }
68embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} 68embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]}
69embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]} 69embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["nrf"]}
70embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 70embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
71embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
71embassy-usb = {version = "0.1.0", path = "../embassy-usb", optional=true } 72embassy-usb = {version = "0.1.0", path = "../embassy-usb", optional=true }
72 73
73embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 74embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs
index efccfeca3..d34d9a0c8 100644
--- a/embassy-nrf/src/spim.rs
+++ b/embassy-nrf/src/spim.rs
@@ -4,6 +4,7 @@ use core::marker::PhantomData;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 5use core::task::Poll;
6 6
7use embassy_embedded_hal::SetConfig;
7use embassy_hal_common::unborrow; 8use embassy_hal_common::unborrow;
8pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 9pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
9use futures::future::poll_fn; 10use futures::future::poll_fn;
@@ -521,3 +522,46 @@ cfg_if::cfg_if! {
521 } 522 }
522 } 523 }
523} 524}
525
526impl<'d, T: Instance> SetConfig for Spim<'d, T> {
527 type Config = Config;
528 fn set_config(&mut self, config: &Self::Config) {
529 let r = T::regs();
530 // Configure mode.
531 let mode = config.mode;
532 r.config.write(|w| {
533 match mode {
534 MODE_0 => {
535 w.order().msb_first();
536 w.cpol().active_high();
537 w.cpha().leading();
538 }
539 MODE_1 => {
540 w.order().msb_first();
541 w.cpol().active_high();
542 w.cpha().trailing();
543 }
544 MODE_2 => {
545 w.order().msb_first();
546 w.cpol().active_low();
547 w.cpha().leading();
548 }
549 MODE_3 => {
550 w.order().msb_first();
551 w.cpol().active_low();
552 w.cpha().trailing();
553 }
554 }
555
556 w
557 });
558
559 // Configure frequency.
560 let frequency = config.frequency;
561 r.frequency.write(|w| w.frequency().variant(frequency));
562
563 // Set over-read character
564 let orc = config.orc;
565 r.orc.write(|w| unsafe { w.orc().bits(orc) });
566 }
567}
diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs
index c3921104e..2088691b2 100644
--- a/embassy-nrf/src/twim.rs
+++ b/embassy-nrf/src/twim.rs
@@ -15,6 +15,7 @@ use core::task::Poll;
15#[cfg(feature = "time")] 15#[cfg(feature = "time")]
16use embassy::time::{Duration, Instant}; 16use embassy::time::{Duration, Instant};
17use embassy::waitqueue::AtomicWaker; 17use embassy::waitqueue::AtomicWaker;
18use embassy_embedded_hal::SetConfig;
18use embassy_hal_common::unborrow; 19use embassy_hal_common::unborrow;
19use futures::future::poll_fn; 20use futures::future::poll_fn;
20 21
@@ -24,6 +25,7 @@ use crate::interrupt::{Interrupt, InterruptExt};
24use crate::util::{slice_in_ram, slice_in_ram_or}; 25use crate::util::{slice_in_ram, slice_in_ram_or};
25use crate::{gpio, pac, Unborrow}; 26use crate::{gpio, pac, Unborrow};
26 27
28#[derive(Clone, Copy)]
27pub enum Frequency { 29pub enum Frequency {
28 #[doc = "26738688: 100 kbps"] 30 #[doc = "26738688: 100 kbps"]
29 K100 = 26738688, 31 K100 = 26738688,
@@ -877,3 +879,12 @@ cfg_if::cfg_if! {
877 } 879 }
878 } 880 }
879} 881}
882
883impl<'d, T: Instance> SetConfig for Twim<'d, T> {
884 type Config = Config;
885 fn set_config(&mut self, config: &Self::Config) {
886 let r = T::regs();
887 r.frequency
888 .write(|w| unsafe { w.frequency().bits(config.frequency as u32) });
889 }
890}
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 217221b0e..95ae76cd2 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -20,7 +20,7 @@ flavors = [
20unstable-pac = [] 20unstable-pac = []
21 21
22# Enable nightly-only features 22# Enable nightly-only features
23nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async"] 23nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly"]
24 24
25# Implement embedded-hal 1.0 alpha traits. 25# Implement embedded-hal 1.0 alpha traits.
26# Implement embedded-hal-async traits if `nightly` is set as well. 26# Implement embedded-hal-async traits if `nightly` is set as well.
@@ -30,6 +30,7 @@ unstable-traits = ["embedded-hal-1"]
30embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz", "nightly"] } 30embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz", "nightly"] }
31embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]} 31embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-3"]}
32embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 32embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
33embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
33embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["rp"]} 34embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["rp"]}
34atomic-polyfill = "0.1.5" 35atomic-polyfill = "0.1.5"
35defmt = { version = "0.3", optional = true } 36defmt = { version = "0.3", optional = true }
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index e988e41d2..6b3f2238a 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -1,5 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_embedded_hal::SetConfig;
3use embassy_hal_common::unborrow; 4use embassy_hal_common::unborrow;
4pub use embedded_hal_02::spi::{Phase, Polarity}; 5pub use embedded_hal_02::spi::{Phase, Polarity};
5 6
@@ -350,3 +351,20 @@ mod eh1 {
350 } 351 }
351 } 352 }
352} 353}
354
355impl<'d, T: Instance> SetConfig for Spi<'d, T> {
356 type Config = Config;
357 fn set_config(&mut self, config: &Self::Config) {
358 let p = self.inner.regs();
359 let (presc, postdiv) = calc_prescs(config.frequency);
360 unsafe {
361 p.cpsr().write(|w| w.set_cpsdvsr(presc));
362 p.cr0().write(|w| {
363 w.set_dss(0b0111); // 8bit
364 w.set_spo(config.polarity == Polarity::IdleHigh);
365 w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
366 w.set_scr(postdiv);
367 });
368 }
369 }
370}
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index a21384be6..a5c444fbb 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -35,6 +35,7 @@ embassy = { version = "0.1.0", path = "../embassy" }
35embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]} 35embassy-cortex-m = { version = "0.1.0", path = "../embassy-cortex-m", features = ["prio-bits-4"]}
36embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"] } 36embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"] }
37embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 37embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
38embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" }
38embassy-net = { version = "0.1.0", path = "../embassy-net", optional = true } 39embassy-net = { version = "0.1.0", path = "../embassy-net", optional = true }
39embassy-usb = {version = "0.1.0", path = "../embassy-usb", optional = true } 40embassy-usb = {version = "0.1.0", path = "../embassy-usb", optional = true }
40 41
@@ -90,7 +91,7 @@ time-driver-tim12 = ["_time-driver"]
90time-driver-tim15 = ["_time-driver"] 91time-driver-tim15 = ["_time-driver"]
91 92
92# Enable nightly-only features 93# Enable nightly-only features
93nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb"] 94nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb", "embassy-embedded-hal/nightly"]
94 95
95# Reexport stm32-metapac at `embassy_stm32::pac`. 96# Reexport stm32-metapac at `embassy_stm32::pac`.
96# This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. 97# This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version.
diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs
index f56e50f9b..c328224fa 100644
--- a/embassy-stm32/src/i2c/v1.rs
+++ b/embassy-stm32/src/i2c/v1.rs
@@ -1,5 +1,6 @@
1use core::marker::PhantomData; 1use core::marker::PhantomData;
2 2
3use embassy_embedded_hal::SetConfig;
3use embassy_hal_common::unborrow; 4use embassy_hal_common::unborrow;
4 5
5use crate::gpio::sealed::AFType; 6use crate::gpio::sealed::AFType;
@@ -449,3 +450,23 @@ impl Timings {
449 } 450 }
450 } 451 }
451} 452}
453
454impl<'d, T: Instance> SetConfig for I2c<'d, T> {
455 type Config = Hertz;
456 fn set_config(&mut self, config: &Self::Config) {
457 let timings = Timings::new(T::frequency(), *config);
458 unsafe {
459 T::regs().cr2().modify(|reg| {
460 reg.set_freq(timings.freq);
461 });
462 T::regs().ccr().modify(|reg| {
463 reg.set_f_s(timings.mode.f_s());
464 reg.set_duty(timings.duty.duty());
465 reg.set_ccr(timings.ccr);
466 });
467 T::regs().trise().modify(|reg| {
468 reg.set_trise(timings.trise);
469 });
470 }
471 }
472}
diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs
index 08b43bebd..672f09399 100644
--- a/embassy-stm32/src/i2c/v2.rs
+++ b/embassy-stm32/src/i2c/v2.rs
@@ -4,6 +4,7 @@ use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicUsize, Ordering}; 5use atomic_polyfill::{AtomicUsize, Ordering};
6use embassy::waitqueue::AtomicWaker; 6use embassy::waitqueue::AtomicWaker;
7use embassy_embedded_hal::SetConfig;
7use embassy_hal_common::drop::OnDrop; 8use embassy_hal_common::drop::OnDrop;
8use embassy_hal_common::unborrow; 9use embassy_hal_common::unborrow;
9use futures::future::poll_fn; 10use futures::future::poll_fn;
@@ -941,3 +942,19 @@ cfg_if::cfg_if! {
941 } 942 }
942 } 943 }
943} 944}
945
946impl<'d, T: Instance> SetConfig for I2c<'d, T> {
947 type Config = Hertz;
948 fn set_config(&mut self, config: &Self::Config) {
949 let timings = Timings::new(T::frequency(), *config);
950 unsafe {
951 T::regs().timingr().write(|reg| {
952 reg.set_presc(timings.prescale);
953 reg.set_scll(timings.scll);
954 reg.set_sclh(timings.sclh);
955 reg.set_sdadel(timings.sdadel);
956 reg.set_scldel(timings.scldel);
957 });
958 }
959 }
960}
diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs
index 7c142e507..a839bb41e 100644
--- a/embassy-stm32/src/spi/mod.rs
+++ b/embassy-stm32/src/spi/mod.rs
@@ -3,6 +3,7 @@
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::ptr; 4use core::ptr;
5 5
6use embassy_embedded_hal::SetConfig;
6use embassy_hal_common::unborrow; 7use embassy_hal_common::unborrow;
7pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; 8pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
8use futures::future::join; 9use futures::future::join;
@@ -1022,3 +1023,10 @@ foreach_peripheral!(
1022 impl Instance for peripherals::$inst {} 1023 impl Instance for peripherals::$inst {}
1023 }; 1024 };
1024); 1025);
1026
1027impl<'d, T: Instance, Tx, Rx> SetConfig for Spi<'d, T, Tx, Rx> {
1028 type Config = Config;
1029 fn set_config(&mut self, config: &Self::Config) {
1030 self.reconfigure(*config);
1031 }
1032}