Skip to content

Commit

Permalink
Merge pull request tock#3787 from alistair23/alistair/uart-errors
Browse files Browse the repository at this point in the history
capsules: console/virtual_uart: Report receive errors to userspace
  • Loading branch information
bradjc authored Jan 18, 2024
2 parents d4739a3 + b7ef2cd commit 430ebbc
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
15 changes: 10 additions & 5 deletions capsules/core/src/console.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,16 @@ impl<'a> Console<'a> {
} else {
// Note: We have ensured above that rx_buffer is present
app.read_len = read_len;
self.rx_buffer.take().map(|buffer| {
self.rx_in_progress.set(processid);
let _ = self.uart.receive_buffer(buffer, app.read_len);
});
Ok(())
self.rx_buffer
.take()
.map_or(Err(ErrorCode::INVAL), |buffer| {
self.rx_in_progress.set(processid);
if let Err((e, buf)) = self.uart.receive_buffer(buffer, app.read_len) {
self.rx_buffer.replace(buf);
return Err(e);
}
Ok(())
})
}
}
}
Expand Down
37 changes: 30 additions & 7 deletions capsules/core/src/virtualizers/virtual_uart.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,30 @@ impl<'a> uart::ReceiveClient for MuxUart<'a> {
// we just received, or if a new receive has been started, we start the
// underlying UART receive again.
if read_pending {
self.start_receive(next_read_len);
if let Err((e, buf)) = self.start_receive(next_read_len) {
self.buffer.replace(buf);

// Report the error to all devices
self.devices.iter().for_each(|device| {
if device.receiver {
device.rx_buffer.take().map(|rxbuf| {
let state = device.state.get();
let position = device.rx_position.get();

if state == UartDeviceReceiveState::Receiving {
device.state.set(UartDeviceReceiveState::Idle);

device.received_buffer(
rxbuf,
position,
Err(e),
uart::Error::Aborted,
);
}
});
}
});
}
}
}
}
Expand Down Expand Up @@ -253,27 +276,27 @@ impl<'a> MuxUart<'a> {
/// 2. We are in the midst of a read: abort so we can start a new read now
/// (return true)
/// 3. We are idle: start reading (return false)
fn start_receive(&self, rx_len: usize) -> bool {
fn start_receive(&self, rx_len: usize) -> Result<bool, (ErrorCode, &'static mut [u8])> {
self.buffer.take().map_or_else(
|| {
// No rxbuf which means a read is ongoing
if self.completing_read.get() {
// Case (1). Do nothing here, `received_buffer()` handler
// will call start_receive when ready.
false
Ok(false)
} else {
// Case (2). Stop the previous read so we can use the
// `received_buffer()` handler to recalculate the minimum
// length for a read.
let _ = self.uart.receive_abort();
true
Ok(true)
}
},
|rxbuf| {
// Case (3). No ongoing receive calls, we can start one now.
let len = cmp::min(rx_len, rxbuf.len());
let _ = self.uart.receive_buffer(rxbuf, len);
false
self.uart.receive_buffer(rxbuf, len)?;
Ok(false)
},
)
}
Expand Down Expand Up @@ -452,7 +475,7 @@ impl<'a> uart::Receive<'a> for UartDevice<'a> {
self.rx_len.set(rx_len);
self.rx_position.set(0);
self.state.set(UartDeviceReceiveState::Idle);
self.mux.start_receive(rx_len);
self.mux.start_receive(rx_len)?;
self.state.set(UartDeviceReceiveState::Receiving);
Ok(())
}
Expand Down

0 comments on commit 430ebbc

Please sign in to comment.