aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src/usart
diff options
context:
space:
mode:
authorDaniel Trnka <[email protected]>2024-12-21 22:01:36 +0100
committerDaniel Trnka <[email protected]>2024-12-22 17:50:46 +0100
commit2ec81419fa7ca1d1d4c797c1d416c1f226aefb33 (patch)
tree9611485664a9316878caded0fdb58a4a0a04844e /embassy-stm32/src/usart
parent6789b5141f9280f1e3d7c6dfcab1a07fe4620b43 (diff)
stm32/usart: configurable readback in half-duplex mode
Diffstat (limited to 'embassy-stm32/src/usart')
-rw-r--r--embassy-stm32/src/usart/mod.rs54
1 files changed, 44 insertions, 10 deletions
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index 2d801e6bf..98b5c9cfe 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -125,6 +125,33 @@ pub enum StopBits {
125 STOP1P5, 125 STOP1P5,
126} 126}
127 127
128#[derive(Clone, Copy, PartialEq, Eq, Debug)]
129#[cfg_attr(feature = "defmt", derive(defmt::Format))]
130/// Enables or disables receiver so written data are read back in half-duplex mode
131pub enum HalfDuplexReadback {
132 /// Disables receiver so written data are not read back
133 NoReadback,
134 /// Enables receiver so written data are read back
135 Readback,
136}
137
138#[derive(Clone, Copy, PartialEq, Eq, Debug)]
139#[cfg_attr(feature = "defmt", derive(defmt::Format))]
140/// Duplex mode
141pub enum Duplex {
142 /// Full duplex
143 Full,
144 /// Half duplex with possibility to read back written data
145 Half(HalfDuplexReadback),
146}
147
148impl Duplex {
149 /// Returns true if half-duplex
150 fn is_half(&self) -> bool {
151 matches!(self, Duplex::Half(_))
152 }
153}
154
128#[non_exhaustive] 155#[non_exhaustive]
129#[derive(Clone, Copy, PartialEq, Eq, Debug)] 156#[derive(Clone, Copy, PartialEq, Eq, Debug)]
130#[cfg_attr(feature = "defmt", derive(defmt::Format))] 157#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -181,7 +208,7 @@ pub struct Config {
181 pub rx_pull: Pull, 208 pub rx_pull: Pull,
182 209
183 // private: set by new_half_duplex, not by the user. 210 // private: set by new_half_duplex, not by the user.
184 half_duplex: bool, 211 duplex: Duplex,
185} 212}
186 213
187impl Config { 214impl Config {
@@ -220,7 +247,7 @@ impl Default for Config {
220 #[cfg(any(usart_v3, usart_v4))] 247 #[cfg(any(usart_v3, usart_v4))]
221 invert_rx: false, 248 invert_rx: false,
222 rx_pull: Pull::None, 249 rx_pull: Pull::None,
223 half_duplex: false, 250 duplex: Duplex::Full,
224 } 251 }
225 } 252 }
226} 253}
@@ -308,6 +335,7 @@ pub struct UartTx<'d, M: Mode> {
308 cts: Option<PeripheralRef<'d, AnyPin>>, 335 cts: Option<PeripheralRef<'d, AnyPin>>,
309 de: Option<PeripheralRef<'d, AnyPin>>, 336 de: Option<PeripheralRef<'d, AnyPin>>,
310 tx_dma: Option<ChannelAndRequest<'d>>, 337 tx_dma: Option<ChannelAndRequest<'d>>,
338 duplex: Duplex,
311 _phantom: PhantomData<M>, 339 _phantom: PhantomData<M>,
312} 340}
313 341
@@ -413,7 +441,7 @@ impl<'d> UartTx<'d, Async> {
413 let mut cr1 = r.cr1().read(); 441 let mut cr1 = r.cr1().read();
414 if r.cr3().read().hdsel() && !cr1.te() { 442 if r.cr3().read().hdsel() && !cr1.te() {
415 cr1.set_te(true); 443 cr1.set_te(true);
416 cr1.set_re(false); 444 cr1.set_re(self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
417 r.cr1().write_value(cr1); 445 r.cr1().write_value(cr1);
418 } 446 }
419 447
@@ -485,6 +513,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
485 cts, 513 cts,
486 de: None, 514 de: None,
487 tx_dma, 515 tx_dma,
516 duplex: config.duplex,
488 _phantom: PhantomData, 517 _phantom: PhantomData,
489 }; 518 };
490 this.enable_and_configure(&config)?; 519 this.enable_and_configure(&config)?;
@@ -519,7 +548,7 @@ impl<'d, M: Mode> UartTx<'d, M> {
519 let mut cr1 = r.cr1().read(); 548 let mut cr1 = r.cr1().read();
520 if r.cr3().read().hdsel() && !cr1.te() { 549 if r.cr3().read().hdsel() && !cr1.te() {
521 cr1.set_te(true); 550 cr1.set_te(true);
522 cr1.set_re(false); 551 cr1.set_re(self.duplex == Duplex::Half(HalfDuplexReadback::Readback));
523 r.cr1().write_value(cr1); 552 r.cr1().write_value(cr1);
524 } 553 }
525 554
@@ -1149,13 +1178,14 @@ impl<'d> Uart<'d, Async> {
1149 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, 1178 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
1150 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, 1179 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
1151 mut config: Config, 1180 mut config: Config,
1181 readback: HalfDuplexReadback,
1152 half_duplex: HalfDuplexConfig, 1182 half_duplex: HalfDuplexConfig,
1153 ) -> Result<Self, ConfigError> { 1183 ) -> Result<Self, ConfigError> {
1154 #[cfg(not(any(usart_v1, usart_v2)))] 1184 #[cfg(not(any(usart_v1, usart_v2)))]
1155 { 1185 {
1156 config.swap_rx_tx = false; 1186 config.swap_rx_tx = false;
1157 } 1187 }
1158 config.half_duplex = true; 1188 config.duplex = Duplex::Half(readback);
1159 1189
1160 Self::new_inner( 1190 Self::new_inner(
1161 peri, 1191 peri,
@@ -1188,10 +1218,11 @@ impl<'d> Uart<'d, Async> {
1188 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd, 1218 tx_dma: impl Peripheral<P = impl TxDma<T>> + 'd,
1189 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd, 1219 rx_dma: impl Peripheral<P = impl RxDma<T>> + 'd,
1190 mut config: Config, 1220 mut config: Config,
1221 readback: HalfDuplexReadback,
1191 half_duplex: HalfDuplexConfig, 1222 half_duplex: HalfDuplexConfig,
1192 ) -> Result<Self, ConfigError> { 1223 ) -> Result<Self, ConfigError> {
1193 config.swap_rx_tx = true; 1224 config.swap_rx_tx = true;
1194 config.half_duplex = true; 1225 config.duplex = Duplex::Half(readback);
1195 1226
1196 Self::new_inner( 1227 Self::new_inner(
1197 peri, 1228 peri,
@@ -1307,13 +1338,14 @@ impl<'d> Uart<'d, Blocking> {
1307 peri: impl Peripheral<P = T> + 'd, 1338 peri: impl Peripheral<P = T> + 'd,
1308 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 1339 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
1309 mut config: Config, 1340 mut config: Config,
1341 readback: HalfDuplexReadback,
1310 half_duplex: HalfDuplexConfig, 1342 half_duplex: HalfDuplexConfig,
1311 ) -> Result<Self, ConfigError> { 1343 ) -> Result<Self, ConfigError> {
1312 #[cfg(not(any(usart_v1, usart_v2)))] 1344 #[cfg(not(any(usart_v1, usart_v2)))]
1313 { 1345 {
1314 config.swap_rx_tx = false; 1346 config.swap_rx_tx = false;
1315 } 1347 }
1316 config.half_duplex = true; 1348 config.duplex = Duplex::Half(readback);
1317 1349
1318 Self::new_inner( 1350 Self::new_inner(
1319 peri, 1351 peri,
@@ -1343,10 +1375,11 @@ impl<'d> Uart<'d, Blocking> {
1343 peri: impl Peripheral<P = T> + 'd, 1375 peri: impl Peripheral<P = T> + 'd,
1344 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 1376 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
1345 mut config: Config, 1377 mut config: Config,
1378 readback: HalfDuplexReadback,
1346 half_duplex: HalfDuplexConfig, 1379 half_duplex: HalfDuplexConfig,
1347 ) -> Result<Self, ConfigError> { 1380 ) -> Result<Self, ConfigError> {
1348 config.swap_rx_tx = true; 1381 config.swap_rx_tx = true;
1349 config.half_duplex = true; 1382 config.duplex = Duplex::Half(readback);
1350 1383
1351 Self::new_inner( 1384 Self::new_inner(
1352 peri, 1385 peri,
@@ -1388,6 +1421,7 @@ impl<'d, M: Mode> Uart<'d, M> {
1388 cts, 1421 cts,
1389 de, 1422 de,
1390 tx_dma, 1423 tx_dma,
1424 duplex: config.duplex,
1391 }, 1425 },
1392 rx: UartRx { 1426 rx: UartRx {
1393 _phantom: PhantomData, 1427 _phantom: PhantomData,
@@ -1667,14 +1701,14 @@ fn configure(
1667 r.cr3().modify(|w| { 1701 r.cr3().modify(|w| {
1668 #[cfg(not(usart_v1))] 1702 #[cfg(not(usart_v1))]
1669 w.set_onebit(config.assume_noise_free); 1703 w.set_onebit(config.assume_noise_free);
1670 w.set_hdsel(config.half_duplex); 1704 w.set_hdsel(config.duplex.is_half());
1671 }); 1705 });
1672 1706
1673 r.cr1().write(|w| { 1707 r.cr1().write(|w| {
1674 // enable uart 1708 // enable uart
1675 w.set_ue(true); 1709 w.set_ue(true);
1676 1710
1677 if config.half_duplex { 1711 if config.duplex.is_half() {
1678 // The te and re bits will be set by write, read and flush methods. 1712 // The te and re bits will be set by write, read and flush methods.
1679 // Receiver should be enabled by default for Half-Duplex. 1713 // Receiver should be enabled by default for Half-Duplex.
1680 w.set_te(false); 1714 w.set_te(false);