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 not safe to call any Uart methods 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 not safe to call any Uart methods 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 not safe to call any Uart methods 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 /// * The callback must be moved and stored prior to its invocation. 231 /// * Do not hold a lock when invoking the callback. 232 /// 233 /// @param rx_buffer The buffer to read data into. 234 /// @param min_bytes Minimum bytes to read. 235 /// @param callback A callback to invoke when the transaction is completed. 236 /// @param status OK: The operation was successful and the 237 /// buffer has been filled with at least 238 /// `min_bytes` with data. 239 /// CANCELLED: The operation was cancelled 240 /// via CancelRead(). 241 /// May return other implementation-specific 242 /// status codes. 243 /// @param buffer buffer.size() returns the number of 244 /// bytes successfully read into the buffer. 245 /// @returns @rst 246 /// 247 /// .. pw-status-codes:: 248 /// 249 /// OK: The operation was successful started. 250 /// UNAVAILABLE: Another Read() transaction is currently in progress. 251 /// 252 /// May return other implementation-specific status codes. 253 /// 254 /// @endrst 255 virtual Status DoRead( 256 ByteSpan rx_buffer, 257 size_t min_bytes, 258 Function<void(Status status, ConstByteSpan buffer)>&& callback) = 0; 259 260 /// Cancels a current read in progress. 261 /// 262 /// This virtual function will cancel a read in progress. The read's callback 263 /// will be called with status=CANCELLED. 264 /// 265 /// @returns @rst 266 /// 267 /// true: The operation was successfully canceled a transaction in progress 268 /// and the callback will be invoked with status=CANCELLED. 269 /// false: There were no transactions in progress and nothing was 270 /// cancelled. No callback will be invoked. 271 /// 272 /// May return other implementation-specific status codes. 273 /// 274 /// @endrst 275 virtual bool DoCancelRead() = 0; 276 277 /// Writes data from a provided buffer to the UART. 278 /// 279 /// This virtual function attempts to write data from the provided byte 280 /// buffer (`tx_buffer`). 281 /// This virtual function will return immediately. `callback` will be invoked 282 /// when either the buffer fully written, or an error occurs. 283 /// Implementation Notes: 284 /// * The callback may be called in ISR context. 285 /// * The callback must be moved and stored prior to its invocation. 286 /// * Do not hold a lock when invoking the callback. 287 /// 288 /// @param tx_buffer The buffer to write to the UART. 289 /// @param callback A callback to invoke when the transaction is completed. 290 /// @param status status.size() returns the number of bytes 291 /// successfully written from `tx_buffer`. 292 /// @param status OK: The operation was successful and the 293 /// entire buffer has been written. 294 /// CANCELLED: The operation was cancelled 295 /// via CancelWrite(). 296 /// May return other implementation-specific 297 /// status codes. 298 /// @returns @rst 299 /// 300 /// .. pw-status-codes:: 301 /// 302 /// OK: The operation was successful started. 303 /// UNAVAILABLE: Another Write() transaction is currently in progress. 304 /// 305 /// May return other implementation-specific status codes. 306 /// 307 /// @endrst 308 virtual Status DoWrite(ConstByteSpan tx_buffer, 309 Function<void(StatusWithSize status)>&& callback) = 0; 310 311 /// Cancel a current write in progress. 312 /// 313 /// This virtual function will cancel a write in progress. The write's 314 /// callback will be invoked with status=CANCELLED. 315 /// 316 /// @returns @rst 317 /// 318 /// true: The operation was successfully canceled a transaction in progress 319 /// and the callback will be invoked with status=CANCELLED. 320 /// false: There were no transactions in progress and nothing was 321 /// cancelled. No callback will be invoked. 322 /// 323 /// May return other implementation-specific status codes. 324 /// 325 /// @endrst 326 virtual bool DoCancelWrite() = 0; 327 328 /// Ensures all queued data in the UART has been transmitted and the hardware 329 /// FIFO is empty. 330 /// 331 /// This function ensures that all data enqueued before calling this function 332 /// has been transmitted. Any data enqueued after this function completes will 333 /// be transmitted immediately. 334 /// 335 /// @param callback A callback to invoke when the flush is completed. 336 /// @param status OK: The operation was successful and the 337 /// transmit FIFO is empty. 338 /// CANCELLED: The operation was cancelled 339 /// via CancelFlushOutput(). 340 /// May return other implementation-specific 341 /// status codes. 342 /// 343 /// @returns @rst 344 /// 345 /// .. pw-status-codes:: 346 /// 347 /// OK: The operation was successfully started. 348 /// UNAVAILABLE: Another Write() or FlushOutput() operation is currently 349 /// in progress. 350 /// 351 /// May return other implementation-specific status codes. 352 /// 353 /// @endrst DoFlushOutput(Function<void (Status status)> &&)354 virtual Status DoFlushOutput(Function<void(Status status)>&& /*callback*/) { 355 return Status::Unimplemented(); 356 } 357 358 /// Cancels a pending FlushOutput() operation. 359 /// 360 /// This function will cancel an output flush in progress. The DoFlushOutput 361 /// callback will be called with status=CANCELLED. 362 /// 363 /// @returns @rst 364 /// 365 /// true: The operation was successfully canceled a transaction in progress 366 /// and the callback will be invoked with status=CANCELLED. 367 /// false: There were no transactions in progress and nothing was 368 /// cancelled. No callback will be invoked. 369 /// 370 /// @endrst DoCancelFlushOutput()371 virtual bool DoCancelFlushOutput() { return false; } 372 }; 373 374 } // namespace pw::uart 375