xref: /aosp_15_r20/external/pigweed/pw_uart/public/pw_uart/uart.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 
17 #include <cstddef>
18 #include <cstdint>
19 #include <optional>
20 
21 #include "pw_assert/assert.h"
22 #include "pw_bytes/span.h"
23 #include "pw_chrono/system_clock.h"
24 #include "pw_status/status.h"
25 #include "pw_status/status_with_size.h"
26 #include "pw_uart/uart_base.h"
27 
28 namespace pw::uart {
29 
30 /// Represents an abstract UART interface.
31 ///
32 /// The `Uart` interface provides a basic set of methods for performing
33 /// blocking UART communication.
34 
35 class Uart : public UartBase {
36  public:
37   ~Uart() override = default;
38 
39   /// Reads data from the UART into a provided buffer.
40   ///
41   /// This function blocks until `min_bytes` have been read into `rx_buffer`.
42   ///
43   /// @param rx_buffer  The buffer to read data into.
44   /// @param min_bytes  The minimum number of bytes to read before returning.
45   ///
46   /// @returns @rst
47   ///
48   /// .. pw-status-codes::
49   ///
50   ///    OK: The operation was successful.
51   ///
52   /// May return other implementation-specific status codes.
53   ///
54   /// @endrst
ReadAtLeast(ByteSpan rx_buffer,size_t min_bytes)55   StatusWithSize ReadAtLeast(ByteSpan rx_buffer, size_t min_bytes) {
56     return DoTryReadFor(rx_buffer, min_bytes, std::nullopt);
57   }
58 
59   /// Reads data from the UART into a provided buffer.
60   ///
61   /// This function blocks until the entire buffer has been filled.
62   ///
63   /// @param rx_buffer  The buffer to read data into.
64   ///
65   /// @returns @rst
66   ///
67   /// .. pw-status-codes::
68   ///
69   ///    OK: The operation was successful.
70   ///
71   /// May return other implementation-specific status codes.
72   ///
73   /// @endrst
ReadExactly(ByteSpan rx_buffer)74   StatusWithSize ReadExactly(ByteSpan rx_buffer) {
75     return DoTryReadFor(rx_buffer, rx_buffer.size(), std::nullopt);
76   }
77 
78   /// Deprecated: Prefer ReadExactly in new code.
79   ///
80   /// Reads data from the UART into a provided buffer.
81   ///
82   /// This function blocks until the entire buffer has been filled.
83   ///
84   /// @param rx_buffer  The buffer to read data into.
85   ///
86   /// @returns @rst
87   ///
88   /// .. pw-status-codes::
89   ///
90   ///    OK: The operation was successful.
91   ///
92   /// May return other implementation-specific status codes.
93   ///
94   /// @endrst
95   // TODO: https://pwbug.dev/368149122 - Remove after transition
Read(ByteSpan rx_buffer)96   Status Read(ByteSpan rx_buffer) {
97     return DoTryReadFor(rx_buffer, std::nullopt).status();
98   }
99 
100   /// Reads data from the UART into a provided buffer.
101   ///
102   /// This function blocks until either `min_bytes` have been read into buffer
103   /// or the specified timeout has elapsed, whichever occurs first.
104   ///
105   /// @param rx_buffer  The buffer to read data into.
106   /// @param min_bytes  The minimum number of bytes to read before returning.
107   /// @param timeout    The maximum time to wait for data to be read. If zero,
108   ///                   the function will immediately return with at least one
109   ///                   hardware read operation attempt.
110   ///
111   /// @returns @rst
112   ///
113   /// .. pw-status-codes::
114   ///
115   ///    OK: The operation was successful and the entire buffer has been filled
116   ///    with data.
117   ///
118   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
119   ///    could be filled.
120   ///
121   /// May return other implementation-specific status codes.
122   ///
123   /// @endrst
TryReadAtLeastFor(ByteSpan rx_buffer,size_t min_bytes,chrono::SystemClock::duration timeout)124   StatusWithSize TryReadAtLeastFor(ByteSpan rx_buffer,
125                                    size_t min_bytes,
126                                    chrono::SystemClock::duration timeout) {
127     return DoTryReadFor(rx_buffer, min_bytes, timeout);
128   }
129 
130   /// Reads data from the UART into a provided buffer.
131   ///
132   /// This function blocks until either `rx_buffer.size()` bytes have been read
133   /// into buffer or the specified timeout has elapsed, whichever occurs first.
134   ///
135   /// @param rx_buffer  The buffer to read data into.
136   /// @param timeout    The maximum time to wait for data to be read. If zero,
137   ///                   the function will immediately return with at least one
138   ///                   hardware read operation attempt.
139   ///
140   /// @returns @rst
141   ///
142   /// .. pw-status-codes::
143   ///
144   ///    OK: The operation was successful and the entire buffer has been filled
145   ///    with data.
146   ///
147   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
148   ///    could be filled.
149   ///
150   /// May return other implementation-specific status codes.
151   ///
152   /// @endrst
TryReadExactlyFor(ByteSpan rx_buffer,chrono::SystemClock::duration timeout)153   StatusWithSize TryReadExactlyFor(ByteSpan rx_buffer,
154                                    chrono::SystemClock::duration timeout) {
155     return DoTryReadFor(rx_buffer, rx_buffer.size(), timeout);
156   }
157 
158   /// Deprecated: Prefer TryReadExactlyFor in new code.
159   /// Reads data from the UART into a provided buffer.
160   ///
161   /// This function blocks until either `rx_buffer.size()` bytes have been read
162   /// into buffer or the specified timeout has elapsed, whichever occurs first.
163   ///
164   /// @param rx_buffer  The buffer to read data into.
165   /// @param timeout    The maximum time to wait for data to be read. If zero,
166   ///                   the function will immediately return with at least one
167   ///                   hardware read operation attempt.
168   ///
169   /// @returns @rst
170   ///
171   /// .. pw-status-codes::
172   ///
173   ///    OK: The operation was successful and the entire buffer has been filled
174   ///    with data.
175   ///
176   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
177   ///    could be filled.
178   ///
179   /// May return other implementation-specific status codes.
180   ///
181   /// @endrst
TryReadFor(ByteSpan rx_buffer,chrono::SystemClock::duration timeout)182   StatusWithSize TryReadFor(ByteSpan rx_buffer,
183                             chrono::SystemClock::duration timeout) {
184     // TODO: https://pwbug.dev/368149122 - Remove after transition
185     return DoTryReadFor(rx_buffer, timeout);
186   }
187 
188   /// Writes data from the provided buffer to the UART. The function blocks
189   /// until the entire buffer has been written.
190   ///
191   /// @param tx_buffer - The buffer to write data from.
192   ///
193   /// @returns @rst
194   ///
195   /// .. pw-status-codes::
196   ///
197   ///    OK: The operation was successful.
198   ///
199   /// May return other implementation-specific status codes.
200   ///
201   /// @endrst
Write(ConstByteSpan tx_buffer)202   Status Write(ConstByteSpan tx_buffer) {
203     return DoTryWriteFor(tx_buffer, std::nullopt).status();
204   }
205 
206   /// Writes data from the provided buffer to the UART. The function blocks
207   /// until either the entire buffer has been written or the specified timeout
208   /// has elapsed, whichever occurs first.
209   ///
210   /// @param tx_buffer  The buffer to write data from.
211   /// @param timeout    The maximum time to wait for data to be written.
212   ///                   If zero, the function will immediately return with at
213   ///                   least one hardware write operation attempt.
214   ///
215   /// @returns @rst
216   ///
217   /// .. pw-status-codes::
218   ///
219   ///    OK: The operation was successful and the entire buffer has been
220   ///    written.
221   ///
222   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
223   ///    could be written.
224   ///
225   /// May return other implementation-specific status codes.
226   ///
227   /// @endrst
TryWriteFor(ConstByteSpan tx_buffer,chrono::SystemClock::duration timeout)228   StatusWithSize TryWriteFor(ConstByteSpan tx_buffer,
229                              chrono::SystemClock::duration timeout) {
230     return DoTryWriteFor(tx_buffer, timeout);
231   }
232 
233   /// Blocks until all queued data in the UART  has been transmitted and the
234   /// FIFO is empty.
235   ///
236   /// This function ensures that all data enqueued before calling this function
237   /// has been transmitted. Any data enqueued after calling this function will
238   /// be transmitted immediately.
239   ///
240   /// @returns @rst
241   ///
242   /// .. pw-status-codes::
243   ///
244   ///    OK: The operation was successful.
245   ///
246   /// May return other implementation-specific status codes.
247   ///
248   /// @endrst
FlushOutput()249   Status FlushOutput() { return DoFlushOutput(); }
250 
251  private:
252   /// Reads data from the UART into a provided buffer with an optional timeout
253   /// provided.
254   ///
255   /// This virtual function attempts to read data into the provided byte buffer
256   /// (`rx_buffer`). The operation will continue until either the buffer is
257   /// full, an error occurs, or the optional timeout duration expires.
258   ///
259   /// @param rx_buffer  The buffer to read data into.
260   /// @param timeout    An optional timeout duration. If specified, the function
261   ///                   will block for no longer than this duration. If zero,
262   ///                   the function will immediately return with at least one
263   ///                   hardware read operation attempt. If not specified, the
264   ///                   function blocks until the buffer is full.
265   ///
266   /// @returns @rst
267   ///
268   /// .. pw-status-codes::
269   ///
270   ///    OK: The operation was successful and the entire buffer has been
271   ///    filled with data.
272   ///
273   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
274   ///    could be filled.
275   ///
276   /// May return other implementation-specific status codes.
277   ///
278   /// @endrst
279   // TODO: https://pwbug.dev/368149122 - Remove after transition.
DoTryReadFor(ByteSpan rx_buffer,std::optional<chrono::SystemClock::duration> timeout)280   virtual StatusWithSize DoTryReadFor(
281       ByteSpan rx_buffer,
282       std::optional<chrono::SystemClock::duration> timeout) {
283     return DoTryReadFor(rx_buffer, rx_buffer.size(), timeout);
284   }
285 
286   /// Reads data from the UART into a provided buffer with an optional timeout
287   /// provided.
288   ///
289   /// This virtual function attempts to read data into the provided byte buffer
290   /// (`rx_buffer`). The operation will continue until either `min_bytes` have
291   /// been read into the buffer, an error occurs, or the optional timeout
292   /// duration expires.
293   ///
294   /// @param rx_buffer  The buffer to read data into.
295   /// @param min_bytes  The minimum number of bytes to read before returning.
296   /// @param timeout    An optional timeout duration. If specified, the function
297   ///                   will block for no longer than this duration. If zero,
298   ///                   the function will immediately return with at least one
299   ///                   hardware read operation attempt. If not specified, the
300   ///                   function blocks until the buffer is full.
301   ///
302   /// @returns @rst
303   ///
304   /// .. pw-status-codes::
305   ///
306   ///    OK: The operation was successful and the entire buffer has been
307   ///    filled with data.
308   ///
309   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
310   ///    could be filled.
311   ///
312   /// May return other implementation-specific status codes.
313   ///
314   /// @endrst
315   // TODO: https://pwbug.dev/368149122 - Make pure virtual after transition.
DoTryReadFor(ByteSpan,size_t,std::optional<chrono::SystemClock::duration>)316   virtual StatusWithSize DoTryReadFor(
317       ByteSpan /*rx_buffer*/,
318       size_t /*min_bytes*/,
319       std::optional<chrono::SystemClock::duration> /*timeout*/) {
320     return StatusWithSize::Unimplemented();
321   }
322 
323   /// @brief Writes data from a provided buffer to the UART with an optional
324   /// timeout.
325   ///
326   /// This virtual function attempts to write data from the provided byte buffer
327   /// (`tx_buffer`) to the UART. The operation will continue until either the
328   /// buffer is empty, an error occurs, or the optional timeout duration
329   /// expires.
330   ///
331   /// @param tx_buffer  The buffer containing data to be written.
332   /// @param timeout    An optional timeout duration. If specified, the function
333   ///                   will block for no longer than this duration. If zero,
334   ///                   the function will immediately return after at least one
335   ///                   hardware write operation attempt. If not specified, the
336   ///                   function blocks until the buffer is empty.
337   ///
338   /// @returns @rst
339   ///
340   /// .. pw-status-codes::
341   ///
342   ///    OK: The operation was successful and the entire buffer has been
343   ///    written.
344   ///
345   ///    DEADLINE_EXCEEDED: The operation timed out before the entire buffer
346   ///    could be written.
347   ///
348   /// May return other implementation-specific status codes.
349   ///
350   /// @endrst
351   virtual StatusWithSize DoTryWriteFor(
352       ConstByteSpan tx_buffer,
353       std::optional<chrono::SystemClock::duration> timeout) = 0;
354   virtual Status DoFlushOutput() = 0;
355 };
356 
357 }  // namespace pw::uart
358