don't crash if tx buffers fill up.

This commit is contained in:
Dario Nieuwenhuis 2024-06-25 21:15:23 +02:00 committed by Ulf Lilleengen
parent 160e1c38ce
commit 11652ff5c7

View File

@ -1,6 +1,7 @@
#![no_std] #![no_std]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs)] #![warn(missing_docs)]
#![deny(unused_must_use)]
// must be first // must be first
mod fmt; mod fmt;
@ -244,6 +245,10 @@ struct PendingRequest {
waker: Waker, waker: Waker,
} }
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
struct NoFreeBufs;
struct StateInner { struct StateInner {
init: bool, init: bool,
init_waker: WakerRegistration, init_waker: WakerRegistration,
@ -450,13 +455,13 @@ impl StateInner {
return None; return None;
} }
fn send_message(&mut self, msg: &mut Message, data: &[u8]) { fn send_message(&mut self, msg: &mut Message, data: &[u8]) -> Result<(), NoFreeBufs> {
if data.is_empty() { if data.is_empty() {
msg.data = ptr::null_mut(); msg.data = ptr::null_mut();
msg.data_len = 0; msg.data_len = 0;
} else { } else {
assert!(data.len() <= TX_BUF_SIZE); assert!(data.len() <= TX_BUF_SIZE);
let buf_idx = self.find_free_tx_buf().unwrap(); // TODO handle out of bufs let buf_idx = self.find_free_tx_buf().ok_or(NoFreeBufs)?;
let buf = unsafe { addr_of_mut!((*self.cb).tx_bufs[buf_idx]) } as *mut u8; let buf = unsafe { addr_of_mut!((*self.cb).tx_bufs[buf_idx]) } as *mut u8;
unsafe { copy_nonoverlapping(data.as_ptr(), buf, data.len()) } unsafe { copy_nonoverlapping(data.as_ptr(), buf, data.len()) }
msg.data = buf; msg.data = buf;
@ -467,10 +472,10 @@ impl StateInner {
} }
// TODO free data buf if send_message_raw fails. // TODO free data buf if send_message_raw fails.
self.send_message_raw(msg); self.send_message_raw(msg)
} }
fn send_message_raw(&mut self, msg: &Message) { fn send_message_raw(&mut self, msg: &Message) -> Result<(), NoFreeBufs> {
let (ch, ipc_ch) = match msg.channel { let (ch, ipc_ch) = match msg.channel {
1 => (0, 1), // control 1 => (0, 1), // control
2 => (1, 3), // data 2 => (1, 3), // data
@ -478,7 +483,7 @@ impl StateInner {
}; };
// allocate a msg. // allocate a msg.
let idx = self.find_free_message(ch).unwrap(); // TODO handle list full let idx = self.find_free_message(ch).ok_or(NoFreeBufs)?;
debug!("tx seq {} msg: {:?}", self.tx_seq_no, msg); debug!("tx seq {} msg: {:?}", self.tx_seq_no, msg);
@ -491,6 +496,7 @@ impl StateInner {
let ipc = unsafe { &*pac::IPC_NS::ptr() }; let ipc = unsafe { &*pac::IPC_NS::ptr() };
ipc.tasks_send[ipc_ch].write(|w| unsafe { w.bits(1) }); ipc.tasks_send[ipc_ch].write(|w| unsafe { w.bits(1) });
Ok(())
} }
fn handle_control(&mut self, msg: &Message) { fn handle_control(&mut self, msg: &Message) {
@ -626,7 +632,7 @@ impl StateInner {
free_msg.data = msg.data; free_msg.data = msg.data;
free_msg.data_len = msg.data_len; free_msg.data_len = msg.data_len;
self.send_message_raw(&free_msg); unwrap!(self.send_message_raw(&free_msg));
} }
} }
@ -702,7 +708,7 @@ impl<'a> Control<'a> {
} }
msg.param[0..4].copy_from_slice(&req_serial.to_le_bytes()); msg.param[0..4].copy_from_slice(&req_serial.to_le_bytes());
state.send_message(msg, req_data); unwrap!(state.send_message(msg, req_data));
// Setup the pending request state. // Setup the pending request state.
let (req_slot_idx, req_slot) = state let (req_slot_idx, req_slot) = state
@ -838,7 +844,9 @@ impl<'a, TW: embedded_io::Write> Runner<'a, TW> {
msg.id = 0x7006_0004; // IP send msg.id = 0x7006_0004; // IP send
msg.param_len = 12; msg.param_len = 12;
msg.param[4..8].copy_from_slice(&fd.to_le_bytes()); msg.param[4..8].copy_from_slice(&fd.to_le_bytes());
state.send_message(&mut msg, buf); if let Err(e) = state.send_message(&mut msg, buf) {
warn!("tx failed: {:?}", e);
}
self.ch.tx_done(); self.ch.tx_done();
} }