//! Nesting claims and how the preemption threshold works //! //! If you run this program you'll hit the breakpoints as indicated by the //! letters in the comments: A, then B, then C, etc. #![deny(unsafe_code)] #![feature(const_fn)] #![feature(proc_macro)] #![no_std] #[macro_use(task)] extern crate cortex_m_rtfm as rtfm; extern crate stm32f103xx; use stm32f103xx::Interrupt; use rtfm::{app, Resource, Threshold}; app! { device: stm32f103xx, resources: { static LOW: u64 = 0; static HIGH: u64 = 0; }, tasks: { EXTI0: { enabled: true, priority: 1, resources: [LOW, HIGH], }, EXTI1: { enabled: true, priority: 2, resources: [LOW], }, EXTI2: { enabled: true, priority: 3, resources: [HIGH], }, }, } fn init(_p: init::Peripherals, _r: init::Resources) {} fn idle() -> ! { // sets task `exti0` as pending // // because `exti0` has higher priority than `idle` it will be executed // immediately rtfm::set_pending(Interrupt::EXTI0); // ~> exti0 loop { rtfm::wfi(); } } task!(EXTI0, exti0); fn exti0(t: &mut Threshold, r: EXTI0::Resources) { // because this task has a priority of 1 the preemption threshold is also 1 let mut low = r.LOW; let mut high = r.HIGH; // A rtfm::bkpt(); // because `exti1` has higher priority than `exti0` it can preempt it rtfm::set_pending(Interrupt::EXTI1); // ~> exti1 // a claim creates a critical section low.claim_mut(t, |_low, t| { // this claim increases the preemption threshold to 2 // just high enough to not race with task `exti1` for access to the // `LOW` resource // C rtfm::bkpt(); // now `exti1` can't preempt this task because its priority is equal to // the current preemption threshold rtfm::set_pending(Interrupt::EXTI1); // but `exti2` can, because its priority is higher than the current // preemption threshold rtfm::set_pending(Interrupt::EXTI2); // ~> exti2 // E rtfm::bkpt(); // claims can be nested high.claim_mut(t, |_high, _| { // This claim increases the preemption threshold to 3 // now `exti2` can't preempt this task rtfm::set_pending(Interrupt::EXTI2); // F rtfm::bkpt(); }); // upon leaving the critical section the preemption threshold drops to 2 // and `exti2` immediately preempts this task // ~> exti2 }); // once again the preemption threshold drops to 1 // now the pending `exti1` can preempt this task // ~> exti1 } task!(EXTI1, exti1); fn exti1(_t: &mut Threshold, _r: EXTI1::Resources) { // B, H rtfm::bkpt(); } task!(EXTI2, exti2); fn exti2(_t: &mut Threshold, _r: EXTI2::Resources) { // D, G rtfm::bkpt(); }