1use core::marker::PhantomData;
18
19mod hal_02;
20mod hal_1;
21
22pub(crate) mod uart_impls;
23pub use uart_impls::Instance;
24use uart_impls::RegisterBlockImpl;
25
26use crate::gpio::{self, PushPull};
27
28use crate::pac;
29
30use crate::gpio::NoPin;
31use crate::rcc::Clocks;
32
33pub mod dma;
34
35#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
41#[non_exhaustive]
42pub enum Error {
43 Overrun,
45 FrameFormat,
48 Parity,
50 Noise,
52 Other,
54}
55
56#[enumflags2::bitflags]
58#[cfg_attr(feature = "defmt", derive(defmt::Format))]
59#[derive(Debug, Eq, PartialEq, Copy, Clone)]
60#[repr(u32)]
61pub enum Event {
62 Idle = 1 << 4,
64 RxNotEmpty = 1 << 5,
66 TransmissionComplete = 1 << 6,
68 TxEmpty = 1 << 7,
70 ParityError = 1 << 8,
72}
73
74#[enumflags2::bitflags]
76#[cfg_attr(feature = "defmt", derive(defmt::Format))]
77#[derive(Debug, Eq, PartialEq, Copy, Clone)]
78#[repr(u32)]
79pub enum Flag {
80 ParityError = 1 << 0,
82 FramingError = 1 << 1,
84 Noise = 1 << 2,
86 Overrun = 1 << 3,
88 Idle = 1 << 4,
90 RxNotEmpty = 1 << 5,
92 TransmissionComplete = 1 << 6,
94 TxEmpty = 1 << 7,
96 LinBreak = 1 << 8,
98 Cts = 1 << 9,
100}
101
102#[enumflags2::bitflags]
104#[cfg_attr(feature = "defmt", derive(defmt::Format))]
105#[derive(Debug, Eq, PartialEq, Copy, Clone)]
106#[repr(u32)]
107pub enum CFlag {
108 RxNotEmpty = 1 << 5,
110 TransmissionComplete = 1 << 6,
112 LinBreak = 1 << 8,
114}
115
116pub mod config;
117
118pub use config::Config;
119
120pub use gpio::NoPin as NoTx;
122pub use gpio::NoPin as NoRx;
124
125pub use gpio::alt::SerialAsync as CommonPins;
126
127pub trait RxISR {
129 fn is_idle(&self) -> bool;
131
132 fn is_rx_not_empty(&self) -> bool;
134
135 fn clear_idle_interrupt(&self);
137}
138
139pub trait TxISR {
141 fn is_tx_empty(&self) -> bool;
143}
144
145pub trait RxListen {
147 fn listen(&mut self);
152
153 fn unlisten(&mut self);
155
156 fn listen_idle(&mut self);
161
162 fn unlisten_idle(&mut self);
164}
165
166pub trait TxListen {
168 fn listen(&mut self);
173
174 fn unlisten(&mut self);
176}
177
178pub struct Serial<USART: CommonPins, WORD = u8> {
180 tx: Tx<USART, WORD>,
181 rx: Rx<USART, WORD>,
182}
183
184pub struct Rx<USART: CommonPins, WORD = u8> {
186 _word: PhantomData<WORD>,
187 usart: USART,
188 pin: USART::Rx<PushPull>,
189}
190
191pub struct Tx<USART: CommonPins, WORD = u8> {
193 _word: PhantomData<WORD>,
194 usart: USART,
195 pin: USART::Tx<PushPull>,
196}
197
198pub trait SerialExt: Sized + Instance {
199 fn serial<WORD>(
200 self,
201 pins: (impl Into<Self::Tx<PushPull>>, impl Into<Self::Rx<PushPull>>),
202 config: impl Into<config::Config>,
203 clocks: &Clocks,
204 ) -> Result<Serial<Self, WORD>, config::InvalidConfig>;
205
206 fn tx<WORD>(
207 self,
208 tx_pin: impl Into<Self::Tx<PushPull>>,
209 config: impl Into<config::Config>,
210 clocks: &Clocks,
211 ) -> Result<Tx<Self, WORD>, config::InvalidConfig>
212 where
213 NoPin: Into<Self::Rx<PushPull>>,
214 {
215 self.serial((tx_pin, NoPin::new()), config, clocks)
216 .map(|s| s.split().0)
217 }
218
219 fn rx<WORD>(
220 self,
221 rx_pin: impl Into<Self::Rx<PushPull>>,
222 config: impl Into<config::Config>,
223 clocks: &Clocks,
224 ) -> Result<Rx<Self, WORD>, config::InvalidConfig>
225 where
226 NoPin: Into<Self::Tx<PushPull>>,
227 {
228 self.serial((NoPin::new(), rx_pin), config, clocks)
229 .map(|s| s.split().1)
230 }
231}
232
233impl<USART: Instance, WORD> Serial<USART, WORD> {
234 pub fn new(
235 usart: USART,
236 pins: (
237 impl Into<USART::Tx<PushPull>>,
238 impl Into<USART::Rx<PushPull>>,
239 ),
240 config: impl Into<config::Config>,
241 clocks: &Clocks,
242 ) -> Result<Self, config::InvalidConfig> {
243 <USART as crate::Ptr>::RB::new(usart, pins, config, clocks)
244 }
245}
246
247impl<UART: CommonPins, WORD> Serial<UART, WORD> {
248 pub fn split(self) -> (Tx<UART, WORD>, Rx<UART, WORD>) {
249 (self.tx, self.rx)
250 }
251
252 #[allow(clippy::type_complexity)]
253 pub fn release(self) -> (UART, (UART::Tx<PushPull>, UART::Rx<PushPull>)) {
254 (self.tx.usart, (self.tx.pin, self.rx.pin))
255 }
256}
257
258macro_rules! halUsart {
259 ($USART:ty, $Serial:ident, $Rx:ident, $Tx:ident) => {
260 pub type $Serial<WORD = u8> = Serial<$USART, WORD>;
261 pub type $Tx<WORD = u8> = Tx<$USART, WORD>;
262 pub type $Rx<WORD = u8> = Rx<$USART, WORD>;
263
264 impl Instance for $USART {
265 fn set_stopbits(&self, bits: config::StopBits) {
266 use crate::pac::usart1::cr2::STOP;
267 use config::StopBits;
268
269 self.cr2().write(|w| {
270 w.stop().variant(match bits {
271 StopBits::STOP0P5 => STOP::Stop0p5,
272 StopBits::STOP1 => STOP::Stop1,
273 StopBits::STOP1P5 => STOP::Stop1p5,
274 StopBits::STOP2 => STOP::Stop2,
275 })
276 });
277 }
278 }
279
280 impl crate::Ptr for $USART {
281 type RB = crate::serial::uart_impls::RegisterBlockUsart;
282
283 fn ptr() -> *const Self::RB {
284 Self::ptr()
285 }
286 }
287
288 impl crate::Steal for $USART {
289 unsafe fn steal() -> Self {
290 Self::steal()
291 }
292 }
293 };
294}
295pub(crate) use halUsart;
296
297halUsart! { pac::USART1, Serial1, Rx1, Tx1 }
298halUsart! { pac::USART2, Serial2, Rx2, Tx2 }
299halUsart! { pac::USART6, Serial6, Rx6, Tx6 }
300
301#[cfg(feature = "usart3")]
302halUsart! { pac::USART3, Serial3, Rx3, Tx3 }
303
304impl<UART: CommonPins> Rx<UART, u8> {
305 pub(crate) fn with_u16_data(self) -> Rx<UART, u16> {
306 Rx::new(self.usart, self.pin)
307 }
308}
309
310impl<UART: CommonPins> Rx<UART, u16> {
311 pub(crate) fn with_u8_data(self) -> Rx<UART, u8> {
312 Rx::new(self.usart, self.pin)
313 }
314}
315
316impl<UART: CommonPins> Tx<UART, u8> {
317 pub(crate) fn with_u16_data(self) -> Tx<UART, u16> {
318 Tx::new(self.usart, self.pin)
319 }
320}
321
322impl<UART: CommonPins> Tx<UART, u16> {
323 pub(crate) fn with_u8_data(self) -> Tx<UART, u8> {
324 Tx::new(self.usart, self.pin)
325 }
326}
327
328impl<UART: CommonPins, WORD> Rx<UART, WORD> {
329 pub(crate) fn new(usart: UART, pin: UART::Rx<PushPull>) -> Self {
330 Self {
331 _word: PhantomData,
332 usart,
333 pin,
334 }
335 }
336
337 pub fn join(self, tx: Tx<UART, WORD>) -> Serial<UART, WORD> {
338 Serial { tx, rx: self }
339 }
340}
341
342impl<UART: CommonPins, WORD> Tx<UART, WORD> {
343 pub(crate) fn new(usart: UART, pin: UART::Tx<PushPull>) -> Self {
344 Self {
345 _word: PhantomData,
346 usart,
347 pin,
348 }
349 }
350
351 pub fn join(self, rx: Rx<UART, WORD>) -> Serial<UART, WORD> {
352 Serial { tx: self, rx }
353 }
354}
355
356impl<UART: Instance, WORD> AsRef<Tx<UART, WORD>> for Serial<UART, WORD> {
357 #[inline(always)]
358 fn as_ref(&self) -> &Tx<UART, WORD> {
359 &self.tx
360 }
361}
362
363impl<UART: Instance, WORD> AsRef<Rx<UART, WORD>> for Serial<UART, WORD> {
364 #[inline(always)]
365 fn as_ref(&self) -> &Rx<UART, WORD> {
366 &self.rx
367 }
368}
369
370impl<UART: Instance, WORD> AsMut<Tx<UART, WORD>> for Serial<UART, WORD> {
371 #[inline(always)]
372 fn as_mut(&mut self) -> &mut Tx<UART, WORD> {
373 &mut self.tx
374 }
375}
376
377impl<UART: Instance, WORD> AsMut<Rx<UART, WORD>> for Serial<UART, WORD> {
378 #[inline(always)]
379 fn as_mut(&mut self) -> &mut Rx<UART, WORD> {
380 &mut self.rx
381 }
382}
383
384impl<UART: Instance> Serial<UART, u8> {
385 pub fn with_u16_data(self) -> Serial<UART, u16> {
389 Serial {
390 tx: self.tx.with_u16_data(),
391 rx: self.rx.with_u16_data(),
392 }
393 }
394}
395
396impl<UART: Instance> Serial<UART, u16> {
397 pub fn with_u8_data(self) -> Serial<UART, u8> {
401 Serial {
402 tx: self.tx.with_u8_data(),
403 rx: self.rx.with_u8_data(),
404 }
405 }
406}