stm32_rust_template/driver/usart/
stm32f407.rs

1#[cfg(feature = "stm32f407")]
2extern crate alloc;
3
4use super::{
5    ClockPhase, ClockPolarity, Config, DataBits, Event, FlowControl, Mode, ModemControl,
6    ModemStatus, Parity, Result, Status, Usart,
7};
8use crate::mcu::stm32f407::{self, usart::*};
9use crate::utils;
10use alloc::boxed::Box;
11use core::ops::FnMut;
12use core::ptr;
13
14/// Default APB bus clock frequencies in Hz.
15/// Update these to match your clock configuration.
16const PCLK1_HZ: u32 = 16_000_000; // APB1 (USART2/3)
17const PCLK2_HZ: u32 = 16_000_000; // APB2 (USART1)
18
19/// A polling-based USART driver for STM32F407.
20pub struct UsartDriver<'a> {
21    regs: *mut RegisterBlock,
22    _callback: Option<Box<dyn FnMut(Event) + 'a>>,
23    config: Config,
24    tx_count: u32,
25    rx_count: u32,
26}
27
28impl<'a> UsartDriver<'a> {
29    pub fn new(usart_base_addr: u32, config: Config) -> Self {
30        Self {
31            regs: usart_base_addr as *mut RegisterBlock,
32            _callback: None,
33            config,
34            tx_count: 0,
35            rx_count: 0,
36        }
37    }
38
39    /// Create a new USART1 driver instance (APB2 clock)
40    pub fn new_usart1(config: Config) -> Self {
41        Self::new(stm32f407::USART1_BASEADDR, config)
42    }
43
44    /// Create a new USART2 driver instance (APB1 clock)
45    pub fn new_usart2(config: Config) -> Self {
46        Self::new(stm32f407::USART2_BASEADDR, config)
47    }
48
49    /// Create a new USART3 driver instance (APB1 clock)
50    pub fn new_usart3(config: Config) -> Self {
51        Self::new(stm32f407::USART3_BASEADDR, config)
52    }
53
54    fn regs(&self) -> &mut RegisterBlock {
55        unsafe { &mut *self.regs }
56    }
57
58    fn is_on_apb2(&self) -> bool {
59        let base = self.regs as u32;
60        base == stm32f407::USART1_BASEADDR
61    }
62
63    fn compute_brr(&self, baudrate: u32) -> u32 {
64        // Oversampling by 16 (OVER8 = 0)
65        let pclk = if self.is_on_apb2() {
66            PCLK2_HZ
67        } else {
68            PCLK1_HZ
69        };
70        // usartdiv * 16 = pclk / baud (rounded)
71        let usartdiv_times_16 = (pclk + (baudrate / 2)) / baudrate;
72        let mantissa = usartdiv_times_16 / 16;
73        let fraction = usartdiv_times_16 & 0xF;
74        (mantissa << 4) | fraction
75    }
76
77    fn write_cr1(&mut self, f: impl FnOnce(u32) -> u32) {
78        let mut v = unsafe { ptr::read_volatile(&self.regs().cr1) };
79        v = f(v);
80        unsafe { ptr::write_volatile(&mut self.regs().cr1, v) };
81    }
82
83    fn write_cr2(&mut self, f: impl FnOnce(u32) -> u32) {
84        let mut v = unsafe { ptr::read_volatile(&self.regs().cr2) };
85        v = f(v);
86        unsafe { ptr::write_volatile(&mut self.regs().cr2, v) };
87    }
88
89    fn write_cr3(&mut self, f: impl FnOnce(u32) -> u32) {
90        let mut v = unsafe { ptr::read_volatile(&self.regs().cr3) };
91        v = f(v);
92        unsafe { ptr::write_volatile(&mut self.regs().cr3, v) };
93    }
94
95    fn wait_txe(&self) {
96        while unsafe { ptr::read_volatile(&self.regs().sr) } & SR_TXE_MASK == 0 {}
97    }
98
99    fn wait_rxne(&self) {
100        while unsafe { ptr::read_volatile(&self.regs().sr) } & SR_RXNE_MASK == 0 {}
101    }
102
103    fn wait_tc(&self) {
104        while unsafe { ptr::read_volatile(&self.regs().sr) } & SR_TC_MASK == 0 {}
105    }
106}
107
108impl<'a> Usart<'a> for UsartDriver<'a> {
109    fn initialize(&mut self, callback: impl FnMut(Event) + 'a) -> Result<()> {
110        self._callback = Some(Box::new(callback));
111
112        // Disable USART before configuration
113        self.write_cr1(|v| utils::set_bit(v, CR1_UE_POS, false));
114
115        // Apply configuration
116        let cfg = self.config.clone();
117        self.configure(&cfg)?;
118
119        // Enable USART
120        self.write_cr1(|v| utils::set_bit(v, CR1_UE_POS, true));
121        Ok(())
122    }
123
124    fn uninitialize(&mut self) -> Result<()> {
125        self.write_cr1(|v| utils::set_bit(v, CR1_UE_POS, false));
126        self._callback = None;
127        Ok(())
128    }
129
130    fn configure(&mut self, config: &Config) -> Result<()> {
131        self.config = config.clone();
132
133        // Disable before reconfig
134        self.write_cr1(|v| utils::set_bit(v, CR1_UE_POS, false));
135
136        // CR1: word length, parity, RX/TX enable
137        self.write_cr1(|mut v| {
138            // Clear fields we manage
139            v &= !(CR1_M_MASK
140                | CR1_PCE_MASK
141                | CR1_PS_MASK
142                | CR1_TE_MASK
143                | CR1_RE_MASK
144                | CR1_OVER8_MASK
145                | CR1_RWU_MASK
146                | CR1_SBK_MASK
147                | CR1_IDLEIE_MASK
148                | CR1_RXNEIE_MASK
149                | CR1_TCIE_MASK
150                | CR1_TXEIE_MASK
151                | CR1_PEIE_MASK);
152
153            // Word length
154            v = match config.data_bits {
155                DataBits::Bits9 => utils::set_bit(v, CR1_M_POS, true),
156                DataBits::Bits8 => utils::set_bit(v, CR1_M_POS, false),
157                _ => return v, // unsupported values will be handled below by returning Err
158            };
159
160            // Parity
161            match config.parity {
162                Parity::None => {
163                    v = utils::set_bit(v, CR1_PCE_POS, false);
164                }
165                Parity::Even => {
166                    v = utils::set_bit(v, CR1_PCE_POS, true);
167                    v = utils::set_bit(v, CR1_PS_POS, false);
168                }
169                Parity::Odd => {
170                    v = utils::set_bit(v, CR1_PCE_POS, true);
171                    v = utils::set_bit(v, CR1_PS_POS, true);
172                }
173            }
174
175            // TX/RX enable based on mode
176            let enable_tx = matches!(
177                config.mode,
178                Mode::Asynchronous
179                    | Mode::SynchronousMaster
180                    | Mode::SynchronousSlave
181                    | Mode::SingleWire
182                    | Mode::IrDA
183                    | Mode::SmartCard
184            );
185            let enable_rx = matches!(
186                config.mode,
187                Mode::Asynchronous
188                    | Mode::SynchronousMaster
189                    | Mode::SynchronousSlave
190                    | Mode::SingleWire
191                    | Mode::IrDA
192                    | Mode::SmartCard
193            );
194            v = utils::set_bit(v, CR1_TE_POS, enable_tx);
195            v = utils::set_bit(v, CR1_RE_POS, enable_rx);
196
197            v
198        });
199
200        // Reject unsupported data bits (anything other than 8 or 9)
201        match config.data_bits {
202            DataBits::Bits8 | DataBits::Bits9 => {}
203            _ => return Err(-1),
204        }
205
206        // CR2: STOP bits, clock settings for synchronous mode
207        self.write_cr2(|mut v| {
208            // Clear STOP, CLKEN, CPOL, CPHA, LBCL
209            v &= !(CR2_STOP_MASK | CR2_CLKEN_MASK | CR2_CPOL_MASK | CR2_CPHA_MASK | CR2_LBCL_MASK);
210
211            // STOP bits
212            let stop_bits_val = match config.stop_bits {
213                super::StopBits::Bits1 => 0,
214                super::StopBits::Bits0_5 => 1,
215                super::StopBits::Bits2 => 2,
216                super::StopBits::Bits1_5 => 3,
217            } as u32;
218            v = utils::set_bits(v, stop_bits_val, CR2_STOP_POS, CR2_STOP_WIDTH);
219
220            // Synchronous clock settings when required
221            let sync_mode = matches!(
222                config.mode,
223                Mode::SynchronousMaster | Mode::SynchronousSlave
224            );
225            v = utils::set_bit(v, CR2_CLKEN_POS, sync_mode);
226            if sync_mode {
227                v = utils::set_bit(
228                    v,
229                    CR2_CPOL_POS,
230                    matches!(config.clock_polarity, ClockPolarity::CPOL1),
231                );
232                v = utils::set_bit(
233                    v,
234                    CR2_CPHA_POS,
235                    matches!(config.clock_phase, ClockPhase::CPHA1),
236                );
237            }
238
239            v
240        });
241
242        // CR3: hardware flow control and special modes
243        self.write_cr3(|mut v| {
244            // Clear RTSE/CTSE/HDSEL/IREN/SCEN
245            v &= !(CR3_RTSE_MASK | CR3_CTSE_MASK | CR3_HDSEL_MASK | CR3_IREN_MASK | CR3_SCEN_MASK);
246
247            // Flow control
248            match config.flow_control {
249                FlowControl::None => {}
250                FlowControl::RTS => {
251                    v |= CR3_RTSE_MASK;
252                }
253                FlowControl::CTS => {
254                    v |= CR3_CTSE_MASK;
255                }
256                FlowControl::RTS_CTS => {
257                    v |= CR3_RTSE_MASK | CR3_CTSE_MASK;
258                }
259            }
260
261            // Special modes
262            match config.mode {
263                Mode::SingleWire => {
264                    v |= CR3_HDSEL_MASK; // half duplex
265                }
266                Mode::IrDA => {
267                    v |= CR3_IREN_MASK;
268                }
269                Mode::SmartCard => {
270                    v |= CR3_SCEN_MASK;
271                }
272                _ => {}
273            }
274
275            v
276        });
277
278        // Baud rate
279        let brr = self.compute_brr(config.baudrate);
280        unsafe { ptr::write_volatile(&mut self.regs().brr, brr) };
281
282        // Re-enable USART
283        self.write_cr1(|v| utils::set_bit(v, CR1_UE_POS, true));
284        Ok(())
285    }
286
287    fn send(&mut self, data: &[u8]) -> Result<()> {
288        self.tx_count = 0;
289        for &byte in data {
290            self.wait_txe();
291            unsafe { ptr::write_volatile(&mut self.regs().dr, byte as u32) };
292            self.tx_count += 1;
293        }
294        self.wait_tc();
295        if let Some(cb) = &mut self._callback {
296            cb(Event::SEND_COMPLETE | Event::TX_COMPLETE);
297        }
298        Ok(())
299    }
300
301    fn receive(&mut self, data: &mut [u8]) -> Result<()> {
302        self.rx_count = 0;
303        for b in data.iter_mut() {
304            self.wait_rxne();
305            *b = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
306            self.rx_count += 1;
307        }
308        if let Some(cb) = &mut self._callback {
309            cb(Event::RECEIVE_COMPLETE);
310        }
311        Ok(())
312    }
313
314    fn transfer(&mut self, data_out: &[u8], data_in: &mut [u8]) -> Result<()> {
315        if data_in.len() != data_out.len() {
316            return Err(-1);
317        }
318
319        self.tx_count = 0;
320        self.rx_count = 0;
321
322        for (i, &byte) in data_out.iter().enumerate() {
323            self.wait_txe();
324            unsafe { ptr::write_volatile(&mut self.regs().dr, byte as u32) };
325            self.tx_count += 1;
326
327            self.wait_rxne();
328            data_in[i] = unsafe { ptr::read_volatile(&self.regs().dr) as u8 };
329            self.rx_count += 1;
330        }
331        self.wait_tc();
332        if let Some(cb) = &mut self._callback {
333            cb(Event::TRANSFER_COMPLETE);
334        }
335        Ok(())
336    }
337
338    fn get_tx_count(&self) -> u32 {
339        self.tx_count
340    }
341
342    fn get_rx_count(&self) -> u32 {
343        self.rx_count
344    }
345
346    fn get_status(&self) -> Status {
347        let sr = unsafe { ptr::read_volatile(&self.regs().sr) };
348        Status {
349            tx_busy: (sr & SR_TC_MASK) == 0,
350            rx_busy: (sr & SR_RXNE_MASK) != 0,
351            tx_underflow: false,
352            rx_overflow: (sr & SR_ORE_MASK) != 0,
353            rx_break: (sr & SR_LBD_MASK) != 0,
354            rx_framing_error: (sr & SR_FE_MASK) != 0,
355            rx_parity_error: (sr & SR_PE_MASK) != 0,
356        }
357    }
358
359    fn set_modem_control(&mut self, control: ModemControl) -> Result<()> {
360        match control {
361            // Direct manual control of RTS/DTR lines is not supported by this peripheral
362            // (RTS/CTS are managed by hardware when enabled). Return unsupported.
363            ModemControl::RTSClear
364            | ModemControl::RTSSet
365            | ModemControl::DTRClear
366            | ModemControl::DTRSet => Err(-2),
367        }
368    }
369
370    fn get_modem_status(&self) -> ModemStatus {
371        let sr = unsafe { ptr::read_volatile(&self.regs().sr) };
372        ModemStatus {
373            cts: (sr & SR_CTS_MASK) != 0,
374            dsr: false,
375            dcd: false,
376            ri: false,
377        }
378    }
379
380    fn tx_enable(&mut self, enable: bool) -> Result<()> {
381        self.write_cr1(|v| utils::set_bit(v, CR1_TE_POS, enable));
382        Ok(())
383    }
384
385    fn rx_enable(&mut self, enable: bool) -> Result<()> {
386        self.write_cr1(|v| utils::set_bit(v, CR1_RE_POS, enable));
387        Ok(())
388    }
389
390    fn control_break(&mut self, enable: bool) -> Result<()> {
391        // Setting SBK sends a break; it is cleared by hardware.
392        if enable {
393            self.write_cr1(|v| utils::set_bit(v, CR1_SBK_POS, true));
394        }
395        Ok(())
396    }
397
398    fn abort_send(&mut self) -> Result<()> {
399        // Disable transmitter
400        self.write_cr1(|v| utils::set_bit(v, CR1_TE_POS, false));
401        Ok(())
402    }
403
404    fn abort_receive(&mut self) -> Result<()> {
405        // Disable receiver
406        self.write_cr1(|v| utils::set_bit(v, CR1_RE_POS, false));
407        Ok(())
408    }
409
410    fn abort_transfer(&mut self) -> Result<()> {
411        self.write_cr1(|mut v| {
412            v = utils::set_bit(v, CR1_TE_POS, false);
413            v = utils::set_bit(v, CR1_RE_POS, false);
414            v
415        });
416        Ok(())
417    }
418}