cleanup local echo during BIO loading - makes it a bit more reliable

This commit is contained in:
bunnie 2026-06-09 17:52:20 +08:00
parent dc7ac598dc
commit 6e28127cae
7 changed files with 64 additions and 28 deletions

View file

@ -48,6 +48,7 @@ board-dabao = [
bio-math-test = ["bio-lib/c-math-test"]
bio-wheel-test = ["bio-lib/c-colorwheel"]
ctap-bringup = []
usb = []
extra-cmds = []
aestests = ["aes"]
default = ["usb", "bio-math-test", "bio-wheel-test"]
default = []

View file

@ -1,5 +1,8 @@
use core::fmt::Write;
use std::collections::HashMap;
use std::{
collections::HashMap,
sync::{Arc, atomic::AtomicBool},
};
use String;
use bao1x_hal_service::trng;
@ -41,6 +44,7 @@ pub struct CommonEnv {
trng: trng::Trng,
#[allow(dead_code)]
xns: xous_names::XousNames,
echo: Arc<AtomicBool>,
}
impl CommonEnv {
#[allow(dead_code)]
@ -78,11 +82,13 @@ mod ver;
use ver::*;
mod test;
use test::*;
#[cfg(feature = "extra-cmds")]
mod trng_cmd;
#[cfg(feature = "extra-cmds")]
use trng_cmd::*;
#[cfg(feature = "usb")]
#[cfg(feature = "extra-cmds")]
mod usb;
#[cfg(feature = "usb")]
#[cfg(feature = "extra-cmds")]
use usb::*;
#[cfg(feature = "aestests")]
mod aes_cmd;
@ -101,8 +107,9 @@ pub struct CmdEnv {
common_env: CommonEnv,
lastverb: String,
///// 2. declare storage for your command here.
#[cfg(feature = "extra-cmds")]
trng_cmd: TrngCmd,
#[cfg(feature = "usb")]
#[cfg(feature = "extra-cmds")]
usb: Usb,
#[cfg(feature = "aestests")]
aes_cmd: Aes,
@ -111,7 +118,7 @@ pub struct CmdEnv {
bio: BioLoader,
}
impl CmdEnv {
pub fn new(xns: &xous_names::XousNames) -> CmdEnv {
pub fn new(xns: &xous_names::XousNames, echo: Arc<AtomicBool>) -> CmdEnv {
let ticktimer = ticktimer::Ticktimer::new().expect("Couldn't connect to Ticktimer");
// _ prefix allows us to leave the `mut` here without creating a warning.
// the `mut` option is needed for some features.
@ -120,6 +127,7 @@ impl CmdEnv {
cb_registrations: HashMap::new(),
trng: trng::Trng::new(&xns).unwrap(),
xns: xous_names::XousNames::new().unwrap(),
echo,
};
#[cfg(feature = "aestests")]
let aes_cmd = Aes::new(&xns, &mut _common);
@ -127,11 +135,12 @@ impl CmdEnv {
common_env: _common,
lastverb: String::new(),
///// 3. initialize your storage, by calling new()
#[cfg(feature = "extra-cmds")]
trng_cmd: {
log::debug!("trng");
TrngCmd::new()
},
#[cfg(feature = "usb")]
#[cfg(feature = "extra-cmds")]
usb: Usb::new(),
#[cfg(feature = "aestests")]
aes_cmd,
@ -157,10 +166,11 @@ impl CmdEnv {
///// 4. add your command to this array, so that it can be looked up and dispatched
&mut echo_cmd,
&mut ver_cmd,
#[cfg(feature = "extra-cmds")]
&mut self.trng_cmd,
&mut i2cdetect_cmd,
&mut console_cmd,
#[cfg(feature = "usb")]
#[cfg(feature = "extra-cmds")]
&mut self.usb,
#[cfg(feature = "aestests")]
&mut self.aes_cmd,

View file

@ -322,15 +322,29 @@ impl Drop for BioLoader {
impl<'a> ShellCmdApi<'a> for BioLoader {
cmd_api!(bio);
fn process(&mut self, args: String, _env: &mut CommonEnv) -> Result<Option<String>, xous::Error> {
fn process(&mut self, args: String, env: &mut CommonEnv) -> Result<Option<String>, xous::Error> {
let mut ret = String::new();
if args == "ready" {
env.echo.store(false, std::sync::atomic::Ordering::SeqCst);
write!(ret, "OK").unwrap();
return Ok(Some(ret));
}
if args == "echo_on" {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
write!(ret, "OK").unwrap();
return Ok(Some(ret));
}
if args == "echo_off" {
env.echo.store(false, std::sync::atomic::Ordering::SeqCst);
write!(ret, "OK").unwrap();
return Ok(Some(ret));
}
if args == "clear" {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
self.clear();
self.store.write_app_key(APP_BIO_PINS_INDEX, &[0u8; 32]).ok();
self.store.write_app_key(APP_BIO_CLK_INDEX, &[0u8; 32]).ok();
@ -400,6 +414,7 @@ impl<'a> ShellCmdApi<'a> for BioLoader {
}
if args.starts_with("reload") {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
match self.reload() {
Ok(_) => {
write!(ret, "BIO load successful").unwrap();
@ -413,6 +428,7 @@ impl<'a> ShellCmdApi<'a> for BioLoader {
}
if args.starts_with("rx") {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
self.bio_ss.debug(self.resource_grant.cores[0]);
let arg_list: Vec<&str> = args.split_whitespace().collect();
let iters =
@ -439,6 +455,7 @@ impl<'a> ShellCmdApi<'a> for BioLoader {
}
if args.starts_with("tx") {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
let arg_list: Vec<&str> = args.split_whitespace().collect();
if arg_list.len() >= 2 {
let s = arg_list[1].trim();
@ -479,6 +496,7 @@ impl<'a> ShellCmdApi<'a> for BioLoader {
}
if args == "pad" {
env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
// Zero-fill every slot not yet received, then commit.
// This allows the host to send only the chunks that carry real data
// and let the device pad the remainder of the 0xf00-byte buffer.

View file

@ -15,7 +15,7 @@ impl<'a> ShellCmdApi<'a> for Test {
let mut ret = String::new();
#[allow(unused_variables)]
let helpstring = "test [proc] [freemem] [interrupts] [panic] [timer] [env]";
let helpstring = "test [proc] [freemem] [interrupts] [panic] [env]";
let mut tokens = args.split(' ');
@ -23,7 +23,7 @@ impl<'a> ShellCmdApi<'a> for Test {
match sub_cmd {
"timer" => {
let start = _env.ticktimer.elapsed_ms();
log::info!("Starting test");
log::info!("Timer test - runs forever");
let mut seconds = 0;
loop {
let elapsed = _env.ticktimer.elapsed_ms() - start;
@ -33,6 +33,9 @@ impl<'a> ShellCmdApi<'a> for Test {
}
}
}
"echo" => {
_env.echo.store(true, std::sync::atomic::Ordering::SeqCst);
}
"panic" => {
log::info!("System will panic now");
panic!("test panic");

View file

@ -4,7 +4,6 @@ mod ctap;
mod repl;
mod shell;
use cmds::*;
#[cfg(feature = "usb")]
use usb_bao1x::UsbHid;
fn main() {
@ -20,12 +19,9 @@ fn main() {
// spawn the shell thread
shell::start_shell();
#[cfg(feature = "usb")]
{
tt.sleep_ms(500).ok(); // pause for the system to startup
let usb = UsbHid::new();
usb.serial_console_input_injection();
}
tt.sleep_ms(500).ok(); // pause for the system to startup
let usb = UsbHid::new();
usb.serial_console_input_injection();
#[cfg(feature = "ctap-bringup")]
{
@ -33,8 +29,12 @@ fn main() {
crate::ctap::ctap_test();
}
// idle the main thread, all children are spawned
// This idiom creates a dummy server that blocks. This effectively parks the parent
// process, allowing its child threads to run without taking any CPU resources.
let dummy_sid = xous::create_server().unwrap();
loop {
tt.sleep_ms(2_000).ok();
// This call blocks forever since nobody has `dummy_sid` and thus it will never
// receive a message.
let _ = xous::receive_message(dummy_sid);
}
}

View file

@ -1,3 +1,5 @@
use std::sync::{Arc, atomic::AtomicBool};
use xous::MessageEnvelope;
use crate::CmdEnv;
@ -27,13 +29,13 @@ pub(crate) struct Repl {
env: CmdEnv,
}
impl Repl {
pub(crate) fn new(xns: &xous_names::XousNames) -> Self {
pub(crate) fn new(xns: &xous_names::XousNames, echo: Arc<AtomicBool>) -> Self {
Repl {
input: None,
msg: None,
history: Vec::new(),
history_len: HISTORY_DEPTH,
env: CmdEnv::new(xns),
env: CmdEnv::new(xns, echo),
}
}

View file

@ -1,5 +1,6 @@
use std::sync::{Arc, atomic::AtomicBool};
use bao1x_api::*;
#[cfg(feature = "usb")]
use usb_bao1x::UsbHid;
use xous::msg_scalar_unpack;
@ -32,12 +33,12 @@ fn shell() {
let kbd = keyboard::Keyboard::new(&xns).unwrap();
kbd.register_listener(SERVER_NAME_SHELLCHAT, ConsoleOp::Keypress.to_u32().unwrap() as usize);
let mut repl = crate::repl::Repl::new(&xns);
let echo = Arc::new(AtomicBool::new(true));
let mut repl = crate::repl::Repl::new(&xns, echo.clone());
let mut update_repl = false;
let mut was_callback = false;
let mut history_index: isize = 0;
#[cfg(feature = "usb")]
let usb = UsbHid::new();
let mut input = String::new();
@ -48,8 +49,9 @@ fn shell() {
match console_op {
Some(ConsoleOp::Keypress) => msg_scalar_unpack!(msg, k1, _k2, _k3, _k4, {
let k = char::from_u32(k1 as u32).unwrap_or('\u{0000}');
#[cfg(feature = "usb")]
usb.serial_send(&[k1 as u8]).ok();
if echo.load(std::sync::atomic::Ordering::SeqCst) {
usb.serial_send(&[k1 as u8]).ok();
}
if k1 == 0x08 {
// backspace character
input.pop(); // returns None if empty