fix RTC callbacks

This commit is contained in:
bunnie 2021-04-14 02:58:22 +08:00
parent 1994b730b7
commit 75295485a7
11 changed files with 98 additions and 76 deletions

View file

@ -3,7 +3,7 @@
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" >
<vendor>litex</vendor>
<name>SOC</name>
<description><![CDATA[Litex SoC 2021-04-12 22:13:49]]></description>
<description><![CDATA[Litex SoC 2021-04-12 22:36:11]]></description>
<addressUnitBits>8</addressUnitBits>
<width>32</width>
@ -2803,7 +2803,7 @@ again until the interrupt is serviced.]]></description>
<name>SEED1</name>
<description><![CDATA[Bits 32-63 of `SEED_SEED`. Seed used for the build]]></description>
<addressOffset>0x0000</addressOffset>
<resetValue>0x64af9099</resetValue>
<resetValue>0x9878c8f</resetValue>
<size>32</size>
<fields>
<field>
@ -2818,7 +2818,7 @@ again until the interrupt is serviced.]]></description>
<name>SEED0</name>
<description><![CDATA[Bits 0-31 of `SEED_SEED`.]]></description>
<addressOffset>0x0004</addressOffset>
<resetValue>0x108cfc08</resetValue>
<resetValue>0x8f844c5</resetValue>
<size>32</size>
<fields>
<field>

View file

@ -4,6 +4,7 @@ pub(crate) const SERVER_NAME: &str = "_Callback test server_";
pub(crate) enum Opcode {
RegisterTickListener,
RegisterReqListener,
UnregisterReqListener,
Tick,
Req,
}

View file

@ -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!");
}

View file

@ -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<ScalarCallback>; 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] {

View file

@ -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();

View file

@ -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),

View file

@ -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;
}
}
}

View file

@ -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<CID>; 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::<DateTime, _>().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();

View file

@ -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();

View file

@ -3,7 +3,7 @@
<device schemaVersion="1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" >
<vendor>litex</vendor>
<name>SOC</name>
<description><![CDATA[Litex SoC 2021-04-12 22:13:49]]></description>
<description><![CDATA[Litex SoC 2021-04-12 22:36:11]]></description>
<addressUnitBits>8</addressUnitBits>
<width>32</width>
@ -2803,7 +2803,7 @@ again until the interrupt is serviced.]]></description>
<name>SEED1</name>
<description><![CDATA[Bits 32-63 of `SEED_SEED`. Seed used for the build]]></description>
<addressOffset>0x0000</addressOffset>
<resetValue>0x64af9099</resetValue>
<resetValue>0x9878c8f</resetValue>
<size>32</size>
<fields>
<field>
@ -2818,7 +2818,7 @@ again until the interrupt is serviced.]]></description>
<name>SEED0</name>
<description><![CDATA[Bits 0-31 of `SEED_SEED`.]]></description>
<addressOffset>0x0004</addressOffset>
<resetValue>0x108cfc08</resetValue>
<resetValue>0x8f844c5</resetValue>
<size>32</size>
<fields>
<field>

View file

@ -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)?,