aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-10-28 11:13:11 +0000
committerGitHub <[email protected]>2022-10-28 11:13:11 +0000
commita7d5c87049fa533eeb50859b3cd06b046788b007 (patch)
tree1a88758f15fd27e65d68911fec1b206eac78c9a5
parent4e61d83555c1693da025bc7c9c1c8ecf335b65f1 (diff)
parent79b49c6fae7b4f7df2c03ae0be970d154f4faac8 (diff)
Merge #1033
1033: stm32/usart: Add missing constructor with hardware flow control r=Dirbaio a=guillaume-michel This PR follows #1031 and #987 and add missing constructors with hardware flow control. It also factor general UART configuration like word size, parity, ... used in `Uart`, `UartRx`, `UartTx` and `BufferedUart`. Co-authored-by: Guillaume MICHEL <[email protected]>
-rw-r--r--embassy-stm32/src/usart/buffered.rs70
-rw-r--r--embassy-stm32/src/usart/mod.rs173
2 files changed, 171 insertions, 72 deletions
diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs
index 3be0677bd..0a6d6e149 100644
--- a/embassy-stm32/src/usart/buffered.rs
+++ b/embassy-stm32/src/usart/buffered.rs
@@ -46,7 +46,7 @@ impl<'d, T: BasicInstance> Unpin for BufferedUart<'d, T> {}
46impl<'d, T: BasicInstance> BufferedUart<'d, T> { 46impl<'d, T: BasicInstance> BufferedUart<'d, T> {
47 pub fn new( 47 pub fn new(
48 state: &'d mut State<'d, T>, 48 state: &'d mut State<'d, T>,
49 _peri: impl Peripheral<P = T> + 'd, 49 peri: impl Peripheral<P = T> + 'd,
50 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 50 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
51 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 51 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
52 irq: impl Peripheral<P = T::Interrupt> + 'd, 52 irq: impl Peripheral<P = T::Interrupt> + 'd,
@@ -54,36 +54,64 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
54 rx_buffer: &'d mut [u8], 54 rx_buffer: &'d mut [u8],
55 config: Config, 55 config: Config,
56 ) -> BufferedUart<'d, T> { 56 ) -> BufferedUart<'d, T> {
57 into_ref!(_peri, rx, tx, irq); 57 T::enable();
58 T::reset();
59
60 Self::new_inner(state, peri, rx, tx, irq, tx_buffer, rx_buffer, config)
61 }
62
63 pub fn new_with_rtscts(
64 state: &'d mut State<'d, T>,
65 peri: impl Peripheral<P = T> + 'd,
66 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
67 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
68 irq: impl Peripheral<P = T::Interrupt> + 'd,
69 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
70 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
71 tx_buffer: &'d mut [u8],
72 rx_buffer: &'d mut [u8],
73 config: Config,
74 ) -> BufferedUart<'d, T> {
75 into_ref!(cts, rts);
58 76
59 T::enable(); 77 T::enable();
60 T::reset(); 78 T::reset();
61 79
62 let r = T::regs(); 80 unsafe {
81 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
82 cts.set_as_af(cts.af_num(), AFType::Input);
83 T::regs().cr3().write(|w| {
84 w.set_rtse(true);
85 w.set_ctse(true);
86 });
87 }
63 88
64 configure(r, &config, T::frequency(), T::MULTIPLIER); 89 Self::new_inner(state, peri, rx, tx, irq, tx_buffer, rx_buffer, config)
90 }
91
92 fn new_inner(
93 state: &'d mut State<'d, T>,
94 _peri: impl Peripheral<P = T> + 'd,
95 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
96 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
97 irq: impl Peripheral<P = T::Interrupt> + 'd,
98 tx_buffer: &'d mut [u8],
99 rx_buffer: &'d mut [u8],
100 config: Config,
101 ) -> BufferedUart<'d, T> {
102 into_ref!(_peri, rx, tx, irq);
103
104 let r = T::regs();
65 105
66 unsafe { 106 unsafe {
67 rx.set_as_af(rx.af_num(), AFType::Input); 107 rx.set_as_af(rx.af_num(), AFType::Input);
68 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 108 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
109 }
69 110
70 r.cr2().write(|_w| {}); 111 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true);
71 r.cr3().write(|_w| {}); 112
72 r.cr1().write(|w| { 113 unsafe {
73 w.set_ue(true); 114 r.cr1().modify(|w| {
74 w.set_te(true);
75 w.set_re(true);
76 w.set_m0(if config.parity != Parity::ParityNone {
77 vals::M0::BIT9
78 } else {
79 vals::M0::BIT8
80 });
81 w.set_pce(config.parity != Parity::ParityNone);
82 w.set_ps(match config.parity {
83 Parity::ParityOdd => vals::Ps::ODD,
84 Parity::ParityEven => vals::Ps::EVEN,
85 _ => vals::Ps::EVEN,
86 });
87 w.set_rxneie(true); 115 w.set_rxneie(true);
88 w.set_idleie(true); 116 w.set_idleie(true);
89 }); 117 });
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs
index dee466b21..716247d9e 100644
--- a/embassy-stm32/src/usart/mod.rs
+++ b/embassy-stm32/src/usart/mod.rs
@@ -102,7 +102,59 @@ pub struct UartRx<'d, T: BasicInstance, RxDma = NoDma> {
102} 102}
103 103
104impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> { 104impl<'d, T: BasicInstance, TxDma> UartTx<'d, T, TxDma> {
105 fn new(tx_dma: PeripheralRef<'d, TxDma>) -> Self { 105 /// usefull if you only want Uart Tx. It saves 1 pin and consumes a little less power
106 pub fn new(
107 peri: impl Peripheral<P = T> + 'd,
108 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
109 tx_dma: impl Peripheral<P = TxDma> + 'd,
110 config: Config,
111 ) -> Self {
112 T::enable();
113 T::reset();
114
115 Self::new_inner(peri, tx, tx_dma, config)
116 }
117
118 pub fn new_with_cts(
119 peri: impl Peripheral<P = T> + 'd,
120 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
121 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
122 tx_dma: impl Peripheral<P = TxDma> + 'd,
123 config: Config,
124 ) -> Self {
125 into_ref!(cts);
126
127 T::enable();
128 T::reset();
129
130 unsafe {
131 cts.set_as_af(cts.af_num(), AFType::Input);
132 T::regs().cr3().write(|w| {
133 w.set_ctse(true);
134 });
135 }
136 Self::new_inner(peri, tx, tx_dma, config)
137 }
138
139 fn new_inner(
140 _peri: impl Peripheral<P = T> + 'd,
141 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
142 tx_dma: impl Peripheral<P = TxDma> + 'd,
143 config: Config,
144 ) -> Self {
145 into_ref!(_peri, tx, tx_dma);
146
147 let r = T::regs();
148
149 unsafe {
150 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
151 }
152
153 configure(r, &config, T::frequency(), T::MULTIPLIER, false, true);
154
155 // create state once!
156 let _s = T::state();
157
106 Self { 158 Self {
107 tx_dma, 159 tx_dma,
108 phantom: PhantomData, 160 phantom: PhantomData,
@@ -156,44 +208,52 @@ impl<'d, T: BasicInstance, RxDma> UartRx<'d, T, RxDma> {
156 rx_dma: impl Peripheral<P = RxDma> + 'd, 208 rx_dma: impl Peripheral<P = RxDma> + 'd,
157 config: Config, 209 config: Config,
158 ) -> Self { 210 ) -> Self {
159 into_ref!(peri, irq, rx, rx_dma); 211 T::enable();
212 T::reset();
213
214 Self::new_inner(peri, irq, rx, rx_dma, config)
215 }
216
217 pub fn new_with_rts(
218 peri: impl Peripheral<P = T> + 'd,
219 irq: impl Peripheral<P = T::Interrupt> + 'd,
220 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
221 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
222 rx_dma: impl Peripheral<P = RxDma> + 'd,
223 config: Config,
224 ) -> Self {
225 into_ref!(rts);
160 226
161 T::enable(); 227 T::enable();
162 T::reset(); 228 T::reset();
163 229
164 let r = T::regs(); 230 unsafe {
231 rts.set_as_af(rts.af_num(), AFType::OutputPushPull);
232 T::regs().cr3().write(|w| {
233 w.set_rtse(true);
234 });
235 }
236
237 Self::new_inner(peri, irq, rx, rx_dma, config)
238 }
239
240 fn new_inner(
241 peri: impl Peripheral<P = T> + 'd,
242 irq: impl Peripheral<P = T::Interrupt> + 'd,
243 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
244 rx_dma: impl Peripheral<P = RxDma> + 'd,
245 config: Config,
246 ) -> Self {
247 into_ref!(peri, irq, rx, rx_dma);
165 248
166 configure(r, &config, T::frequency(), T::MULTIPLIER); 249 let r = T::regs();
167 250
168 unsafe { 251 unsafe {
169 rx.set_as_af(rx.af_num(), AFType::Input); 252 rx.set_as_af(rx.af_num(), AFType::Input);
170
171 r.cr2().write(|_w| {});
172 r.cr3().write(|w| {
173 // enable Error Interrupt: (Frame error, Noise error, Overrun error)
174 w.set_eie(true);
175 });
176 r.cr1().write(|w| {
177 // enable uart
178 w.set_ue(true);
179 // enable receiver
180 w.set_re(true);
181 // configure word size
182 w.set_m0(if config.parity != Parity::ParityNone {
183 vals::M0::BIT9
184 } else {
185 vals::M0::BIT8
186 });
187 // configure parity
188 w.set_pce(config.parity != Parity::ParityNone);
189 w.set_ps(match config.parity {
190 Parity::ParityOdd => vals::Ps::ODD,
191 Parity::ParityEven => vals::Ps::EVEN,
192 _ => vals::Ps::EVEN,
193 });
194 });
195 } 253 }
196 254
255 configure(r, &config, T::frequency(), T::MULTIPLIER, true, false);
256
197 irq.set_handler(Self::on_interrupt); 257 irq.set_handler(Self::on_interrupt);
198 irq.unpend(); 258 irq.unpend();
199 irq.enable(); 259 irq.enable();
@@ -563,31 +623,13 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
563 623
564 let r = T::regs(); 624 let r = T::regs();
565 625
566 configure(r, &config, T::frequency(), T::MULTIPLIER);
567
568 unsafe { 626 unsafe {
569 rx.set_as_af(rx.af_num(), AFType::Input); 627 rx.set_as_af(rx.af_num(), AFType::Input);
570 tx.set_as_af(tx.af_num(), AFType::OutputPushPull); 628 tx.set_as_af(tx.af_num(), AFType::OutputPushPull);
571
572 r.cr2().write(|_w| {});
573 r.cr1().write(|w| {
574 w.set_ue(true);
575 w.set_te(true);
576 w.set_re(true);
577 w.set_m0(if config.parity != Parity::ParityNone {
578 vals::M0::BIT9
579 } else {
580 vals::M0::BIT8
581 });
582 w.set_pce(config.parity != Parity::ParityNone);
583 w.set_ps(match config.parity {
584 Parity::ParityOdd => vals::Ps::ODD,
585 Parity::ParityEven => vals::Ps::EVEN,
586 _ => vals::Ps::EVEN,
587 });
588 });
589 } 629 }
590 630
631 configure(r, &config, T::frequency(), T::MULTIPLIER, true, true);
632
591 irq.set_handler(UartRx::<T, RxDma>::on_interrupt); 633 irq.set_handler(UartRx::<T, RxDma>::on_interrupt);
592 irq.unpend(); 634 irq.unpend();
593 irq.enable(); 635 irq.enable();
@@ -596,7 +638,10 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
596 let _s = T::state(); 638 let _s = T::state();
597 639
598 Self { 640 Self {
599 tx: UartTx::new(tx_dma), 641 tx: UartTx {
642 tx_dma,
643 phantom: PhantomData,
644 },
600 rx: UartRx { 645 rx: UartRx {
601 _peri: peri, 646 _peri: peri,
602 rx_dma, 647 rx_dma,
@@ -650,12 +695,38 @@ impl<'d, T: BasicInstance, TxDma, RxDma> Uart<'d, T, TxDma, RxDma> {
650 } 695 }
651} 696}
652 697
653fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32) { 698fn configure(r: Regs, config: &Config, pclk_freq: Hertz, multiplier: u32, enable_rx: bool, enable_tx: bool) {
699 if !enable_rx && !enable_tx {
700 panic!("USART: At least one of RX or TX should be enabled");
701 }
702
654 // TODO: better calculation, including error checking and OVER8 if possible. 703 // TODO: better calculation, including error checking and OVER8 if possible.
655 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier; 704 let div = (pclk_freq.0 + (config.baudrate / 2)) / config.baudrate * multiplier;
656 705
657 unsafe { 706 unsafe {
658 r.brr().write_value(regs::Brr(div)); 707 r.brr().write_value(regs::Brr(div));
708 r.cr2().write(|_w| {});
709 r.cr1().write(|w| {
710 // enable uart
711 w.set_ue(true);
712 // enable transceiver
713 w.set_te(enable_tx);
714 // enable receiver
715 w.set_re(enable_rx);
716 // configure word size
717 w.set_m0(if config.parity != Parity::ParityNone {
718 vals::M0::BIT9
719 } else {
720 vals::M0::BIT8
721 });
722 // configure parity
723 w.set_pce(config.parity != Parity::ParityNone);
724 w.set_ps(match config.parity {
725 Parity::ParityOdd => vals::Ps::ODD,
726 Parity::ParityEven => vals::Ps::EVEN,
727 _ => vals::Ps::EVEN,
728 });
729 });
659 } 730 }
660} 731}
661 732