Skip to content

Commit 5a5b424

Browse files
committed
vexos: block on stdout writes with size>2048
1 parent 0885d91 commit 5a5b424

File tree

2 files changed

+24
-12
lines changed

2 files changed

+24
-12
lines changed

library/std/src/sys/pal/vexos/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod pipe;
55
pub mod thread;
66
pub mod time;
77

8+
use crate::sys::stdio;
89
use crate::arch::global_asm;
910
use crate::ptr::{self, addr_of_mut};
1011
use crate::time::{Duration, Instant};
@@ -53,14 +54,13 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
5354
pub unsafe fn cleanup() {
5455
let exit_time = Instant::now();
5556
const FLUSH_TIMEOUT: Duration = Duration::from_millis(15);
56-
const STDIO_CHANNEL: u32 = 1;
5757

5858
// Force the serial buffer to flush
5959
while exit_time.elapsed() < FLUSH_TIMEOUT {
6060
vex_sdk::vexTasksRun();
6161

6262
// If the buffer has been fully flushed, exit the loop
63-
if vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) == (crate::sys::stdio::STDOUT_BUF_SIZE as i32)
63+
if vex_sdk::vexSerialWriteFree(stdio::STDIO_CHANNEL) == (stdio::STDOUT_BUF_SIZE as i32)
6464
{
6565
break;
6666
}

library/std/src/sys/stdio/vexos.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub struct Stdin;
44
pub struct Stdout;
55
pub type Stderr = Stdout;
66

7-
const STDIO_CHANNEL: u32 = 1;
7+
pub const STDIO_CHANNEL: u32 = 1;
88

99
impl Stdin {
1010
pub const fn new() -> Stdin {
@@ -40,17 +40,29 @@ impl Stdout {
4040

4141
impl io::Write for Stdout {
4242
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
43-
let written =
44-
unsafe { vex_sdk::vexSerialWriteBuffer(STDIO_CHANNEL, buf.as_ptr(), buf.len() as u32) };
45-
46-
if written < 0 {
47-
return Err(io::Error::new(
48-
io::ErrorKind::Uncategorized,
49-
"Internal write error occurred.",
50-
));
43+
let mut count = 0;
44+
45+
// HACK: VEXos holds an internal write buffer for serial that is flushed to USB1 roughly every
46+
// millisecond by `vexTasksRun`. For writes larger than 2048 bytes, we must block until that buffer
47+
// is flushed to USB1 before writing the rest of `buf`. In practice, this is fairly nonstandard for
48+
// a `write` implementation but it avoids an guaranteed recursive panic when using macros such as
49+
// `print!` to write large amounts of data to stdout at once.
50+
for chunk in buf.chunks(STDOUT_BUF_SIZE) {
51+
if unsafe { vex_sdk::vexSerialWriteFree(STDIO_CHANNEL) as usize } < chunk.len() {
52+
self.flush().unwrap();
53+
}
54+
55+
count += unsafe { vex_sdk::vexSerialWriteBuffer(STDIO_CHANNEL, chunk.as_ptr(), chunk.len() as u32) };
56+
57+
if count < 0 {
58+
return Err(io::Error::new(
59+
io::ErrorKind::Uncategorized,
60+
"Internal write error occurred.",
61+
));
62+
}
5163
}
5264

53-
Ok(written as usize)
65+
Ok(count as usize)
5466
}
5567

5668
fn flush(&mut self) -> io::Result<()> {

0 commit comments

Comments
 (0)