This repository has been archived on 2024-06-16. You can view files and clone it, but cannot push or open issues or pull requests.
va108xx-hal/examples/cascade.rs
Robin Mueller f376a43f41
Some checks failed
Rust/va108xx-hal/pipeline/head There was a failure building this commit
Major refactoring
- Improved IRQ handling, which makes most unsafe unmask operations
  in user code absolete
- Add first UART RX handlers which use an IRQ
2021-12-19 14:18:10 +01:00

137 lines
4.5 KiB
Rust

//! Simple Cascade example
//!
//! A timer will be periodically started which starts another timer via the cascade feature.
//! This timer will then start another timer with the cascade feature as well.
#![no_main]
#![no_std]
use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use cortex_m_rt::entry;
use panic_rtt_target as _;
use rtt_target::{rprintln, rtt_init_print};
use va108xx_hal::{
pac::{self, interrupt, TIM4, TIM5},
prelude::*,
timer::{
default_ms_irq_handler, set_up_ms_delay_provider, CascadeCtrl, CascadeSource,
CountDownTimer, Event, IrqCfg,
},
};
static CSD_TGT_1: Mutex<RefCell<Option<CountDownTimer<TIM4>>>> = Mutex::new(RefCell::new(None));
static CSD_TGT_2: Mutex<RefCell<Option<CountDownTimer<TIM5>>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
rtt_init_print!();
rprintln!("-- VA108xx Cascade example application--");
let mut dp = pac::Peripherals::take().unwrap();
let mut delay = set_up_ms_delay_provider(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM0);
// Will be started periodically to trigger a cascade
let mut cascade_triggerer =
CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM3).auto_disable(true);
cascade_triggerer.listen(
Event::TimeOut,
IrqCfg::new(va108xx::Interrupt::OC1, true, false),
Some(&mut dp.IRQSEL),
Some(&mut dp.SYSCONFIG),
);
// First target for cascade
let mut cascade_target_1 =
CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM4).auto_deactivate(true);
cascade_target_1
.cascade_0_source(CascadeSource::TimBase, Some(3))
.expect("Configuring cascade source for TIM4 failed");
let mut csd_cfg = CascadeCtrl::default();
csd_cfg.enb_start_src_csd0 = true;
// Use trigger mode here
csd_cfg.trg_csd0 = true;
cascade_target_1.cascade_control(csd_cfg);
// Normally it should already be sufficient to activate IRQ in the CTRL
// register but a full interrupt is use here to display print output when
// the timer expires
cascade_target_1.listen(
Event::TimeOut,
IrqCfg::new(va108xx::Interrupt::OC2, true, false),
Some(&mut dp.IRQSEL),
Some(&mut dp.SYSCONFIG),
);
// The counter will only activate when the cascade signal is coming in so
// it is okay to call start here to set the reset value
cascade_target_1.start(1.hz());
// Activated by first cascade target
let mut cascade_target_2 =
CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM5).auto_deactivate(true);
// Set TIM4 as cascade source
cascade_target_2
.cascade_1_source(CascadeSource::TimBase, Some(4))
.expect("Configuring cascade source for TIM5 failed");
csd_cfg = CascadeCtrl::default();
csd_cfg.enb_start_src_csd1 = true;
// Use trigger mode here
csd_cfg.trg_csd1 = true;
cascade_target_2.cascade_control(csd_cfg);
// Normally it should already be sufficient to activate IRQ in the CTRL
// register but a full interrupt is use here to display print output when
// the timer expires
cascade_target_2.listen(
Event::TimeOut,
IrqCfg::new(va108xx::Interrupt::OC3, true, false),
Some(&mut dp.IRQSEL),
Some(&mut dp.SYSCONFIG),
);
// The counter will only activate when the cascade signal is coming in so
// it is okay to call start here to set the reset value
cascade_target_2.start(1.hz());
// Unpend all IRQs
unsafe {
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC0);
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC1);
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC2);
cortex_m::peripheral::NVIC::unmask(pac::Interrupt::OC3);
}
// Make both cascade targets accessible from the IRQ handler with the Mutex dance
cortex_m::interrupt::free(|cs| {
CSD_TGT_1.borrow(cs).replace(Some(cascade_target_1));
CSD_TGT_2.borrow(cs).replace(Some(cascade_target_2));
});
loop {
rprintln!("-- Triggering cascade in 0.5 seconds --");
cascade_triggerer.start(2.hz());
delay.delay_ms(5000_u16);
}
}
#[interrupt]
fn OC0() {
default_ms_irq_handler()
}
#[interrupt]
fn OC1() {
static mut IDX: u32 = 0;
rprintln!("{}: Cascade triggered timed out", IDX);
*IDX += 1;
}
#[interrupt]
fn OC2() {
static mut IDX: u32 = 0;
rprintln!("{}: First cascade target timed out", IDX);
*IDX += 1;
}
#[interrupt]
fn OC3() {
static mut IDX: u32 = 0;
rprintln!("{}: Second cascade target timed out", IDX);
*IDX += 1;
}