diff --git a/emulation/renode.svd b/emulation/renode.svd index cf9ab5389..9d5fc26c1 100644 --- a/emulation/renode.svd +++ b/emulation/renode.svd @@ -3,7 +3,7 @@ litex SOC - + 8 32 @@ -2803,7 +2803,7 @@ again until the interrupt is serviced.]]> SEED1 0x0000 - 0x64af9099 + 0x9878c8f 32 @@ -2818,7 +2818,7 @@ again until the interrupt is serviced.]]> SEED0 0x0004 - 0x108cfc08 + 0x8f844c5 32 diff --git a/services/cb-test-srv/src/api.rs b/services/cb-test-srv/src/api.rs index 32fa0582d..3096a09c2 100644 --- a/services/cb-test-srv/src/api.rs +++ b/services/cb-test-srv/src/api.rs @@ -4,6 +4,7 @@ pub(crate) const SERVER_NAME: &str = "_Callback test server_"; pub(crate) enum Opcode { RegisterTickListener, RegisterReqListener, + UnregisterReqListener, Tick, Req, } diff --git a/services/cb-test-srv/src/lib.rs b/services/cb-test-srv/src/lib.rs index ca3dba75e..5ec94c15f 100644 --- a/services/cb-test-srv/src/lib.rs +++ b/services/cb-test-srv/src/lib.rs @@ -43,12 +43,18 @@ impl CbTestServer { } } pub fn hook_req_callback(&mut self, cb: fn(u32)) -> Result<(), xous::Error> { - log::trace!("hooking req callback"); + log::info!("hooking req callback"); if unsafe{REQ_CB}.is_some() { return Err(xous::Error::MemoryInUse) } unsafe{REQ_CB = Some(cb)}; - if self.req_cb_sid.is_none() { + if let Some(sid) = self.req_cb_sid { + let sid_tuple = sid.to_u32(); + xous::send_message(self.conn, + Message::new_scalar(Opcode::RegisterReqListener.to_usize().unwrap(), + sid_tuple.0 as usize, sid_tuple.1 as usize, sid_tuple.2 as usize, sid_tuple.3 as usize + )).unwrap(); + } else { let sid = xous::create_server().unwrap(); self.req_cb_sid = Some(sid); let sid_tuple = sid.to_u32(); @@ -61,6 +67,10 @@ impl CbTestServer { Ok(()) } pub fn unhook_req_callback(&mut self) -> Result<(), xous::Error> { + log::info!("UNhooking req callback"); + unsafe{REQ_CB = None}; + + /* if let Some(sid) = self.req_cb_sid.take() { // tell my handler thread to quit log::trace!("connect for unhook"); @@ -78,8 +88,14 @@ impl CbTestServer { } } log::trace!("nullifying local state"); - self.req_cb_sid = None; - unsafe{REQ_CB = None}; + self.req_cb_sid = None; */ + if let Some(sid) = self.req_cb_sid { + let sid_tuple = sid.to_u32(); + xous::send_message(self.conn, + Message::new_scalar(Opcode::UnregisterReqListener.to_usize().unwrap(), + sid_tuple.0 as usize, sid_tuple.1 as usize, sid_tuple.2 as usize, sid_tuple.3 as usize + )).unwrap(); + } Ok(()) } } @@ -124,7 +140,7 @@ fn tick_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) { fn req_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) { let sid = xous::SID::from_u32(sid0 as u32, sid1 as u32, sid2 as u32, sid3 as u32); - log::trace!("req callback server started"); + log::info!("req callback server started with SID {:x?}", sid); loop { let msg = xous::receive_message(sid).unwrap(); log::trace!("req callback got msg: {:?}", msg); @@ -134,7 +150,10 @@ fn req_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) { if let Some(cb) = REQ_CB { cb(result as u32) } else { - break; + // we got a callback message after we unregistered + // not fatal, it just means the server may not have received + // our unregistration message in time + continue; } } }), @@ -146,6 +165,6 @@ fn req_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) { } } } - log::trace!("req callback server exiting"); + log::info!("req callback server exiting"); xous::destroy_server(sid).expect("can't destroy my server on exit!"); } \ No newline at end of file diff --git a/services/cb-test-srv/src/main.rs b/services/cb-test-srv/src/main.rs index 229793efb..27f34eae2 100644 --- a/services/cb-test-srv/src/main.rs +++ b/services/cb-test-srv/src/main.rs @@ -26,14 +26,14 @@ fn pump_thread() { loop { xous::send_message(server_conn, xous::Message::new_scalar(Opcode::Tick.to_usize().unwrap(), 0, 0, 0, 0)).expect("couldn't send Tick message"); - ticktimer.sleep_ms(500).expect("couldn't sleep"); + ticktimer.sleep_ms(100).expect("couldn't sleep"); } } #[xous::xous_main] fn shell_main() -> ! { log_server::init_wait().unwrap(); - log::set_max_level(log::LevelFilter::Debug); + log::set_max_level(log::LevelFilter::Info); log::info!("my PID is {}", xous::process::id()); let xns = xous_names::XousNames::new().unwrap(); @@ -43,7 +43,7 @@ fn shell_main() -> ! { log::info!("pump thread started"); let mut tick_cb: [Option; 32] = [None; 32]; - let mut req_cb: [bool; 32] = [false; 32]; + let mut req_cb: [bool; 34] = [false; 34]; let mut ticks = 0; let mut state = 0; @@ -83,21 +83,20 @@ fn shell_main() -> ! { } else { log::error!("cid out of allowable range"); } - /* - let mut found = false; - for entry in req_cb.iter_mut() { - if *entry == None { - *entry = cid; - found = true; - break; - } + }), + Some(Opcode::UnregisterReqListener) => msg_scalar_unpack!(msg, sid0, sid1, sid2, sid3, { + let sid = xous::SID::from_u32(sid0 as _, sid1 as _, sid2 as _, sid3 as _); + let cid = xous::connect(sid).unwrap(); // if the connection already exists, this just looks it up in the table + log::info!("UnregisterReqListener cid {}", cid); + if (cid as usize) < req_cb.len() { + req_cb[cid as usize] = false; + } else { + log::error!("cid out of allowable range"); } - if !found { - log::error!("RegisterTickListener ran out of space registering callback"); - }*/ + unsafe{xous::disconnect(cid).unwrap()}; }), Some(Opcode::Req) => msg_scalar_unpack!(msg, _, _, _, _, { - //log::debug!("req_cb: {:?}", req_cb); + log::debug!("req_cb: {:?}", req_cb); // send results to request listeners for cid in 1..req_cb.len() { // 0 is not a valid connection if req_cb[cid as usize] { diff --git a/services/ime-frontend/src/main.rs b/services/ime-frontend/src/main.rs index 0baf244d4..0727a1fc4 100644 --- a/services/ime-frontend/src/main.rs +++ b/services/ime-frontend/src/main.rs @@ -601,7 +601,7 @@ fn xmain() -> ! { let dbglistener = true; let dbgcanvas = false; log_server::init_wait().unwrap(); - log::set_max_level(log::LevelFilter::Trace); + log::set_max_level(log::LevelFilter::Info); info!("my PID is {}", xous::process::id()); let xns = xous_names::XousNames::new().unwrap(); diff --git a/services/rtc/src/api.rs b/services/rtc/src/api.rs index 272d2db9b..9ec0771e4 100644 --- a/services/rtc/src/api.rs +++ b/services/rtc/src/api.rs @@ -35,6 +35,9 @@ pub(crate) enum Opcode { /// register a callback for the datetime RegisterDateTimeCallback, + /// unregister a callback for the datetime + UnregisterDateTimeCallback, + /// sets the datetime SetDateTime, //(DateTime), diff --git a/services/rtc/src/lib.rs b/services/rtc/src/lib.rs index 2e10d299e..e6a0a9b5f 100644 --- a/services/rtc/src/lib.rs +++ b/services/rtc/src/lib.rs @@ -30,25 +30,14 @@ impl Rtc { buf.lend(self.conn, Opcode::SetDateTime.to_u32().unwrap()).map(|_| ()) } pub fn unhook_rtc_callback(&mut self) -> Result<(), xous::Error> { - if let Some(sid) = self.callback_sid.take() { - // tell my handler thread to quit - log::trace!("connect for unhook"); - let cid = xous::connect(sid).expect("can't connect to CB server for disconnect message"); - log::trace!("sending drop to conn {}", cid); - send_message(cid, - Message::new_scalar(Return::Drop.to_usize().unwrap(), 0, 0, 0, 0) - ).unwrap(); - log::trace!("disconnecting unhook connection"); - unsafe{ - match xous::disconnect(cid) { - Ok(_) => log::trace!("disconnected unhook connection"), - Err(e) => log::error!("unhook rtc got error: {:?}", e), - }; - } - } - log::trace!("nullifying local state"); - self.callback_sid = None; unsafe{RTC_CB = None}; + if let Some(sid) = self.callback_sid { + let sid_tuple = sid.to_u32(); + xous::send_message(self.conn, + Message::new_scalar(Opcode::UnregisterDateTimeCallback.to_usize().unwrap(), + sid_tuple.0 as usize, sid_tuple.1 as usize, sid_tuple.2 as usize, sid_tuple.3 as usize + )).unwrap(); + } Ok(()) } pub fn hook_rtc_callback(&mut self, cb: fn(DateTime)) -> Result<(), xous::Error> { @@ -57,7 +46,13 @@ impl Rtc { return Err(xous::Error::MemoryInUse) } unsafe{RTC_CB = Some(cb)}; - if self.callback_sid.is_none() { + if let Some(sid) = self.callback_sid { + let sid_tuple = sid.to_u32(); + xous::send_message(self.conn, + Message::new_scalar(Opcode::RegisterDateTimeCallback.to_usize().unwrap(), + sid_tuple.0 as usize, sid_tuple.1 as usize, sid_tuple.2 as usize, sid_tuple.3 as usize + )).unwrap(); + } else { let sid = xous::create_server().unwrap(); self.callback_sid = Some(sid); let sid_tuple = sid.to_u32(); @@ -135,7 +130,10 @@ fn rtc_cb_server(sid0: usize, sid1: usize, sid2: usize, sid3: usize) { if let Some(cb) = RTC_CB { cb(dt) } else { - break; + // callback happened after we unregistered + // this is a race condition, but it's also a harmless side effect + // we handle it by just ignoring the message + continue; } } } diff --git a/services/rtc/src/main.rs b/services/rtc/src/main.rs index 6f8e005df..5d3770348 100644 --- a/services/rtc/src/main.rs +++ b/services/rtc/src/main.rs @@ -6,7 +6,7 @@ mod api; use num_traits::{FromPrimitive, ToPrimitive}; use xous_ipc::Buffer; use api::{Return, Opcode, DateTime}; -use xous::{CID, msg_scalar_unpack}; +use xous::msg_scalar_unpack; use core::sync::atomic::{AtomicU32, Ordering}; static CB_TO_MAIN_CONN: AtomicU32 = AtomicU32::new(0); @@ -534,7 +534,7 @@ fn xmain() -> ! { use crate::implementation::Rtc; log_server::init_wait().unwrap(); - log::set_max_level(log::LevelFilter::Trace); + log::set_max_level(log::LevelFilter::Info); log::info!("my PID is {}", xous::process::id()); let xns = xous_names::XousNames::new().unwrap(); @@ -549,7 +549,7 @@ fn xmain() -> ! { let mut rtc = Rtc::new(&xns); let ticktimer = ticktimer_server::Ticktimer::new().expect("can't connect to ticktimer"); - let mut dt_cb_conns: [Option; 32] = [None; 32]; + let mut dt_cb_conns: [bool; 34] = [false; 34]; log::trace!("ready to accept requests"); loop { let msg = xous::receive_message(rtc_sid).unwrap(); @@ -586,33 +586,35 @@ fn xmain() -> ! { }, Some(Opcode::RegisterDateTimeCallback) => msg_scalar_unpack!(msg, sid0, sid1, sid2, sid3, { let sid = xous::SID::from_u32(sid0 as _, sid1 as _, sid2 as _, sid3 as _); - let cid = Some(xous::connect(sid).unwrap()); - let mut found = false; - for entry in dt_cb_conns.iter_mut() { - if *entry == None { - *entry = cid; - found = true; - break; - } - } - if !found { - log::error!("RegisterDateTimeCallback listener ran out of space registering callback"); + let cid = xous::connect(sid).unwrap(); + if (cid as usize) < dt_cb_conns.len() { + dt_cb_conns[cid as usize] = true; } else { - log::trace!("RegisterDateTimeCallback completed"); + // this should "never" happen because we only have up to 32 connections possible per server + log::error!("RegisterDateTimeCallback received a CID out of range"); + } + }), + Some(Opcode::UnregisterDateTimeCallback) => msg_scalar_unpack!(msg, sid0, sid1, sid2, sid3, { + let sid = xous::SID::from_u32(sid0 as _, sid1 as _, sid2 as _, sid3 as _); + let cid = xous::connect(sid).unwrap(); + if (cid as usize) < dt_cb_conns.len() { + dt_cb_conns[cid as usize] = false; + } else { + log::error!("UnregisterDateTimeCallback CID out of allowable range"); } }), Some(Opcode::ResponseDateTime) => { let incoming_buffer = unsafe { Buffer::from_memory_message(msg.body.memory_message().unwrap()) }; let dt = incoming_buffer.to_original::().unwrap(); log::trace!("ResponseDateTime received: {:?}", dt); - for maybe_conn in dt_cb_conns.iter_mut() { - if let Some(conn) = maybe_conn { + for cid in 1..dt_cb_conns.len() { // 0 is not a valid connection + if dt_cb_conns[cid as usize] { let outgoing_buf = Buffer::into_buf(dt).or(Err(xous::Error::InternalError)).unwrap(); - log::trace!("ResponeDateTime sending to {}", *conn); - match outgoing_buf.lend(*conn, Return::ReturnDateTime.to_u32().unwrap()) { + log::trace!("ResponeDateTime sending to {}", cid); + match outgoing_buf.lend(cid as u32, Return::ReturnDateTime.to_u32().unwrap()) { Err(xous::Error::ServerNotFound) => { log::trace!("ServerNotFound, dropping connection"); - *maybe_conn = None + dt_cb_conns[cid] = false; }, Ok(_) => { log::trace!("RespondeDateTime sent successfully"); @@ -667,14 +669,14 @@ fn xmain() -> ! { xous::disconnect(cb_to_main_conn).unwrap(); } } - for entry in dt_cb_conns.iter_mut() { - if let Some(conn) = entry { - xous::send_message(*conn, + for cid in 1..dt_cb_conns.len() { + if dt_cb_conns[cid as usize] { + xous::send_message(cid as u32, xous::Message::new_scalar(Return::Drop.to_usize().unwrap(), 0, 0, 0, 0) ).unwrap(); - unsafe{xous::disconnect(*conn).unwrap();} + unsafe{xous::disconnect(cid as u32).unwrap();} + dt_cb_conns[cid as usize] = false; } - *entry = None; } xns.unregister_server(rtc_sid).unwrap(); xous::destroy_server(rtc_sid).unwrap(); diff --git a/services/shellchat/src/main.rs b/services/shellchat/src/main.rs index 6d3706bfe..f05d5f320 100644 --- a/services/shellchat/src/main.rs +++ b/services/shellchat/src/main.rs @@ -250,7 +250,7 @@ pub(crate) const SERVER_NAME_SHELLCHAT: &str = "_Shell chat application_"; #[xous::xous_main] fn xmain() -> ! { log_server::init_wait().unwrap(); - log::set_max_level(log::LevelFilter::Trace); + log::set_max_level(log::LevelFilter::Info); info!("my PID is {}", xous::process::id()); let xns = xous_names::XousNames::new().unwrap(); diff --git a/svd2utra/examples/soc.svd b/svd2utra/examples/soc.svd index cf9ab5389..9d5fc26c1 100644 --- a/svd2utra/examples/soc.svd +++ b/svd2utra/examples/soc.svd @@ -3,7 +3,7 @@ litex SOC - + 8 32 @@ -2803,7 +2803,7 @@ again until the interrupt is serviced.]]> SEED1 0x0000 - 0x64af9099 + 0x9878c8f 32 @@ -2818,7 +2818,7 @@ again until the interrupt is serviced.]]> SEED0 0x0004 - 0x108cfc08 + 0x8f844c5 32 diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 22de200d8..361888a41 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -98,7 +98,7 @@ fn try_main() -> Result<(), DynError> { &cbtest_pkgs, )?, Some("renode-image-debug") => renode_image(true, &hw_pkgs)?, - Some("run") => run(false, &cbtest_pkgs)?, + Some("run") => run(false, &hw_pkgs)?, Some("hw-image") => build_hw_image(false, env::args().nth(2), &hw_pkgs)?, Some("benchmark") => build_hw_image(false, env::args().nth(2), &benchmark_pkgs)?, Some("fcc-agent") => build_hw_image(false, env::args().nth(2), &fcc_pkgs)?,