v0.9.1: Serial::write_queue locks serial port while busy-waiting
Serial::write_queue does:
// Start of new block, ensure TX FIFO empty
if n % 16 == 0 {
while !self.serial.lsr.read().thre().bit() {}
}
That prevents the a receive task from running, causing characters to be dropped.
In our code we have these two tasks, that due to priority ceiling can't run at the same time inside the critical region:
#[task(resources = [to_xray_queue, xray_serial])]
fn dump_to_xray(cx: dump_to_xray::Context) {
let mut xray_serial = cx.resources.xray_serial;
let mut to_xray_queue = cx.resources.to_xray_queue;
xray_serial.lock(|s| to_xray_queue.lock(|q| s.write_queue(q)));
}
#[task(binds = USART0, priority = 5, resources = [from_xray_queue, xray_serial], spawn = [dump_from_xray])]
fn usart0(cx: usart0::Context) {
let mut xray_serial = Exclusive(cx.resources.xray_serial);
let mut from_xray_queue = Exclusive(cx.resources.from_xray_queue);
if let Some(int_id) = xray_serial.lock(|s| s.read_iir()) {
match int_id {
INTID_A::RDA => {
// Get data from serial port
if let Ok(c) = xray_serial.lock(|s| s.read()) {
let _ = from_xray_queue.lock(|q| q.enqueue(c));
}
// Signal dump over can
let _ = cx.spawn.dump_from_xray();
}
_ => (),
}
}
}