kernel/hil/
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//! Interface for UART communication.
6
7use crate::ErrorCode;
8
9/// Number of stop bits to send after each word.
10#[derive(Copy, Clone, Debug, PartialEq)]
11pub enum StopBits {
12    /// Include one stop bit after each word.
13    One = 1,
14    /// Include two stop bits after each word.
15    Two = 2,
16}
17
18/// Parity bit configuration.
19#[derive(Copy, Clone, Debug, PartialEq)]
20pub enum Parity {
21    /// No parity bits.
22    None = 0,
23    /// Add a parity bit to ensure an odd number of 1 bits in the word.
24    Odd = 1,
25    /// Add a parity bit to ensure an even number of 1 bits in the word.
26    Even = 2,
27}
28
29/// Number of bits in each word.
30#[derive(Copy, Clone, Debug, PartialEq)]
31pub enum Width {
32    /// Six bits per word.
33    Six = 6,
34    /// Seven bits per word.
35    Seven = 7,
36    /// Eight bits per word.
37    Eight = 8,
38}
39
40/// UART parameters for configuring the bus.
41#[derive(Copy, Clone, Debug)]
42pub struct Parameters {
43    /// Baud rate in bit/s.
44    pub baud_rate: u32,
45    /// Number of bits per word.
46    pub width: Width,
47    /// Parity bit configuration.
48    pub parity: Parity,
49    /// Number of stop bits per word.
50    pub stop_bits: StopBits,
51    /// Whether UART flow control is enabled.
52    pub hw_flow_control: bool,
53}
54
55/// The type of error encountered during UART transaction.
56#[derive(Copy, Clone, Debug, PartialEq)]
57pub enum Error {
58    /// No error occurred and the command completed successfully
59    None,
60
61    /// Parity error during receive
62    ParityError,
63
64    /// Framing error during receive
65    FramingError,
66
67    /// Overrun error during receive
68    OverrunError,
69
70    /// Repeat call of transmit or receive before initial command complete
71    RepeatCallError,
72
73    /// UART hardware was reset
74    ResetError,
75
76    /// UART hardware was disconnected
77    BreakError,
78
79    /// Read or write was aborted early
80    Aborted,
81}
82
83/// Trait for a full UART device.
84///
85/// This includes configuring the bus, transmitting data, and receiving data.
86pub trait Uart<'a>: Configure + Transmit<'a> + Receive<'a> {}
87
88/// Trait for sending and receiving on UART.
89///
90/// This includes transmitting data and receiving data.
91///
92/// Capsules can use this to require a UART device that can both send and
93/// receive but do not need the ability to configure the bus settings.
94pub trait UartData<'a>: Transmit<'a> + Receive<'a> {}
95
96/// Trait for a full advanced UART device.
97///
98/// This includes configuring the bus, transmitting data, and the advanced
99/// reception operations.
100pub trait UartAdvanced<'a>: Configure + Transmit<'a> + ReceiveAdvanced<'a> {}
101
102/// Trait for both receive and transmit callbacks.
103pub trait Client: ReceiveClient + TransmitClient {}
104
105// Provide blanket implementations for all trait groups
106impl<'a, T: Configure + Transmit<'a> + Receive<'a>> Uart<'a> for T {}
107impl<'a, T: Transmit<'a> + Receive<'a>> UartData<'a> for T {}
108impl<'a, T: Configure + Transmit<'a> + ReceiveAdvanced<'a>> UartAdvanced<'a> for T {}
109impl<T: ReceiveClient + TransmitClient> Client for T {}
110
111/// Trait for configuring a UART.
112pub trait Configure {
113    /// Set the configuration parameters for the UART bus.
114    ///
115    /// ### Return values
116    ///
117    /// - `Ok(())`: The bus was configured correctly.
118    /// - `Err(OFF)`: The underlying hardware is currently not available,
119    ///   perhaps because it has not been initialized or in the case of a shared
120    ///   hardware USART controller because it is set up for SPI.
121    /// - `Err(INVAL)`: Impossible parameters (e.g. a [`Parameters::baud_rate`]
122    ///   of 0).
123    /// - `Err(ENOSUPPORT)`: The underlying UART cannot satisfy this
124    ///   configuration.
125    fn configure(&self, params: Parameters) -> Result<(), ErrorCode>;
126}
127
128/// Trait for sending data via a UART bus.
129pub trait Transmit<'a> {
130    /// Set the transmit client, which will be called when transmissions
131    /// complete.
132    fn set_transmit_client(&self, client: &'a dyn TransmitClient);
133
134    /// Transmit a buffer of data.
135    ///
136    /// If the transmission is not started successfully, this function will
137    /// return `Err()` and no callback will be called.
138    ///
139    /// Each byte in `tx_buffer` is a UART transfer word of 8 or fewer bits. The
140    /// word width is determined by the UART configuration, truncating any more
141    /// significant bits. E.g., `0x18f` transmitted in 8N1 will be sent as
142    /// `0x8f` and in 7N1 will be sent as `0x0f`. Clients that need to transfer
143    /// 9-bit words should use [`Transmit::transmit_word`].
144    ///
145    /// Calling [`Transmit::transmit_buffer`] while there is an outstanding
146    /// [`Transmit::transmit_buffer`] or [`Transmit::transmit_word`] operation
147    /// will return [`ErrorCode::BUSY`].
148    ///
149    /// ### Return values
150    ///
151    /// - `Ok(())`: The transmission started successfully.
152    ///   [`TransmitClient::transmitted_buffer`] will be called.
153    /// - `Err(OFF)`: The underlying hardware is not available, perhaps because
154    ///   it has not been initialized or in the case of a shared hardware USART
155    ///   controller because it is set up for SPI.
156    /// - `Err(BUSY)`: the UART is already transmitting and has not made a
157    ///   transmission callback yet.
158    /// - `Err(SIZE)` : `tx_len` is larger than the passed slice.
159    /// - `Err(FAIL)`: some other error.
160    fn transmit_buffer(
161        &self,
162        tx_buffer: &'static mut [u8],
163        tx_len: usize,
164    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
165
166    /// Transmit a single word of data asynchronously.
167    ///
168    /// The word length is determined by the UART configuration: it can be 6, 7,
169    /// 8, or 9 bits long.
170    ///
171    /// If initiating the transmission failed, this function will return `Err()`
172    /// and no callback will be made.
173    ///
174    /// ### Return values
175    ///
176    /// - `Ok(())`: The transmission started successfully.
177    ///   [`TransmitClient::transmitted_word`] will be called.
178    /// - `Err(OFF)`: The underlying hardware is not available, perhaps because
179    ///   it has not been initialized or in the case of a shared hardware USART
180    ///   controller because it is set up for SPI.
181    /// - `Err(BUSY)`: the UART is already transmitting and has not made a
182    ///   transmission callback yet.
183    /// - `Err(FAIL)`: not supported, or some other error.
184    fn transmit_word(&self, word: u32) -> Result<(), ErrorCode>;
185
186    /// Abort an outstanding call to `transmit_word` or `transmit_buffer`.
187    ///
188    /// The return code indicates whether the call has fully terminated or there
189    /// will be a callback. Cancelled calls to [`Transmit::transmit_buffer`]
190    /// MUST always make a callback, to return the passed buffer back to the
191    /// caller.
192    ///
193    /// If this function returns `Ok(())`, there will be no future callback and
194    /// the client may retransmit immediately. If this function returns any
195    /// `Err()` there will be a callback. This means that if there is no
196    /// outstanding call to [`Transmit::transmit_word`] or
197    /// [`Transmit::transmit_buffer`] then a call to this function returns
198    /// `Ok(())`.
199    ///
200    /// ### Return values
201    ///
202    /// - `Ok(())`: The cancel happened immediate and no callback will be
203    ///   generated.
204    /// - `Err(BUSY)`: There was a transmit operation outstanding and it was
205    ///   cancelled successfully. There will be an appropriate callback (based
206    ///   on the type of transmission) with a result of `Err(CANCEL)`.
207    /// - `Err(FAIL)`: if the outstanding call to either transmit operation
208    ///   could not be synchronously cancelled. A callback will be made on the
209    ///   client indicating whether the call was successfully cancelled.
210    fn transmit_abort(&self) -> Result<(), ErrorCode>;
211}
212
213/// Trait for receiving data via a UART bus.
214pub trait Receive<'a> {
215    /// Set the receive client, which will be called when reads complete.
216    fn set_receive_client(&self, client: &'a dyn ReceiveClient);
217
218    /// Receive `rx_len` bytes into `rx_buffer`.
219    ///
220    /// If this function returns `Ok(())`, there will be a callback to the
221    /// [`ReceiveClient::received_buffer`] when the receive is complete.
222    ///
223    /// Each byte in `rx_buffer` will be a UART transfer word of 8 or fewer
224    /// bits. The width is determined by the UART configuration. Clients that
225    /// need to transfer 9-bit words should use [`Receive::receive_word`].
226    ///
227    /// ### Return values
228    ///
229    /// - `Ok(())`: The receive started successfully and a
230    ///   [`ReceiveClient::received_buffer`] callback will be generated when the
231    ///   read completes.
232    /// - `Err(OFF)`: The underlying hardware is not available, perhaps because
233    ///   it has not been initialized or in the case of a shared hardware USART
234    ///   controller because it is set up for SPI.
235    /// - `Err(BUSY)`: the UART is already receiving and has not made a
236    ///   reception `complete` callback yet.
237    /// - `Err(SIZE)`: `rx_len` is larger than the passed slice.
238    fn receive_buffer(
239        &self,
240        rx_buffer: &'static mut [u8],
241        rx_len: usize,
242    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
243
244    /// Receive a single word of data.
245    ///
246    /// The word length is determined by the UART configuration: it can be 6, 7,
247    /// 8, or 9 bits long.
248    ///
249    /// ### Return values
250    ///
251    /// - `Ok(())`: The receive started successfully and
252    ///   [`ReceiveClient::received_word`] will be called.
253    /// - `Err(OFF)`: The underlying hardware is not available, perhaps because
254    ///   it has not been initialized or in the case of a shared hardware USART
255    ///   controller because it is set up for SPI.
256    /// - `Err(BUSY)`: the UART is already receiving and has not made a
257    ///   reception callback yet.
258    /// - `Err(FAIL)`: not supported or some other error.
259    fn receive_word(&self) -> Result<(), ErrorCode>;
260
261    /// Abort any ongoing receive transfers and return what has been received.
262    ///
263    /// If there was an ongoing receive, the received data and the receive
264    /// buffer will be provided in the correct callback, either
265    /// [`ReceiveClient::received_word`] or [`ReceiveClient::received_buffer`].
266    ///
267    /// If there is no outstanding receive operation, `Ok(())` is returned and
268    /// there will be no callback.
269    ///
270    ///  ### Return values
271    ///
272    ///  - `Ok(())`: The abort was successful because there was nothing to
273    ///    abort. There will be no callback.
274    ///  - `Err(BUSY)`: There is a receive in progress and it canceling it has
275    ///    started successfully. A callback will be generated later with a
276    ///    result of `Err(CANCEL)`.
277    ///  - `Err(FAIL)`: Cancelling an ongoing receive did not occur correctly. A
278    ///    future callback will be generated when the receive finishes.
279    fn receive_abort(&self) -> Result<(), ErrorCode>;
280}
281
282/// Trait implemented by a UART transmitter to receive callbacks when
283/// operations complete.
284pub trait TransmitClient {
285    /// A call to [`Transmit::transmit_word`] completed.
286    ///
287    /// A call to [`Transmit::transmit_word`] or [`Transmit::transmit_buffer`]
288    /// made within this callback SHOULD NOT return `Err(BUSY)`. When this
289    /// callback is made the UART should be ready to receive another call.
290    ///
291    /// `rval` indicates whether the word was successfully transmitted. Possible
292    /// `rval` values:
293    ///
294    /// - `Ok(())`: The word was successfully transmitted.
295    /// - `Err(CANCEL)`: The call to [`Transmit::transmit_word`] was cancelled
296    ///   and the word was not transmitted.
297    /// - `Err(FAIL)`: The transmission failed in some way.
298    fn transmitted_word(&self, _rval: Result<(), ErrorCode>) {}
299
300    /// A call to [`Transmit::transmit_buffer`] completed.
301    ///
302    /// A call to [`Transmit::transmit_word`] or [`Transmit::transmit_buffer`]
303    /// made within this callback SHOULD NOT return `Err(BUSY)`. When this
304    /// callback is made the UART should be ready to receive another call.
305    ///
306    /// The `tx_len` argument specifies how many words were transmitted. If the
307    /// transmission was successful, `tx_len` in the callback will be the same
308    /// as `tx_len` in the initiating call.
309    ///
310    /// `rval` indicates whether the buffer was successfully transmitted.
311    /// Possible `rval` values:
312    ///
313    /// - `Ok(())`: The full buffer was successfully transmitted.
314    /// - `Err(CANCEL)`: The call to [`Transmit::transmit_buffer`] was cancelled
315    ///   and the buffer was not fully transmitted. `tx_len` contains how many
316    ///   words were transmitted.
317    /// - `Err(SIZE)`: The buffer could only be partially transmitted. `tx_len`
318    ///   contains how many words were transmitted.
319    /// - `Err(FAIL)`: The transmission failed in some way.
320    fn transmitted_buffer(
321        &self,
322        tx_buffer: &'static mut [u8],
323        tx_len: usize,
324        rval: Result<(), ErrorCode>,
325    );
326}
327
328/// Trait implemented by a UART receiver to receive callbacks when
329/// operations complete.
330pub trait ReceiveClient {
331    /// A call to [`Receive::receive_word`] completed.
332    ///
333    /// A call to [`Receive::receive_word`] or [`Receive::receive_buffer`] made
334    /// within this callback SHOULD NOT return `Err(BUSY)`. When this callback
335    /// is made the UART should be ready to receive another call.
336    ///
337    /// `rval` indicates whether a word was successfully received. Possible
338    /// `rval` values:
339    ///
340    /// - `Ok(())`: The word was successfully received.
341    /// - `Err(CANCEL)`: The call to [`Receive::receive_word`] was cancelled and
342    ///   the word was not received: `word` should be ignored.
343    /// - `Err(FAIL)`: The reception failed in some way and `word` should be
344    ///   ignored. `error` may contain further information on the sort of error.
345    fn received_word(&self, _word: u32, _rval: Result<(), ErrorCode>, _error: Error) {}
346
347    /// A call to [`Receive::receive_buffer`] completed.
348    ///
349    /// A call to [`Receive::receive_word`] or [`Receive::receive_buffer`] made
350    /// within this callback SHOULD NOT return `Err(BUSY)`. When this callback
351    /// is made the UART should be ready to receive another call.
352    ///
353    /// The `rx_len` argument specifies how many words were received. If the
354    /// receive was successful, `rx_len` in the callback will be the same
355    /// as `rx_len` in the initiating call.
356    ///
357    /// `rval` indicates whether a buffer was successfully received. Possible
358    /// `rval` values:
359    ///
360    /// - `Ok(())`: The full buffer was successfully received.
361    /// - `Err(CANCEL)`: The call to [`Receive::receive_buffer`] was cancelled
362    ///   and the buffer was not fully received. `rx_len` contains how many
363    ///   words were received.
364    /// - `Err(SIZE)`: The buffer could only be partially received. `rx_len`
365    ///   contains how many words were received.
366    /// - `Err(FAIL)`: The reception failed in some way: `error` may contain
367    ///   further information.
368    fn received_buffer(
369        &self,
370        rx_buffer: &'static mut [u8],
371        rx_len: usize,
372        rval: Result<(), ErrorCode>,
373        error: Error,
374    );
375}
376
377/// Trait with optional UART features that certain hardware may support.
378///
379/// The operations in this trait are not required for basic UART operation, but
380/// provide useful abstractions that capsules may want to be able to leverage.
381///
382/// The interfaces are included here because some hardware platforms may be able
383/// to directly implement them, while others platforms may need to emulate them
384/// in software. The ones that can implement them in hardware should be able to
385/// leverage that efficiency, and by placing the interfaces here in the HIL they
386/// can do that.
387///
388/// Other interface ideas that have been discussed, but are not included due to
389/// the lack of a clear use case, but are noted here in case they might help
390/// someone in the future:
391/// - `receive_until_terminator()`: This would read in bytes until a specified
392///   byte is received (or the buffer is full) and then return to the client.
393/// - `receive_len_then_message()`: This would do a one byte read to get a
394///   length byte and then read that many more bytes from UART before returning
395///   to the client.
396pub trait ReceiveAdvanced<'a>: Receive<'a> {
397    /// Receive data until `interbyte_timeout` bit periods have passed since the
398    /// last byte or buffer is full.
399    ///
400    /// This does not timeout until at least one byte has been received.
401    ///
402    /// ### Arguments:
403    ///
404    /// - `rx_buffer`: Buffer to receive into.
405    /// - `rx_len`: Maximum number of bytes to receive.
406    /// - `interbyte_timeout`: number of bit periods to wait between bytes
407    ///   before returning.
408    ///
409    /// ### Return values
410    ///
411    /// - `Ok(())`: Receive was started correctly.
412    ///   [`ReceiveClient::received_buffer]` will be called.
413    /// - `Err(OFF)`: The underlying hardware is not available, perhaps because
414    ///   it has not been initialized or in the case of a shared hardware USART
415    ///   controller because it is set up for SPI.
416    /// - `Err(BUSY)`: the UART is already receiving and has not made a
417    ///   reception callback yet.
418    /// - `Err(SIZE)`: `rx_len` is larger than the passed slice.
419    fn receive_automatic(
420        &self,
421        rx_buffer: &'static mut [u8],
422        rx_len: usize,
423        interbyte_timeout: u8,
424    ) -> Result<(), (ErrorCode, &'static mut [u8])>;
425}