You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've been experiencing an intermittent hang. My tasks awaiting an embassy-timeTimer stop waking up, while the rest of my tasks continue to function as normal. In addition, causing a new task to await a Timer unfreezes the time driver.
By exposing some of the internals of embassy-rp's time-driver, I was able to see the state of the timer queue after my system had hung:
Debug:TimerDebug{current_time:2637680334,// Result of reading the TIMERRAWH/L registerfire_time:1703154155,// ALARM0's fire timearmed:false,// ALARM0's armed bit in the ARMED registerenabled:true,// ALARM0's interrupt enable bit in the INTE registertimer_queue:[TaskData{state:1,// The Task's state u8loc:536880272,// The memory location of the TaskHeaderexpires_at:1703173985,},TaskData{state:1,loc:536880208,expires_at:1703253822,},TaskData{state:1,loc:536880448,expires_at:1703154155,},],}
The fact that the alarm was not armed made me think I was looking for a race condition in the timer queue's implementation. I believe the offending code is here, in the IRQ itself:
// This can happen if it was set more than 2^32 us in the future.
TIMER.alarm(n).write_value(timestamp asu32);
}
});
// clear the irq
TIMER.intr().write(|w| w.set_alarm(n,true));
}
(Comments beginning with % are mine)
fncheck_alarm(&self){let n = 0;
critical_section::with(|cs| {let alarm = &self.alarms.borrow(cs);let timestamp = alarm.timestamp.get();// % Lets say that the current timestamp has elapsedif timestamp <= self.now(){// % Trigger alarm is called, which sets the next alarmself.trigger_alarm(cs)}else{// Not elapsed, arm it again.// This can happen if it was set more than 2^32 us in the future.TIMER.alarm(n).write_value(timestamp asu32);}});// % set_alarm does check to make sure that the alarm has not// % elapsed by the time has finished setting it, but if the alarm was very// % nearly about to expire, it could go off here, and the interrupt// % is clobbered by the next line// clear the irqTIMER.intr().write(|w| w.set_alarm(n,true));}
I think the fix would be to check that the alarm is still armed before returning from the IRQ, and if it is not, it should circle back and set a new one. I'm very willing to make a PR to address this, but I want to get input on whether maintainer's think this is an issue or not first.
The text was updated successfully, but these errors were encountered:
I've been experiencing an intermittent hang. My tasks awaiting an
embassy-time
Timer
stop waking up, while the rest of my tasks continue to function as normal. In addition, causing a new task to await a Timer unfreezes the time driver.By exposing some of the internals of
embassy-rp
'stime-driver
, I was able to see the state of the timer queue after my system had hung:The fact that the alarm was not armed made me think I was looking for a race condition in the timer queue's implementation. I believe the offending code is here, in the IRQ itself:
embassy/embassy-rp/src/time_driver.rs
Lines 86 to 102 in e8ec586
(Comments beginning with % are mine)
I think the fix would be to check that the alarm is still armed before returning from the IRQ, and if it is not, it should circle back and set a new one. I'm very willing to make a PR to address this, but I want to get input on whether maintainer's think this is an issue or not first.
The text was updated successfully, but these errors were encountered: