Fix Cc::wait never resolving and refactor some APIs

I think the interrupt was getting immediately re-triggered as soon as the handler exited, so I disabled the interrupt in the handler.
This commit is contained in:
Liam Murphy 2021-06-29 10:33:41 +10:00
parent 02781ed744
commit e7addf094b
3 changed files with 49 additions and 67 deletions

View file

@ -82,7 +82,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
let r = U::regs(); let r = U::regs();
let timer = Timer::new_irqless(timer); let mut timer = Timer::new_irqless(timer);
rxd.conf().write(|w| w.input().connect().drive().h0h1()); rxd.conf().write(|w| w.input().connect().drive().h0h1());
r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) }); r.psel.rxd.write(|w| unsafe { w.bits(rxd.psel_bits()) });
@ -137,9 +137,9 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
let timeout = 0x8000_0000 / (config.baudrate as u32 / 40); let timeout = 0x8000_0000 / (config.baudrate as u32 / 40);
timer.set_frequency(Frequency::F16MHz); timer.set_frequency(Frequency::F16MHz);
timer.cc0().set(timeout); timer.cc(0).write(timeout);
timer.cc0().short_compare_clear(); timer.cc(0).short_compare_clear();
timer.cc0().short_compare_stop(); timer.cc(0).short_compare_stop();
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
@ -148,7 +148,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
ppi_ch1.enable(); ppi_ch1.enable();
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
ppi_ch2.set_event(timer.cc0().event_compare()); ppi_ch2.set_event(timer.cc(0).event_compare());
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
ppi_ch2.enable(); ppi_ch2.enable();
@ -180,7 +180,7 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
let r = U::regs(); let r = U::regs();
let timeout = 0x8000_0000 / (baudrate as u32 / 40); let timeout = 0x8000_0000 / (baudrate as u32 / 40);
state.timer.cc0().set(timeout); state.timer.cc(0).write(timeout);
state.timer.clear(); state.timer.clear();
r.baudrate.write(|w| w.baudrate().variant(baudrate)); r.baudrate.write(|w| w.baudrate().variant(baudrate));

View file

