Merge pull request #25 from robamu-org/mueller/cascade
added cascade example
This commit is contained in:
commit
470346a019
10
CHANGELOG.md
10
CHANGELOG.md
@ -6,6 +6,16 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
|
## [unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- TIM Cascade example
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `CountDownTimer` new function now expects an `impl Into<Hertz>` instead of `Hertz`
|
||||||
|
|
||||||
## [0.2.3]
|
## [0.2.3]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -21,7 +21,7 @@ once_cell = { version = "1.8.0", default-features = false }
|
|||||||
libm = "0.2.1"
|
libm = "0.2.1"
|
||||||
|
|
||||||
[dependencies.va108xx]
|
[dependencies.va108xx]
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
rt = ["va108xx/rt"]
|
rt = ["va108xx/rt"]
|
||||||
@ -51,3 +51,7 @@ required-features = ["rt"]
|
|||||||
[[example]]
|
[[example]]
|
||||||
name = "pwm"
|
name = "pwm"
|
||||||
required-features = ["rt"]
|
required-features = ["rt"]
|
||||||
|
|
||||||
|
[[example]]
|
||||||
|
name = "cascade"
|
||||||
|
required-features = ["rt"]
|
||||||
|
143
examples/cascade.rs
Normal file
143
examples/cascade.rs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
//! 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_timer, CascadeCtrl, CascadeSource, CountDownTimer, Delay,
|
||||||
|
Event,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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 timer = set_up_ms_timer(
|
||||||
|
&mut dp.SYSCONFIG,
|
||||||
|
&mut dp.IRQSEL,
|
||||||
|
50.mhz().into(),
|
||||||
|
dp.TIM0,
|
||||||
|
pac::Interrupt::OC0,
|
||||||
|
);
|
||||||
|
let mut delay = Delay::new(timer);
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
&mut dp.SYSCONFIG,
|
||||||
|
&mut dp.IRQSEL,
|
||||||
|
va108xx::Interrupt::OC1,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 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,
|
||||||
|
&mut dp.SYSCONFIG,
|
||||||
|
&mut dp.IRQSEL,
|
||||||
|
va108xx::Interrupt::OC2,
|
||||||
|
);
|
||||||
|
// 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,
|
||||||
|
&mut dp.SYSCONFIG,
|
||||||
|
&mut dp.IRQSEL,
|
||||||
|
va108xx::Interrupt::OC3,
|
||||||
|
);
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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;
|
||||||
|
}
|
@ -139,7 +139,7 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Application logic
|
// Application logic
|
||||||
let mut delay_tim = CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz().into(), dp.TIM1);
|
let mut delay_tim = CountDownTimer::new(&mut dp.SYSCONFIG, 50.mhz(), dp.TIM1);
|
||||||
loop {
|
loop {
|
||||||
match SPI_BUS_SEL {
|
match SPI_BUS_SEL {
|
||||||
SpiBusSelect::SpiAPortA | SpiBusSelect::SpiAPortB => {
|
SpiBusSelect::SpiAPortA | SpiBusSelect::SpiAPortB => {
|
||||||
|
199
src/timer.rs
199
src/timer.rs
@ -42,8 +42,61 @@ pub enum Event {
|
|||||||
TimeOut,
|
TimeOut,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, PartialEq, Copy, Clone)]
|
||||||
|
pub struct CascadeCtrl {
|
||||||
|
/// Enable Cascade 0 signal active as a requirement for counting
|
||||||
|
pub enb_start_src_csd0: bool,
|
||||||
|
/// Invert Cascade 0, making it active low
|
||||||
|
pub inv_csd0: bool,
|
||||||
|
/// Enable Cascade 1 signal active as a requirement for counting
|
||||||
|
pub enb_start_src_csd1: bool,
|
||||||
|
/// Invert Cascade 1, making it active low
|
||||||
|
pub inv_csd1: bool,
|
||||||
|
/// Specify required operation if both Cascade 0 and Cascade 1 are active.
|
||||||
|
/// 0 is a logical AND of both cascade signals, 1 is a logical OR
|
||||||
|
pub dual_csd_op: bool,
|
||||||
|
/// Enable trigger mode for Cascade 0. In trigger mode, couting will start with the selected
|
||||||
|
/// cascade signal active, but once the counter is active, cascade control will be ignored
|
||||||
|
pub trg_csd0: bool,
|
||||||
|
/// Trigger mode, identical to [`trg_csd0`](CascadeCtrl) but for Cascade 1
|
||||||
|
pub trg_csd1: bool,
|
||||||
|
/// Enable Cascade 2 signal active as a requirement to stop counting. This mode is similar
|
||||||
|
/// to the REQ_STOP control bit, but signalled by a Cascade source
|
||||||
|
pub enb_stop_src_csd2: bool,
|
||||||
|
/// Invert Cascade 2, making it active low
|
||||||
|
pub inv_csd2: bool,
|
||||||
|
/// The counter is automatically disabled if the corresponding Cascade 2 level-sensitive input
|
||||||
|
/// souce is active when the count reaches 0. If the counter is not 0, the cascade control is
|
||||||
|
/// ignored
|
||||||
|
pub trg_csd2: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum CascadeSel {
|
||||||
|
Csd0 = 0,
|
||||||
|
Csd1 = 1,
|
||||||
|
Csd2 = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The numbers are the base numbers for bundles like PORTA, PORTB or TIM
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum CascadeSource {
|
||||||
|
PortABase = 0,
|
||||||
|
PortBBase = 32,
|
||||||
|
TimBase = 64,
|
||||||
|
RamSbe = 96,
|
||||||
|
RamMbe = 97,
|
||||||
|
RomSbe = 98,
|
||||||
|
RomMbe = 99,
|
||||||
|
Txev = 100,
|
||||||
|
ClockDividerBase = 120,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum TimerErrors {
|
pub enum TimerErrors {
|
||||||
Canceled,
|
Canceled,
|
||||||
|
/// Invalid input for Cascade source
|
||||||
|
InvalidCsdSourceInput,
|
||||||
}
|
}
|
||||||
|
|
||||||
//==================================================================================================
|
//==================================================================================================
|
||||||
@ -350,13 +403,84 @@ unsafe impl<TIM: ValidTim> TimRegInterface for CountDownTimer<TIM> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! csd_sel {
|
||||||
|
($func_name:ident, $csd_reg:ident) => {
|
||||||
|
/// Configure the Cascade sources
|
||||||
|
pub fn $func_name(
|
||||||
|
&mut self,
|
||||||
|
src: CascadeSource,
|
||||||
|
id: Option<u8>,
|
||||||
|
) -> Result<(), TimerErrors> {
|
||||||
|
let mut id_num = 0;
|
||||||
|
if let CascadeSource::PortABase
|
||||||
|
| CascadeSource::PortBBase
|
||||||
|
| CascadeSource::ClockDividerBase
|
||||||
|
| CascadeSource::TimBase = src
|
||||||
|
{
|
||||||
|
if id.is_none() {
|
||||||
|
return Err(TimerErrors::InvalidCsdSourceInput);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if id.is_some() {
|
||||||
|
id_num = id.unwrap();
|
||||||
|
}
|
||||||
|
match src {
|
||||||
|
CascadeSource::PortABase => {
|
||||||
|
if id_num > 55 {
|
||||||
|
return Err(TimerErrors::InvalidCsdSourceInput);
|
||||||
|
}
|
||||||
|
self.tim.reg().$csd_reg.write(|w| unsafe {
|
||||||
|
w.cassel().bits(CascadeSource::PortABase as u8 + id_num)
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CascadeSource::PortBBase => {
|
||||||
|
if id_num > 23 {
|
||||||
|
return Err(TimerErrors::InvalidCsdSourceInput);
|
||||||
|
}
|
||||||
|
self.tim.reg().$csd_reg.write(|w| unsafe {
|
||||||
|
w.cassel().bits(CascadeSource::PortBBase as u8 + id_num)
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CascadeSource::TimBase => {
|
||||||
|
if id_num > 23 {
|
||||||
|
return Err(TimerErrors::InvalidCsdSourceInput);
|
||||||
|
}
|
||||||
|
self.tim.reg().$csd_reg.write(|w| unsafe {
|
||||||
|
w.cassel().bits(CascadeSource::TimBase as u8 + id_num)
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
CascadeSource::ClockDividerBase => {
|
||||||
|
if id_num > 7 {
|
||||||
|
return Err(TimerErrors::InvalidCsdSourceInput);
|
||||||
|
}
|
||||||
|
self.tim.reg().cascade0.write(|w| unsafe {
|
||||||
|
w.cassel()
|
||||||
|
.bits(CascadeSource::ClockDividerBase as u8 + id_num)
|
||||||
|
});
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.tim
|
||||||
|
.reg()
|
||||||
|
.$csd_reg
|
||||||
|
.write(|w| unsafe { w.cassel().bits(src as u8) });
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl<TIM: ValidTim> CountDownTimer<TIM> {
|
impl<TIM: ValidTim> CountDownTimer<TIM> {
|
||||||
/// Configures a TIM peripheral as a periodic count down timer
|
/// Configures a TIM peripheral as a periodic count down timer
|
||||||
pub fn new(syscfg: &mut SYSCONFIG, sys_clk: Hertz, tim: TIM) -> Self {
|
pub fn new(syscfg: &mut SYSCONFIG, sys_clk: impl Into<Hertz>, tim: TIM) -> Self {
|
||||||
enable_tim_clk(syscfg, TIM::TIM_ID);
|
enable_tim_clk(syscfg, TIM::TIM_ID);
|
||||||
let cd_timer = CountDownTimer {
|
let cd_timer = CountDownTimer {
|
||||||
tim: unsafe { TimRegister::new(tim) },
|
tim: unsafe { TimRegister::new(tim) },
|
||||||
sys_clk,
|
sys_clk: sys_clk.into(),
|
||||||
rst_val: 0,
|
rst_val: 0,
|
||||||
curr_freq: 0.hz(),
|
curr_freq: 0.hz(),
|
||||||
listening: false,
|
listening: false,
|
||||||
@ -380,7 +504,7 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
Event::TimeOut => {
|
Event::TimeOut => {
|
||||||
enable_peripheral_clock(syscfg, PeripheralClocks::Irqsel);
|
enable_peripheral_clock(syscfg, PeripheralClocks::Irqsel);
|
||||||
irqsel.tim[TIM::TIM_ID as usize].write(|w| unsafe { w.bits(interrupt as u32) });
|
irqsel.tim[TIM::TIM_ID as usize].write(|w| unsafe { w.bits(interrupt as u32) });
|
||||||
self.tim.reg().ctrl.modify(|_, w| w.irq_enb().set_bit());
|
self.enable_interrupt();
|
||||||
self.listening = true;
|
self.listening = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -391,12 +515,22 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
Event::TimeOut => {
|
Event::TimeOut => {
|
||||||
enable_peripheral_clock(syscfg, PeripheralClocks::Irqsel);
|
enable_peripheral_clock(syscfg, PeripheralClocks::Irqsel);
|
||||||
irqsel.tim[TIM::TIM_ID as usize].write(|w| unsafe { w.bits(IRQ_DST_NONE) });
|
irqsel.tim[TIM::TIM_ID as usize].write(|w| unsafe { w.bits(IRQ_DST_NONE) });
|
||||||
self.tim.reg().ctrl.modify(|_, w| w.irq_enb().clear_bit());
|
self.disable_interrupt();
|
||||||
self.listening = false;
|
self.listening = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn enable_interrupt(&mut self) {
|
||||||
|
self.tim.reg().ctrl.modify(|_, w| w.irq_enb().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn disable_interrupt(&mut self) {
|
||||||
|
self.tim.reg().ctrl.modify(|_, w| w.irq_enb().clear_bit());
|
||||||
|
}
|
||||||
|
|
||||||
pub fn release(self, syscfg: &mut SYSCONFIG) -> TIM {
|
pub fn release(self, syscfg: &mut SYSCONFIG) -> TIM {
|
||||||
self.tim.reg().ctrl.write(|w| w.enable().clear_bit());
|
self.tim.reg().ctrl.write(|w| w.enable().clear_bit());
|
||||||
syscfg
|
syscfg
|
||||||
@ -405,6 +539,28 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
self.tim.release()
|
self.tim.release()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load the count down timer with a timeout but do not start it.
|
||||||
|
pub fn load(&mut self, timeout: impl Into<Hertz>) {
|
||||||
|
self.tim.reg().ctrl.modify(|_, w| w.enable().clear_bit());
|
||||||
|
self.curr_freq = timeout.into();
|
||||||
|
self.rst_val = self.sys_clk.0 / self.curr_freq.0;
|
||||||
|
unsafe {
|
||||||
|
self.tim.reg().rst_value.write(|w| w.bits(self.rst_val));
|
||||||
|
self.tim.reg().cnt_value.write(|w| w.bits(self.rst_val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn enable(&mut self) {
|
||||||
|
self.tim.reg().ctrl.modify(|_, w| w.enable().set_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn disable(&mut self) {
|
||||||
|
self.tim.reg().ctrl.modify(|_, w| w.enable().clear_bit());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable the counter, setting both enable and active bit to 0
|
||||||
pub fn auto_disable(self, enable: bool) -> Self {
|
pub fn auto_disable(self, enable: bool) -> Self {
|
||||||
if enable {
|
if enable {
|
||||||
self.tim
|
self.tim
|
||||||
@ -420,6 +576,10 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This option only applies when the Auto-Disable functionality is 0.
|
||||||
|
///
|
||||||
|
/// The active bit is changed to 0 when count reaches 0, but the counter stays
|
||||||
|
/// enabled. When Auto-Disable is 1, Auto-Deactivate is implied
|
||||||
pub fn auto_deactivate(self, enable: bool) -> Self {
|
pub fn auto_deactivate(self, enable: bool) -> Self {
|
||||||
if enable {
|
if enable {
|
||||||
self.tim
|
self.tim
|
||||||
@ -435,6 +595,26 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Configure the cascade parameters
|
||||||
|
pub fn cascade_control(&mut self, ctrl: CascadeCtrl) {
|
||||||
|
self.tim.reg().csd_ctrl.write(|w| {
|
||||||
|
w.csden0().bit(ctrl.enb_start_src_csd0);
|
||||||
|
w.csdinv0().bit(ctrl.inv_csd0);
|
||||||
|
w.csden1().bit(ctrl.enb_start_src_csd1);
|
||||||
|
w.csdinv1().bit(ctrl.inv_csd1);
|
||||||
|
w.dcasop().bit(ctrl.dual_csd_op);
|
||||||
|
w.csdtrg0().bit(ctrl.trg_csd0);
|
||||||
|
w.csdtrg1().bit(ctrl.trg_csd1);
|
||||||
|
w.csden2().bit(ctrl.enb_stop_src_csd2);
|
||||||
|
w.csdinv2().bit(ctrl.inv_csd2);
|
||||||
|
w.csdtrg2().bit(ctrl.trg_csd2)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
csd_sel!(cascade_0_source, cascade0);
|
||||||
|
csd_sel!(cascade_1_source, cascade1);
|
||||||
|
csd_sel!(cascade_2_source, cascade2);
|
||||||
|
|
||||||
pub fn curr_freq(&self) -> Hertz {
|
pub fn curr_freq(&self) -> Hertz {
|
||||||
self.curr_freq
|
self.curr_freq
|
||||||
}
|
}
|
||||||
@ -448,18 +628,13 @@ impl<TIM: ValidTim> CountDownTimer<TIM> {
|
|||||||
impl<TIM: ValidTim> CountDown for CountDownTimer<TIM> {
|
impl<TIM: ValidTim> CountDown for CountDownTimer<TIM> {
|
||||||
type Time = Hertz;
|
type Time = Hertz;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
fn start<T>(&mut self, timeout: T)
|
fn start<T>(&mut self, timeout: T)
|
||||||
where
|
where
|
||||||
T: Into<Hertz>,
|
T: Into<Hertz>,
|
||||||
{
|
{
|
||||||
self.tim.reg().ctrl.modify(|_, w| w.enable().clear_bit());
|
self.load(timeout);
|
||||||
self.curr_freq = timeout.into();
|
self.enable();
|
||||||
self.rst_val = self.sys_clk.0 / self.curr_freq.0;
|
|
||||||
unsafe {
|
|
||||||
self.tim.reg().rst_value.write(|w| w.bits(self.rst_val));
|
|
||||||
self.tim.reg().cnt_value.write(|w| w.bits(self.rst_val));
|
|
||||||
}
|
|
||||||
self.tim.reg().ctrl.modify(|_, w| w.enable().set_bit());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return `Ok` if the timer has wrapped. Peripheral will automatically clear the
|
/// Return `Ok` if the timer has wrapped. Peripheral will automatically clear the
|
||||||
|
Reference in New Issue
Block a user