From 9d895a63832336590ce6780ea38825d2e0183573 Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Mon, 15 Feb 2021 21:38:36 -0300 Subject: [PATCH 1/3] Add RTC timer for stm32f4 --- embassy-stm32f4-examples/.cargo/config | 2 +- embassy-stm32f4-examples/Cargo.toml | 4 +- embassy-stm32f4-examples/memory.x | 2 +- embassy-stm32f4-examples/src/bin/rtc_async.rs | 65 ++++ embassy-stm32f4/src/interrupt.rs | 60 +++ embassy-stm32f4/src/lib.rs | 1 + embassy-stm32f4/src/rtc.rs | 364 ++++++++++++++++++ 7 files changed, 494 insertions(+), 4 deletions(-) create mode 100644 embassy-stm32f4-examples/src/bin/rtc_async.rs create mode 100644 embassy-stm32f4/src/rtc.rs diff --git a/embassy-stm32f4-examples/.cargo/config b/embassy-stm32f4-examples/.cargo/config index 707494d6..83685398 100644 --- a/embassy-stm32f4-examples/.cargo/config +++ b/embassy-stm32f4-examples/.cargo/config @@ -1,5 +1,5 @@ [target.'cfg(all(target_arch = "arm", target_os = "none"))'] -runner = "probe-run --chip STM32F411CEUx --defmt" +runner = "probe-run --chip STM32F401CCUx --defmt" rustflags = [ # LLD (shipped with the Rust toolchain) is used as the default linker diff --git a/embassy-stm32f4-examples/Cargo.toml b/embassy-stm32f4-examples/Cargo.toml index e81f85ff..21696437 100644 --- a/embassy-stm32f4-examples/Cargo.toml +++ b/embassy-stm32f4-examples/Cargo.toml @@ -18,7 +18,7 @@ defmt-error = [] [dependencies] embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } -embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4", features = ["stm32f405"] } +embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4", features = ["stm32f401"] } defmt = "0.1.3" defmt-rtt = "0.1.0" @@ -27,6 +27,6 @@ cortex-m = "0.7.1" cortex-m-rt = "0.6.13" embedded-hal = { version = "0.2.4" } panic-probe = "0.1.0" -stm32f4xx-hal = { version = "0.8.3", features = ["rt", "stm32f405"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"} +stm32f4xx-hal = { version = "0.8.3", features = ["rt", "stm32f401"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"} futures = { version = "0.3.8", default-features = false, features = ["async-await"] } rtt-target = { version = "0.3", features = ["cortex-m"] } diff --git a/embassy-stm32f4-examples/memory.x b/embassy-stm32f4-examples/memory.x index ee4d4d59..efa700b8 100644 --- a/embassy-stm32f4-examples/memory.x +++ b/embassy-stm32f4-examples/memory.x @@ -1,5 +1,5 @@ MEMORY { - FLASH : ORIGIN = 0x08000000, LENGTH = 64K + FLASH : ORIGIN = 0x08000000, LENGTH = 64K RAM : ORIGIN = 0x20000000, LENGTH = 32K } diff --git a/embassy-stm32f4-examples/src/bin/rtc_async.rs b/embassy-stm32f4-examples/src/bin/rtc_async.rs new file mode 100644 index 00000000..e5321226 --- /dev/null +++ b/embassy-stm32f4-examples/src/bin/rtc_async.rs @@ -0,0 +1,65 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use example_common::*; + +use cortex_m_rt::entry; +use defmt::panic; +use embassy::executor::{task, Executor}; +use embassy::time::{Duration, Timer}; +use embassy::util::Forever; +use embassy_stm32f4::{interrupt, pac, rtc}; +use stm32f4xx_hal::prelude::*; + +#[task] +async fn run1() { + loop { + info!("BIG INFREQUENT TICK"); + Timer::after(Duration::from_ticks(32768 * 2)).await; + } +} + +#[task] +async fn run2() { + loop { + info!("tick"); + Timer::after(Duration::from_ticks(13000)).await; + } +} + +static RTC: Forever> = Forever::new(); +static ALARM: Forever> = Forever::new(); +static EXECUTOR: Forever = Forever::new(); + +#[entry] +fn main() -> ! { + info!("Hello World!"); + + let p = unwrap!(pac::Peripherals::take()); + + p.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled()); + let rcc = p.RCC.constrain(); + let clocks = rcc.cfgr.freeze(); + + p.DBGMCU.cr.modify(|_, w| { + w.dbg_sleep().set_bit(); + w.dbg_standby().set_bit(); + w.dbg_stop().set_bit() + }); + + let rtc = RTC.put(rtc::RTC::new(p.TIM2, interrupt::take!(TIM2), clocks)); + rtc.start(); + + unsafe { embassy::time::set_clock(rtc) }; + + let alarm = ALARM.put(rtc.alarm1()); + let executor = EXECUTOR.put(Executor::new()); + executor.set_alarm(alarm); + executor.run(|spawner| { + unwrap!(spawner.spawn(run1())); + unwrap!(spawner.spawn(run2())); + }); +} diff --git a/embassy-stm32f4/src/interrupt.rs b/embassy-stm32f4/src/interrupt.rs index c75e4b82..8336df7d 100644 --- a/embassy-stm32f4/src/interrupt.rs +++ b/embassy-stm32f4/src/interrupt.rs @@ -94,6 +94,66 @@ where } } +#[cfg(feature = "stm32f401")] +mod irqs { + use super::*; + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(DMA1_STREAM7); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(FPU); + declare!(SPI4); +} + #[cfg(feature = "stm32f405")] mod irqs { use super::*; diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs index 02668b7e..eb8530ea 100644 --- a/embassy-stm32f4/src/lib.rs +++ b/embassy-stm32f4/src/lib.rs @@ -312,6 +312,7 @@ pub(crate) mod fmt; pub mod exti; pub mod interrupt; +pub mod rtc; pub mod serial; pub use cortex_m_rt::interrupt; diff --git a/embassy-stm32f4/src/rtc.rs b/embassy-stm32f4/src/rtc.rs new file mode 100644 index 00000000..7dc3a563 --- /dev/null +++ b/embassy-stm32f4/src/rtc.rs @@ -0,0 +1,364 @@ +use core::cell::Cell; +use core::convert::TryInto; +use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; + +use embassy::time::{Clock, TICKS_PER_SECOND}; +use stm32f4xx_hal::bb; +use stm32f4xx_hal::rcc::Clocks; + +use crate::interrupt; +use crate::interrupt::{CriticalSection, Mutex, OwnedInterrupt}; + +// RTC timekeeping works with something we call "periods", which are time intervals +// of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. +// +// A `period` count is maintained in parallel to the RTC hardware `counter`, like this: +// - `period` and `counter` start at 0 +// - `period` is incremented on overflow (at counter value 0) +// - `period` is incremented "midway" between overflows (at counter value 0x8000) +// +// Therefore, when `period` is even, counter is in 0..0x7FFF. When odd, counter is in 0x8000..0xFFFF +// This allows for now() to return the correct value even if it races an overflow. +// +// To get `now()`, `period` is read first, then `counter` is read. If the counter value matches +// the expected range for the `period` parity, we're done. If it doesn't, this means that +// a new period start has raced us between reading `period` and `counter`, so we assume the `counter` value +// corresponds to the next period. +// +// `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. + +fn calc_now(period: u32, counter: u16) -> u64 { + ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) +} + +struct AlarmState { + timestamp: Cell, + callback: Cell>, +} + +impl AlarmState { + fn new() -> Self { + Self { + timestamp: Cell::new(u64::MAX), + callback: Cell::new(None), + } + } +} + +// TODO: This is sometimes wasteful, try to find a better way +const ALARM_COUNT: usize = 3; + +pub struct RTC { + rtc: T, + irq: T::Interrupt, + + /// Number of 2^23 periods elapsed since boot. + period: AtomicU32, + + /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. + alarms: Mutex<[AlarmState; ALARM_COUNT]>, + + clocks: Clocks, +} + +impl RTC { + pub fn new(rtc: T, irq: T::Interrupt, clocks: Clocks) -> Self { + Self { + rtc, + irq, + period: AtomicU32::new(0), + alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), + clocks, + } + } + + pub fn start(&'static self) { + self.rtc.enable_clock(); + self.rtc.stop_and_reset(); + + let multiplier = if T::ppre(&self.clocks) == 1 { 1 } else { 2 }; + let freq = T::pclk(&self.clocks) * multiplier; + let psc = freq / TICKS_PER_SECOND as u32 - 1; + let psc: u16 = psc.try_into().unwrap(); + + self.rtc.set_psc_arr(psc, u16::MAX); + // Mid-way point + self.rtc.set_compare(0, 0x8000); + self.rtc.set_compare_interrupt(0, true); + + self.irq.set_handler( + |ptr| unsafe { + let this = &*(ptr as *const () as *const Self); + this.on_interrupt(); + }, + self as *const _ as *mut _, + ); + self.irq.unpend(); + self.irq.enable(); + + self.rtc.start(); + } + + fn on_interrupt(&self) { + if self.rtc.overflow_interrupt_status() { + self.rtc.overflow_clear_flag(); + self.next_period(); + } + + // Half overflow + if self.rtc.compare_interrupt_status(0) { + self.rtc.compare_clear_flag(0); + self.next_period(); + } + + for n in 1..=ALARM_COUNT { + if self.rtc.compare_interrupt_status(n) { + self.rtc.compare_clear_flag(n); + interrupt::free(|cs| self.trigger_alarm(n, cs)); + } + } + } + + fn next_period(&self) { + interrupt::free(|cs| { + let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; + let t = (period as u64) << 15; + + for n in 1..=ALARM_COUNT { + let alarm = &self.alarms.borrow(cs)[n - 1]; + let at = alarm.timestamp.get(); + + let diff = at - t; + if diff < 0xc000 { + self.rtc.set_compare(n, at as u16); + self.rtc.set_compare_interrupt(n, true); + } + } + }) + } + + fn trigger_alarm(&self, n: usize, cs: &CriticalSection) { + self.rtc.set_compare_interrupt(n, false); + + let alarm = &self.alarms.borrow(cs)[n - 1]; + alarm.timestamp.set(u64::MAX); + + // Call after clearing alarm, so the callback can set another alarm. + if let Some((f, ctx)) = alarm.callback.get() { + f(ctx); + } + } + + fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { + interrupt::free(|cs| { + let alarm = &self.alarms.borrow(cs)[n - 1]; + alarm.callback.set(Some((callback, ctx))); + }) + } + + fn set_alarm(&self, n: usize, timestamp: u64) { + interrupt::free(|cs| { + let alarm = &self.alarms.borrow(cs)[n - 1]; + alarm.timestamp.set(timestamp); + + let t = self.now(); + if timestamp <= t { + self.trigger_alarm(n, cs); + return; + } + + let diff = timestamp - t; + if diff < 0xc000 { + let safe_timestamp = timestamp.max(t + 3); + self.rtc.set_compare(n, safe_timestamp as u16); + self.rtc.set_compare_interrupt(n, true); + } else { + self.rtc.set_compare_interrupt(n, false); + } + }) + } + + pub fn alarm1(&'static self) -> Alarm { + Alarm { n: 1, rtc: self } + } + pub fn alarm2(&'static self) -> Option> { + if T::REAL_ALARM_COUNT >= 2 { + Some(Alarm { n: 2, rtc: self }) + } else { + None + } + } + pub fn alarm3(&'static self) -> Option> { + if T::REAL_ALARM_COUNT >= 3 { + Some(Alarm { n: 3, rtc: self }) + } else { + None + } + } +} + +impl embassy::time::Clock for RTC { + fn now(&self) -> u64 { + let period = self.period.load(Ordering::Relaxed); + compiler_fence(Ordering::Acquire); + let counter = self.rtc.counter(); + calc_now(period, counter) + } +} + +pub struct Alarm { + n: usize, + rtc: &'static RTC, +} + +impl embassy::time::Alarm for Alarm { + fn set_callback(&self, callback: fn(*mut ()), ctx: *mut ()) { + self.rtc.set_alarm_callback(self.n, callback, ctx); + } + + fn set(&self, timestamp: u64) { + self.rtc.set_alarm(self.n, timestamp); + } + + fn clear(&self) { + self.rtc.set_alarm(self.n, u64::MAX); + } +} + +mod sealed { + pub trait Sealed {} +} + +pub trait Instance: sealed::Sealed + Sized + 'static { + type Interrupt: OwnedInterrupt; + const REAL_ALARM_COUNT: usize; + + fn enable_clock(&self); + fn set_compare(&self, n: usize, value: u16); + fn set_compare_interrupt(&self, n: usize, enable: bool); + fn compare_interrupt_status(&self, n: usize) -> bool; + fn compare_clear_flag(&self, n: usize); + fn overflow_interrupt_status(&self) -> bool; + fn overflow_clear_flag(&self); + fn set_psc_arr(&self, psc: u16, arr: u16); + fn stop_and_reset(&self); + fn start(&self); + fn counter(&self) -> u16; + fn ppre(clocks: &Clocks) -> u8; + fn pclk(clocks: &Clocks) -> u32; +} + +mod tim2 { + use super::*; + use stm32f4xx_hal::pac::{RCC, TIM2}; + + impl sealed::Sealed for TIM2 {} + + impl Instance for TIM2 { + type Interrupt = interrupt::TIM2Interrupt; + const REAL_ALARM_COUNT: usize = 3; + + fn enable_clock(&self) { + // NOTE(unsafe) It will only be used for atomic operations + unsafe { + let rcc = &*RCC::ptr(); + + bb::set(&rcc.apb1enr, 0); + bb::set(&rcc.apb1rstr, 0); + bb::clear(&rcc.apb1rstr, 0); + } + } + + fn set_compare(&self, n: usize, value: u16) { + // NOTE(unsafe) these registers accept all the range of u16 values + match n { + 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), + 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), + 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), + 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), + _ => {} + } + } + + fn set_compare_interrupt(&self, n: usize, enable: bool) { + if n > 3 { + return; + } + let bit = n as u8 + 1; + unsafe { + if enable { + bb::set(&self.dier, bit); + } else { + bb::clear(&self.dier, bit); + } + } + } + + fn compare_interrupt_status(&self, n: usize) -> bool { + let status = self.sr.read(); + match n { + 0 => status.cc1if().bit_is_set(), + 1 => status.cc2if().bit_is_set(), + 2 => status.cc3if().bit_is_set(), + 3 => status.cc4if().bit_is_set(), + _ => false, + } + } + + fn compare_clear_flag(&self, n: usize) { + if n > 3 { + return; + } + let bit = n as u8 + 1; + unsafe { + bb::clear(&self.sr, bit); + } + } + + fn overflow_interrupt_status(&self) -> bool { + self.sr.read().uif().bit_is_set() + } + + fn overflow_clear_flag(&self) { + unsafe { + bb::clear(&self.sr, 0); + } + } + + fn set_psc_arr(&self, psc: u16, arr: u16) { + // NOTE(unsafe) All u16 values are valid + self.psc.write(|w| unsafe { w.bits(psc.into()) }); + self.arr.write(|w| unsafe { w.bits(arr.into()) }); + + unsafe { + // Set URS, generate update, clear URS + bb::set(&self.cr1, 2); + self.egr.write(|w| w.ug().set_bit()); + bb::clear(&self.cr1, 2); + } + } + + fn stop_and_reset(&self) { + unsafe { + bb::clear(&self.cr1, 0); + } + self.cnt.reset(); + } + + fn start(&self) { + unsafe { bb::set(&self.cr1, 0) } + } + + fn counter(&self) -> u16 { + self.cnt.read().bits() as u16 + } + + fn ppre(clocks: &Clocks) -> u8 { + clocks.ppre1() + } + + fn pclk(clocks: &Clocks) -> u32 { + clocks.pclk1().0 + } + } +} From fc7977bd9ac0a2c58942bbd3987230a3c7066a9b Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Tue, 16 Feb 2021 18:25:06 -0300 Subject: [PATCH 2/3] Add remaining stm32f4 timers --- embassy-stm32f4/src/rtc.rs | 345 ++++++++++++++++++++++++++----------- 1 file changed, 243 insertions(+), 102 deletions(-) diff --git a/embassy-stm32f4/src/rtc.rs b/embassy-stm32f4/src/rtc.rs index 7dc3a563..28344271 100644 --- a/embassy-stm32f4/src/rtc.rs +++ b/embassy-stm32f4/src/rtc.rs @@ -26,7 +26,6 @@ use crate::interrupt::{CriticalSection, Mutex, OwnedInterrupt}; // corresponds to the next period. // // `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. - fn calc_now(period: u32, counter: u16) -> u64 { ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) } @@ -48,6 +47,13 @@ impl AlarmState { // TODO: This is sometimes wasteful, try to find a better way const ALARM_COUNT: usize = 3; +/// RTC timer that can be used by the executor and to set alarms. +/// +/// It can work with Timers 2, 3, 4, 5, 9 and 12. Timers 9 and 12 only have one alarm available, +/// while the others have three each. +/// This timer works internally with a unit of 2^15 ticks, which means that if a call to +/// [`embassy::time::Clock::now`] is blocked for that amount of ticks the returned value will be +/// wrong (an old value). The current default tick rate is 32768 ticks per second. pub struct RTC { rtc: T, irq: T::Interrupt, @@ -240,6 +246,7 @@ pub trait Instance: sealed::Sealed + Sized + 'static { fn compare_clear_flag(&self, n: usize); fn overflow_interrupt_status(&self) -> bool; fn overflow_clear_flag(&self); + // This method should ensure that the values are really updated before returning fn set_psc_arr(&self, psc: u16, arr: u16); fn stop_and_reset(&self); fn start(&self); @@ -248,117 +255,251 @@ pub trait Instance: sealed::Sealed + Sized + 'static { fn pclk(clocks: &Clocks) -> u32; } -mod tim2 { - use super::*; - use stm32f4xx_hal::pac::{RCC, TIM2}; +#[allow(unused_macros)] +macro_rules! impl_timer { + ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 3) => { + mod $module { + use super::*; + use stm32f4xx_hal::pac::{$TYPE, RCC}; - impl sealed::Sealed for TIM2 {} + impl sealed::Sealed for $TYPE {} - impl Instance for TIM2 { - type Interrupt = interrupt::TIM2Interrupt; - const REAL_ALARM_COUNT: usize = 3; + impl Instance for $TYPE { + type Interrupt = interrupt::$INT; + const REAL_ALARM_COUNT: usize = 3; - fn enable_clock(&self) { - // NOTE(unsafe) It will only be used for atomic operations - unsafe { - let rcc = &*RCC::ptr(); + fn enable_clock(&self) { + // NOTE(unsafe) It will only be used for atomic operations + unsafe { + let rcc = &*RCC::ptr(); - bb::set(&rcc.apb1enr, 0); - bb::set(&rcc.apb1rstr, 0); - bb::clear(&rcc.apb1rstr, 0); - } - } + bb::set(&rcc.$apbenr, $enrbit); + bb::set(&rcc.$apbrstr, $rstrbit); + bb::clear(&rcc.$apbrstr, $rstrbit); + } + } - fn set_compare(&self, n: usize, value: u16) { - // NOTE(unsafe) these registers accept all the range of u16 values - match n { - 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), - 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), - 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), - 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), - _ => {} - } - } + fn set_compare(&self, n: usize, value: u16) { + // NOTE(unsafe) these registers accept all the range of u16 values + match n { + 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), + 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), + 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), + 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), + _ => {} + } + } - fn set_compare_interrupt(&self, n: usize, enable: bool) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - if enable { - bb::set(&self.dier, bit); - } else { - bb::clear(&self.dier, bit); + fn set_compare_interrupt(&self, n: usize, enable: bool) { + if n > 3 { + return; + } + let bit = n as u8 + 1; + unsafe { + if enable { + bb::set(&self.dier, bit); + } else { + bb::clear(&self.dier, bit); + } + } + } + + fn compare_interrupt_status(&self, n: usize) -> bool { + let status = self.sr.read(); + match n { + 0 => status.cc1if().bit_is_set(), + 1 => status.cc2if().bit_is_set(), + 2 => status.cc3if().bit_is_set(), + 3 => status.cc4if().bit_is_set(), + _ => false, + } + } + + fn compare_clear_flag(&self, n: usize) { + if n > 3 { + return; + } + let bit = n as u8 + 1; + unsafe { + bb::clear(&self.sr, bit); + } + } + + fn overflow_interrupt_status(&self) -> bool { + self.sr.read().uif().bit_is_set() + } + + fn overflow_clear_flag(&self) { + unsafe { + bb::clear(&self.sr, 0); + } + } + + fn set_psc_arr(&self, psc: u16, arr: u16) { + // NOTE(unsafe) All u16 values are valid + self.psc.write(|w| unsafe { w.bits(psc.into()) }); + self.arr.write(|w| unsafe { w.bits(arr.into()) }); + + unsafe { + // Set URS, generate update, clear URS + bb::set(&self.cr1, 2); + self.egr.write(|w| w.ug().set_bit()); + bb::clear(&self.cr1, 2); + } + } + + fn stop_and_reset(&self) { + unsafe { + bb::clear(&self.cr1, 0); + } + self.cnt.reset(); + } + + fn start(&self) { + unsafe { bb::set(&self.cr1, 0) } + } + + fn counter(&self) -> u16 { + self.cnt.read().bits() as u16 + } + + fn ppre(clocks: &Clocks) -> u8 { + clocks.$ppre() + } + + fn pclk(clocks: &Clocks) -> u32 { + clocks.$pclk().0 } } } + }; - fn compare_interrupt_status(&self, n: usize) -> bool { - let status = self.sr.read(); - match n { - 0 => status.cc1if().bit_is_set(), - 1 => status.cc2if().bit_is_set(), - 2 => status.cc3if().bit_is_set(), - 3 => status.cc4if().bit_is_set(), - _ => false, + ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 1) => { + mod $module { + use super::*; + use stm32f4xx_hal::pac::{$TYPE, RCC}; + + impl sealed::Sealed for $TYPE {} + + impl Instance for $TYPE { + type Interrupt = interrupt::$INT; + const REAL_ALARM_COUNT: usize = 1; + + fn enable_clock(&self) { + // NOTE(unsafe) It will only be used for atomic operations + unsafe { + let rcc = &*RCC::ptr(); + + bb::set(&rcc.$apbenr, $enrbit); + bb::set(&rcc.$apbrstr, $rstrbit); + bb::clear(&rcc.$apbrstr, $rstrbit); + } + } + + fn set_compare(&self, n: usize, value: u16) { + // NOTE(unsafe) these registers accept all the range of u16 values + match n { + 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), + 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), + _ => {} + } + } + + fn set_compare_interrupt(&self, n: usize, enable: bool) { + if n > 1 { + return; + } + let bit = n as u8 + 1; + unsafe { + if enable { + bb::set(&self.dier, bit); + } else { + bb::clear(&self.dier, bit); + } + } + } + + fn compare_interrupt_status(&self, n: usize) -> bool { + let status = self.sr.read(); + match n { + 0 => status.cc1if().bit_is_set(), + 1 => status.cc2if().bit_is_set(), + _ => false, + } + } + + fn compare_clear_flag(&self, n: usize) { + if n > 1 { + return; + } + let bit = n as u8 + 1; + unsafe { + bb::clear(&self.sr, bit); + } + } + + fn overflow_interrupt_status(&self) -> bool { + self.sr.read().uif().bit_is_set() + } + + fn overflow_clear_flag(&self) { + unsafe { + bb::clear(&self.sr, 0); + } + } + + fn set_psc_arr(&self, psc: u16, arr: u16) { + // NOTE(unsafe) All u16 values are valid + self.psc.write(|w| unsafe { w.bits(psc.into()) }); + self.arr.write(|w| unsafe { w.bits(arr.into()) }); + + unsafe { + // Set URS, generate update, clear URS + bb::set(&self.cr1, 2); + self.egr.write(|w| w.ug().set_bit()); + bb::clear(&self.cr1, 2); + } + } + + fn stop_and_reset(&self) { + unsafe { + bb::clear(&self.cr1, 0); + } + self.cnt.reset(); + } + + fn start(&self) { + unsafe { bb::set(&self.cr1, 0) } + } + + fn counter(&self) -> u16 { + self.cnt.read().bits() as u16 + } + + fn ppre(clocks: &Clocks) -> u8 { + clocks.$ppre() + } + + fn pclk(clocks: &Clocks) -> u32 { + clocks.$pclk().0 + } } } - - fn compare_clear_flag(&self, n: usize) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - bb::clear(&self.sr, bit); - } - } - - fn overflow_interrupt_status(&self) -> bool { - self.sr.read().uif().bit_is_set() - } - - fn overflow_clear_flag(&self) { - unsafe { - bb::clear(&self.sr, 0); - } - } - - fn set_psc_arr(&self, psc: u16, arr: u16) { - // NOTE(unsafe) All u16 values are valid - self.psc.write(|w| unsafe { w.bits(psc.into()) }); - self.arr.write(|w| unsafe { w.bits(arr.into()) }); - - unsafe { - // Set URS, generate update, clear URS - bb::set(&self.cr1, 2); - self.egr.write(|w| w.ug().set_bit()); - bb::clear(&self.cr1, 2); - } - } - - fn stop_and_reset(&self) { - unsafe { - bb::clear(&self.cr1, 0); - } - self.cnt.reset(); - } - - fn start(&self) { - unsafe { bb::set(&self.cr1, 0) } - } - - fn counter(&self) -> u16 { - self.cnt.read().bits() as u16 - } - - fn ppre(clocks: &Clocks) -> u8 { - clocks.ppre1() - } - - fn pclk(clocks: &Clocks) -> u32 { - clocks.pclk1().0 - } - } + }; } + +#[cfg(not(feature = "stm32f410"))] +impl_timer!(tim2: (TIM2, TIM2Interrupt, apb1enr, 0, apb1rstr, 0, ppre1, pclk1), 3); + +#[cfg(not(feature = "stm32f410"))] +impl_timer!(tim3: (TIM3, TIM3Interrupt, apb1enr, 1, apb1rstr, 1, ppre1, pclk1), 3); + +#[cfg(not(feature = "stm32f410"))] +impl_timer!(tim4: (TIM4, TIM4Interrupt, apb1enr, 2, apb1rstr, 2, ppre1, pclk1), 3); + +impl_timer!(tim5: (TIM5, TIM5Interrupt, apb1enr, 3, apb1rstr, 3, ppre1, pclk1), 3); + +impl_timer!(tim9: (TIM9, TIM1_BRK_TIM9Interrupt, apb2enr, 16, apb2rstr, 16, ppre2, pclk2), 1); + +#[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411")))] +impl_timer!(tim12: (TIM12, TIM8_BRK_TIM12Interrupt, apb1enr, 6, apb1rstr, 6, ppre1, pclk1), 1); From e16e3780fd16929eec3b1b62942c6dffcfe90711 Mon Sep 17 00:00:00 2001 From: Thales Fragoso Date: Wed, 17 Feb 2021 19:35:00 -0300 Subject: [PATCH 3/3] Add missing interrupts for stm32f4 --- embassy-stm32f4/src/interrupt.rs | 711 +++++++++++++++++++++++++++++++ 1 file changed, 711 insertions(+) diff --git a/embassy-stm32f4/src/interrupt.rs b/embassy-stm32f4/src/interrupt.rs index 8336df7d..4ecc7625 100644 --- a/embassy-stm32f4/src/interrupt.rs +++ b/embassy-stm32f4/src/interrupt.rs @@ -250,6 +250,155 @@ mod irqs { // declare!(DMA2D); } +#[cfg(feature = "stm32f407")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FSMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(UART4); + declare!(UART5); + declare!(TIM6_DAC); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(ETH); + declare!(ETH_WKUP); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(OTG_HS_EP1_OUT); + declare!(OTG_HS_EP1_IN); + declare!(OTG_HS_WKUP); + declare!(OTG_HS); + declare!(DCMI); + declare!(CRYP); + declare!(HASH_RNG); + declare!(FPU); + declare!(LCD_TFT); + declare!(LCD_TFT_1); +} + +#[cfg(feature = "stm32f410")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(PWM1_UP); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(DMA1_STREAM7); + declare!(TIM5); + declare!(TIM6_DAC1); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(EXTI19); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(EXTI20); + declare!(RNG); + declare!(FPU); + declare!(SPI5); + declare!(I2C4_EV); + declare!(I2C4_ER); + declare!(LPTIM1); +} + #[cfg(feature = "stm32f411")] mod irqs { use super::*; @@ -313,4 +462,566 @@ mod irqs { declare!(SPI5); } +#[cfg(feature = "stm32f412")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM12); + declare!(TIM13); + declare!(TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FSMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(TIM6_DACUNDER); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(DFSDM1_FLT0); + declare!(DFSDM1_FLT1); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(HASH_RNG); + declare!(FPU); + declare!(SPI4); + declare!(SPI5); + declare!(QUAD_SPI); + declare!(I2CFMP1_EVENT); + declare!(I2CFMP1_ERROR); +} + +#[cfg(feature = "stm32f413")] +mod irqs { + use super::*; + + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EVT); + declare!(I2C1_ERR); + declare!(I2C2_EVT); + declare!(I2C2_ERR); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(EXTI17_RTC_ALARM); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FSMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(USART4); + declare!(UART5); + declare!(TIM6_GLB_IT_DAC1_DAC2); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(DFSDM1_FLT0); + declare!(DFSDM1_FLT1); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(CAN3_TX); + declare!(CAN3_RX0); + declare!(CAN3_RX1); + declare!(CAN3_SCE); + declare!(CRYPTO); + declare!(RNG); + declare!(FPU); + declare!(USART7); + declare!(USART8); + declare!(SPI4); + declare!(SPI5); + declare!(SAI1); + declare!(UART9); + declare!(UART10); + declare!(QUADSPI); + declare!(I2CFMP1EVENT); + declare!(I2CFMP1ERROR); + declare!(LPTIM1_OR_IT_EIT_23); + declare!(DFSDM2_FILTER1); + declare!(DFSDM2_FILTER2); + declare!(DFSDM2_FILTER3); + declare!(DFSDM2_FILTER4); +} + +#[cfg(feature = "stm32f427")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(UART4); + declare!(UART5); + declare!(TIM6_DAC); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(ETH); + declare!(ETH_WKUP); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(OTG_HS_EP1_OUT); + declare!(OTG_HS_EP1_IN); + declare!(OTG_HS_WKUP); + declare!(OTG_HS); + declare!(DCMI); + declare!(CRYP); + declare!(HASH_RNG); + declare!(FPU); + declare!(UART7); + declare!(UART8); + declare!(SPI4); + declare!(SPI5); + declare!(SPI6); + declare!(LCD_TFT); + declare!(LCD_TFT_1); +} + +#[cfg(feature = "stm32f429")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(UART4); + declare!(UART5); + declare!(TIM6_DAC); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(ETH); + declare!(ETH_WKUP); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(OTG_HS_EP1_OUT); + declare!(OTG_HS_EP1_IN); + declare!(OTG_HS_WKUP); + declare!(OTG_HS); + declare!(DCMI); + declare!(CRYP); + declare!(HASH_RNG); + declare!(FPU); + declare!(UART7); + declare!(UART8); + declare!(SPI4); + declare!(SPI5); + declare!(SPI6); + declare!(SAI1); + declare!(LCD_TFT); + declare!(LCD_TFT_1); + declare!(DMA2D); +} + +#[cfg(feature = "stm32f446")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(UART4); + declare!(UART5); + declare!(TIM6_DAC); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(ETH); + declare!(ETH_WKUP); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(DCMI); + declare!(FPU); + declare!(UART7); + declare!(UART8); + declare!(SPI4); + declare!(LCD_TFT); + declare!(LCD_TFT_1); +} + +#[cfg(feature = "stm32f469")] +mod irqs { + use super::*; + + declare!(WWDG); + declare!(PVD); + declare!(TAMP_STAMP); + declare!(RTC_WKUP); + declare!(FLASH); + declare!(RCC); + declare!(EXTI0); + declare!(EXTI1); + declare!(EXTI2); + declare!(EXTI3); + declare!(EXTI4); + declare!(DMA1_STREAM0); + declare!(DMA1_STREAM1); + declare!(DMA1_STREAM2); + declare!(DMA1_STREAM3); + declare!(DMA1_STREAM4); + declare!(DMA1_STREAM5); + declare!(DMA1_STREAM6); + declare!(ADC); + declare!(CAN1_TX); + declare!(CAN1_RX0); + declare!(CAN1_RX1); + declare!(CAN1_SCE); + declare!(EXTI9_5); + declare!(TIM1_BRK_TIM9); + declare!(TIM1_UP_TIM10); + declare!(TIM1_TRG_COM_TIM11); + declare!(TIM1_CC); + declare!(TIM2); + declare!(TIM3); + declare!(TIM4); + declare!(I2C1_EV); + declare!(I2C1_ER); + declare!(I2C2_EV); + declare!(I2C2_ER); + declare!(SPI1); + declare!(SPI2); + declare!(USART1); + declare!(USART2); + declare!(USART3); + declare!(EXTI15_10); + declare!(RTC_ALARM); + declare!(OTG_FS_WKUP); + declare!(TIM8_BRK_TIM12); + declare!(TIM8_UP_TIM13); + declare!(TIM8_TRG_COM_TIM14); + declare!(TIM8_CC); + declare!(DMA1_STREAM7); + declare!(FMC); + declare!(SDIO); + declare!(TIM5); + declare!(SPI3); + declare!(UART4); + declare!(UART5); + declare!(TIM6_DAC); + declare!(TIM7); + declare!(DMA2_STREAM0); + declare!(DMA2_STREAM1); + declare!(DMA2_STREAM2); + declare!(DMA2_STREAM3); + declare!(DMA2_STREAM4); + declare!(ETH); + declare!(ETH_WKUP); + declare!(CAN2_TX); + declare!(CAN2_RX0); + declare!(CAN2_RX1); + declare!(CAN2_SCE); + declare!(OTG_FS); + declare!(DMA2_STREAM5); + declare!(DMA2_STREAM6); + declare!(DMA2_STREAM7); + declare!(USART6); + declare!(I2C3_EV); + declare!(I2C3_ER); + declare!(OTG_HS_EP1_OUT); + declare!(OTG_HS_EP1_IN); + declare!(OTG_HS_WKUP); + declare!(OTG_HS); + declare!(DCMI); + declare!(CRYP); + declare!(HASH_RNG); + declare!(FPU); + declare!(UART7); + declare!(UART8); + declare!(SPI4); + declare!(SPI5); + declare!(SPI6); + declare!(SAI1); + declare!(LCD_TFT); + declare!(LCD_TFT_1); + declare!(DMA2D); + declare!(QUADSPI); + declare!(DSIHOST); +} + pub use irqs::*;