@ -115,7 +115,7 @@ impl<'d, T: Instance> Timer<'d, T> {
// TODO: is there a reason someone would want to set this lower? // TODO: is there a reason someone would want to set this lower?
regs.bitmode.write(|w| w.bitmode()._32bit()); regs.bitmode.write(|w| w.bitmode()._32bit());
let this = Self { let mut this = Self {
phantom: PhantomData, phantom: PhantomData,
}; };
@ -125,14 +125,13 @@ impl<'d, T: Instance> Timer<'d, T> {
// Initialize the counter at 0. // Initialize the counter at 0.
this.clear(); this.clear();
// Initialize all the shorts as disabled.
for n in 0..T::CCS { for n in 0..T::CCS {
let cc = Cc::<T> { let cc = this.cc(n);
n, // Initialize all the shorts as disabled.
phantom: PhantomData,
};
cc.unshort_compare_clear(); cc.unshort_compare_clear();
cc.unshort_compare_stop(); cc.unshort_compare_stop();
// Initialize the CC registers as 0.
cc.write(0);
} }
this this
@ -196,57 +195,36 @@ impl<'d, T: Instance> Timer<'d, T> {
.events_compare() .events_compare()
.is_generated() .is_generated()
{ {
// Clear the interrupt, otherwise the interrupt will be repeatedly raised as soon as the interrupt handler exits.
// We can't clear the event, because it's used to poll whether the future is done or still pending.
regs.intenclr.write(|w| match n {
0 => w.compare0().clear(),
1 => w.compare1().clear(),
2 => w.compare2().clear(),
3 => w.compare3().clear(),
4 => w.compare4().clear(),
5 => w.compare5().clear(),
_ => unreachable!("No timers have more than 6 CC registers"),
});
T::waker(n).wake(); T::waker(n).wake();
} }
} }
} }
/// Returns the 0th CC register. /// Returns this timer's `n`th CC register.
pub fn cc0<'a>(&'a self) -> Cc<'a, T> { ///
Cc { /// # Panics
n: 0, /// Panics if `n` >= the number of CC registers this timer has (4 for a normal timer, 6 for an extended timer).
phantom: PhantomData, pub fn cc(&mut self, n: usize) -> Cc<T> {
if n >= T::CCS {
panic!(
"Cannot get CC register {} of timer with {} CC registers.",
n,
T::CCS
);
} }
}
/// Returns the 1st CC register.
pub fn cc1<'a>(&'a self) -> Cc<'a, T> {
Cc { Cc {
n: 1, n,
phantom: PhantomData,
}
}
/// Returns the 2nd CC register.
pub fn cc2<'a>(&'a self) -> Cc<'a, T> {
Cc {
n: 2,
phantom: PhantomData,
}
}
/// Returns the 3rd CC register.
pub fn cc3<'a>(&'a self) -> Cc<'a, T> {
Cc {
n: 3,
phantom: PhantomData,
}
}
}
impl<'d, T: ExtendedInstance> Timer<'d, T> {
/// Returns the 4th CC register.
pub fn cc4<'a>(&'a self) -> Cc<'a, T> {
Cc {
n: 4,
phantom: PhantomData,
}
}
/// Returns the 5th CC register.
pub fn cc5<'a>(&'a self) -> Cc<'a, T> {
Cc {
n: 5,
phantom: PhantomData, phantom: PhantomData,
} }
} }
@ -266,14 +244,14 @@ pub struct Cc<'a, T: Instance> {
impl<'a, T: Instance> Cc<'a, T> { impl<'a, T: Instance> Cc<'a, T> {
/// Get the current value stored in the register. /// Get the current value stored in the register.
pub fn value(&self) -> u32 { pub fn read(&self) -> u32 {
T::regs().cc[self.n].read().cc().bits() T::regs().cc[self.n].read().cc().bits()
} }
/// Set the value stored in the register. /// Set the value stored in the register.
/// ///
/// `event_compare` will fire when the timer's counter reaches this value. /// `event_compare` will fire when the timer's counter reaches this value.
pub fn set(&self, value: u32) { pub fn write(&self, value: u32) {
// SAFETY: there are no invalid values for the CC register. // SAFETY: there are no invalid values for the CC register.
T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) }) T::regs().cc[self.n].write(|w| unsafe { w.cc().bits(value) })
} }
@ -281,7 +259,7 @@ impl<'a, T: Instance> Cc<'a, T> {
/// Capture the current value of the timer's counter in this register, and return it. /// Capture the current value of the timer's counter in this register, and return it.
pub fn capture(&self) -> u32 { pub fn capture(&self) -> u32 {
T::regs().tasks_capture[self.n].write(|w| w.tasks_capture().trigger()); T::regs().tasks_capture[self.n].write(|w| w.tasks_capture().trigger());
self.value() self.read()
} }
/// Returns this CC register's CAPTURE task, for use with PPI. /// Returns this CC register's CAPTURE task, for use with PPI.
@ -359,7 +337,9 @@ impl<'a, T: Instance> Cc<'a, T> {
} }
/// Wait until the timer's counter reaches the value stored in this register. /// Wait until the timer's counter reaches the value stored in this register.
pub async fn wait(&self) { ///
/// This requires a mutable reference so that this task's waker cannot be overwritten by a second call to `wait`.
pub async fn wait(&mut self) {
let regs = T::regs(); let regs = T::regs();
// Enable the interrupt for this CC's COMPARE event. // Enable the interrupt for this CC's COMPARE event.
@ -394,6 +374,8 @@ impl<'a, T: Instance> Cc<'a, T> {
.events_compare() .events_compare()
.is_generated() .is_generated()
{ {
// Reset the register for next time
regs.events_compare[self.n].write(|w| w.events_compare().not_generated());
Poll::Ready(()) Poll::Ready(())
} else { } else {
Poll::Pending Poll::Pending
@ -401,7 +383,7 @@ impl<'a, T: Instance> Cc<'a, T> {
}) })
.await; .await;
// Trigger the interrupt to be disabled. // The interrupt was already disabled in the interrupt handler, so there's no need to disable it again.
drop(on_drop); on_drop.defuse();
} }
} }

View file

@ -318,7 +318,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
) -> Self { ) -> Self {
let baudrate = config.baudrate; let baudrate = config.baudrate;
let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config); let uarte = Uarte::new(uarte, irq, rxd, txd, cts, rts, config);
let timer = Timer::new_irqless(timer); let mut timer = Timer::new_irqless(timer);
unborrow!(ppi_ch1, ppi_ch2); unborrow!(ppi_ch1, ppi_ch2);
@ -333,9 +333,9 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
let timeout = 0x8000_0000 / (baudrate as u32 / 40); let timeout = 0x8000_0000 / (baudrate as u32 / 40);
timer.set_frequency(Frequency::F16MHz); timer.set_frequency(Frequency::F16MHz);
timer.cc0().set(timeout); timer.cc(0).write(timeout);
timer.cc0().short_compare_clear(); timer.cc(0).short_compare_clear();
timer.cc0().short_compare_stop(); timer.cc(0).short_compare_stop();
let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable()); let mut ppi_ch1 = Ppi::new(ppi_ch1.degrade_configurable());
ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy)); ppi_ch1.set_event(Event::from_reg(&r.events_rxdrdy));
@ -344,7 +344,7 @@ impl<'d, U: Instance, T: TimerInstance> UarteWithIdle<'d, U, T> {
ppi_ch1.enable(); ppi_ch1.enable();
let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable()); let mut ppi_ch2 = Ppi::new(ppi_ch2.degrade_configurable());
ppi_ch2.set_event(timer.cc0().event_compare()); ppi_ch2.set_event(timer.cc(0).event_compare());
ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx)); ppi_ch2.set_task(Task::from_reg(&r.tasks_stoprx));
ppi_ch2.enable(); ppi_ch2.enable();