apollo3/
uart.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! UART driver.
6
7use core::cell::Cell;
8use kernel::ErrorCode;
9
10use kernel::hil;
11use kernel::hil::uart;
12use kernel::utilities::cells::OptionalCell;
13use kernel::utilities::cells::TakeCell;
14use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
15use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
16use kernel::utilities::StaticRef;
17
18const UART0_BASE: StaticRef<UartRegisters> =
19    unsafe { StaticRef::new(0x4001_C000 as *const UartRegisters) };
20
21pub const UART1_BASE: StaticRef<UartRegisters> =
22    unsafe { StaticRef::new(0x4001_D000 as *const UartRegisters) };
23
24register_structs! {
25    pub UartRegisters {
26        (0x000 => dr: ReadWrite<u32, DR::Register>),
27        (0x004 => rsr: ReadWrite<u32, RSR::Register>),
28        (0x008 => _reserved0),
29        (0x018 => fr: ReadWrite<u32, FR::Register>),
30        (0x01c => _reserved1),
31        (0x020 => ilpr: ReadWrite<u32, ILPR::Register>),
32        (0x024 => ibrd: ReadWrite<u32, IBRD::Register>),
33        (0x028 => fbrd: ReadWrite<u32, FBRD::Register>),
34        (0x02c => lcrh: ReadWrite<u32, LCRH::Register>),
35        (0x030 => cr: ReadWrite<u32, CR::Register>),
36        (0x034 => ifls: ReadWrite<u32, IFLS::Register>),
37        (0x038 => ier: ReadWrite<u32, IER::Register>),
38        (0x03c => ies: ReadWrite<u32, IES::Register>),
39        (0x040 => mis: ReadWrite<u32, MIS::Register>),
40        (0x044 => iec: ReadWrite<u32, IEC::Register>),
41        (0x048 => @END),
42    }
43}
44
45register_bitfields![u32,
46    DR [
47        DATA OFFSET(0) NUMBITS(8) [],
48        FEDATA OFFSET(8) NUMBITS(1) [],
49        PEDATA OFFSET(9) NUMBITS(1) [],
50        BEDATA OFFSET(10) NUMBITS(1) [],
51        OEDATA OFFSET(11) NUMBITS(1) []
52    ],
53    RSR [
54        FESTAT OFFSET(0) NUMBITS(1) [],
55        PESTAT OFFSET(1) NUMBITS(1) [],
56        BESTAT OFFSET(2) NUMBITS(1) [],
57        OESTAT OFFSET(4) NUMBITS(1) []
58    ],
59    FR [
60        CTS OFFSET(0) NUMBITS(1) [],
61        DSR OFFSET(1) NUMBITS(1) [],
62        DCD OFFSET(2) NUMBITS(1) [],
63        BUSY OFFSET(3) NUMBITS(1) [],
64        RXFE OFFSET(4) NUMBITS(1) [],
65        TXFF OFFSET(5) NUMBITS(1) [],
66        RXFF OFFSET(6) NUMBITS(1) [],
67        TXFE OFFSET(7) NUMBITS(1) [],
68        TXBUSY OFFSET(8) NUMBITS(1) []
69    ],
70    ILPR [
71        ILPDVSR OFFSET(0) NUMBITS(8) []
72    ],
73    IBRD [
74        DIVINT OFFSET(0) NUMBITS(16) []
75    ],
76    FBRD [
77        DIVFRAC OFFSET(0) NUMBITS(6) []
78    ],
79    LCRH [
80        BRK OFFSET(0) NUMBITS(1) [],
81        PEN OFFSET(1) NUMBITS(1) [],
82        EPS OFFSET(2) NUMBITS(1) [],
83        STP2 OFFSET(3) NUMBITS(1) [],
84        FEN OFFSET(4) NUMBITS(1) [],
85        WLEN OFFSET(5) NUMBITS(2) [],
86        SPS OFFSET(7) NUMBITS(1) []
87    ],
88    CR [
89        UARTEN OFFSET(0) NUMBITS(1) [],
90        SIREN OFFSET(1) NUMBITS(1) [],
91        SIRLP OFFSET(2) NUMBITS(1) [],
92        CLKEN OFFSET(3) NUMBITS(1) [],
93        CLKSEL OFFSET(4) NUMBITS(2) [
94            CLK_24MHZ = 0x1,
95            CLK_12MHZ = 0x2,
96            CLK_6MHZ = 0x3,
97            CLK_3MHZ = 0x4
98        ],
99        LBE OFFSET(7) NUMBITS(1) [],
100        TXE OFFSET(8) NUMBITS(1) [],
101        RXE OFFSET(9) NUMBITS(1) [],
102        DTR OFFSET(10) NUMBITS(1) [],
103        RTS OFFSET(11) NUMBITS(1) [],
104        OUT1 OFFSET(12) NUMBITS(1) [],
105        OUT2 OFFSET(13) NUMBITS(1) [],
106        RTSEN OFFSET(14) NUMBITS(1) [],
107        CTSEN OFFSET(15) NUMBITS(1) []
108    ],
109    IFLS [
110        TXIFLSEL OFFSET(0) NUMBITS(3) [],
111        RXIFLSEL OFFSET(3) NUMBITS(3) []
112    ],
113    IER [
114        TXCMPMIM OFFSET(0) NUMBITS(1) [],
115        CTSMIM OFFSET(1) NUMBITS(1) [],
116        DCDMIM OFFSET(2) NUMBITS(1) [],
117        DSRMIM OFFSET(3) NUMBITS(1) [],
118        RXIM OFFSET(4) NUMBITS(1) [],
119        TXIM OFFSET(5) NUMBITS(1) [],
120        RTIM OFFSET(6) NUMBITS(1) [],
121        FEIM OFFSET(7) NUMBITS(1) [],
122        PEIM OFFSET(8) NUMBITS(1) [],
123        BEIM OFFSET(9) NUMBITS(1) [],
124        OEIM OFFSET(10) NUMBITS(1) []
125    ],
126    IES [
127        TXCMPMIS OFFSET(0) NUMBITS(1) [],
128        CTSMIS OFFSET(1) NUMBITS(1) [],
129        DCDMIS OFFSET(2) NUMBITS(1) [],
130        DSRMIS OFFSET(3) NUMBITS(1) [],
131        RXIS OFFSET(4) NUMBITS(1) [],
132        TXIS OFFSET(5) NUMBITS(1) [],
133        RTIS OFFSET(6) NUMBITS(1) [],
134        FEIS OFFSET(7) NUMBITS(1) [],
135        PEIS OFFSET(8) NUMBITS(1) [],
136        BEIS OFFSET(9) NUMBITS(1) [],
137        OEIS OFFSET(10) NUMBITS(1) []
138    ],
139    MIS [
140        TXCMPMMIS OFFSET(0) NUMBITS(1) [],
141        CTSMMIS OFFSET(1) NUMBITS(1) [],
142        DCDMMIS OFFSET(2) NUMBITS(1) [],
143        DSRMMIS OFFSET(3) NUMBITS(1) [],
144        RXMIS OFFSET(4) NUMBITS(1) [],
145        TXMIS OFFSET(5) NUMBITS(1) [],
146        RTMIS OFFSET(6) NUMBITS(1) [],
147        FEMIS OFFSET(7) NUMBITS(1) [],
148        PEMIS OFFSET(8) NUMBITS(1) [],
149        BEMIS OFFSET(9) NUMBITS(1) [],
150        OEMIS OFFSET(10) NUMBITS(1) []
151    ],
152    IEC [
153        TXCMPMMIC OFFSET(0) NUMBITS(1) [],
154        CTSMMIC OFFSET(1) NUMBITS(1) [],
155        DCDMMIC OFFSET(2) NUMBITS(1) [],
156        DSRMMIC OFFSET(3) NUMBITS(1) [],
157        RXIC OFFSET(4) NUMBITS(1) [],
158        TXIC OFFSET(5) NUMBITS(1) [],
159        RTIC OFFSET(6) NUMBITS(1) [],
160        FEIC OFFSET(7) NUMBITS(1) [],
161        PEIC OFFSET(8) NUMBITS(1) [],
162        BEIC OFFSET(9) NUMBITS(1) [],
163        OEMC OFFSET(10) NUMBITS(1) []
164    ]
165];
166
167pub struct Uart<'a> {
168    registers: StaticRef<UartRegisters>,
169    clock_frequency: u32,
170    tx_client: OptionalCell<&'a dyn hil::uart::TransmitClient>,
171    rx_client: OptionalCell<&'a dyn hil::uart::ReceiveClient>,
172
173    tx_buffer: TakeCell<'static, [u8]>,
174    tx_len: Cell<usize>,
175    tx_index: Cell<usize>,
176
177    rx_buffer: TakeCell<'static, [u8]>,
178    rx_len: Cell<usize>,
179    rx_index: Cell<usize>,
180}
181
182#[derive(Copy, Clone)]
183pub struct UartParams {
184    pub baud_rate: u32,
185}
186
187impl Uart<'_> {
188    // unsafe bc of UART0_BASE usage, called twice would alias location
189    pub fn new_uart_0() -> Self {
190        Self {
191            registers: UART0_BASE,
192            clock_frequency: 24_000_000,
193            tx_client: OptionalCell::empty(),
194            rx_client: OptionalCell::empty(),
195            tx_buffer: TakeCell::empty(),
196            tx_len: Cell::new(0),
197            tx_index: Cell::new(0),
198            rx_buffer: TakeCell::empty(),
199            rx_len: Cell::new(0),
200            rx_index: Cell::new(0),
201        }
202    }
203
204    // unsafe bc of UART0_BASE usage, called twice would alias location
205    pub fn new_uart_1() -> Self {
206        Self {
207            registers: UART1_BASE,
208            clock_frequency: 24_000_000,
209            tx_client: OptionalCell::empty(),
210            rx_client: OptionalCell::empty(),
211            tx_buffer: TakeCell::empty(),
212            tx_len: Cell::new(0),
213            tx_index: Cell::new(0),
214            rx_buffer: TakeCell::empty(),
215            rx_len: Cell::new(0),
216            rx_index: Cell::new(0),
217        }
218    }
219
220    fn set_baud_rate(&self, baud_rate: u32) {
221        let regs = self.registers;
222
223        let baud_clk = 16 * baud_rate;
224        let integer_divisor = self.clock_frequency / baud_clk;
225        let intermediate_long = (self.clock_frequency * 64) / baud_clk;
226        let fraction_divisor_long = intermediate_long - (integer_divisor * 64);
227
228        regs.ibrd.write(IBRD::DIVINT.val(integer_divisor));
229        regs.fbrd.write(FBRD::DIVFRAC.val(fraction_divisor_long));
230    }
231
232    fn enable_tx_interrupt(&self) {
233        let regs = self.registers;
234
235        // Set TX FIFO to fire at 0
236        regs.ifls.modify(IFLS::TXIFLSEL.val(0));
237
238        regs.ier.modify(IER::TXIM::SET + IER::TXCMPMIM::SET);
239    }
240
241    fn disable_tx_interrupt(&self) {
242        let regs = self.registers;
243
244        regs.ier.modify(IER::TXIM::CLEAR + IER::TXCMPMIM::CLEAR);
245        regs.iec.modify(IEC::TXIC::SET + IEC::TXCMPMMIC::SET);
246    }
247
248    fn enable_rx_interrupt(&self) {
249        let regs = self.registers;
250
251        // Set RX FIFO to fire at 1
252        regs.ifls.modify(IFLS::RXIFLSEL.val(1));
253
254        regs.ier.modify(IER::RXIM::SET + IER::RTIM::SET);
255    }
256
257    fn disable_rx_interrupt(&self) {
258        let regs = self.registers;
259
260        regs.ier.modify(IER::RXIM::CLEAR + IER::RTIM::CLEAR);
261        regs.iec.modify(IEC::RXIC::SET + IEC::RTIC::SET);
262    }
263
264    fn tx_progress(&self) {
265        let regs = self.registers;
266        let idx = self.tx_index.get();
267        let len = self.tx_len.get();
268
269        if idx < len {
270            // If we are going to transmit anything, we first need to enable the
271            // TX interrupt. This ensures that we will get an interrupt, where
272            // we can either call the callback from, or continue transmitting
273            // bytes.
274            self.enable_tx_interrupt();
275
276            // Read from the transmit buffer and send bytes to the UART hardware
277            // until either the buffer is empty or the UART hardware is full.
278            self.tx_buffer.map(|tx_buf| {
279                let tx_len = len - idx;
280
281                for i in 0..tx_len {
282                    if regs.fr.is_set(FR::TXFF) {
283                        break;
284                    }
285                    let tx_idx = idx + i;
286                    regs.dr.write(DR::DATA.val(tx_buf[tx_idx] as u32));
287                    self.tx_index.set(tx_idx + 1)
288                }
289            });
290        }
291    }
292
293    fn rx_progress(&self) {
294        let regs = self.registers;
295        let idx = self.rx_index.get();
296        let len = self.rx_len.get();
297
298        if idx < len {
299            // Read from the transmit buffer and send bytes to the UART hardware
300            // until either the buffer is empty or the UART hardware is full.
301            self.rx_buffer.map(|rx_buf| {
302                let rx_len = len - idx;
303
304                for i in 0..rx_len {
305                    if regs.fr.is_set(FR::RXFE) {
306                        break;
307                    }
308
309                    let rx_idx = idx + i;
310                    let charecter = regs.dr.read(DR::DATA);
311
312                    rx_buf[rx_idx] = charecter as u8;
313
314                    self.rx_index.set(rx_idx + 1)
315                }
316            });
317        }
318
319        if self.rx_index.get() < self.rx_len.get() {
320            // Enable interrupts to get future events
321            self.enable_rx_interrupt();
322        }
323    }
324
325    pub fn handle_interrupt(&self) {
326        let regs = self.registers;
327        let irq = regs.ies.extract();
328
329        if irq.is_set(IES::TXCMPMIS) {
330            // TXRIS Interrupt
331            self.disable_tx_interrupt();
332
333            if self.tx_index.get() >= self.tx_len.get() {
334                // We sent everything to the UART hardware, now from an
335                // interrupt callback we can issue the callback.
336
337                // Disable the UART
338                if self.rx_buffer.is_none() {
339                    regs.cr.modify(CR::UARTEN::CLEAR);
340                }
341                regs.cr.modify(CR::TXE::CLEAR);
342
343                self.tx_client.map(|client| {
344                    self.tx_buffer.take().map(|tx_buf| {
345                        client.transmitted_buffer(tx_buf, self.tx_len.get(), Ok(()));
346                    });
347                });
348            } else {
349                // We have more to transmit, so continue in tx_progress().
350                self.tx_progress();
351            }
352        }
353
354        if irq.is_set(IES::RTIS) {
355            self.disable_rx_interrupt();
356
357            self.rx_progress();
358
359            if self.rx_index.get() >= self.rx_len.get() {
360                // Disable the UART
361                if self.tx_buffer.is_none() {
362                    regs.cr.modify(CR::UARTEN::CLEAR);
363                }
364                regs.cr.modify(CR::RXE::CLEAR);
365
366                self.rx_client.map(|client| {
367                    self.rx_buffer.take().map(|rx_buf| {
368                        client.received_buffer(
369                            rx_buf,
370                            self.rx_len.get(),
371                            Ok(()),
372                            uart::Error::None,
373                        );
374                    });
375                });
376            }
377        }
378    }
379
380    pub fn transmit_sync(&self, bytes: &[u8]) {
381        let regs = self.registers;
382        for b in bytes.iter() {
383            while regs.fr.is_set(FR::TXFF) {}
384            regs.dr.write(DR::DATA.val(*b as u32));
385        }
386    }
387}
388
389impl hil::uart::Configure for Uart<'_> {
390    fn configure(&self, params: hil::uart::Parameters) -> Result<(), ErrorCode> {
391        let regs = self.registers;
392
393        // Disable UART
394        regs.cr
395            .write(CR::UARTEN::CLEAR + CR::RXE::CLEAR + CR::TXE::CLEAR);
396
397        // Enable the clocks
398        regs.cr.modify(CR::CLKEN::SET + CR::CLKSEL::CLK_24MHZ);
399
400        // Set the baud rate
401        self.set_baud_rate(params.baud_rate);
402
403        // Setup the UART
404        regs.cr.modify(CR::RTSEN::CLEAR + CR::CTSEN::CLEAR);
405        // Enalbe FIFO
406        regs.lcrh.write(LCRH::FEN::SET);
407        // Set 8 data bits, no parity, 1 stop bit and no flow control
408        regs.lcrh.modify(LCRH::WLEN.val(3) + LCRH::FEN::SET);
409
410        // Disable interrupts
411        regs.ier.set(0x00);
412        regs.iec.set(0xFF);
413
414        Ok(())
415    }
416}
417
418impl<'a> hil::uart::Transmit<'a> for Uart<'a> {
419    fn set_transmit_client(&self, client: &'a dyn hil::uart::TransmitClient) {
420        self.tx_client.set(client);
421    }
422
423    fn transmit_buffer(
424        &self,
425        tx_data: &'static mut [u8],
426        tx_len: usize,
427    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
428        if tx_len == 0 || tx_len > tx_data.len() {
429            Err((ErrorCode::SIZE, tx_data))
430        } else if self.tx_buffer.is_some() {
431            Err((ErrorCode::BUSY, tx_data))
432        } else {
433            // Save the buffer so we can keep sending it.
434            self.tx_buffer.replace(tx_data);
435            self.tx_len.set(tx_len);
436            self.tx_index.set(0);
437
438            // Enable the UART
439            self.registers.cr.modify(CR::UARTEN::SET + CR::TXE::SET);
440
441            self.tx_progress();
442            Ok(())
443        }
444    }
445
446    fn transmit_abort(&self) -> Result<(), ErrorCode> {
447        Err(ErrorCode::FAIL)
448    }
449
450    fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
451        Err(ErrorCode::FAIL)
452    }
453}
454
455impl<'a> hil::uart::Receive<'a> for Uart<'a> {
456    fn set_receive_client(&self, client: &'a dyn hil::uart::ReceiveClient) {
457        self.rx_client.set(client);
458    }
459
460    fn receive_buffer(
461        &self,
462        rx_buffer: &'static mut [u8],
463        rx_len: usize,
464    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
465        if rx_len == 0 || rx_len > rx_buffer.len() {
466            Err((ErrorCode::SIZE, rx_buffer))
467        } else {
468            // Save the buffer so we can keep sending it.
469            self.rx_buffer.replace(rx_buffer);
470            self.rx_len.set(rx_len);
471            self.rx_index.set(0);
472
473            // Enable the UART
474            self.registers.cr.modify(CR::UARTEN::SET + CR::RXE::SET);
475
476            self.rx_progress();
477            Ok(())
478        }
479    }
480
481    fn receive_abort(&self) -> Result<(), ErrorCode> {
482        Err(ErrorCode::FAIL)
483    }
484
485    fn receive_word(&self) -> Result<(), ErrorCode> {
486        Err(ErrorCode::FAIL)
487    }
488}