diff options
| -rw-r--r-- | embassy-hal-common/src/ring_buffer.rs | 45 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/v2.rs | 226 | ||||
| -rw-r--r-- | examples/stm32l0/Cargo.toml | 1 | ||||
| -rw-r--r-- | examples/stm32l0/src/bin/usart_irq.rs | 51 | ||||
| m--------- | stm32-data | 0 |
7 files changed, 324 insertions, 15 deletions
diff --git a/embassy-hal-common/src/ring_buffer.rs b/embassy-hal-common/src/ring_buffer.rs index 18795787f..6829f62f5 100644 --- a/embassy-hal-common/src/ring_buffer.rs +++ b/embassy-hal-common/src/ring_buffer.rs | |||
| @@ -67,6 +67,14 @@ impl<'a> RingBuffer<'a> { | |||
| 67 | self.empty = self.start == self.end; | 67 | self.empty = self.start == self.end; |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | pub fn is_full(&self) -> bool { | ||
| 71 | self.start == self.end && !self.empty | ||
| 72 | } | ||
| 73 | |||
| 74 | pub fn is_empty(&self) -> bool { | ||
| 75 | self.empty | ||
| 76 | } | ||
| 77 | |||
| 70 | pub fn clear(&mut self) { | 78 | pub fn clear(&mut self) { |
| 71 | self.start = 0; | 79 | self.start = 0; |
| 72 | self.end = 0; | 80 | self.end = 0; |
| @@ -82,3 +90,40 @@ impl<'a> RingBuffer<'a> { | |||
| 82 | } | 90 | } |
| 83 | } | 91 | } |
| 84 | } | 92 | } |
| 93 | |||
| 94 | #[cfg(test)] | ||
| 95 | mod tests { | ||
| 96 | use super::*; | ||
| 97 | |||
| 98 | #[test] | ||
| 99 | fn push_pop() { | ||
| 100 | let mut b = [0; 4]; | ||
| 101 | let mut rb = RingBuffer::new(&mut b); | ||
| 102 | let buf = rb.push_buf(); | ||
| 103 | assert_eq!(4, buf.len()); | ||
| 104 | buf[0] = 1; | ||
| 105 | buf[1] = 2; | ||
| 106 | buf[2] = 3; | ||
| 107 | buf[3] = 4; | ||
| 108 | rb.push(4); | ||
| 109 | |||
| 110 | let buf = rb.pop_buf(); | ||
| 111 | assert_eq!(4, buf.len()); | ||
| 112 | assert_eq!(1, buf[0]); | ||
| 113 | rb.pop(1); | ||
| 114 | |||
| 115 | let buf = rb.pop_buf(); | ||
| 116 | assert_eq!(3, buf.len()); | ||
| 117 | assert_eq!(2, buf[0]); | ||
| 118 | rb.pop(1); | ||
| 119 | |||
| 120 | let buf = rb.pop_buf(); | ||
| 121 | assert_eq!(2, buf.len()); | ||
| 122 | assert_eq!(3, buf[0]); | ||
| 123 | rb.pop(1); | ||
| 124 | |||
| 125 | let buf = rb.pop_buf(); | ||
| 126 | assert_eq!(1, buf.len()); | ||
| 127 | assert_eq!(4, buf[0]); | ||
| 128 | } | ||
| 129 | } | ||
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 9b9db0f0c..fd121f6db 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -23,7 +23,7 @@ sdio-host = { version = "0.5.0" } | |||
| 23 | embedded-sdmmc = { git = "https://github.com/thalesfragoso/embedded-sdmmc-rs", branch = "async", optional = true } | 23 | embedded-sdmmc = { git = "https://github.com/thalesfragoso/embedded-sdmmc-rs", branch = "async", optional = true } |
| 24 | critical-section = "0.2.1" | 24 | critical-section = "0.2.1" |
| 25 | bare-metal = "1.0.0" | 25 | bare-metal = "1.0.0" |
| 26 | atomic-polyfill = "0.1.2" | 26 | atomic-polyfill = "0.1.3" |
| 27 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } | 27 | stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt"] } |
| 28 | vcell = { version = "0.1.3", optional = true } | 28 | vcell = { version = "0.1.3", optional = true } |
| 29 | 29 | ||
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index 9df00d3a8..c1cdd8d73 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -8,6 +8,7 @@ pub use _version::*; | |||
| 8 | 8 | ||
| 9 | use crate::gpio::Pin; | 9 | use crate::gpio::Pin; |
| 10 | use crate::rcc::RccPeripheral; | 10 | use crate::rcc::RccPeripheral; |
| 11 | use embassy::interrupt::Interrupt; | ||
| 11 | 12 | ||
| 12 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | 13 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| 13 | pub enum DataBits { | 14 | pub enum DataBits { |
| @@ -100,7 +101,9 @@ pub(crate) mod sealed { | |||
| 100 | } | 101 | } |
| 101 | } | 102 | } |
| 102 | 103 | ||
| 103 | pub trait Instance: sealed::Instance + RccPeripheral {} | 104 | pub trait Instance: sealed::Instance + RccPeripheral { |
| 105 | type Interrupt: Interrupt; | ||
| 106 | } | ||
| 104 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} | 107 | pub trait RxPin<T: Instance>: sealed::RxPin<T> {} |
| 105 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} | 108 | pub trait TxPin<T: Instance>: sealed::TxPin<T> {} |
| 106 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} | 109 | pub trait CtsPin<T: Instance>: sealed::CtsPin<T> {} |
| @@ -109,15 +112,18 @@ pub trait CkPin<T: Instance>: sealed::CkPin<T> {} | |||
| 109 | pub trait RxDma<T: Instance>: sealed::RxDma<T> + dma::Channel {} | 112 | pub trait RxDma<T: Instance>: sealed::RxDma<T> + dma::Channel {} |
| 110 | pub trait TxDma<T: Instance>: sealed::TxDma<T> + dma::Channel {} | 113 | pub trait TxDma<T: Instance>: sealed::TxDma<T> + dma::Channel {} |
| 111 | 114 | ||
| 112 | crate::pac::peripherals!( | 115 | crate::pac::interrupts!( |
| 113 | (usart, $inst:ident) => { | 116 | ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { |
| 114 | impl sealed::Instance for peripherals::$inst { | 117 | impl sealed::Instance for peripherals::$inst { |
| 115 | fn regs(&self) -> crate::pac::usart::Usart { | 118 | fn regs(&self) -> crate::pac::usart::Usart { |
| 116 | crate::pac::$inst | 119 | crate::pac::$inst |
| 117 | } | 120 | } |
| 118 | } | 121 | } |
| 119 | 122 | ||
| 120 | impl Instance for peripherals::$inst {} | 123 | impl Instance for peripherals::$inst { |
| 124 | type Interrupt = crate::interrupt::$irq; | ||
| 125 | } | ||
| 126 | |||
| 121 | }; | 127 | }; |
| 122 | ); | 128 | ); |
| 123 | 129 | ||
diff --git a/embassy-stm32/src/usart/v2.rs b/embassy-stm32/src/usart/v2.rs index 50996dbbf..92c0cbc2e 100644 --- a/embassy-stm32/src/usart/v2.rs +++ b/embassy-stm32/src/usart/v2.rs | |||
| @@ -1,6 +1,12 @@ | |||
| 1 | use atomic_polyfill::{compiler_fence, Ordering}; | ||
| 1 | use core::future::Future; | 2 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | 3 | use core::marker::PhantomData; |
| 3 | use embassy::util::Unborrow; | 4 | use core::pin::Pin; |
| 5 | use core::task::Context; | ||
| 6 | use core::task::Poll; | ||
| 7 | use embassy::util::{Unborrow, WakerRegistration}; | ||
| 8 | use embassy_hal_common::peripheral::{PeripheralMutex, PeripheralState, StateStorage}; | ||
| 9 | use embassy_hal_common::ring_buffer::RingBuffer; | ||
| 4 | use embassy_hal_common::unborrow; | 10 | use embassy_hal_common::unborrow; |
| 5 | use futures::TryFutureExt; | 11 | use futures::TryFutureExt; |
| 6 | 12 | ||
| @@ -12,7 +18,6 @@ pub struct Uart<'d, T: Instance, TxDma = NoDma, RxDma = NoDma> { | |||
| 12 | inner: T, | 18 | inner: T, |
| 13 | phantom: PhantomData<&'d mut T>, | 19 | phantom: PhantomData<&'d mut T>, |
| 14 | tx_dma: TxDma, | 20 | tx_dma: TxDma, |
| 15 | #[allow(dead_code)] | ||
| 16 | rx_dma: RxDma, | 21 | rx_dma: RxDma, |
| 17 | } | 22 | } |
| 18 | 23 | ||
| @@ -153,25 +158,226 @@ impl<'d, T: Instance, RxDma> embedded_hal::blocking::serial::Write<u8> | |||
| 153 | } | 158 | } |
| 154 | 159 | ||
| 155 | // rustfmt::skip because intellij removes the 'where' claus on the associated type. | 160 | // rustfmt::skip because intellij removes the 'where' claus on the associated type. |
| 156 | #[rustfmt::skip] | ||
| 157 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma> | 161 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Write for Uart<'d, T, TxDma, RxDma> |
| 158 | where TxDma: crate::usart::TxDma<T> | 162 | where |
| 163 | TxDma: crate::usart::TxDma<T>, | ||
| 159 | { | 164 | { |
| 160 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a; | 165 | // rustfmt::skip because rustfmt removes the 'where' claus on the associated type. |
| 166 | #[rustfmt::skip] | ||
| 167 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> +'a; | ||
| 161 | 168 | ||
| 162 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { | 169 | fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { |
| 163 | self.write_dma(buf).map_err(|_| embassy_traits::uart::Error::Other) | 170 | self.write_dma(buf) |
| 171 | .map_err(|_| embassy_traits::uart::Error::Other) | ||
| 164 | } | 172 | } |
| 165 | } | 173 | } |
| 166 | 174 | ||
| 167 | // rustfmt::skip because intellij removes the 'where' claus on the associated type. | ||
| 168 | #[rustfmt::skip] | ||
| 169 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Read for Uart<'d, T, TxDma, RxDma> | 175 | impl<'d, T: Instance, TxDma, RxDma> embassy_traits::uart::Read for Uart<'d, T, TxDma, RxDma> |
| 170 | where RxDma: crate::usart::RxDma<T> | 176 | where |
| 177 | RxDma: crate::usart::RxDma<T>, | ||
| 171 | { | 178 | { |
| 179 | // rustfmt::skip because rustfmt removes the 'where' claus on the associated type. | ||
| 180 | #[rustfmt::skip] | ||
| 172 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a; | 181 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), embassy_traits::uart::Error>> + 'a; |
| 173 | 182 | ||
| 174 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { | 183 | fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 175 | self.read_dma(buf).map_err(|_| embassy_traits::uart::Error::Other) | 184 | self.read_dma(buf) |
| 185 | .map_err(|_| embassy_traits::uart::Error::Other) | ||
| 186 | } | ||
| 187 | } | ||
| 188 | |||
| 189 | pub struct State<'d, T: Instance>(StateStorage<StateInner<'d, T>>); | ||
| 190 | impl<'d, T: Instance> State<'d, T> { | ||
| 191 | pub fn new() -> Self { | ||
| 192 | Self(StateStorage::new()) | ||
| 193 | } | ||
| 194 | } | ||
| 195 | |||
| 196 | pub struct StateInner<'d, T: Instance> { | ||
| 197 | uart: Uart<'d, T, NoDma, NoDma>, | ||
| 198 | phantom: PhantomData<&'d mut T>, | ||
| 199 | |||
| 200 | rx_waker: WakerRegistration, | ||
| 201 | rx: RingBuffer<'d>, | ||
| 202 | |||
| 203 | tx_waker: WakerRegistration, | ||
| 204 | tx: RingBuffer<'d>, | ||
| 205 | } | ||
| 206 | |||
| 207 | unsafe impl<'d, T: Instance> Send for StateInner<'d, T> {} | ||
| 208 | unsafe impl<'d, T: Instance> Sync for StateInner<'d, T> {} | ||
| 209 | |||
| 210 | pub struct BufferedUart<'d, T: Instance> { | ||
| 211 | inner: PeripheralMutex<'d, StateInner<'d, T>>, | ||
| 212 | } | ||
| 213 | |||
| 214 | impl<'d, T: Instance> Unpin for BufferedUart<'d, T> {} | ||
| 215 | |||
| 216 | impl<'d, T: Instance> BufferedUart<'d, T> { | ||
| 217 | pub unsafe fn new( | ||
| 218 | state: &'d mut State<'d, T>, | ||
| 219 | uart: Uart<'d, T, NoDma, NoDma>, | ||
| 220 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | ||
| 221 | tx_buffer: &'d mut [u8], | ||
| 222 | rx_buffer: &'d mut [u8], | ||
| 223 | ) -> BufferedUart<'d, T> { | ||
| 224 | unborrow!(irq); | ||
| 225 | |||
| 226 | let r = uart.inner.regs(); | ||
| 227 | r.cr1().modify(|w| { | ||
| 228 | w.set_rxneie(true); | ||
| 229 | w.set_idleie(true); | ||
| 230 | }); | ||
| 231 | |||
| 232 | Self { | ||
| 233 | inner: PeripheralMutex::new_unchecked(irq, &mut state.0, move || StateInner { | ||
| 234 | uart, | ||
| 235 | phantom: PhantomData, | ||
| 236 | tx: RingBuffer::new(tx_buffer), | ||
| 237 | tx_waker: WakerRegistration::new(), | ||
| 238 | |||
| 239 | rx: RingBuffer::new(rx_buffer), | ||
| 240 | rx_waker: WakerRegistration::new(), | ||
| 241 | }), | ||
| 242 | } | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | impl<'d, T: Instance> StateInner<'d, T> | ||
| 247 | where | ||
| 248 | Self: 'd, | ||
| 249 | { | ||
| 250 | fn on_rx(&mut self) { | ||
| 251 | let r = self.uart.inner.regs(); | ||
| 252 | unsafe { | ||
| 253 | let sr = r.isr().read(); | ||
| 254 | if sr.pe() { | ||
| 255 | r.icr().write(|w| { | ||
| 256 | w.set_pe(true); | ||
| 257 | }); | ||
| 258 | trace!("Parity error"); | ||
| 259 | } else if sr.fe() { | ||
| 260 | r.icr().write(|w| { | ||
| 261 | w.set_fe(true); | ||
| 262 | }); | ||
| 263 | trace!("Framing error"); | ||
| 264 | } else if sr.nf() { | ||
| 265 | r.icr().write(|w| { | ||
| 266 | w.set_nf(true); | ||
| 267 | }); | ||
| 268 | trace!("Noise error"); | ||
| 269 | } else if sr.ore() { | ||
| 270 | r.icr().write(|w| { | ||
| 271 | w.set_ore(true); | ||
| 272 | }); | ||
| 273 | trace!("Overrun error"); | ||
| 274 | } else if sr.rxne() { | ||
| 275 | let buf = self.rx.push_buf(); | ||
| 276 | if buf.is_empty() { | ||
| 277 | self.rx_waker.wake(); | ||
| 278 | } else { | ||
| 279 | buf[0] = r.rdr().read().0 as u8; | ||
| 280 | self.rx.push(1); | ||
| 281 | } | ||
| 282 | } else if sr.idle() { | ||
| 283 | r.icr().write(|w| { | ||
| 284 | w.set_idle(true); | ||
| 285 | }); | ||
| 286 | self.rx_waker.wake(); | ||
| 287 | }; | ||
| 288 | } | ||
| 289 | } | ||
| 290 | |||
| 291 | fn on_tx(&mut self) { | ||
| 292 | let r = self.uart.inner.regs(); | ||
| 293 | unsafe { | ||
| 294 | if r.isr().read().txe() { | ||
| 295 | let buf = self.tx.pop_buf(); | ||
| 296 | if !buf.is_empty() { | ||
| 297 | r.cr1().modify(|w| { | ||
| 298 | w.set_txeie(true); | ||
| 299 | }); | ||
| 300 | r.tdr().write_value(regs::Dr(buf[0].into())); | ||
| 301 | self.tx.pop(1); | ||
| 302 | self.tx_waker.wake(); | ||
| 303 | } else { | ||
| 304 | // Disable interrupt until we have something to transmit again | ||
| 305 | r.cr1().modify(|w| { | ||
| 306 | w.set_txeie(false); | ||
| 307 | }); | ||
| 308 | } | ||
| 309 | } | ||
| 310 | } | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | impl<'d, T: Instance> PeripheralState for StateInner<'d, T> | ||
| 315 | where | ||
| 316 | Self: 'd, | ||
| 317 | { | ||
| 318 | type Interrupt = T::Interrupt; | ||
| 319 | fn on_interrupt(&mut self) { | ||
| 320 | self.on_rx(); | ||
| 321 | self.on_tx(); | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | impl<'d, T: Instance> embassy::io::AsyncBufRead for BufferedUart<'d, T> { | ||
| 326 | fn poll_fill_buf( | ||
| 327 | mut self: Pin<&mut Self>, | ||
| 328 | cx: &mut Context<'_>, | ||
| 329 | ) -> Poll<Result<&[u8], embassy::io::Error>> { | ||
| 330 | self.inner.with(|state| { | ||
| 331 | compiler_fence(Ordering::SeqCst); | ||
| 332 | |||
| 333 | // We have data ready in buffer? Return it. | ||
| 334 | let buf = state.rx.pop_buf(); | ||
| 335 | if !buf.is_empty() { | ||
| 336 | let buf: &[u8] = buf; | ||
| 337 | // Safety: buffer lives as long as uart | ||
| 338 | let buf: &[u8] = unsafe { core::mem::transmute(buf) }; | ||
| 339 | return Poll::Ready(Ok(buf)); | ||
| 340 | } | ||
| 341 | |||
| 342 | state.rx_waker.register(cx.waker()); | ||
| 343 | Poll::<Result<&[u8], embassy::io::Error>>::Pending | ||
| 344 | }) | ||
| 345 | } | ||
| 346 | fn consume(mut self: Pin<&mut Self>, amt: usize) { | ||
| 347 | let signal = self.inner.with(|state| { | ||
| 348 | let full = state.rx.is_full(); | ||
| 349 | state.rx.pop(amt); | ||
| 350 | full | ||
| 351 | }); | ||
| 352 | if signal { | ||
| 353 | self.inner.pend(); | ||
| 354 | } | ||
| 355 | } | ||
| 356 | } | ||
| 357 | |||
| 358 | impl<'d, T: Instance> embassy::io::AsyncWrite for BufferedUart<'d, T> { | ||
| 359 | fn poll_write( | ||
| 360 | mut self: Pin<&mut Self>, | ||
| 361 | cx: &mut Context<'_>, | ||
| 362 | buf: &[u8], | ||
| 363 | ) -> Poll<Result<usize, embassy::io::Error>> { | ||
| 364 | let (poll, empty) = self.inner.with(|state| { | ||
| 365 | let empty = state.tx.is_empty(); | ||
| 366 | let tx_buf = state.tx.push_buf(); | ||
| 367 | if tx_buf.is_empty() { | ||
| 368 | state.tx_waker.register(cx.waker()); | ||
| 369 | return (Poll::Pending, empty); | ||
| 370 | } | ||
| 371 | |||
| 372 | let n = core::cmp::min(tx_buf.len(), buf.len()); | ||
| 373 | tx_buf[..n].copy_from_slice(&buf[..n]); | ||
| 374 | state.tx.push(n); | ||
| 375 | |||
| 376 | (Poll::Ready(Ok(n)), empty) | ||
| 377 | }); | ||
| 378 | if empty { | ||
| 379 | self.inner.pend(); | ||
| 380 | } | ||
| 381 | poll | ||
| 176 | } | 382 | } |
| 177 | } | 383 | } |
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index 6c594df66..9b3166154 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml | |||
| @@ -21,6 +21,7 @@ embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "def | |||
| 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } |
| 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32l072cz", "time-driver-tim3"] } | 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32l072cz", "time-driver-tim3"] } |
| 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } |
| 24 | embassy-macros = { path = "../../embassy-macros" } | ||
| 24 | 25 | ||
| 25 | defmt = "0.2.0" | 26 | defmt = "0.2.0" |
| 26 | defmt-rtt = "0.2.0" | 27 | defmt-rtt = "0.2.0" |
diff --git a/examples/stm32l0/src/bin/usart_irq.rs b/examples/stm32l0/src/bin/usart_irq.rs new file mode 100644 index 000000000..5c79d0671 --- /dev/null +++ b/examples/stm32l0/src/bin/usart_irq.rs | |||
| @@ -0,0 +1,51 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(trait_alias)] | ||
| 4 | #![feature(type_alias_impl_trait)] | ||
| 5 | #![allow(incomplete_features)] | ||
| 6 | |||
| 7 | #[path = "../example_common.rs"] | ||
| 8 | mod example_common; | ||
| 9 | |||
| 10 | use example_common::*; | ||
| 11 | |||
| 12 | use defmt::panic; | ||
| 13 | use embassy::executor::Spawner; | ||
| 14 | use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; | ||
| 15 | use embassy_stm32::dma::NoDma; | ||
| 16 | use embassy_stm32::interrupt; | ||
| 17 | use embassy_stm32::usart::{BufferedUart, Config, State, Uart}; | ||
| 18 | use embassy_stm32::{rcc, Peripherals}; | ||
| 19 | |||
| 20 | #[embassy::main] | ||
| 21 | async fn main(_spawner: Spawner, mut p: Peripherals) { | ||
| 22 | let mut rcc = rcc::Rcc::new(p.RCC); | ||
| 23 | rcc.enable_debug_wfe(&mut p.DBGMCU, true); | ||
| 24 | |||
| 25 | static mut TX_BUFFER: [u8; 8] = [0; 8]; | ||
| 26 | static mut RX_BUFFER: [u8; 256] = [0; 256]; | ||
| 27 | |||
| 28 | let mut config = Config::default(); | ||
| 29 | config.baudrate = 9600; | ||
| 30 | |||
| 31 | let usart = Uart::new(p.USART1, p.PA10, p.PA9, NoDma, NoDma, config); | ||
| 32 | let mut state = State::new(); | ||
| 33 | let mut usart = unsafe { | ||
| 34 | BufferedUart::new( | ||
| 35 | &mut state, | ||
| 36 | usart, | ||
| 37 | interrupt::take!(USART1), | ||
| 38 | &mut TX_BUFFER, | ||
| 39 | &mut RX_BUFFER, | ||
| 40 | ) | ||
| 41 | }; | ||
| 42 | |||
| 43 | usart.write_all(b"Hello Embassy World!\r\n").await.unwrap(); | ||
| 44 | info!("wrote Hello, starting echo"); | ||
| 45 | |||
| 46 | let mut buf = [0; 4]; | ||
| 47 | loop { | ||
| 48 | usart.read_exact(&mut buf[..]).await.unwrap(); | ||
| 49 | usart.write_all(&buf[..]).await.unwrap(); | ||
| 50 | } | ||
| 51 | } | ||
diff --git a/stm32-data b/stm32-data | |||
| Subproject af0611ff9b29f2c0ab675a4f0e51d8241a4097f | Subproject 79ab92a38d1cbb47dda2f6f8556fe1abc9a14f3 | ||
