1 // Copyright 2024 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 <cstdint> 18 19 #include "pw_bytes/span.h" 20 #include "pw_function/function.h" 21 #include "pw_status/status.h" 22 #include "pw_status/status_with_size.h" 23 #include "pw_uart/uart_base.h" 24 25 namespace pw::uart { 26 27 /// Represents an abstract UART interface. 28 /// 29 /// The `UartNonBlocking` interface provides a basic set of methods for 30 /// performing Non-Blocking UART communication. 31 32 class UartNonBlocking : public UartBase { 33 public: 34 ~UartNonBlocking() override = default; 35 36 /// Reads exactly `rx_buffer.size()` bytes from the UART into the provided 37 /// buffer. 38 /// 39 /// This function calls `callback` after the entirety of `rx_buffer` is filled 40 /// with data. This may be called from interrupt context. 41 /// The callback may be called in ISR context. 42 /// It is safe to call `Read`/`Write` from the callback context. 43 /// 44 /// @param rx_buffer The buffer to read data into. 45 /// @param callback A callback to invoke when the transaction is completed. 46 /// @param status OK: The operation was successful and the 47 /// entire buffer has been filled with data. 48 /// CANCELLED: The operation was cancelled 49 /// via CancelRead(). 50 /// May return other implementation-specific 51 /// status codes. 52 /// @param buffer buffer.size() returns the number of 53 /// bytes successfully read into the buffer. 54 /// If `status`=OK, the buffer is identical 55 /// to rx_buffer 56 /// 57 /// @returns @rst 58 /// 59 /// .. pw-status-codes:: 60 /// 61 /// OK: The operation was successfully started. 62 /// UNAVAILABLE: Another Read() transaction is currently in progress. 63 /// 64 /// May return other implementation-specific status codes. 65 /// 66 /// @endrst ReadExactly(ByteSpan rx_buffer,Function<void (Status status,ConstByteSpan buffer)> && callback)67 Status ReadExactly( 68 ByteSpan rx_buffer, 69 Function<void(Status status, ConstByteSpan buffer)>&& callback) { 70 return DoRead(rx_buffer, rx_buffer.size(), std::move(callback)); 71 } 72 73 /// Reads at least `min_bytes` and at most `rx_buffer.size()` bytes from the 74 /// UART into the provided buffer. 75 /// 76 /// This function calls `callback` after `rx_buffer` is filled with at least 77 /// `min_bytes` of data. This may be called from interrupt context. 78 /// The callback may be called in ISR context. 79 /// It is safe to call `Read`/`Write` from the callback context. 80 /// 81 /// @param rx_buffer The buffer to read data into. 82 /// @param min_bytes Minimum bytes to read. 83 /// @param callback A callback to invoke when the transaction is completed. 84 /// @param status OK: The operation was successful and the 85 /// buffer has been filled with at least 86 /// `min_bytes` with data. 87 /// CANCELLED: The operation was cancelled 88 /// via CancelRead(). 89 /// May return other implementation-specific 90 /// status codes. 91 /// @param buffer buffer.size() returns the number of 92 /// bytes successfully read into the buffer. 93 /// 94 /// @returns @rst 95 /// 96 /// .. pw-status-codes:: 97 /// 98 /// OK: The operation was successfully started. 99 /// UNAVAILABLE: Another Read() transaction is currently in progress. 100 /// 101 /// May return other implementation-specific status codes. 102 /// 103 /// @endrst ReadAtLeast(ByteSpan rx_buffer,size_t min_bytes,Function<void (Status status,ConstByteSpan buffer)> && callback)104 Status ReadAtLeast( 105 ByteSpan rx_buffer, 106 size_t min_bytes, 107 Function<void(Status status, ConstByteSpan buffer)>&& callback) { 108 return DoRead(rx_buffer, min_bytes, std::move(callback)); 109 } 110 111 /// Cancel a current read in progress. 112 /// 113 /// This function will cancel a read in progress. The read's callback will 114 /// be invoked with status=CANCELLED. 115 /// 116 /// @returns @rst 117 /// 118 /// true: The operation was successfully canceled a transaction in progress 119 /// and the callback will be invoked with status=CANCELLED. 120 /// false: There were no transactions in progress and nothing was 121 /// cancelled. No callback will be invoked. 122 /// 123 /// @endrst CancelRead()124 bool CancelRead() { return DoCancelRead(); } 125 126 /// Writes data from a provided buffer to the UART. 127 /// 128 /// This function calls `callback` after the entirety of `tx_buffer` is 129 /// written to the UART. This may be called from interrupt context. 130 /// The callback may be called in ISR context. 131 /// It is safe to call `Read`/`Write` from the callback context. 132 /// 133 /// @param tx_buffer The buffer to write to the UART. 134 /// @param callback A callback to invoke when the transaction is completed. 135 /// @param status status.size() returns the number of bytes 136 /// successfully written from `tx_buffer`. 137 /// OK: The operation was successful and the 138 /// entire buffer has been written. 139 /// CANCELLED: The operation was cancelled 140 /// via CancelWrite(). 141 /// May return other implementation-specific 142 /// status codes. 143 /// 144 /// @returns @rst 145 /// 146 /// .. pw-status-codes:: 147 /// 148 /// OK: The operation was successfully started. 149 /// UNAVAILABLE: Another Write() transaction is currently in progress. 150 /// 151 /// May return other implementation-specific status codes. 152 /// 153 /// @endrst Write(ConstByteSpan tx_buffer,Function<void (StatusWithSize status)> && callback)154 Status Write(ConstByteSpan tx_buffer, 155 Function<void(StatusWithSize status)>&& callback) { 156 return DoWrite(tx_buffer, std::move(callback)); 157 } 158 159 /// Cancel a current write in progress. 160 /// 161 /// This function will cancel a write in progress. The write's callback will 162 /// be called with status=CANCELLED. 163 /// 164 /// @returns @rst 165 /// 166 /// true: The operation was successfully canceled a transaction in progress 167 /// and the callback will be invoked with status=CANCELLED. 168 /// false: There were no transactions in progress and nothing was 169 /// cancelled. No callback will be invoked. 170 /// 171 /// @endrst CancelWrite()172 bool CancelWrite() { return DoCancelWrite(); } 173 174 /// Ensures all queued data in the UART has been transmitted and the hardware 175 /// FIFO is empty. 176 /// 177 /// This function ensures that all data enqueued before calling this function 178 /// has been transmitted. Any data enqueued after this function completes will 179 /// be transmitted immediately. 180 /// 181 /// @param callback A callback to invoke when the flush is completed. 182 /// @param status OK: The operation was successful and the 183 /// transmit FIFO is empty. 184 /// CANCELLED: The operation was cancelled 185 /// via CancelFlushOutput(). 186 /// May return other implementation-specific 187 /// status codes. 188 /// 189 /// @returns @rst 190 /// 191 /// .. pw-status-codes:: 192 /// 193 /// OK: The operation was successfully started. 194 /// UNAVAILABLE: Another Write() or FlushOutput() operation is currently 195 /// in progress. 196 /// 197 /// May return other implementation-specific status codes. 198 /// 199 /// @endrst FlushOutput(Function<void (Status status)> && callback)200 Status FlushOutput(Function<void(Status status)>&& callback) { 201 return DoFlushOutput(std::move(callback)); 202 } 203 204 /// Cancels a pending FlushOutput() operation. 205 /// 206 /// This function will cancel an output flush in progress. The FlushOutput 207 /// callback will be called with status=CANCELLED. 208 /// 209 /// @returns @rst 210 /// 211 /// true: The operation was successfully canceled a transaction in progress 212 /// and the callback will be invoked with status=CANCELLED. 213 /// false: There were no transactions in progress and nothing was 214 /// cancelled. No callback will be invoked. 215 /// 216 /// @endrst CancelFlushOutput()217 bool CancelFlushOutput() { return DoCancelFlushOutput(); } 218 219 private: 220 /// Reads at least `min_bytes` and at most `rx_buffer.size()` bytes from the 221 /// UART into the provided buffer. 222 /// 223 /// This virtual function attempts to read data into the provided byte buffer 224 /// (`rx_buffer`). 225 /// This virtual function will return immediately. `callback` will be invoked 226 /// when the buffer has been filled with at least `min_bytes`, or an error 227 /// occurs. 228 /// Implementation Notes: 229 /// * The callback may be called in ISR context. 230 /// * It is safe to call `DoRead`/`DoWrite` from the callback context. 231 /// * To prevent infinite recurssion the callback should never be called 232 /// synchronously from `DoRead`. 233 /// * The callback must be moved and stored prior to its invocation. 234 /// * Do not hold a lock when invoking the callback. 235 /// 236 /// @param rx_buffer The buffer to read data into. 237 /// @param min_bytes Minimum bytes to read. 238 /// @param callback A callback to invoke when the transaction is completed. 239 /// @param status OK: The operation was successful and the 240 /// buffer has been filled with at least 241 /// `min_bytes` with data. 242 /// CANCELLED: The operation was cancelled 243 /// via CancelRead(). 244 /// May return other implementation-specific 245 /// status codes. 246 /// @param buffer buffer.size() returns the number of 247 /// bytes successfully read into the buffer. 248 /// @returns @rst 249 /// 250 /// .. pw-status-codes:: 251 /// 252 /// OK: The operation was successful started. 253 /// UNAVAILABLE: Another Read() transaction is currently in progress. 254 /// 255 /// May return other implementation-specific status codes. 256 /// 257 /// @endrst 258 virtual Status DoRead( 259 ByteSpan rx_buffer, 260 size_t min_bytes, 261 Function<void(Status status, ConstByteSpan buffer)>&& callback) = 0; 262 263 /// Cancels a current read in progress. 264 /// 265 /// This virtual function will cancel a read in progress. The read's callback 266 /// will be called with status=CANCELLED. 267 /// 268 /// @returns @rst 269 /// 270 /// true: The operation was successfully canceled a transaction in progress 271 /// and the callback will be invoked with status=CANCELLED. 272 /// false: There were no transactions in progress and nothing was 273 /// cancelled. No callback will be invoked. 274 /// 275 /// May return other implementation-specific status codes. 276 /// 277 /// @endrst 278 virtual bool DoCancelRead() = 0; 279 280 /// Writes data from a provided buffer to the UART. 281 /// 282 /// This virtual function attempts to write data from the provided byte 283 /// buffer (`tx_buffer`). 284 /// This virtual function will return immediately. `callback` will be invoked 285 /// when either the buffer fully written, or an error occurs. 286 /// Implementation Notes: 287 /// * The callback may be called in ISR context. 288 /// * It is safe to call `DoRead`/`DoWrite` from the callback context. 289 /// * To prevent infinite recurssion the callback should never be called 290 /// synchronously from `DoRead`. 291 /// * The callback must be moved and stored prior to its invocation. 292 /// * Do not hold a lock when invoking the callback. 293 /// 294 /// @param tx_buffer The buffer to write to the UART. 295 /// @param callback A callback to invoke when the transaction is completed. 296 /// @param status status.size() returns the number of bytes 297 /// successfully written from `tx_buffer`. 298 /// @param status OK: The operation was successful and the 299 /// entire buffer has been written. 300 /// CANCELLED: The operation was cancelled 301 /// via CancelWrite(). 302 /// May return other implementation-specific 303 /// status codes. 304 /// @returns @rst 305 /// 306 /// .. pw-status-codes:: 307 /// 308 /// OK: The operation was successful started. 309 /// UNAVAILABLE: Another Write() transaction is currently in progress. 310 /// 311 /// May return other implementation-specific status codes. 312 /// 313 /// @endrst 314 virtual Status DoWrite(ConstByteSpan tx_buffer, 315 Function<void(StatusWithSize status)>&& callback) = 0; 316 317 /// Cancel a current write in progress. 318 /// 319 /// This virtual function will cancel a write in progress. The write's 320 /// callback will be invoked with status=CANCELLED. 321 /// 322 /// @returns @rst 323 /// 324 /// true: The operation was successfully canceled a transaction in progress 325 /// and the callback will be invoked with status=CANCELLED. 326 /// false: There were no transactions in progress and nothing was 327 /// cancelled. No callback will be invoked. 328 /// 329 /// May return other implementation-specific status codes. 330 /// 331 /// @endrst 332 virtual bool DoCancelWrite() = 0; 333 334 /// Ensures all queued data in the UART has been transmitted and the hardware 335 /// FIFO is empty. 336 /// 337 /// This function ensures that all data enqueued before calling this function 338 /// has been transmitted. Any data enqueued after this function completes will 339 /// be transmitted immediately. 340 /// 341 /// @param callback A callback to invoke when the flush is completed. 342 /// @param status OK: The operation was successful and the 343 /// transmit FIFO is empty. 344 /// CANCELLED: The operation was cancelled 345 /// via CancelFlushOutput(). 346 /// May return other implementation-specific 347 /// status codes. 348 /// 349 /// @returns @rst 350 /// 351 /// .. pw-status-codes:: 352 /// 353 /// OK: The operation was successfully started. 354 /// UNAVAILABLE: Another Write() or FlushOutput() operation is currently 355 /// in progress. 356 /// 357 /// May return other implementation-specific status codes. 358 /// 359 /// @endrst DoFlushOutput(Function<void (Status status)> &&)360 virtual Status DoFlushOutput(Function<void(Status status)>&& /*callback*/) { 361 return Status::Unimplemented(); 362 } 363 364 /// Cancels a pending FlushOutput() operation. 365 /// 366 /// This function will cancel an output flush in progress. The DoFlushOutput 367 /// callback will be called with status=CANCELLED. 368 /// 369 /// @returns @rst 370 /// 371 /// true: The operation was successfully canceled a transaction in progress 372 /// and the callback will be invoked with status=CANCELLED. 373 /// false: There were no transactions in progress and nothing was 374 /// cancelled. No callback will be invoked. 375 /// 376 /// @endrst DoCancelFlushOutput()377 virtual bool DoCancelFlushOutput() { return false; } 378 }; 379 380 } // namespace pw::uart 381