aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/Cargo.toml12
-rw-r--r--embassy-rp/src/gpio.rs124
-rw-r--r--embassy-rp/src/spi.rs185
-rw-r--r--examples/rp/.cargo/config.toml2
-rw-r--r--examples/rp/Cargo.toml2
-rw-r--r--examples/rp/src/bin/spi.rs2
-rw-r--r--examples/rp/src/bin/spi_display.rs4
7 files changed, 253 insertions, 78 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index cb6544028..a957af6b2 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -12,6 +12,13 @@ edition = "2018"
12# There are no plans to make this stable. 12# There are no plans to make this stable.
13unstable-pac = [] 13unstable-pac = []
14 14
15# Enable nightly-only features
16nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async"]
17
18# Implement embedded-hal 1.0 alpha traits.
19# Implement embedded-hal-async traits if `nightly` is set as well.
20unstable-traits = ["embedded-hal-1"]
21
15[dependencies] 22[dependencies]
16embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz", "nightly"] } 23embassy = { version = "0.1.0", path = "../embassy", features = [ "time-tick-1mhz", "nightly"] }
17embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" } 24embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common" }
@@ -25,4 +32,7 @@ critical-section = "0.2.5"
25 32
26rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="9ad7223a48a065e612bc7dc7be5bf5bd0b41cfc4", features = ["rt"] } 33rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="9ad7223a48a065e612bc7dc7be5bf5bd0b41cfc4", features = ["rt"] }
27#rp2040-pac2 = { path = "../../rp/rp2040-pac2", features = ["rt"] } 34#rp2040-pac2 = { path = "../../rp/rp2040-pac2", features = ["rt"] }
28embedded-hal = { version = "0.2.6", features = [ "unproven" ] } 35
36embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
37embedded-hal-1 = { package = "embedded-hal", version = "1.0.0-alpha.6", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
38embedded-hal-async = { version = "0.0.1", git = "https://github.com/embassy-rs/embedded-hal", branch = "embassy", optional = true}
diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs
index f9a5eff50..598759036 100644
--- a/embassy-rp/src/gpio.rs
+++ b/embassy-rp/src/gpio.rs
@@ -8,7 +8,6 @@ use crate::peripherals;
8 8
9use embassy::util::Unborrow; 9use embassy::util::Unborrow;
10use embassy_hal_common::{unborrow, unsafe_impl_unborrow}; 10use embassy_hal_common::{unborrow, unsafe_impl_unborrow};
11use embedded_hal::digital::v2 as digital;
12 11
13/// Represents a digital input or output level. 12/// Represents a digital input or output level.
14#[derive(Debug, Eq, PartialEq)] 13#[derive(Debug, Eq, PartialEq)]
@@ -81,18 +80,6 @@ impl<'d, T: Pin> Drop for Input<'d, T> {
81 } 80 }
82} 81}
83 82
84impl<'d, T: Pin> digital::InputPin for Input<'d, T> {
85 type Error = Infallible;
86
87 fn is_high(&self) -> Result<bool, Self::Error> {
88 Ok(self.is_high())
89 }
90
91 fn is_low(&self) -> Result<bool, Self::Error> {
92 Ok(self.is_low())
93 }
94}
95
96pub struct Output<'d, T: Pin> { 83pub struct Output<'d, T: Pin> {
97 pin: T, 84 pin: T,
98 phantom: PhantomData<&'d mut T>, 85 phantom: PhantomData<&'d mut T>,
@@ -151,34 +138,6 @@ impl<'d, T: Pin> Drop for Output<'d, T> {
151 } 138 }
152} 139}
153 140
154impl<'d, T: Pin> digital::OutputPin for Output<'d, T> {
155 type Error = Infallible;
156
157 /// Set the output as high.
158 fn set_high(&mut self) -> Result<(), Self::Error> {
159 self.set_high();
160 Ok(())
161 }
162
163 /// Set the output as low.
164 fn set_low(&mut self) -> Result<(), Self::Error> {
165 self.set_low();
166 Ok(())
167 }
168}
169
170impl<'d, T: Pin> digital::StatefulOutputPin for Output<'d, T> {
171 /// Is the output pin set as high?
172 fn is_set_high(&self) -> Result<bool, Self::Error> {
173 Ok(self.is_set_high())
174 }
175
176 /// Is the output pin set as low?
177 fn is_set_low(&self) -> Result<bool, Self::Error> {
178 Ok(self.is_set_low())
179 }
180}
181
182pub(crate) mod sealed { 141pub(crate) mod sealed {
183 use super::*; 142 use super::*;
184 143
@@ -296,3 +255,86 @@ impl_pin!(PIN_QSPI_SD0, Bank::Qspi, 2);
296impl_pin!(PIN_QSPI_SD1, Bank::Qspi, 3); 255impl_pin!(PIN_QSPI_SD1, Bank::Qspi, 3);
297impl_pin!(PIN_QSPI_SD2, Bank::Qspi, 4); 256impl_pin!(PIN_QSPI_SD2, Bank::Qspi, 4);
298impl_pin!(PIN_QSPI_SD3, Bank::Qspi, 5); 257impl_pin!(PIN_QSPI_SD3, Bank::Qspi, 5);
258
259// ====================
260
261mod eh02 {
262 use super::*;
263
264 impl<'d, T: Pin> embedded_hal_02::digital::v2::InputPin for Input<'d, T> {
265 type Error = Infallible;
266
267 fn is_high(&self) -> Result<bool, Self::Error> {
268 Ok(self.is_high())
269 }
270
271 fn is_low(&self) -> Result<bool, Self::Error> {
272 Ok(self.is_low())
273 }
274 }
275
276 impl<'d, T: Pin> embedded_hal_02::digital::v2::OutputPin for Output<'d, T> {
277 type Error = Infallible;
278
279 fn set_high(&mut self) -> Result<(), Self::Error> {
280 Ok(self.set_high())
281 }
282
283 fn set_low(&mut self) -> Result<(), Self::Error> {
284 Ok(self.set_low())
285 }
286 }
287
288 impl<'d, T: Pin> embedded_hal_02::digital::v2::StatefulOutputPin for Output<'d, T> {
289 fn is_set_high(&self) -> Result<bool, Self::Error> {
290 Ok(self.is_set_high())
291 }
292
293 fn is_set_low(&self) -> Result<bool, Self::Error> {
294 Ok(self.is_set_low())
295 }
296 }
297}
298
299#[cfg(feature = "unstable-traits")]
300mod eh1 {
301 use super::*;
302
303 impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Input<'d, T> {
304 type Error = Infallible;
305 }
306
307 impl<'d, T: Pin> embedded_hal_1::digital::blocking::InputPin for Input<'d, T> {
308 fn is_high(&self) -> Result<bool, Self::Error> {
309 Ok(self.is_high())
310 }
311
312 fn is_low(&self) -> Result<bool, Self::Error> {
313 Ok(self.is_low())
314 }
315 }
316
317 impl<'d, T: Pin> embedded_hal_1::digital::ErrorType for Output<'d, T> {
318 type Error = Infallible;
319 }
320
321 impl<'d, T: Pin> embedded_hal_1::digital::blocking::OutputPin for Output<'d, T> {
322 fn set_high(&mut self) -> Result<(), Self::Error> {
323 Ok(self.set_high())
324 }
325
326 fn set_low(&mut self) -> Result<(), Self::Error> {
327 Ok(self.set_low())
328 }
329 }
330
331 impl<'d, T: Pin> embedded_hal_1::digital::blocking::StatefulOutputPin for Output<'d, T> {
332 fn is_set_high(&self) -> Result<bool, Self::Error> {
333 Ok(self.is_set_high())
334 }
335
336 fn is_set_low(&self) -> Result<bool, Self::Error> {
337 Ok(self.is_set_low())
338 }
339 }
340}
diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs
index 3d498aff9..549e1bd06 100644
--- a/embassy-rp/src/spi.rs
+++ b/embassy-rp/src/spi.rs
@@ -2,28 +2,33 @@ use core::marker::PhantomData;
2 2
3use embassy::util::Unborrow; 3use embassy::util::Unborrow;
4use embassy_hal_common::unborrow; 4use embassy_hal_common::unborrow;
5use embedded_hal::blocking::spi as eh;
6use embedded_hal::spi as ehnb;
7 5
8use crate::gpio::sealed::Pin as _; 6use crate::gpio::sealed::Pin as _;
9use crate::gpio::{AnyPin, Pin as GpioPin}; 7use crate::gpio::{AnyPin, Pin as GpioPin};
10use crate::{pac, peripherals}; 8use crate::{pac, peripherals};
11 9
12pub use ehnb::{Phase, Polarity}; 10pub use embedded_hal_02::spi::{Phase, Polarity};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
14#[non_exhaustive]
15pub enum Error {
16 // No errors for now
17}
13 18
14#[non_exhaustive] 19#[non_exhaustive]
15pub struct Config { 20pub struct Config {
16 pub frequency: u32, 21 pub frequency: u32,
17 pub phase: ehnb::Phase, 22 pub phase: Phase,
18 pub polarity: ehnb::Polarity, 23 pub polarity: Polarity,
19} 24}
20 25
21impl Default for Config { 26impl Default for Config {
22 fn default() -> Self { 27 fn default() -> Self {
23 Self { 28 Self {
24 frequency: 1_000_000, 29 frequency: 1_000_000,
25 phase: ehnb::Phase::CaptureOnFirstTransition, 30 phase: Phase::CaptureOnFirstTransition,
26 polarity: ehnb::Polarity::IdleLow, 31 polarity: Polarity::IdleLow,
27 } 32 }
28 } 33 }
29} 34}
@@ -130,8 +135,8 @@ impl<'d, T: Instance> Spi<'d, T> {
130 p.cpsr().write(|w| w.set_cpsdvsr(presc)); 135 p.cpsr().write(|w| w.set_cpsdvsr(presc));
131 p.cr0().write(|w| { 136 p.cr0().write(|w| {
132 w.set_dss(0b0111); // 8bit 137 w.set_dss(0b0111); // 8bit
133 w.set_spo(config.polarity == ehnb::Polarity::IdleHigh); 138 w.set_spo(config.polarity == Polarity::IdleHigh);
134 w.set_sph(config.phase == ehnb::Phase::CaptureOnSecondTransition); 139 w.set_sph(config.phase == Phase::CaptureOnSecondTransition);
135 w.set_scr(postdiv); 140 w.set_scr(postdiv);
136 }); 141 });
137 p.cr1().write(|w| { 142 p.cr1().write(|w| {
@@ -157,7 +162,7 @@ impl<'d, T: Instance> Spi<'d, T> {
157 } 162 }
158 } 163 }
159 164
160 pub fn write(&mut self, data: &[u8]) { 165 pub fn blocking_write(&mut self, data: &[u8]) -> Result<(), Error> {
161 unsafe { 166 unsafe {
162 let p = self.inner.regs(); 167 let p = self.inner.regs();
163 for &b in data { 168 for &b in data {
@@ -166,11 +171,12 @@ impl<'d, T: Instance> Spi<'d, T> {
166 while !p.sr().read().rne() {} 171 while !p.sr().read().rne() {}
167 let _ = p.dr().read(); 172 let _ = p.dr().read();
168 } 173 }
169 self.flush();
170 } 174 }
175 self.flush()?;
176 Ok(())
171 } 177 }
172 178
173 pub fn transfer(&mut self, data: &mut [u8]) { 179 pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<(), Error> {
174 unsafe { 180 unsafe {
175 let p = self.inner.regs(); 181 let p = self.inner.regs();
176 for b in data { 182 for b in data {
@@ -179,15 +185,50 @@ impl<'d, T: Instance> Spi<'d, T> {
179 while !p.sr().read().rne() {} 185 while !p.sr().read().rne() {}
180 *b = p.dr().read().data() as u8; 186 *b = p.dr().read().data() as u8;
181 } 187 }
182 self.flush();
183 } 188 }
189 self.flush()?;
190 Ok(())
191 }
192
193 pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<(), Error> {
194 unsafe {
195 let p = self.inner.regs();
196 for b in data {
197 while !p.sr().read().tnf() {}
198 p.dr().write(|w| w.set_data(0));
199 while !p.sr().read().rne() {}
200 *b = p.dr().read().data() as u8;
201 }
202 }
203 self.flush()?;
204 Ok(())
205 }
206
207 pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
208 unsafe {
209 let p = self.inner.regs();
210 let len = read.len().max(write.len());
211 for i in 0..len {
212 let wb = write.get(i).copied().unwrap_or(0);
213 while !p.sr().read().tnf() {}
214 p.dr().write(|w| w.set_data(wb as _));
215 while !p.sr().read().rne() {}
216 let rb = p.dr().read().data() as u8;
217 if let Some(r) = read.get_mut(i) {
218 *r = rb;
219 }
220 }
221 }
222 self.flush()?;
223 Ok(())
184 } 224 }
185 225
186 pub fn flush(&mut self) { 226 pub fn flush(&mut self) -> Result<(), Error> {
187 unsafe { 227 unsafe {
188 let p = self.inner.regs(); 228 let p = self.inner.regs();
189 while p.sr().read().bsy() {} 229 while p.sr().read().bsy() {}
190 } 230 }
231 Ok(())
191 } 232 }
192 233
193 pub fn set_frequency(&mut self, freq: u32) { 234 pub fn set_frequency(&mut self, freq: u32) {
@@ -209,23 +250,6 @@ impl<'d, T: Instance> Spi<'d, T> {
209 } 250 }
210} 251}
211 252
212impl<'d, T: Instance> eh::Write<u8> for Spi<'d, T> {
213 type Error = core::convert::Infallible;
214
215 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
216 self.write(words);
217 Ok(())
218 }
219}
220
221impl<'d, T: Instance> eh::Transfer<u8> for Spi<'d, T> {
222 type Error = core::convert::Infallible;
223 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
224 self.transfer(words);
225 Ok(words)
226 }
227}
228
229mod sealed { 253mod sealed {
230 use super::*; 254 use super::*;
231 255
@@ -281,3 +305,102 @@ impl_pin!(PIN_16, SPI0, MisoPin);
281impl_pin!(PIN_17, SPI0, CsPin); 305impl_pin!(PIN_17, SPI0, CsPin);
282impl_pin!(PIN_18, SPI0, ClkPin); 306impl_pin!(PIN_18, SPI0, ClkPin);
283impl_pin!(PIN_19, SPI0, MosiPin); 307impl_pin!(PIN_19, SPI0, MosiPin);
308
309// ====================
310
311mod eh02 {
312 use super::*;
313
314 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Transfer<u8> for Spi<'d, T> {
315 type Error = Error;
316 fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> {
317 self.blocking_transfer_in_place(words)?;
318 Ok(words)
319 }
320 }
321
322 impl<'d, T: Instance> embedded_hal_02::blocking::spi::Write<u8> for Spi<'d, T> {
323 type Error = Error;
324
325 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
326 self.blocking_write(words)
327 }
328 }
329}
330
331#[cfg(feature = "unstable-traits")]
332mod eh1 {
333 use super::*;
334
335 impl embedded_hal_1::spi::Error for Error {
336 fn kind(&self) -> embedded_hal_1::spi::ErrorKind {
337 match *self {}
338 }
339 }
340
341 impl<'d, T: Instance> embedded_hal_1::spi::ErrorType for Spi<'d, T> {
342 type Error = Error;
343 }
344
345 impl<'d, T: Instance> embedded_hal_1::spi::blocking::Read<u8> for Spi<'d, T> {
346 fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
347 self.blocking_transfer(words, &[])
348 }
349
350 fn read_transaction(&mut self, words: &mut [&mut [u8]]) -> Result<(), Self::Error> {
351 for buf in words {
352 self.blocking_read(buf)?
353 }
354 Ok(())
355 }
356 }
357
358 impl<'d, T: Instance> embedded_hal_1::spi::blocking::Write<u8> for Spi<'d, T> {
359 fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
360 self.blocking_write(words)
361 }
362
363 fn write_transaction(&mut self, words: &[&[u8]]) -> Result<(), Self::Error> {
364 for buf in words {
365 self.blocking_write(buf)?
366 }
367 Ok(())
368 }
369
370 fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
371 where
372 WI: IntoIterator<Item = u8>,
373 {
374 for w in words {
375 self.blocking_write(&[w])?;
376 }
377 Ok(())
378 }
379 }
380
381 impl<'d, T: Instance> embedded_hal_1::spi::blocking::ReadWrite<u8> for Spi<'d, T> {
382 fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
383 self.blocking_transfer(read, write)
384 }
385
386 fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
387 self.blocking_transfer_in_place(words)
388 }
389
390 fn transaction<'a>(
391 &mut self,
392 operations: &mut [embedded_hal_1::spi::blocking::Operation<'a, u8>],
393 ) -> Result<(), Self::Error> {
394 use embedded_hal_1::spi::blocking::Operation;
395 for o in operations {
396 match o {
397 Operation::Read(b) => self.blocking_read(b)?,
398 Operation::Write(b) => self.blocking_write(b)?,
399 Operation::Transfer(r, w) => self.blocking_transfer(r, w)?,
400 Operation::TransferInPlace(b) => self.blocking_transfer_in_place(b)?,
401 }
402 }
403 Ok(())
404 }
405 }
406}
diff --git a/examples/rp/.cargo/config.toml b/examples/rp/.cargo/config.toml
index 1ce57510b..ac54f9693 100644
--- a/examples/rp/.cargo/config.toml
+++ b/examples/rp/.cargo/config.toml
@@ -1,5 +1,5 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))'] 1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2runner = "probe-run-rp --chip RP2040" 2runner = "probe-run --chip RP2040"
3 3
4[build] 4[build]
5target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+ 5target = "thumbv6m-none-eabi" # Cortex-M0 and Cortex-M0+
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index b3dfb04dc..c067fbbcf 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -7,7 +7,7 @@ version = "0.1.0"
7 7
8[dependencies] 8[dependencies]
9embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } 9embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] }
10embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt"] } 10embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac"] }
11atomic-polyfill = "0.1.5" 11atomic-polyfill = "0.1.5"
12 12
13defmt = "0.3" 13defmt = "0.3"
diff --git a/examples/rp/src/bin/spi.rs b/examples/rp/src/bin/spi.rs
index 71dec94f3..3348dc999 100644
--- a/examples/rp/src/bin/spi.rs
+++ b/examples/rp/src/bin/spi.rs
@@ -34,7 +34,7 @@ async fn main(_spawner: Spawner, p: Peripherals) {
34 loop { 34 loop {
35 cs.set_low(); 35 cs.set_low();
36 let mut buf = [0x90, 0x00, 0x00, 0xd0, 0x00, 0x00]; 36 let mut buf = [0x90, 0x00, 0x00, 0xd0, 0x00, 0x00];
37 spi.transfer(&mut buf); 37 spi.blocking_transfer_in_place(&mut buf).unwrap();
38 cs.set_high(); 38 cs.set_high();
39 39
40 let x = (buf[1] as u32) << 5 | (buf[2] as u32) >> 3; 40 let x = (buf[1] as u32) << 5 | (buf[2] as u32) >> 3;
diff --git a/examples/rp/src/bin/spi_display.rs b/examples/rp/src/bin/spi_display.rs
index 96f0cf378..01149c250 100644
--- a/examples/rp/src/bin/spi_display.rs
+++ b/examples/rp/src/bin/spi_display.rs
@@ -131,7 +131,7 @@ impl<'a> embedded_hal::blocking::spi::Write<u8> for DisplaySpi<'a> {
131 this.display_cs.set_low(); 131 this.display_cs.set_low();
132 this.last_mode = SpiMode::Display; 132 this.last_mode = SpiMode::Display;
133 } 133 }
134 this.spi.write(words); 134 this.spi.write(words).unwrap();
135 Ok(()) 135 Ok(())
136 } 136 }
137} 137}
@@ -147,7 +147,7 @@ impl<'a> embedded_hal::blocking::spi::Transfer<u8> for TouchSpi<'a> {
147 this.display_cs.set_high(); 147 this.display_cs.set_high();
148 this.last_mode = SpiMode::Touch; 148 this.last_mode = SpiMode::Touch;
149 } 149 }
150 this.spi.transfer(words); 150 this.spi.transfer(words).unwrap();
151 Ok(words) 151 Ok(words)
152 } 152 }
153} 153}