Skip to content

Commit d059c11

Browse files
Enable macro less implementations of multiple usarts
1 parent 66b869d commit d059c11

File tree

1 file changed

+43
-104
lines changed

1 file changed

+43
-104
lines changed

src/serial.rs

Lines changed: 43 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use core::fmt::{Result, Write};
2-
use core::marker::PhantomData;
2+
use core::ops::Deref;
33
use core::ptr;
44

55
use embedded_hal::prelude::*;
66
use nb::block;
77
use void::Void;
88

99
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
10-
use crate::stm32::{RCC, USART1, USART2};
10+
use crate::stm32::{usart1, RCC, USART1, USART2};
1111

1212
use crate::gpio::*;
1313
use crate::rcc::Clocks;
@@ -83,12 +83,14 @@ pub struct Serial<USART, PINS> {
8383

8484
/// Serial receiver
8585
pub struct Rx<USART> {
86-
_usart: PhantomData<USART>,
86+
// This is ok, because the USART types only contains PhantomData
87+
usart: *const USART,
8788
}
8889

8990
/// Serial transmitter
9091
pub struct Tx<USART> {
91-
_usart: PhantomData<USART>,
92+
// This is ok, because the USART types only contains PhantomData
93+
usart: *const USART,
9294
}
9395

9496
/// USART1
@@ -117,75 +119,6 @@ impl<PINS> Serial<USART1, PINS> {
117119

118120
Serial { usart, pins }
119121
}
120-
121-
pub fn split(self) -> (Tx<USART1>, Rx<USART1>) {
122-
(
123-
Tx {
124-
_usart: PhantomData,
125-
},
126-
Rx {
127-
_usart: PhantomData,
128-
},
129-
)
130-
}
131-
pub fn release(self) -> (USART1, PINS) {
132-
(self.usart, self.pins)
133-
}
134-
}
135-
136-
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
137-
impl embedded_hal::serial::Read<u8> for Rx<USART1> {
138-
type Error = Error;
139-
140-
fn read(&mut self) -> nb::Result<u8, Error> {
141-
// NOTE(unsafe) atomic read with no side effects
142-
let isr = unsafe { (*USART1::ptr()).isr.read() };
143-
144-
Err(if isr.pe().bit_is_set() {
145-
nb::Error::Other(Error::Parity)
146-
} else if isr.fe().bit_is_set() {
147-
nb::Error::Other(Error::Framing)
148-
} else if isr.nf().bit_is_set() {
149-
nb::Error::Other(Error::Noise)
150-
} else if isr.ore().bit_is_set() {
151-
nb::Error::Other(Error::Overrun)
152-
} else if isr.rxne().bit_is_set() {
153-
// NOTE(read_volatile) see `write_volatile` below
154-
return Ok(unsafe { ptr::read_volatile(&(*USART1::ptr()).rdr as *const _ as *const _) });
155-
} else {
156-
nb::Error::WouldBlock
157-
})
158-
}
159-
}
160-
161-
#[cfg(any(feature = "stm32f042", feature = "stm32f030"))]
162-
impl embedded_hal::serial::Write<u8> for Tx<USART1> {
163-
type Error = Void;
164-
165-
fn flush(&mut self) -> nb::Result<(), Self::Error> {
166-
// NOTE(unsafe) atomic read with no side effects
167-
let isr = unsafe { (*USART1::ptr()).isr.read() };
168-
169-
if isr.tc().bit_is_set() {
170-
Ok(())
171-
} else {
172-
Err(nb::Error::WouldBlock)
173-
}
174-
}
175-
176-
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
177-
// NOTE(unsafe) atomic read with no side effects
178-
let isr = unsafe { (*USART1::ptr()).isr.read() };
179-
180-
if isr.txe().bit_is_set() {
181-
// NOTE(unsafe) atomic write to stateless register
182-
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
183-
unsafe { ptr::write_volatile(&(*USART1::ptr()).tdr as *const _ as *mut _, byte) }
184-
Ok(())
185-
} else {
186-
Err(nb::Error::WouldBlock)
187-
}
188-
}
189122
}
190123

191124
/// USART2
@@ -218,33 +151,21 @@ impl<PINS> Serial<USART2, PINS> {
218151

219152
Serial { usart, pins }
220153
}
221-
222-
pub fn split(self) -> (Tx<USART2>, Rx<USART2>) {
223-
(
224-
Tx {
225-
_usart: PhantomData,
226-
},
227-
Rx {
228-
_usart: PhantomData,
229-
},
230-
)
231-
}
232-
pub fn release(self) -> (USART2, PINS) {
233-
(self.usart, self.pins)
234-
}
235154
}
236155

