Line data Source code
1 1 : /* 2 : * Copyright (c) 2023 Nordic Semiconductor ASA 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : /** 8 : * @file 9 : * @brief Helper module for receiving using UART Asynchronous API. 10 : */ 11 : 12 : #ifndef ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ 13 : #define ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ 14 : 15 : #ifdef __cplusplus 16 : extern "C" { 17 : #endif 18 : 19 : #include <zephyr/kernel.h> 20 : 21 : /* @brief RX buffer structure which holds the buffer and its state. */ 22 0 : struct uart_async_rx_buf { 23 : /* Write index which is incremented whenever new data is reported to be 24 : * received to that buffer. 25 : */ 26 0 : uint8_t wr_idx:7; 27 : 28 : /* Set to one if buffer is released by the driver. */ 29 0 : uint8_t completed:1; 30 : 31 : /* Location which is passed to the UART driver. */ 32 0 : uint8_t buffer[]; 33 : }; 34 : 35 : /** @brief UART asynchronous RX helper structure. */ 36 1 : struct uart_async_rx { 37 : /* Pointer to the configuration structure. Structure must be persistent. */ 38 0 : const struct uart_async_rx_config *config; 39 : 40 : /* Total amount of pending bytes. Bytes may be spread across multiple RX buffers. */ 41 0 : atomic_t pending_bytes; 42 : 43 : /* Number of buffers which are free. */ 44 0 : atomic_t free_buf_cnt; 45 : 46 : /* Single buffer size. */ 47 0 : uint8_t buf_len; 48 : 49 : /* Index of the next buffer to be provided to the driver. */ 50 0 : uint8_t drv_buf_idx; 51 : 52 : /* Current buffer from which data is being consumed. */ 53 0 : uint8_t rd_buf_idx; 54 : 55 : /* Current read index in the buffer from which data is being consumed. 56 : * Read index which is incremented whenever data is consumed from the buffer. 57 : */ 58 0 : uint8_t rd_idx; 59 : }; 60 : 61 : /** @brief UART asynchronous RX helper configuration structure. */ 62 1 : struct uart_async_rx_config { 63 : /* Pointer to the buffer. */ 64 0 : uint8_t *buffer; 65 : 66 : /* Buffer length. */ 67 0 : size_t length; 68 : 69 : /* Number of buffers into provided space shall be split. */ 70 0 : uint8_t buf_cnt; 71 : }; 72 : 73 : /** @brief Get RX buffer length. 74 : * 75 : * @param async_rx Pointer to the helper instance. 76 : * 77 : * @return Buffer length. 78 : */ 79 1 : static inline uint8_t uart_async_rx_get_buf_len(struct uart_async_rx *async_rx) 80 : { 81 : return async_rx->buf_len; 82 : } 83 : 84 : /** @brief Get amount of space dedicated for managing each buffer state. 85 : * 86 : * User buffer provided during the initialization is split into chunks and each 87 : * chunk has overhead. This overhead can be used to calculate actual space used 88 : * for UART data. 89 : * 90 : * @return Overhead space in bytes. 91 : */ 92 1 : #define UART_ASYNC_RX_BUF_OVERHEAD offsetof(struct uart_async_rx_buf, buffer) 93 : 94 : /** @brief Initialize the helper instance. 95 : * 96 : * @param async_rx Pointer to the helper instance. 97 : * @param config Configuration. Must be persistent. 98 : * 99 : * @retval 0 on successful initialization. 100 : */ 101 1 : int uart_async_rx_init(struct uart_async_rx *async_rx, 102 : const struct uart_async_rx_config *config); 103 : 104 : /** @brief Reset state of the helper instance. 105 : * 106 : * Helper can be reset after RX abort to discard all received data and bring 107 : * the helper to its initial state. 108 : * 109 : * @param async_rx Pointer to the helper instance. 110 : */ 111 1 : void uart_async_rx_reset(struct uart_async_rx *async_rx); 112 : 113 : /** @brief Indicate received data. 114 : * 115 : * Function shall be called from @ref UART_RX_RDY context. 116 : * 117 : * @param async_rx Pointer to the helper instance. 118 : * @param buffer Buffer received in the UART driver event. 119 : * @param length Length received in the UART driver event. 120 : */ 121 1 : void uart_async_rx_on_rdy(struct uart_async_rx *async_rx, uint8_t *buffer, size_t length); 122 : 123 : /** @brief Get next RX buffer. 124 : * 125 : * Returned pointer shall be provided to @ref uart_rx_buf_rsp or @ref uart_rx_enable. 126 : * If null is returned that indicates that there are no available buffers since all 127 : * buffers are used by the driver or contain not consumed data. 128 : * 129 : * @param async_rx Pointer to the helper instance. 130 : * 131 : * @return Pointer to the next RX buffer or null if no buffer available. 132 : */ 133 1 : uint8_t *uart_async_rx_buf_req(struct uart_async_rx *async_rx); 134 : 135 : /** @brief Indicate that buffer is no longer used by the UART driver. 136 : * 137 : * Function shall be called on @ref UART_RX_BUF_RELEASED event. 138 : * 139 : * @param async_rx Pointer to the helper instance. 140 : * @param buf Buffer pointer received in the UART driver event. 141 : */ 142 1 : void uart_async_rx_on_buf_rel(struct uart_async_rx *async_rx, uint8_t *buf); 143 : 144 : /** @brief Claim received data for processing. 145 : * 146 : * Helper module works in the zero copy mode. It provides a pointer to the buffer 147 : * that was directly used by the UART driver. Since received data is spread across 148 : * multiple buffers there is no possibility to read all data at once. It can only be 149 : * consumed in chunks. After data is processed, @ref uart_async_rx_data_consume is 150 : * used to indicate that data is consumed. 151 : * 152 : * @param async_rx Pointer to the helper instance. 153 : * @param data Location where address to the buffer is written. Untouched if no data to claim. 154 : * @param length Amount of requested data. 155 : * 156 : * @return Amount valid of data in the @p data buffer. 0 is returned when there is no data. 157 : */ 158 1 : size_t uart_async_rx_data_claim(struct uart_async_rx *async_rx, uint8_t **data, size_t length); 159 : 160 : /** @brief Consume claimed data. 161 : * 162 : * It pairs with @ref uart_async_rx_data_claim. 163 : * 164 : * @param async_rx Pointer to the helper instance. 165 : * @param length Amount of data to consume. It must be less or equal than amount of claimed data. 166 : * 167 : * @retval true If there are free buffers in the pool after data got consumed. 168 : * @retval false If there are no free buffers. 169 : */ 170 1 : bool uart_async_rx_data_consume(struct uart_async_rx *async_rx, size_t length); 171 : 172 : #ifdef __cplusplus 173 : } 174 : #endif 175 : 176 : #endif /* ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ */