esp32/
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::utilities::cells::OptionalCell;
12use kernel::utilities::cells::TakeCell;
13use kernel::utilities::registers::interfaces::{ReadWriteable, Readable, Writeable};
14use kernel::utilities::registers::{register_bitfields, register_structs, ReadWrite};
15use kernel::utilities::StaticRef;
16
17pub const UART0_BASE: StaticRef<UartRegisters> =
18    unsafe { StaticRef::new(0x6000_0000 as *const UartRegisters) };
19
20register_structs! {
21    pub UartRegisters {
22        (0x000 => fifo: ReadWrite<u32, FIFO::Register>),
23        (0x004 => int_raw: ReadWrite<u32, INT::Register>),
24        (0x008 => int_st: ReadWrite<u32, INT::Register>),
25        (0x00C => int_ena: ReadWrite<u32, INT::Register>),
26        (0x010 => int_clr: ReadWrite<u32, INT::Register>),
27        (0x014 => clkdiv: ReadWrite<u32, CLKDIV::Register>),
28        (0x018 => autobaud: ReadWrite<u32, AUTOBAUD::Register>),
29        (0x01C => status: ReadWrite<u32, STATUS::Register>),
30        (0x020 => conf0: ReadWrite<u32, CONF0::Register>),
31        (0x024 => conf1: ReadWrite<u32, CONF1::Register>),
32        (0x028 => lowpulse: ReadWrite<u32, LOWPULSE::Register>),
33        (0x02C => highpulse: ReadWrite<u32, HIGHPULSE::Register>),
34        (0x030 => rxd_cnt: ReadWrite<u32, RXD_CNT::Register>),
35        (0x034 => flow_config: ReadWrite<u32, FLOW_CONFIG::Register>),
36        (0x038 => sleep_conf: ReadWrite<u32, SLEEP_CONF::Register>),
37        (0x03C => swfc_conf: ReadWrite<u32, SWFC_CONF::Register>),
38        (0x040 => idle_conf: ReadWrite<u32, IDLE_CONF::Register>),
39        (0x044 => rs485_conf: ReadWrite<u32, RS485_CONF::Register>),
40        (0x048 => at_cmd_precnt: ReadWrite<u32, AT_CMD_PRECNT::Register>),
41        (0x04C => at_cmd_postcnt: ReadWrite<u32, AT_CMD_POSTCNT::Register>),
42        (0x050 => at_cmd_gaptout: ReadWrite<u32, AT_CMD_GAPTOUT::Register>),
43        (0x054 => at_cmd_char: ReadWrite<u32, AT_CMD_CHAR::Register>),
44        (0x058 => mem_conf: ReadWrite<u32, MEM_CONF::Register>),
45        (0x05C => _reserved0),
46        (0x064 => mem_cnt_status: ReadWrite<u32, MEM_CNT_STATUS::Register>),
47        (0x068 => pospulse: ReadWrite<u32, POSPULSE::Register>),
48        (0x06C => negpulse: ReadWrite<u32, NEGPULSE::Register>),
49        (0x070 => @END),
50    }
51}
52
53register_bitfields![u32,
54    FIFO [
55        RXFIFO_RD_BYTE OFFSET(0) NUMBITS(8) [],
56    ],
57    INT [
58        RXFIFO_FULL_INT OFFSET(0) NUMBITS(1) [],
59        TXFIFO_EMPTY_INT OFFSET(1) NUMBITS(1) [],
60        PARITY_ERR_INT OFFSET(2) NUMBITS(1) [],
61        FRM_ERR_INT OFFSET(3) NUMBITS(1) [],
62        RXFIFO_OVF_INT OFFSET(4) NUMBITS(1) [],
63        DSR_CHG_INT OFFSET(5) NUMBITS(1) [],
64        CTS_CHG_INT OFFSET(6) NUMBITS(1) [],
65        BRK_DET_INT OFFSET(7) NUMBITS(1) [],
66        RXFIFO_TOUT_INT OFFSET(8) NUMBITS(1) [],
67        SW_XON_INT OFFSET(9) NUMBITS(1) [],
68        SW_XOFF_INT OFFSET(10) NUMBITS(1) [],
69        GLITCH_DET_INT OFFSET(11) NUMBITS(1) [],
70        TX_BRK_DONE_INT OFFSET(12) NUMBITS(1) [],
71        TX_BRK_IDLE_DONE_INT OFFSET(13) NUMBITS(1) [],
72        TX_DONE_INT OFFSET(14) NUMBITS(1) [],
73        RS485_PARITY_ERR_INT OFFSET(15) NUMBITS(1) [],
74        RS485_FRM_ERR_INT OFFSET(16) NUMBITS(1) [],
75        RS485_CLASH_INT OFFSET(17) NUMBITS(1) [],
76        AT_CMD_CHAR_DET_INT OFFSET(18) NUMBITS(1) [],
77    ],
78    CLKDIV [
79        CLKDIV OFFSET(0) NUMBITS(20) [],
80        CLKDIV_FRAG OFFSET(20) NUMBITS(4) [],
81    ],
82    AUTOBAUD [
83        AUTOBAUD_EN OFFSET(0) NUMBITS(1) [],
84        GLITCH_FILT OFFSET(8) NUMBITS(8) [],
85    ],
86    STATUS [
87        RXFIFO_CNT OFFSET(0) NUMBITS(8) [],
88        ST_URX_OUT OFFSET(8) NUMBITS(4) [],
89        DSRN OFFSET(13) NUMBITS(1) [],
90        CTSN OFFSET(14) NUMBITS(1) [],
91        RXD OFFSET(15) NUMBITS(1) [],
92        TXFIFO_CNT OFFSET(16) NUMBITS(8) [],
93        ST_UTX_OUT OFFSET(24) NUMBITS(4) [],
94        DTRN OFFSET(29) NUMBITS(1) [],
95        RTSN OFFSET(30) NUMBITS(1) [],
96        TXD OFFSET(31) NUMBITS(1) [],
97    ],
98    CONF0 [
99        PARITY OFFSET(0) NUMBITS(1) [],
100        PARITY_EN OFFSET(1) NUMBITS(1) [],
101        BIT_NUM OFFSET(2) NUMBITS(2) [],
102        STOP_BIT_NUM OFFSET(4) NUMBITS(2) [],
103        SW_RTS OFFSET(6) NUMBITS(1) [],
104        SW_DTR OFFSET(7) NUMBITS(1) [],
105        TXD_BRK OFFSET(8) NUMBITS(1) [],
106        IRDA_DPLX OFFSET(9) NUMBITS(1) [],
107        IRDA_TX_EN OFFSET(10) NUMBITS(1) [],
108        IRDA_WCTL OFFSET(11) NUMBITS(1) [],
109        IRDA_TX_INV OFFSET(12) NUMBITS(1) [],
110        IRDA_RX_INV OFFSET(13) NUMBITS(1) [],
111        LOOPBACK OFFSET(14) NUMBITS(1) [],
112        TX_FLOW_EN OFFSET(15) NUMBITS(1) [],
113        IRDA_EN OFFSET(16) NUMBITS(1) [],
114        RXFIFO_RST OFFSET(17) NUMBITS(1) [],
115        TXFIFO_RST OFFSET(18) NUMBITS(1) [],
116        RXD_INV OFFSET(19) NUMBITS(1) [],
117        CTS_INV OFFSET(20) NUMBITS(1) [],
118        DSR_INV OFFSET(21) NUMBITS(1) [],
119        TXD_INV OFFSET(22) NUMBITS(1) [],
120        RTS_INV OFFSET(23) NUMBITS(1) [],
121        DTR_INV OFFSET(24) NUMBITS(1) [],
122        TICK_REF_ALWAYS_ON OFFSET(27) NUMBITS(1) [],
123    ],
124    CONF1 [
125        RXFIFO_FULL_THRHD OFFSET(0) NUMBITS(7) [],
126        TXFIFO_EMPTY_THRHD OFFSET(8) NUMBITS(6) [],
127        RX_FLOW_THRHD OFFSET(16) NUMBITS(6) [],
128        RX_FLOW_EN OFFSET(23) NUMBITS(1) [],
129        RX_TOUT_THRHD OFFSET(24) NUMBITS(7) [],
130        RX_TOUT_EN OFFSET(31) NUMBITS(1) [],
131    ],
132    LOWPULSE [
133        LOWPULSE_MIN_CNT OFFSET(0) NUMBITS(20) [],
134    ],
135    HIGHPULSE [
136        HIGHPULSE_MIN_CNT OFFSET(0) NUMBITS(20) []
137    ],
138    RXD_CNT [
139        RXD_EDGE_CNT OFFSET(0) NUMBITS(10) [],
140    ],
141    FLOW_CONFIG [
142        SW_FLOW_CON_EN OFFSET(0) NUMBITS(1) [],
143        XONOFF_DEL OFFSET(1) NUMBITS(1) [],
144        FORCE_XON OFFSET(2) NUMBITS(1) [],
145        FORCE_XOFF OFFSET(3) NUMBITS(1) [],
146        SEND_XON OFFSET(4) NUMBITS(1) [],
147        SEND_XOFF OFFSET(5) NUMBITS(1) [],
148    ],
149    SLEEP_CONF [
150        ACTIVE_THRESHOLD OFFSET(0) NUMBITS(10) [],
151    ],
152    SWFC_CONF [
153        XON_THRESHOLD OFFSET(0) NUMBITS(8) [],
154        XOFF_THRESHOLD OFFSET(8) NUMBITS(8) [],
155        XON_CHAR OFFSET(16) NUMBITS(8) [],
156        XOFF_CHAR OFFSET(24) NUMBITS(8) [],
157    ],
158    IDLE_CONF [
159        RX_IDLE_THRHD OFFSET(0) NUMBITS(10) [],
160        TX_IDLE_NUM OFFSET(10) NUMBITS(10) [],
161        TX_BRK_NUM OFFSET(20) NUMBITS(8) [],
162    ],
163    RS485_CONF [
164        RS485_EN OFFSET(0) NUMBITS(1) [],
165        DL0_EN OFFSET(1) NUMBITS(1) [],
166        DL1_EN OFFSET(2) NUMBITS(1) [],
167        RS485TX_RX_EN OFFSET(3) NUMBITS(1) [],
168        RS485RXBY_TX_EN OFFSET(4) NUMBITS(1) [],
169        RS485_RX_DLY_NUM OFFSET(5) NUMBITS(1) [],
170        RS485_TX_DLY_NUM OFFSET(6) NUMBITS(4) [],
171    ],
172    AT_CMD_PRECNT [
173        PRE_IDLE_NUM OFFSET(0) NUMBITS(24) [],
174    ],
175    AT_CMD_POSTCNT [
176        POST_IDLE_NUM OFFSET(0) NUMBITS(24) [],
177    ],
178    AT_CMD_GAPTOUT [
179        RX_GAP_TOUT OFFSET(0) NUMBITS(24) [],
180    ],
181    AT_CMD_CHAR [
182        AT_CMD_CHAR_REG OFFSET(0) NUMBITS(8) [],
183        CHAR_NUM OFFSET(8) NUMBITS(8) [],
184    ],
185    MEM_CONF [
186        MEM_PD OFFSET(0) NUMBITS(1) [],
187        RX_SIZE OFFSET(3) NUMBITS(4) [],
188        TX_SIZE OFFSET(7) NUMBITS(4) [],
189        RX_FLOW_THRHD_H3 OFFSET(15) NUMBITS(3) [],
190        RX_TOUT_THRHD_H3 OFFSET(18) NUMBITS(3) [],
191        XON_THRESHOLD_H2 OFFSET(21) NUMBITS(2) [],
192        XOFF_THRESHOLD_H2 OFFSET(23) NUMBITS(2) [],
193        RX_MEM_FULL_THRHD OFFSET(25) NUMBITS(3) [],
194        TX_MEM_EMPTY_THRHD OFFSET(28) NUMBITS(3) [],
195    ],
196    MEM_CNT_STATUS [
197        RX_MEM_CNT OFFSET(0) NUMBITS(3) [],
198        TX_MEM_CNT OFFSET(3) NUMBITS(3) [],
199    ],
200    POSPULSE [
201        POSEDGE_MIN_CNT OFFSET(0) NUMBITS(20) [],
202    ],
203    NEGPULSE [
204        NEGEDGE_MIN_CNT OFFSET(0) NUMBITS(20) [],
205    ],
206];
207
208pub struct Uart<'a> {
209    registers: StaticRef<UartRegisters>,
210    tx_client: OptionalCell<&'a dyn hil::uart::TransmitClient>,
211    rx_client: OptionalCell<&'a dyn hil::uart::ReceiveClient>,
212
213    tx_buffer: TakeCell<'static, [u8]>,
214    tx_len: Cell<usize>,
215    tx_index: Cell<usize>,
216
217    rx_buffer: TakeCell<'static, [u8]>,
218    rx_index: Cell<usize>,
219    rx_len: Cell<usize>,
220}
221
222#[derive(Copy, Clone)]
223pub struct UartParams {
224    pub baud_rate: u32,
225}
226
227impl<'a> Uart<'a> {
228    pub fn new(base: StaticRef<UartRegisters>) -> Uart<'a> {
229        Uart {
230            registers: base,
231            tx_client: OptionalCell::empty(),
232            rx_client: OptionalCell::empty(),
233            tx_buffer: TakeCell::empty(),
234            tx_len: Cell::new(0),
235            tx_index: Cell::new(0),
236            rx_buffer: TakeCell::empty(),
237            rx_index: Cell::new(0),
238            rx_len: Cell::new(0),
239        }
240    }
241
242    fn enable_tx_interrupt(&self) {
243        let regs = self.registers;
244
245        regs.int_ena.modify(
246            INT::TXFIFO_EMPTY_INT::SET
247                + INT::TX_BRK_DONE_INT::SET
248                + INT::TX_BRK_IDLE_DONE_INT::SET
249                + INT::TX_DONE_INT::SET,
250        );
251    }
252
253    pub fn clear_tx_interrupt(&self) {
254        let regs = self.registers;
255
256        regs.int_clr.modify(
257            INT::TXFIFO_EMPTY_INT::SET
258                + INT::TX_BRK_DONE_INT::SET
259                + INT::TX_BRK_IDLE_DONE_INT::SET
260                + INT::TX_DONE_INT::SET,
261        );
262    }
263
264    pub fn disable_tx_interrupt(&self) {
265        let regs = self.registers;
266        regs.int_ena.modify(
267            INT::TXFIFO_EMPTY_INT::CLEAR
268                + INT::TX_BRK_DONE_INT::CLEAR
269                + INT::TX_BRK_IDLE_DONE_INT::CLEAR
270                + INT::TX_DONE_INT::CLEAR,
271        );
272    }
273
274    fn enable_rx_interrupt(&self) {
275        let regs = self.registers;
276
277        regs.int_ena.modify(
278            INT::RXFIFO_FULL_INT::SET + INT::RXFIFO_OVF_INT::SET + INT::RXFIFO_TOUT_INT::SET,
279        );
280    }
281
282    pub fn clear_rx_interrupt(&self) {
283        let regs = self.registers;
284
285        regs.int_clr.modify(
286            INT::RXFIFO_FULL_INT::SET + INT::RXFIFO_OVF_INT::SET + INT::RXFIFO_TOUT_INT::SET,
287        );
288    }
289
290    pub fn disable_rx_interrupt(&self) {
291        let regs = self.registers;
292        regs.int_ena.modify(
293            INT::RXFIFO_FULL_INT::CLEAR + INT::RXFIFO_OVF_INT::CLEAR + INT::RXFIFO_TOUT_INT::CLEAR,
294        );
295    }
296
297    fn tx_progress(&self) {
298        let regs = self.registers;
299        let idx = self.tx_index.get();
300        let len = self.tx_len.get();
301
302        if idx < len {
303            // Read from the transmit buffer and send bytes to the UART hardware
304            // until either the buffer is empty or the UART hardware is full.
305            self.tx_buffer.map(|tx_buf| {
306                let tx_len = len - idx;
307
308                for i in 0..tx_len {
309                    if regs.status.read(STATUS::TXFIFO_CNT) >= 127 {
310                        break;
311                    }
312                    let tx_idx = idx + i;
313                    regs.fifo
314                        .write(FIFO::RXFIFO_RD_BYTE.val(tx_buf[tx_idx] as u32));
315                    self.tx_index.set(tx_idx + 1)
316                }
317            });
318        }
319    }
320
321    fn rx_progress(&self) {
322        let regs = self.registers;
323        let idx = self.rx_index.get();
324        let len = self.rx_len.get();
325
326        if idx < len {
327            // Read from the UART hardware and write them to the receive buffer
328            // until either the buffer is full or the UART hardware is empty.
329            self.rx_buffer.map(|rx_buf| {
330                let rx_len = len - idx;
331
332                for i in 0..rx_len {
333                    if regs.status.read(STATUS::RXFIFO_CNT) == 0 {
334                        break;
335                    }
336                    let rx_idx = idx + i;
337                    rx_buf[rx_idx] = regs.fifo.read(FIFO::RXFIFO_RD_BYTE) as u8;
338                    self.rx_index.set(rx_idx + 1)
339                }
340            });
341        }
342    }
343
344    pub fn handle_interrupt(&self) {
345        let regs = self.registers;
346        let intrs = regs.int_st.extract();
347
348        if intrs.is_set(INT::TXFIFO_EMPTY_INT) {
349            self.clear_tx_interrupt();
350            if self.tx_index.get() == self.tx_len.get() {
351                self.disable_tx_interrupt();
352                // We sent everything to the UART hardware, now from an
353                // interrupt callback we can issue the callback.
354                self.tx_client.map(|client| {
355                    self.tx_buffer.take().map(|tx_buf| {
356                        client.transmitted_buffer(tx_buf, self.tx_len.get(), Ok(()));
357                    });
358                });
359            } else {
360                // We have more to transmit, so continue in tx_progress().
361                self.tx_progress();
362            }
363        }
364
365        if intrs.is_set(INT::RXFIFO_FULL_INT) || intrs.is_set(INT::RXFIFO_TOUT_INT) {
366            self.clear_rx_interrupt();
367            if self.rx_index.get() == self.rx_len.get() {
368                self.disable_rx_interrupt();
369                // We received everything from the UART hardware, now from an
370                // interrupt callback we can issue the callback.
371                self.rx_client.map(|client| {
372                    self.rx_buffer.take().map(|rx_buf| {
373                        client.received_buffer(
374                            rx_buf,
375                            self.rx_len.get(),
376                            Ok(()),
377                            hil::uart::Error::None,
378                        );
379                    });
380                });
381            } else {
382                // We have more to receive, so continue in rx_progress().
383                self.rx_progress();
384            }
385        }
386    }
387
388    pub fn transmit_sync(&self, bytes: &[u8]) {
389        let regs = self.registers;
390        for b in bytes.iter() {
391            while regs.status.read(STATUS::TXFIFO_CNT) > 8 {}
392            regs.fifo.write(FIFO::RXFIFO_RD_BYTE.val(*b as u32));
393        }
394    }
395}
396
397impl hil::uart::Configure for Uart<'_> {
398    fn configure(&self, _params: hil::uart::Parameters) -> Result<(), ErrorCode> {
399        // Disable all interrupts for now
400        self.disable_rx_interrupt();
401        self.disable_tx_interrupt();
402
403        Ok(())
404    }
405}
406
407impl<'a> hil::uart::Transmit<'a> for Uart<'a> {
408    fn set_transmit_client(&self, client: &'a dyn hil::uart::TransmitClient) {
409        self.tx_client.set(client);
410    }
411
412    fn transmit_buffer(
413        &self,
414        tx_data: &'static mut [u8],
415        tx_len: usize,
416    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
417        if tx_len == 0 || tx_len > tx_data.len() {
418            Err((ErrorCode::SIZE, tx_data))
419        } else if self.tx_buffer.is_some() {
420            Err((ErrorCode::BUSY, tx_data))
421        } else {
422            // Save the buffer so we can keep sending it.
423            self.tx_buffer.replace(tx_data);
424            self.tx_len.set(tx_len);
425            self.tx_index.set(0);
426
427            self.enable_tx_interrupt();
428
429            self.tx_progress();
430            Ok(())
431        }
432    }
433
434    fn transmit_word(&self, _word: u32) -> Result<(), ErrorCode> {
435        Err(ErrorCode::FAIL)
436    }
437
438    fn transmit_abort(&self) -> Result<(), ErrorCode> {
439        Err(ErrorCode::FAIL)
440    }
441}
442
443/* UART receive is not implemented yet, mostly due to a lack of tests available */
444impl<'a> hil::uart::Receive<'a> for Uart<'a> {
445    fn set_receive_client(&self, client: &'a dyn hil::uart::ReceiveClient) {
446        self.rx_client.set(client);
447    }
448
449    fn receive_buffer(
450        &self,
451        rx_buffer: &'static mut [u8],
452        rx_len: usize,
453    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
454        if rx_len == 0 || rx_len > rx_buffer.len() {
455            return Err((ErrorCode::SIZE, rx_buffer));
456        }
457
458        self.rx_buffer.replace(rx_buffer);
459        self.rx_index.set(0);
460        self.rx_len.set(rx_len);
461
462        self.enable_rx_interrupt();
463
464        self.rx_progress();
465
466        Ok(())
467    }
468
469    fn receive_word(&self) -> Result<(), ErrorCode> {
470        Err(ErrorCode::FAIL)
471    }
472
473    fn receive_abort(&self) -> Result<(), ErrorCode> {
474        Err(ErrorCode::FAIL)
475    }
476}