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