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_ */
|