Skip to main content

nrf52/
uarte.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//! Universal asynchronous receiver/transmitter with EasyDMA (UARTE)
6//!
7//! Author
8//! -------------------
9//!
10//! * Author: Niklas Adolfsson <niklasadolfsson1@gmail.com>
11//! * Date: March 10 2018
12
13use core::cell::Cell;
14use kernel::ErrorCode;
15use kernel::hil::uart;
16use kernel::utilities::StaticRef;
17use kernel::utilities::cells::{MapCell, OptionalCell};
18use kernel::utilities::dma_slice::DmaSubSliceMut;
19use kernel::utilities::leasable_buffer::SubSliceMut;
20use kernel::utilities::registers::interfaces::{Readable, Writeable};
21use kernel::utilities::registers::{ReadOnly, ReadWrite, WriteOnly, register_bitfields};
22use nrf5x::gpio::Pin;
23use nrf5x::pinmux;
24
25const UARTE_MAX_BUFFER_SIZE: usize = 0xff;
26
27pub const UARTE0_BASE: StaticRef<crate::uarte::UarteRegisters> =
28    unsafe { StaticRef::new(0x40002000 as *const crate::uarte::UarteRegisters) };
29
30#[repr(C)]
31pub struct UarteRegisters {
32    task_startrx: WriteOnly<u32, Task::Register>,
33    task_stoprx: WriteOnly<u32, Task::Register>,
34    task_starttx: WriteOnly<u32, Task::Register>,
35    task_stoptx: WriteOnly<u32, Task::Register>,
36    _reserved1: [u32; 7],
37    task_flush_rx: WriteOnly<u32, Task::Register>,
38    _reserved2: [u32; 52],
39    event_cts: ReadWrite<u32, Event::Register>,
40    event_ncts: ReadWrite<u32, Event::Register>,
41    _reserved3: [u32; 2],
42    event_endrx: ReadWrite<u32, Event::Register>,
43    _reserved4: [u32; 3],
44    event_endtx: ReadWrite<u32, Event::Register>,
45    event_error: ReadWrite<u32, Event::Register>,
46    _reserved6: [u32; 7],
47    event_rxto: ReadWrite<u32, Event::Register>,
48    _reserved7: [u32; 1],
49    event_rxstarted: ReadWrite<u32, Event::Register>,
50    event_txstarted: ReadWrite<u32, Event::Register>,
51    _reserved8: [u32; 1],
52    event_txstopped: ReadWrite<u32, Event::Register>,
53    _reserved9: [u32; 41],
54    shorts: ReadWrite<u32, Shorts::Register>,
55    _reserved10: [u32; 64],
56    intenset: ReadWrite<u32, Interrupt::Register>,
57    intenclr: ReadWrite<u32, Interrupt::Register>,
58    _reserved11: [u32; 93],
59    errorsrc: ReadWrite<u32, ErrorSrc::Register>,
60    _reserved12: [u32; 31],
61    enable: ReadWrite<u32, Uart::Register>,
62    _reserved13: [u32; 1],
63    pselrts: ReadWrite<u32, Psel::Register>,
64    pseltxd: ReadWrite<u32, Psel::Register>,
65    pselcts: ReadWrite<u32, Psel::Register>,
66    pselrxd: ReadWrite<u32, Psel::Register>,
67    _reserved14: [u32; 3],
68    baudrate: ReadWrite<u32, Baudrate::Register>,
69    _reserved15: [u32; 3],
70    rxd_ptr: ReadWrite<u32, Pointer::Register>,
71    rxd_maxcnt: ReadWrite<u32, Counter::Register>,
72    rxd_amount: ReadOnly<u32, Counter::Register>,
73    _reserved16: [u32; 1],
74    txd_ptr: ReadWrite<u32, Pointer::Register>,
75    txd_maxcnt: ReadWrite<u32, Counter::Register>,
76    txd_amount: ReadOnly<u32, Counter::Register>,
77    _reserved17: [u32; 7],
78    config: ReadWrite<u32, Config::Register>,
79}
80
81register_bitfields! [u32,
82    /// Start task
83    Task [
84        ENABLE OFFSET(0) NUMBITS(1)
85    ],
86
87    /// Read event
88    Event [
89        READY OFFSET(0) NUMBITS(1)
90    ],
91
92    /// Shortcuts
93    Shorts [
94        // Shortcut between ENDRX and STARTRX
95        ENDRX_STARTRX OFFSET(5) NUMBITS(1),
96        // Shortcut between ENDRX and STOPRX
97        ENDRX_STOPRX OFFSET(6) NUMBITS(1)
98    ],
99
100    /// UART Interrupts
101    Interrupt [
102        CTS OFFSET(0) NUMBITS(1),
103        NCTS OFFSET(1) NUMBITS(1),
104        ENDRX OFFSET(4) NUMBITS(1),
105        ENDTX OFFSET(8) NUMBITS(1),
106        ERROR OFFSET(9) NUMBITS(1),
107        RXTO OFFSET(17) NUMBITS(1),
108        RXSTARTED OFFSET(19) NUMBITS(1),
109        TXSTARTED OFFSET(20) NUMBITS(1),
110        TXSTOPPED OFFSET(22) NUMBITS(1)
111    ],
112
113    /// UART Errors
114    ErrorSrc [
115        OVERRUN OFFSET(0) NUMBITS(1),
116        PARITY OFFSET(1) NUMBITS(1),
117        FRAMING OFFSET(2) NUMBITS(1),
118        BREAK OFFSET(3) NUMBITS(1)
119    ],
120
121    /// Enable UART
122    Uart [
123        ENABLE OFFSET(0) NUMBITS(4) [
124            ON = 8,
125            OFF = 0
126        ]
127    ],
128
129    /// Pin select
130    Psel [
131        // Pin number. MSB is actually the port indicator, but since we number
132        // pins sequentially the binary representation of the pin number has
133        // the port bit set correctly. So, for simplicity we just treat the
134        // pin number as a 6 bit field.
135        PIN OFFSET(0) NUMBITS(6),
136        // Connect/Disconnect
137        CONNECT OFFSET(31) NUMBITS(1)
138    ],
139
140    /// Baudrate
141    Baudrate [
142        BAUDRAUTE OFFSET(0) NUMBITS(32)
143    ],
144
145    /// DMA pointer
146    Pointer [
147        POINTER OFFSET(0) NUMBITS(32)
148    ],
149
150    /// Counter value
151    Counter [
152        COUNTER OFFSET(0) NUMBITS(8)
153    ],
154
155    /// Configuration of parity and flow control
156    Config [
157        HWFC OFFSET(0) NUMBITS(1),
158        PARITY OFFSET(1) NUMBITS(3)
159    ]
160];
161
162/// Wrapper for managing MMIO for UARTE.
163pub struct UarteRegistersManager {
164    /// MMIO registers for the UARTE peripheral.
165    registers: StaticRef<UarteRegisters>,
166    /// Holding place for the TX DMA buffer while DMA in progress.
167    tx_dma_buf: MapCell<DmaSubSliceMut<'static, u8>>,
168    /// Holding place for the RX DMA buffer while DMA in progress.
169    rx_dma_buf: MapCell<DmaSubSliceMut<'static, u8>>,
170}
171
172impl UarteRegistersManager {
173    /// Create a DMA-enabled register manager for UARTE.
174    ///
175    /// # Safety
176    ///
177    /// This controls DMA hardware. As such, it must be unique. This requires:
178    ///
179    /// - This constructor must be called at most once.
180    /// - There must not be any other code that accesses the DMA buffer and
181    ///   length registers.
182    pub unsafe fn new_uarte0() -> Self {
183        Self {
184            registers: UARTE0_BASE,
185            tx_dma_buf: MapCell::empty(),
186            rx_dma_buf: MapCell::empty(),
187        }
188    }
189
190    /// Start a UART transmission with DMA.
191    ///
192    /// # Return
193    ///
194    /// `Ok(())` on successfully starting the DMA operation. `Err(())` if the
195    /// DMA is busy and the operation could not be started.
196    pub fn start_tx_dma(&self, buf: SubSliceMut<'static, u8>) -> Result<(), ()> {
197        if self.tx_dma_pending() {
198            return Err(());
199        }
200
201        // To create a DmaFence we must trust the implementation.
202        //
203        // # Safety
204        //
205        // The architecture-provided version is correct for the nRF52.
206        let fence = unsafe { cortexm4f::dma_fence::CortexMDmaFence::new() };
207
208        // Create DmaSlice for the TX buffer. This ensures that we can soundly
209        // share it with the DMA hardware.
210        let tx_dma_slice = DmaSubSliceMut::new_static(buf, fence);
211
212        // Provide the DmaSlice buffer to the hardware DMA engine.
213        self.registers.txd_ptr.set(tx_dma_slice.ptr_addr() as u32);
214
215        // Specify the length to transmit.
216        self.registers
217            .txd_maxcnt
218            .write(Counter::COUNTER.val(tx_dma_slice.len() as u32));
219
220        // Save the DmaSlice while the DMA operation executes.
221        self.tx_dma_buf.replace(tx_dma_slice);
222
223        // Start the TX DMA operation
224        self.registers.task_starttx.write(Task::ENABLE::SET);
225
226        Ok(())
227    }
228
229    pub fn finish_tx_dma(&self) -> Option<(SubSliceMut<'static, u8>, usize)> {
230        // End the DMA operation so it is safe to retrieve the buffer.
231        self.registers.event_endtx.write(Event::READY::CLEAR);
232
233        self.tx_dma_buf.take().map(|dma_slice| {
234            // To create a DmaFence we must trust the implementation.
235            //
236            // # Safety
237            //
238            // The architecture-provided version is correct for the nRF52.
239            let fence = unsafe { cortexm4f::dma_fence::CortexMDmaFence::new() };
240
241            // # Safety
242            //
243            // We must ensure that the DMA hardware no longer has any access
244            // to this buffer. We ensure that by setting the `event_endtx`
245            // event before taking the dma slice back.
246            let buf = unsafe { dma_slice.take(fence) };
247
248            let tx_bytes = self.registers.txd_amount.get() as usize;
249
250            (buf, tx_bytes)
251        })
252    }
253
254    pub fn tx_dma_pending(&self) -> bool {
255        self.tx_dma_buf.is_some()
256    }
257
258    /// Start a UART reception with DMA.
259    ///
260    /// # Return
261    ///
262    /// `Ok(())` on successfully starting the DMA operation. `Err(())` if the
263    /// DMA is busy and the operation could not be started.
264    pub fn start_rx_dma(&self, buf: SubSliceMut<'static, u8>) -> Result<(), ()> {
265        if self.rx_dma_pending() {
266            return Err(());
267        }
268
269        // To create a DmaFence we must trust the implementation.
270        //
271        // # Safety
272        //
273        // The architecture-provided version is correct for the nRF52.
274        let fence = unsafe { cortexm4f::dma_fence::CortexMDmaFence::new() };
275
276        // Create DmaSlice for the RX buffer. This ensures that we can soundly
277        // share it with the DMA hardware.
278        let rx_dma_slice = DmaSubSliceMut::new_static(buf, fence);
279
280        // Provide the DmaSlice buffer to the hardware DMA engine.
281        self.registers.rxd_ptr.set(rx_dma_slice.ptr_addr() as u32);
282
283        // Specify the length to transmit.
284        self.registers
285            .rxd_maxcnt
286            .write(Counter::COUNTER.val(rx_dma_slice.len() as u32));
287
288        // Save the DmaSlice while the DMA operation executes.
289        self.rx_dma_buf.replace(rx_dma_slice);
290
291        // Start the RX DMA operation
292        self.registers.task_startrx.write(Task::ENABLE::SET);
293
294        Ok(())
295    }
296
297    pub fn finish_rx_dma(&self) -> Option<(SubSliceMut<'static, u8>, usize)> {
298        // End the DMA operation so it is safe to retrieve the buffer.
299        self.registers.event_endrx.write(Event::READY::CLEAR);
300
301        self.rx_dma_buf.take().map(|dma_slice| {
302            // To create a DmaFence we must trust the implementation.
303            //
304            // # Safety
305            //
306            // The architecture-provided version is correct for the nRF52.
307            let fence = unsafe { cortexm4f::dma_fence::CortexMDmaFence::new() };
308
309            // # Safety
310            //
311            // We must ensure that the DMA hardware no longer has any access
312            // to this buffer. We ensure that by setting the `event_endrx`
313            // event before taking the dma slice back.
314            let buf = unsafe { dma_slice.take(fence) };
315
316            let rx_bytes = self.registers.rxd_amount.get() as usize;
317
318            (buf, rx_bytes)
319        })
320    }
321
322    pub fn rx_dma_pending(&self) -> bool {
323        self.rx_dma_buf.is_some()
324    }
325}
326
327/// UARTE
328// It should never be instanced outside this module but because a static mutable reference to it
329// is exported outside this module it must be `pub`
330pub struct Uarte<'a> {
331    registers: UarteRegistersManager,
332    tx_client: OptionalCell<&'a dyn uart::TransmitClient>,
333    tx_len: Cell<usize>,
334    rx_client: OptionalCell<&'a dyn uart::ReceiveClient>,
335    rx_len: Cell<usize>,
336    rx_abort_in_progress: Cell<bool>,
337}
338
339#[derive(Copy, Clone)]
340pub struct UARTParams {
341    pub baud_rate: u32,
342}
343
344impl<'a> Uarte<'a> {
345    /// Constructor
346    // This should only be constructed once
347    pub fn new(registers: UarteRegistersManager) -> Uarte<'a> {
348        Uarte {
349            registers,
350            tx_client: OptionalCell::empty(),
351            // tx_buffer: kernel::utilities::cells::TakeCell::empty(),
352            tx_len: Cell::new(0),
353            // tx_remaining_bytes: Cell::new(0),
354            rx_client: OptionalCell::empty(),
355            rx_len: Cell::new(0),
356            rx_abort_in_progress: Cell::new(false),
357        }
358    }
359
360    fn initialize_inner(&self, txd: Pin, rxd: Pin, cts: Option<Pin>, rts: Option<Pin>) {
361        self.disable_uart();
362
363        // Stop any ongoing TX or RX DMA transmissions
364        self.registers
365            .registers
366            .task_stoptx
367            .write(Task::ENABLE::SET);
368        self.registers
369            .registers
370            .task_stoprx
371            .write(Task::ENABLE::SET);
372
373        // Make sure we clear the endtx and endrx interrupts since
374        // that is what we rely on to know when the DMA TX
375        // finishes. Normally, we clear this interrupt as we handle
376        // it, so this is not necessary. However, a bootloader (or
377        // some other startup code) may have setup TX interrupts, and
378        // there may be one pending. We clear it to be safe.
379        self.registers
380            .registers
381            .event_endtx
382            .write(Event::READY::CLEAR);
383        self.registers
384            .registers
385            .event_endrx
386            .write(Event::READY::CLEAR);
387
388        self.registers
389            .registers
390            .pseltxd
391            .write(Psel::PIN.val(txd as _));
392        self.registers
393            .registers
394            .pselrxd
395            .write(Psel::PIN.val(rxd as _));
396        cts.map_or_else(
397            || {
398                // If no CTS pin is provided, then we need to mark it as
399                // disconnected in the register.
400                self.registers.registers.pselcts.write(Psel::CONNECT::SET);
401            },
402            |c| {
403                self.registers
404                    .registers
405                    .pselcts
406                    .write(Psel::PIN.val(c as _));
407            },
408        );
409        rts.map_or_else(
410            || {
411                // If no RTS pin is provided, then we need to mark it as
412                // disconnected in the register.
413                self.registers.registers.pselrts.write(Psel::CONNECT::SET);
414            },
415            |r| {
416                self.registers
417                    .registers
418                    .pselrts
419                    .write(Psel::PIN.val(r as _));
420            },
421        );
422
423        self.enable_uart();
424    }
425
426    /// Configure which pins the UART should use for txd, rxd, cts and rts
427    pub fn initialize(
428        &self,
429        txd: pinmux::Pinmux,
430        rxd: pinmux::Pinmux,
431        cts: Option<pinmux::Pinmux>,
432        rts: Option<pinmux::Pinmux>,
433    ) {
434        self.initialize_inner(
435            txd.into(),
436            rxd.into(),
437            cts.map(Into::into),
438            rts.map(Into::into),
439        )
440    }
441
442    // The datasheet gives a non-exhaustive list of example settings for
443    // typical bauds. The register is actually just a simple clock divider,
444    // as explained and with implementation from:
445    // https://devzone.nordicsemi.com/f/nordic-q-a/43280/technical-question-regarding-uart-baud-rate-generator-baudrate-register-offset-0x524
446    //
447    // Technically only RX is limited to 1MBaud, can TX up to 8MBaud:
448    // https://devzone.nordicsemi.com/f/nordic-q-a/84204/framing-error-and-noisy-data-when-using-uarte-at-high-baud-rate
449    pub fn get_divider_for_baud(baud_rate: u32) -> Result<u32, ErrorCode> {
450        if baud_rate > 1_000_000 || baud_rate < 1200 {
451            return Err(ErrorCode::INVAL);
452        }
453
454        // force 64 bit values for precision
455        let system_clock = 16000000u64; // TODO: Support dynamic clock
456        let scalar = 32u64;
457        let target_baud: u64 = baud_rate.into();
458
459        // n.b. bits 11-0 are ignored by hardware
460        let divider64 = (((target_baud << scalar) + (system_clock >> 1)) / system_clock) + 0x800;
461        let divider = (divider64 & 0xffff_f000) as u32;
462
463        Ok(divider)
464    }
465
466    fn set_baud_rate(&self, baud_rate: u32) -> Result<(), ErrorCode> {
467        let divider = Self::get_divider_for_baud(baud_rate)?;
468        self.registers.registers.baudrate.set(divider);
469
470        Ok(())
471    }
472
473    // Enable UART peripheral, this need to disabled for low power applications
474    fn enable_uart(&self) {
475        self.registers.registers.enable.write(Uart::ENABLE::ON);
476    }
477
478    #[allow(dead_code)]
479    fn disable_uart(&self) {
480        self.registers.registers.enable.write(Uart::ENABLE::OFF);
481    }
482
483    fn enable_rx_interrupts(&self) {
484        self.registers
485            .registers
486            .intenset
487            .write(Interrupt::ENDRX::SET);
488    }
489
490    fn enable_tx_interrupts(&self) {
491        self.registers
492            .registers
493            .intenset
494            .write(Interrupt::ENDTX::SET);
495    }
496
497    fn disable_rx_interrupts(&self) {
498        self.registers
499            .registers
500            .intenclr
501            .write(Interrupt::ENDRX::SET);
502    }
503
504    fn disable_tx_interrupts(&self) {
505        self.registers
506            .registers
507            .intenclr
508            .write(Interrupt::ENDTX::SET);
509    }
510
511    /// UART interrupt handler that listens for both tx_end and rx_end events
512    #[inline(never)]
513    pub fn handle_interrupt(&self) {
514        if self.tx_ready() {
515            self.disable_tx_interrupts();
516
517            if let Some((mut buf, transmitted_length)) = self.registers.finish_tx_dma() {
518                let active_range = buf.active_range();
519
520                // Calculate the remaining bytes to transmit based on the length to
521                // transmit, the window we just tried to transmit, and how many
522                // bytes we actually did transmit.
523                //
524                // <-----buffer------------------->
525                //          <-active range->
526                // [        [              ]      ]
527                let remaining_bytes = self
528                    .tx_len
529                    .get()
530                    .saturating_sub(active_range.start)
531                    .saturating_sub(transmitted_length);
532
533                if remaining_bytes == 0 {
534                    // We sent everything.
535                    self.tx_client.map(|client| {
536                        client.transmitted_buffer(buf.take(), self.tx_len.get(), Ok(()));
537                    });
538                } else {
539                    // Send the next portion of the buffer.
540
541                    // Reset back to the original slice.
542                    buf.reset();
543                    // Limit to just the portion of the buffer we are transmitting from.
544                    buf.slice(0..self.tx_len.get());
545                    // Skip what has already been transmitted.
546                    buf.slice((self.tx_len.get() - remaining_bytes)..);
547                    // Limit to at most the `UARTE_MAX_BUFFER_SIZE` bytes.
548                    buf.slice(0..UARTE_MAX_BUFFER_SIZE);
549                    // Send via DMA.
550                    let _ = self.registers.start_tx_dma(buf);
551                    // Re-enable interrupts.
552                    self.enable_tx_interrupts();
553                }
554            }
555        }
556
557        if self.rx_ready() {
558            self.disable_rx_interrupts();
559
560            // Clear the ENDRX event
561            self.registers
562                .registers
563                .event_endrx
564                .write(Event::READY::CLEAR);
565
566            if let Some((mut buf, received_length)) = self.registers.finish_rx_dma() {
567                let active_range = buf.active_range();
568
569                // Check if this ENDRX is due to an abort. If so, we want to
570                // do the receive callback immediately.
571                if self.rx_abort_in_progress.get() {
572                    self.rx_abort_in_progress.set(false);
573
574                    // Calculate how many bytes we actually received.
575                    let received_bytes = active_range.start + received_length;
576
577                    // Notify the client.
578                    self.rx_client.map(|client| {
579                        client.received_buffer(
580                            buf.take(),
581                            received_bytes,
582                            Err(ErrorCode::CANCEL),
583                            uart::Error::None,
584                        );
585                    });
586                } else {
587                    // In the normal case, we need to either pass call the callback
588                    // or do another read to get more bytes.
589
590                    // Calculate the remaining bytes to receive based on the length to
591                    // receive, the window we just tried to receive into, and how many
592                    // bytes we actually did receive.
593                    //
594                    //
595                    // <-----buffer------------------->
596                    //          <-active range->
597                    // [        [              ]      ]
598                    let remaining_bytes = self
599                        .rx_len
600                        .get()
601                        .saturating_sub(active_range.start)
602                        .saturating_sub(received_length);
603
604                    if remaining_bytes == 0 {
605                        // Signal client that the read is done
606                        self.rx_client.map(|client| {
607                            client.received_buffer(
608                                buf.take(),
609                                self.rx_len.get(),
610                                Ok(()),
611                                uart::Error::None,
612                            );
613                        });
614                    } else {
615                        // Receive into the next portion of the buffer.
616
617                        // Reset back to the original slice.
618                        buf.reset();
619                        // Limit to just the portion of the buffer we are receiving into.
620                        buf.slice(0..self.rx_len.get());
621                        // Skip what has already been received.
622                        buf.slice((self.rx_len.get() - remaining_bytes)..);
623                        // Limit to at most the `UARTE_MAX_BUFFER_SIZE` bytes.
624                        buf.slice(0..UARTE_MAX_BUFFER_SIZE);
625                        // Receive via DMA.
626                        let _ = self.registers.start_rx_dma(buf);
627                        // Re-enable interrupts.
628                        self.enable_rx_interrupts();
629                    }
630                }
631            }
632        }
633    }
634
635    /// Check if the UART transmission is done
636    pub fn tx_ready(&self) -> bool {
637        self.registers.registers.event_endtx.is_set(Event::READY)
638    }
639
640    /// Check if either the rx_buffer is full or the UART has timed out
641    pub fn rx_ready(&self) -> bool {
642        self.registers.registers.event_endrx.is_set(Event::READY)
643    }
644
645    // Helper function used by both transmit_word and transmit_buffer
646    fn setup_buffer_transmit(&self, buf: &'static mut [u8], tx_len: usize) {
647        // Save the total length to transmit as we may need to send over
648        // multiple iterations.
649        self.tx_len.set(tx_len);
650
651        // Create a `SubSlice` to simplify tracking which part we are sending,
652        // and slice the sub slice to either the total buffer to send or what
653        // fits in one send buffer.
654        let mut slice_to_send = SubSliceMut::new(buf);
655        slice_to_send.slice(0..core::cmp::min(tx_len, UARTE_MAX_BUFFER_SIZE));
656
657        // Send the buffer using DMA. This is managed by the register manager to
658        // ensure we are safely using DMA.
659        let _ = self.registers.start_tx_dma(slice_to_send);
660
661        // Enable interrupts so we get a interrupt when the transmission has
662        // finished.
663        self.enable_tx_interrupts();
664    }
665
666    fn setup_buffer_receive(&self, buf: &'static mut [u8], rx_len: usize) {
667        // Save the total length to receive.
668        self.rx_len.set(rx_len);
669
670        // Create a `SubSlice` to simplify tracking which part we have received
671        // into.
672        let mut slice_to_receive = SubSliceMut::new(buf);
673        slice_to_receive.slice(0..core::cmp::min(rx_len, UARTE_MAX_BUFFER_SIZE));
674
675        // Use the buffer with DMA. This is managed by the register manager to
676        // ensure we are safely using DMA.
677        let _ = self.registers.start_rx_dma(slice_to_receive);
678
679        // Enable interrupts so we get a interrupt when the receive has
680        // finished.
681        self.enable_rx_interrupts();
682    }
683}
684
685impl<'a> uart::Transmit<'a> for Uarte<'a> {
686    fn set_transmit_client(&self, client: &'a dyn uart::TransmitClient) {
687        self.tx_client.set(client);
688    }
689
690    fn transmit_buffer(
691        &self,
692        tx_data: &'static mut [u8],
693        tx_len: usize,
694    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
695        if tx_len == 0 || tx_len > tx_data.len() {
696            Err((ErrorCode::SIZE, tx_data))
697        } else if self.registers.tx_dma_pending() {
698            Err((ErrorCode::BUSY, tx_data))
699        } else {
700            self.setup_buffer_transmit(tx_data, tx_len);
701            Ok(())
702        }
703    }
704
705    fn transmit_word(&self, _data: u32) -> Result<(), ErrorCode> {
706        Err(ErrorCode::FAIL)
707    }
708
709    fn transmit_abort(&self) -> Result<(), ErrorCode> {
710        Err(ErrorCode::FAIL)
711    }
712}
713
714impl uart::Configure for Uarte<'_> {
715    fn configure(&self, params: uart::Parameters) -> Result<(), ErrorCode> {
716        // These could probably be implemented, but are currently ignored, so
717        // throw an error.
718        if params.stop_bits != uart::StopBits::One {
719            return Err(ErrorCode::NOSUPPORT);
720        }
721        if params.parity != uart::Parity::None {
722            return Err(ErrorCode::NOSUPPORT);
723        }
724        if params.hw_flow_control {
725            return Err(ErrorCode::NOSUPPORT);
726        }
727
728        self.set_baud_rate(params.baud_rate)?;
729
730        Ok(())
731    }
732}
733
734impl<'a> uart::Receive<'a> for Uarte<'a> {
735    fn set_receive_client(&self, client: &'a dyn uart::ReceiveClient) {
736        self.rx_client.set(client);
737    }
738
739    fn receive_buffer(
740        &self,
741        rx_buf: &'static mut [u8],
742        rx_len: usize,
743    ) -> Result<(), (ErrorCode, &'static mut [u8])> {
744        if rx_len > rx_buf.len() {
745            Err((ErrorCode::SIZE, rx_buf))
746        } else if self.registers.rx_dma_pending() {
747            Err((ErrorCode::BUSY, rx_buf))
748        } else {
749            self.setup_buffer_receive(rx_buf, rx_len);
750            Ok(())
751        }
752    }
753
754    fn receive_word(&self) -> Result<(), ErrorCode> {
755        Err(ErrorCode::FAIL)
756    }
757
758    fn receive_abort(&self) -> Result<(), ErrorCode> {
759        // Trigger the STOPRX event to cancel the current receive call.
760        if !self.registers.rx_dma_pending() {
761            Ok(())
762        } else {
763            self.rx_abort_in_progress.set(true);
764            self.registers
765                .registers
766                .task_stoprx
767                .write(Task::ENABLE::SET);
768            Err(ErrorCode::BUSY)
769        }
770    }
771}
772
773#[cfg(test)]
774mod tests {
775    use kernel::ErrorCode;
776
777    #[test]
778    fn baud_rate_divider_calculation() {
779        use crate::uarte::Uarte;
780
781        assert_eq!(Uarte::get_divider_for_baud(0), Err(ErrorCode::INVAL));
782        assert_eq!(
783            Uarte::get_divider_for_baud(4_000_000),
784            Err(ErrorCode::INVAL)
785        );
786
787        // The constants below are the list from the Nordic technical documents.
788        //
789        // n.b., some datasheet constants do not match formula constants,
790        // so we skip those, see nordic forum thread for details:
791        // https://devzone.nordicsemi.com/f/nordic-q-a/84204/framing-error-and-noisy-data-when-using-uarte-at-high-baud-rate
792        //
793        // This is a *datasheet bug*, i.e., for a target baud of 115200, the
794        // datasheet divisor yields 115108 (-0.079% err) where direct
795        // computation of the divider yields 115203 (+0.002% err). Both work in
796        // practice, but the error here is an annoying and uncharacteristic
797        // Nordic quirk.
798        assert_eq!(Uarte::get_divider_for_baud(1200), Ok(0x0004F000));
799        assert_eq!(Uarte::get_divider_for_baud(2400), Ok(0x0009D000));
800        assert_eq!(Uarte::get_divider_for_baud(4800), Ok(0x0013B000));
801        assert_eq!(Uarte::get_divider_for_baud(9600), Ok(0x00275000));
802        //assert_eq!(u.get_divider_for_baud(14400), Ok(0x003AF000));
803        assert_eq!(Uarte::get_divider_for_baud(19200), Ok(0x004EA000));
804        //assert_eq!(u.get_divider_for_baud(28800), Ok(0x0075C000));
805        //assert_eq!(u.get_divider_for_baud(38400), Ok(0x009D0000));
806        //assert_eq!(u.get_divider_for_baud(57600), Ok(0x00EB0000));
807        assert_eq!(Uarte::get_divider_for_baud(76800), Ok(0x013A9000));
808        //assert_eq!(u.get_divider_for_baud(115200), Ok(0x01D60000));
809        //assert_eq!(u.get_divider_for_baud(230400), Ok(0x03B00000));
810        assert_eq!(Uarte::get_divider_for_baud(250000), Ok(0x04000000));
811        //assert_eq!(u.get_divider_for_baud(460800), Ok(0x07400000));
812        //assert_eq!(u.get_divider_for_baud(921600), Ok(0x0F000000));
813        assert_eq!(Uarte::get_divider_for_baud(1000000), Ok(0x10000000));
814        //
815        // For completeness of testing, we do verify that the calculation works
816        // as-expected to generate the empirically correct divisors.  (i.e.,
817        // these are not the datasheet constants, but are the correct divisors
818        // for the desired bauds):
819        assert_eq!(Uarte::get_divider_for_baud(14400), Ok(0x003B0000));
820        assert_eq!(Uarte::get_divider_for_baud(28800), Ok(0x0075F000));
821        assert_eq!(Uarte::get_divider_for_baud(38400), Ok(0x009D5000));
822        assert_eq!(Uarte::get_divider_for_baud(57600), Ok(0x00EBF000));
823        assert_eq!(Uarte::get_divider_for_baud(115200), Ok(0x01D7E000));
824        assert_eq!(Uarte::get_divider_for_baud(230400), Ok(0x03AFB000));
825        assert_eq!(Uarte::get_divider_for_baud(460800), Ok(0x075F7000));
826        assert_eq!(Uarte::get_divider_for_baud(921600), Ok(0x0EBEE000));
827    }
828}