-
-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Handle embedded_io_async::Read/Write Guarantee #235
base: main
Are you sure you want to change the base?
Changes from all commits
3c5e989
6f56895
d809183
2662afb
ddebc25
68ca896
c7aa5fc
d05529e
7db2732
816a9b0
fe03f08
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,7 @@ use crate::{ | |
}; | ||
|
||
use super::driver::SplitDriverError; | ||
use heapless::Vec; | ||
|
||
// Receive split message from peripheral via serial and process it | ||
/// | ||
|
@@ -42,44 +43,90 @@ pub(crate) async fn run_serial_peripheral_monitor< | |
/// Serial driver for BOTH split central and peripheral | ||
pub(crate) struct SerialSplitDriver<S: Read + Write> { | ||
serial: S, | ||
buffer: [u8; SPLIT_MESSAGE_MAX_SIZE], | ||
n_bytes_part: usize, | ||
} | ||
|
||
impl<S: Read + Write> SerialSplitDriver<S> { | ||
pub(crate) fn new(serial: S) -> Self { | ||
Self { serial } | ||
Self { | ||
serial, | ||
buffer: [0_u8; SPLIT_MESSAGE_MAX_SIZE], | ||
n_bytes_part: 0, | ||
} | ||
} | ||
} | ||
|
||
impl<S: Read + Write> SplitReader for SerialSplitDriver<S> { | ||
async fn read(&mut self) -> Result<SplitMessage, SplitDriverError> { | ||
let mut buf = [0_u8; SPLIT_MESSAGE_MAX_SIZE]; | ||
let n_bytes = self | ||
.serial | ||
.read(&mut buf) | ||
.await | ||
.map_err(|_e| SplitDriverError::SerialError)?; | ||
if n_bytes == 0 { | ||
return Err(SplitDriverError::EmptyMessage); | ||
async fn read(&mut self) -> Result<Vec<SplitMessage, 2>, SplitDriverError> { | ||
const SENTINEL: u8 = 0x00; | ||
let mut messages = Vec::new(); | ||
while self.n_bytes_part < self.buffer.len() { | ||
let n_bytes = self | ||
.serial | ||
.read(&mut self.buffer[self.n_bytes_part..]) | ||
.await | ||
.inspect_err(|_e| self.n_bytes_part = 0) | ||
.map_err(|_e| SplitDriverError::SerialError)?; | ||
if n_bytes == 0 { | ||
return Err(SplitDriverError::EmptyMessage); | ||
} | ||
|
||
self.n_bytes_part += n_bytes; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check if |
||
if self.buffer[..self.n_bytes_part].contains(&SENTINEL) { | ||
break; | ||
} | ||
} | ||
let message: SplitMessage = postcard::from_bytes(&buf).map_err(|e| { | ||
error!("Postcard deserialize split message error: {}", e); | ||
SplitDriverError::DeserializeError | ||
})?; | ||
Ok(message) | ||
|
||
let mut start_byte = 0; | ||
let mut end_byte = start_byte; | ||
while end_byte < self.n_bytes_part { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The buffer size is |
||
let value = self.buffer[end_byte]; | ||
if value == SENTINEL { | ||
postcard::from_bytes_cobs(&mut self.buffer[start_byte..=end_byte]).map_or_else( | ||
|e| error!("Postcard deserialize split message error: {}", e), | ||
|message| { | ||
messages | ||
.push(message) | ||
.unwrap_or_else(|_m| error!("Split message vector full")); | ||
}, | ||
); | ||
start_byte = end_byte + 1; | ||
} | ||
|
||
end_byte += 1; | ||
} | ||
|
||
if start_byte != self.n_bytes_part { | ||
// Store Partial Message for Next Read | ||
self.buffer.copy_within(start_byte..self.n_bytes_part, 0); | ||
self.n_bytes_part = self.n_bytes_part - start_byte; | ||
} else { | ||
// Reset Buffer | ||
self.n_bytes_part = 0; | ||
} | ||
|
||
Ok(messages) | ||
} | ||
} | ||
|
||
impl<S: Read + Write> SplitWriter for SerialSplitDriver<S> { | ||
async fn write(&mut self, message: &SplitMessage) -> Result<usize, SplitDriverError> { | ||
let mut buf = [0_u8; SPLIT_MESSAGE_MAX_SIZE]; | ||
let bytes = postcard::to_slice(message, &mut buf).map_err(|e| { | ||
let bytes = postcard::to_slice_cobs(message, &mut buf).map_err(|e| { | ||
error!("Postcard serialize split message error: {}", e); | ||
SplitDriverError::SerializeError | ||
})?; | ||
self.serial | ||
.write(bytes) | ||
.await | ||
.map_err(|_e| SplitDriverError::SerialError) | ||
let mut remaining_bytes = bytes.len(); | ||
while remaining_bytes > 0 { | ||
let sent_bytes = self | ||
.serial | ||
.write(&bytes[bytes.len() - remaining_bytes..]) | ||
.await | ||
.map_err(|_e| SplitDriverError::SerialError)?; | ||
remaining_bytes -= sent_bytes; | ||
} | ||
Ok(bytes.len()) | ||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the trait, each
read
call should read only oneSplitMessage
, not two. It defines "expected behavior", should not be affected by the serial implementation