| /* |
| * Copyright (c) 2023 Nordic Semiconductor ASA |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @file |
| * @brief Helper module for receiving using UART Asynchronous API. |
| */ |
| |
| #ifndef ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ |
| #define ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| #include <zephyr/kernel.h> |
| |
| /* @brief RX buffer structure which holds the buffer and its state. */ |
| struct uart_async_rx_buf { |
| /* Write index which is incremented whenever new data is reported to be |
| * received to that buffer. |
| */ |
| uint8_t wr_idx:7; |
| |
| /* Set to one if buffer is released by the driver. */ |
| uint8_t completed:1; |
| |
| /* Location which is passed to the UART driver. */ |
| uint8_t buffer[]; |
| }; |
| |
| /** @brief UART asynchronous RX helper structure. */ |
| struct uart_async_rx { |
| /* Pointer to the configuration structure. Structure must be persistent. */ |
| const struct uart_async_rx_config *config; |
| |
| /* Total amount of pending bytes. Bytes may be spread across multiple RX buffers. */ |
| atomic_t pending_bytes; |
| |
| /* Number of buffers which are free. */ |
| atomic_t free_buf_cnt; |
| |
| /* Single buffer size. */ |
| uint8_t buf_len; |
| |
| /* Index of the next buffer to be provided to the driver. */ |
| uint8_t drv_buf_idx; |
| |
| /* Current buffer from which data is being consumed. */ |
| uint8_t rd_buf_idx; |
| |
| /* Current read index in the buffer from which data is being consumed. |
| * Read index which is incremented whenever data is consumed from the buffer. |
| */ |
| uint8_t rd_idx; |
| }; |
| |
| /** @brief UART asynchronous RX helper configuration structure. */ |
| struct uart_async_rx_config { |
| /* Pointer to the buffer. */ |
| uint8_t *buffer; |
| |
| /* Buffer length. */ |
| size_t length; |
| |
| /* Number of buffers into provided space shall be split. */ |
| uint8_t buf_cnt; |
| }; |
| |
| /** @brief Get RX buffer length. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * |
| * @return Buffer length. |
| */ |
| static inline uint8_t uart_async_rx_get_buf_len(struct uart_async_rx *async_rx) |
| { |
| return async_rx->buf_len; |
| } |
| |
| /** @brief Get amount of space dedicated for managing each buffer state. |
| * |
| * User buffer provided during the initialization is split into chunks and each |
| * chunk has overhead. This overhead can be used to calculate actual space used |
| * for UART data. |
| * |
| * @return Overhead space in bytes. |
| */ |
| #define UART_ASYNC_RX_BUF_OVERHEAD offsetof(struct uart_async_rx_buf, buffer) |
| |
| /** @brief Initialize the helper instance. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * @param config Configuration. Must be persistent. |
| * |
| * @retval 0 on successful initialization. |
| */ |
| int uart_async_rx_init(struct uart_async_rx *async_rx, |
| const struct uart_async_rx_config *config); |
| |
| /** @brief Reset state of the helper instance. |
| * |
| * Helper can be reset after RX abort to discard all received data and bring |
| * the helper to its initial state. |
| * |
| * @param async_rx Pointer to the helper instance. |
| */ |
| void uart_async_rx_reset(struct uart_async_rx *async_rx); |
| |
| /** @brief Indicate received data. |
| * |
| * Function shall be called from @ref UART_RX_RDY context. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * @param buffer Buffer received in the UART driver event. |
| * @param length Length received in the UART driver event. |
| */ |
| void uart_async_rx_on_rdy(struct uart_async_rx *async_rx, uint8_t *buffer, size_t length); |
| |
| /** @brief Get next RX buffer. |
| * |
| * Returned pointer shall be provided to @ref uart_rx_buf_rsp or @ref uart_rx_enable. |
| * If null is returned that indicates that there are no available buffers since all |
| * buffers are used by the driver or contain not consumed data. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * |
| * @return Pointer to the next RX buffer or null if no buffer available. |
| */ |
| uint8_t *uart_async_rx_buf_req(struct uart_async_rx *async_rx); |
| |
| /** @brief Indicate that buffer is no longer used by the UART driver. |
| * |
| * Function shall be called on @ref UART_RX_BUF_RELEASED event. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * @param buf Buffer pointer received in the UART driver event. |
| */ |
| void uart_async_rx_on_buf_rel(struct uart_async_rx *async_rx, uint8_t *buf); |
| |
| /** @brief Claim received data for processing. |
| * |
| * Helper module works in the zero copy mode. It provides a pointer to the buffer |
| * that was directly used by the UART driver. Since received data is spread across |
| * multiple buffers there is no possibility to read all data at once. It can only be |
| * consumed in chunks. After data is processed, @ref uart_async_rx_data_consume is |
| * used to indicate that data is consumed. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * @param data Location where address to the buffer is written. Untouched if no data to claim. |
| * @param length Amount of requested data. |
| * |
| * @return Amount valid of data in the @p data buffer. 0 is returned when there is no data. |
| */ |
| size_t uart_async_rx_data_claim(struct uart_async_rx *async_rx, uint8_t **data, size_t length); |
| |
| /** @brief Consume claimed data. |
| * |
| * It pairs with @ref uart_async_rx_data_claim. |
| * |
| * @param async_rx Pointer to the helper instance. |
| * @param length Amount of data to consume. It must be less or equal than amount of claimed data. |
| * |
| * @retval true If there are free buffers in the pool after data got consumed. |
| * @retval false If there are no free buffers. |
| */ |
| bool uart_async_rx_data_consume(struct uart_async_rx *async_rx, size_t length); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* ZEPHYR_DRIVERS_SERIAL_UART_ASYNC_RX_H_ */ |