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