pw_sys_io: Add TryReadByte(byte* dest) function
This adds a non-blocking version of ReadByte() that enables writing, for
example, a superloop that combines custom processing simultaneously with
byte input handling for the RPC subsystem.
Change-Id: I9cb1e6ae8c944ca7cdff6d4bff101ac52e80b53a
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/23980
Reviewed-by: Armando Montanez <amontanez@google.com>
Commit-Queue: Keir Mierle <keir@google.com>
diff --git a/pw_sys_io/public/pw_sys_io/sys_io.h b/pw_sys_io/public/pw_sys_io/sys_io.h
index 5973579..477c719 100644
--- a/pw_sys_io/public/pw_sys_io/sys_io.h
+++ b/pw_sys_io/public/pw_sys_io/sys_io.h
@@ -51,9 +51,18 @@
// This function will block until it either succeeds or fails to read a byte
// from the pw_sys_io backend.
//
-// Returns Status::Ok() if a byte was successfully read.
+// Returns Status::Ok() - A byte was successfully read.
+// Status::ResourceExhausted() - if the underlying source vanished.
Status ReadByte(std::byte* dest);
+// Read a single byte from the sys io backend, if available.
+// Implemented by: Backend
+//
+// Returns Status::Ok() - A byte was successfully read, and is in dest.
+// Status::Unavailable() - No byte is available to read; try later.
+// Status::Unimplemented() - Not supported on this target.
+Status TryReadByte(std::byte* dest);
+
// Write a single byte out the sys io backend.
// Implemented by: Backend
//
diff --git a/pw_sys_io_arduino/sys_io_arduino.cc b/pw_sys_io_arduino/sys_io_arduino.cc
index c06f3a9..de6c344 100644
--- a/pw_sys_io_arduino/sys_io_arduino.cc
+++ b/pw_sys_io_arduino/sys_io_arduino.cc
@@ -35,11 +35,17 @@
Status ReadByte(std::byte* dest) {
while (true) {
- if (Serial.available()) {
- *dest = static_cast<std::byte>(Serial.read());
- break;
+ if (TryReadByte(dest).ok()) {
+ return Status::Ok();
}
}
+}
+
+Status TryReadByte(std::byte* dest) {
+ if (!Serial.available()) {
+ return Status::Unavailable();
+ }
+ *dest = static_cast<std::byte>(Serial.read());
return Status::Ok();
}
diff --git a/pw_sys_io_baremetal_lm3s6965evb/sys_io_baremetal.cc b/pw_sys_io_baremetal_lm3s6965evb/sys_io_baremetal.cc
index ddf901e..86cc341 100644
--- a/pw_sys_io_baremetal_lm3s6965evb/sys_io_baremetal.cc
+++ b/pw_sys_io_baremetal_lm3s6965evb/sys_io_baremetal.cc
@@ -90,15 +90,21 @@
// see if a byte is ready yet.
Status ReadByte(std::byte* dest) {
while (true) {
- if (uart0.receive_error) {
- // Writing anything to this register clears all errors.
- uart0.receive_error = 0xff;
- }
- if (uart0.status_flags & kRxFifoFullMask) {
- *dest = static_cast<std::byte>(uart0.data_register);
- break;
+ if (TryReadByte(dest).ok()) {
+ return Status::Ok();
}
}
+}
+
+Status TryReadByte(std::byte* dest) {
+ if (uart0.receive_error) {
+ // Writing anything to this register clears all errors.
+ uart0.receive_error = 0xff;
+ }
+ if (!(uart0.status_flags & kRxFifoFullMask)) {
+ return Status::Unavailable();
+ }
+ *dest = static_cast<std::byte>(uart0.data_register);
return Status::Ok();
}
diff --git a/pw_sys_io_baremetal_stm32f429/sys_io_baremetal.cc b/pw_sys_io_baremetal_stm32f429/sys_io_baremetal.cc
index 80cb169..846e34c 100644
--- a/pw_sys_io_baremetal_stm32f429/sys_io_baremetal.cc
+++ b/pw_sys_io_baremetal_stm32f429/sys_io_baremetal.cc
@@ -170,11 +170,20 @@
// see if a byte is ready yet.
Status ReadByte(std::byte* dest) {
while (true) {
- if (usart1.status & kReadDataReady) {
- *dest = static_cast<std::byte>(usart1.data_register);
- break;
+ if (TryReadByte(dest).ok()) {
+ return Status::Ok();
}
}
+}
+
+// Wait for a byte to read on USART1. This blocks until a byte is read. This is
+// extremely inefficient as it requires the target to burn CPU cycles polling to
+// see if a byte is ready yet.
+Status TryReadByte(std::byte* dest) {
+ if (!(usart1.status & kReadDataReady)) {
+ return Status::Unavailable();
+ }
+ *dest = static_cast<std::byte>(usart1.data_register);
return Status::Ok();
}
diff --git a/pw_sys_io_stdio/sys_io.cc b/pw_sys_io_stdio/sys_io.cc
index 04ab9b0..53c9d5e 100644
--- a/pw_sys_io_stdio/sys_io.cc
+++ b/pw_sys_io_stdio/sys_io.cc
@@ -31,6 +31,11 @@
return Status::Ok();
}
+Status TryReadByte(std::byte*) {
+ // TryReadByte() is not (yet) supported on hosts.
+ return Status::Unimplemented();
+}
+
Status WriteByte(std::byte b) {
if (std::putchar(static_cast<char>(b)) == EOF) {
return Status::Internal();