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}