237-
#[cfg(any(
238-
feature = "stm32f042",
239-
feature = "stm32f030x8",
240-
feature = "stm32f030x8"
241-
))]
242-
impl embedded_hal::serial::Read<u8> for Rx<USART2> {
156+
// It's s needed for the impls, but rustc doesn't recognize that
157+
#[allow(dead_code)]
158+
type SerialRegisterBlock = usart1::RegisterBlock;
159+
160+
impl<USART> embedded_hal::serial::Read<u8> for Rx<USART>
161+
where
162+
USART: Deref<Target = SerialRegisterBlock>,
163+
{
243164
type Error = Error;
244165

245166
fn read(&mut self) -> nb::Result<u8, Error> {
246167
// NOTE(unsafe) atomic read with no side effects
247-
let isr = unsafe { (*USART2::ptr()).isr.read() };
168+
let isr = unsafe { (*self.usart).isr.read() };
248169

249170
Err(if isr.pe().bit_is_set() {
250171
nb::Error::Other(Error::Parity)
@@ -256,24 +177,22 @@ impl embedded_hal::serial::Read<u8> for Rx<USART2> {
256177
nb::Error::Other(Error::Overrun)
257178
} else if isr.rxne().bit_is_set() {
258179
// NOTE(read_volatile) see `write_volatile` below
259-
return Ok(unsafe { ptr::read_volatile(&(*USART2::ptr()).rdr as *const _ as *const _) });
180+
return Ok(unsafe { ptr::read_volatile(&(*self.usart).rdr as *const _ as *const _) });
260181
} else {
261182
nb::Error::WouldBlock
262183
})
263184
}
264185
}
265186

266-
#[cfg(any(
267-
feature = "stm32f042",
268-
feature = "stm32f030x8",
269-
feature = "stm32f030x8"
270-
))]
271-
impl embedded_hal::serial::Write<u8> for Tx<USART2> {
187+
impl<USART> embedded_hal::serial::Write<u8> for Tx<USART>
188+
where
189+
USART: Deref<Target = SerialRegisterBlock>,
190+
{
272191
type Error = Void;
273192

274193
fn flush(&mut self) -> nb::Result<(), Self::Error> {
275194
// NOTE(unsafe) atomic read with no side effects
276-
let isr = unsafe { (*USART2::ptr()).isr.read() };
195+
let isr = unsafe { (*self.usart).isr.read() };
277196

278197
if isr.tc().bit_is_set() {
279198
Ok(())
@@ -284,19 +203,39 @@ impl embedded_hal::serial::Write<u8> for Tx<USART2> {
284203

285204
fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> {
286205
// NOTE(unsafe) atomic read with no side effects
287-
let isr = unsafe { (*USART2::ptr()).isr.read() };
206+
let isr = unsafe { (*self.usart).isr.read() };
288207

289208
if isr.txe().bit_is_set() {
290209
// NOTE(unsafe) atomic write to stateless register
291210
// NOTE(write_volatile) 8-bit write that's not possible through the svd2rust API
292-
unsafe { ptr::write_volatile(&(*USART2::ptr()).tdr as *const _ as *mut _, byte) }
211+
unsafe { ptr::write_volatile(&(*self.usart).tdr as *const _ as *mut _, byte) }
293212
Ok(())
294213
} else {
295214
Err(nb::Error::WouldBlock)
296215
}
297216
}
298217
}
299218

219+
impl<USART, PINS> Serial<USART, PINS>
220+
where
221+
USART: Deref<Target = SerialRegisterBlock>,
222+
PINS: Pins<USART>,
223+
{
224+
pub fn split(self) -> (Tx<USART>, Rx<USART>) {
225+
(
226+
Tx {
227+
usart: &self.usart as *const _,
228+
},
229+
Rx {
230+
usart: &self.usart as *const _,
231+
},
232+
)
233+
}
234+
pub fn release(self) -> (USART, PINS) {
235+
(self.usart, self.pins)
236+
}
237+
}
238+
300239
impl<USART> Write for Tx<USART>
301240
where
302241
Tx<USART>: embedded_hal::serial::Write<u8>,

0 commit comments

Comments
 (0)