vexide_core/program.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
//! Functions for modifying the state of the current
//! user program.
use core::{convert::Infallible, fmt::Debug, time::Duration};
use vex_sdk::{vexSerialWriteFree, vexSystemExitRequest, vexTasksRun};
use crate::{io, time::Instant};
/// A trait that can be implemented for arbitrary return types in the main function.
pub trait Termination {
/// Run specific termination logic.
/// Unlike in the standard library, this function does not return a status code.
fn report(self);
}
impl Termination for () {
fn report(self) {}
}
impl Termination for ! {
fn report(self) {}
}
impl Termination for Infallible {
fn report(self) {}
}
impl<T: Termination, E: Debug> Termination for Result<T, E> {
fn report(self) {
match self {
Ok(t) => t.report(),
Err(e) => io::println!("Error: {e:?}"),
}
}
}
const FLUSH_TIMEOUT: Duration = Duration::from_millis(15);
/// Exits the program using vexSystemExitRequest.
/// This function will not instantly exit the program,
/// but will instead wait up to 15mS to force the serial buffer to flush.
pub fn exit() -> ! {
let exit_time = Instant::now();
unsafe {
// Force the serial buffer to flush
while exit_time.elapsed() < FLUSH_TIMEOUT {
vexTasksRun();
// If the buffer has been fully flushed, exit the loop
if vexSerialWriteFree(io::STDIO_CHANNEL) == (io::Stdout::INTERNAL_BUFFER_SIZE as i32) {
break;
}
}
// Request program exit.
vexSystemExitRequest();
// Loop while vexos decides what to do with our exit request.
loop {
vexTasksRun();
}
}
}