mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
Merge pull request #3263 from liarokapisv/stm32-dual-boot-init-fix
stm32: fix dma nvic issues on dual core lines
This commit is contained in:
commit
e30a888823
@ -1494,6 +1494,36 @@ fn main() {
|
||||
.flat_map(|p| &p.registers)
|
||||
.any(|p| p.kind == "dmamux");
|
||||
|
||||
let mut dma_irqs: BTreeMap<&str, Vec<String>> = BTreeMap::new();
|
||||
|
||||
for p in METADATA.peripherals {
|
||||
if let Some(r) = &p.registers {
|
||||
if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" || r.kind == "lpdma" {
|
||||
for irq in p.interrupts {
|
||||
let ch_name = format!("{}_{}", p.name, irq.signal);
|
||||
let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name).unwrap();
|
||||
|
||||
// Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it.
|
||||
if has_dmamux && ch.dmamux.is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
dma_irqs.entry(irq.interrupt).or_default().push(ch_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "_dual-core")]
|
||||
let mut dma_ch_to_irq: BTreeMap<&str, Vec<String>> = BTreeMap::new();
|
||||
|
||||
#[cfg(feature = "_dual-core")]
|
||||
for (irq, channels) in &dma_irqs {
|
||||
for channel in channels {
|
||||
dma_ch_to_irq.entry(channel).or_default().push(irq.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
for (ch_idx, ch) in METADATA.dma_channels.iter().enumerate() {
|
||||
// Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it.
|
||||
if has_dmamux && ch.dmamux.is_none() {
|
||||
@ -1502,6 +1532,16 @@ fn main() {
|
||||
|
||||
let name = format_ident!("{}", ch.name);
|
||||
let idx = ch_idx as u8;
|
||||
#[cfg(feature = "_dual-core")]
|
||||
let irq = {
|
||||
let irq_name = if let Some(x) = &dma_ch_to_irq.get(ch.name) {
|
||||
format_ident!("{}", x.get(0).unwrap())
|
||||
} else {
|
||||
panic!("failed to find dma interrupt")
|
||||
};
|
||||
quote!(crate::pac::Interrupt::#irq_name)
|
||||
};
|
||||
|
||||
g.extend(quote!(dma_channel_impl!(#name, #idx);));
|
||||
|
||||
let dma = format_ident!("{}", ch.dma);
|
||||
@ -1532,6 +1572,7 @@ fn main() {
|
||||
None => quote!(),
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "_dual-core"))]
|
||||
dmas.extend(quote! {
|
||||
crate::dma::ChannelInfo {
|
||||
dma: #dma_info,
|
||||
@ -1539,31 +1580,20 @@ fn main() {
|
||||
#dmamux
|
||||
},
|
||||
});
|
||||
#[cfg(feature = "_dual-core")]
|
||||
dmas.extend(quote! {
|
||||
crate::dma::ChannelInfo {
|
||||
dma: #dma_info,
|
||||
num: #ch_num,
|
||||
irq: #irq,
|
||||
#dmamux
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// ========
|
||||
// Generate DMA IRQs.
|
||||
|
||||
let mut dma_irqs: BTreeMap<&str, Vec<String>> = BTreeMap::new();
|
||||
|
||||
for p in METADATA.peripherals {
|
||||
if let Some(r) = &p.registers {
|
||||
if r.kind == "dma" || r.kind == "bdma" || r.kind == "gpdma" {
|
||||
for irq in p.interrupts {
|
||||
let ch_name = format!("{}_{}", p.name, irq.signal);
|
||||
let ch = METADATA.dma_channels.iter().find(|c| c.name == ch_name).unwrap();
|
||||
|
||||
// Some H7 chips have BDMA1 hardcoded for DFSDM, ie no DMAMUX. It's unsupported, skip it.
|
||||
if has_dmamux && ch.dmamux.is_none() {
|
||||
continue;
|
||||
}
|
||||
|
||||
dma_irqs.entry(irq.interrupt).or_default().push(ch_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dma_irqs: TokenStream = dma_irqs
|
||||
.iter()
|
||||
.map(|(irq, channels)| {
|
||||
|
@ -15,6 +15,8 @@ use crate::{interrupt, pac};
|
||||
pub(crate) struct ChannelInfo {
|
||||
pub(crate) dma: DmaInfo,
|
||||
pub(crate) num: usize,
|
||||
#[cfg(feature = "_dual-core")]
|
||||
pub(crate) irq: pac::Interrupt,
|
||||
#[cfg(dmamux)]
|
||||
pub(crate) dmamux: super::DmamuxInfo,
|
||||
}
|
||||
@ -259,10 +261,12 @@ pub(crate) unsafe fn init(
|
||||
foreach_interrupt! {
|
||||
($peri:ident, dma, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||
crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, dma_priority);
|
||||
#[cfg(not(feature = "_dual-core"))]
|
||||
crate::interrupt::typelevel::$irq::enable();
|
||||
};
|
||||
($peri:ident, bdma, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||
crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, bdma_priority);
|
||||
#[cfg(not(feature = "_dual-core"))]
|
||||
crate::interrupt::typelevel::$irq::enable();
|
||||
};
|
||||
}
|
||||
@ -341,6 +345,11 @@ impl AnyChannel {
|
||||
options: TransferOptions,
|
||||
) {
|
||||
let info = self.info();
|
||||
#[cfg(feature = "_dual-core")]
|
||||
{
|
||||
use embassy_hal_internal::interrupt::InterruptExt as _;
|
||||
info.irq.enable();
|
||||
}
|
||||
|
||||
#[cfg(dmamux)]
|
||||
super::dmamux::configure_dmamux(&info.dmamux, _request);
|
||||
|
@ -18,6 +18,8 @@ use crate::pac::gpdma::vals;
|
||||
pub(crate) struct ChannelInfo {
|
||||
pub(crate) dma: pac::gpdma::Gpdma,
|
||||
pub(crate) num: usize,
|
||||
#[cfg(feature = "_dual-core")]
|
||||
pub(crate) irq: pac::Interrupt,
|
||||
}
|
||||
|
||||
/// GPDMA transfer options.
|
||||
@ -57,6 +59,7 @@ pub(crate) unsafe fn init(cs: critical_section::CriticalSection, irq_priority: P
|
||||
foreach_interrupt! {
|
||||
($peri:ident, gpdma, $block:ident, $signal_name:ident, $irq:ident) => {
|
||||
crate::interrupt::typelevel::$irq::set_priority_with_cs(cs, irq_priority);
|
||||
#[cfg(not(feature = "_dual-core"))]
|
||||
crate::interrupt::typelevel::$irq::enable();
|
||||
};
|
||||
}
|
||||
@ -67,6 +70,12 @@ impl AnyChannel {
|
||||
/// Safety: Must be called with a matching set of parameters for a valid dma channel
|
||||
pub(crate) unsafe fn on_irq(&self) {
|
||||
let info = self.info();
|
||||
#[cfg(feature = "_dual-core")]
|
||||
{
|
||||
use embassy_hal_internal::interrupt::InterruptExt as _;
|
||||
info.irq.enable();
|
||||
}
|
||||
|
||||
let state = &STATE[self.id as usize];
|
||||
|
||||
let ch = info.dma.ch(info.num);
|
||||
|
@ -197,6 +197,7 @@ pub use crate::pac::NVIC_PRIO_BITS;
|
||||
|
||||
/// `embassy-stm32` global configuration.
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
/// RCC config.
|
||||
pub rcc: rcc::Config,
|
||||
@ -303,6 +304,7 @@ mod dual_core {
|
||||
pub struct SharedData {
|
||||
init_flag: AtomicUsize,
|
||||
clocks: UnsafeCell<MaybeUninit<Clocks>>,
|
||||
config: UnsafeCell<MaybeUninit<Config>>,
|
||||
}
|
||||
|
||||
unsafe impl Sync for SharedData {}
|
||||
@ -325,6 +327,8 @@ mod dual_core {
|
||||
rcc::set_freqs_ptr(shared_data.clocks.get());
|
||||
let p = init_hw(config);
|
||||
|
||||
unsafe { *shared_data.config.get() }.write(config);
|
||||
|
||||
shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst);
|
||||
|
||||
p
|
||||
@ -372,9 +376,23 @@ mod dual_core {
|
||||
fn init_secondary_hw(shared_data: &'static SharedData) -> Peripherals {
|
||||
rcc::set_freqs_ptr(shared_data.clocks.get());
|
||||
|
||||
let config = unsafe { (*shared_data.config.get()).assume_init() };
|
||||
|
||||
// We use different timers on the different cores, so we have to still initialize one here
|
||||
#[cfg(feature = "_time-driver")]
|
||||
critical_section::with(|cs| {
|
||||
unsafe {
|
||||
dma::init(
|
||||
cs,
|
||||
#[cfg(bdma)]
|
||||
config.bdma_interrupt_priority,
|
||||
#[cfg(dma)]
|
||||
config.dma_interrupt_priority,
|
||||
#[cfg(gpdma)]
|
||||
config.gpdma_interrupt_priority,
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "_time-driver")]
|
||||
// must be after rcc init
|
||||
time_driver::init(cs);
|
||||
});
|
||||
|
@ -16,6 +16,7 @@ pub enum LseMode {
|
||||
Bypass,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LseConfig {
|
||||
pub frequency: Hertz,
|
||||
pub mode: LseMode,
|
||||
@ -80,6 +81,7 @@ fn bdcr() -> Reg<Bdcr, RW> {
|
||||
return crate::pac::RCC.csr1();
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct LsConfig {
|
||||
pub rtc: RtcClockSource,
|
||||
pub lsi: bool,
|
||||
|
@ -37,6 +37,7 @@ pub struct Hsi {
|
||||
|
||||
/// Clocks configutation
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
/// HSI Configuration
|
||||
pub hsi: Option<Hsi>,
|
||||
|
@ -76,6 +76,7 @@ pub enum HrtimClockSource {
|
||||
|
||||
/// Clocks configutation
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
pub hsi: bool,
|
||||
pub hse: Option<Hse>,
|
||||
|
@ -63,6 +63,7 @@ pub struct Pll {
|
||||
/// Used to calculate flash waitstates. See
|
||||
/// RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock frequency
|
||||
#[cfg(stm32f2)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum VoltageScale {
|
||||
/// 2.7 to 3.6 V
|
||||
Range0,
|
||||
@ -76,6 +77,7 @@ pub enum VoltageScale {
|
||||
|
||||
/// Configuration of the core clocks
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
pub hsi: bool,
|
||||
pub hse: Option<Hse>,
|
||||
|
@ -33,6 +33,7 @@ pub struct Hse {
|
||||
/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output
|
||||
/// dividers. Be sure to keep check the datasheet for your specific part for the appropriate
|
||||
/// frequency ranges for each of these settings.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Pll {
|
||||
/// PLL Source clock selection.
|
||||
pub source: PllSource,
|
||||
@ -55,6 +56,7 @@ pub struct Pll {
|
||||
|
||||
/// Clocks configutation
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
/// HSI Enable
|
||||
pub hsi: bool,
|
||||
|
@ -32,6 +32,7 @@ pub struct Hse {
|
||||
/// Use this struct to configure the PLL source, input frequency, multiplication factor, and output
|
||||
/// dividers. Be sure to keep check the datasheet for your specific part for the appropriate
|
||||
/// frequency ranges for each of these settings.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Pll {
|
||||
/// PLL Source clock selection.
|
||||
pub source: PllSource,
|
||||
@ -54,6 +55,7 @@ pub struct Pll {
|
||||
|
||||
/// Clocks configutation
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
/// HSI Enable
|
||||
pub hsi: bool,
|
||||
|
@ -120,7 +120,7 @@ impl From<TimerPrescaler> for Timpre {
|
||||
/// Power supply configuration
|
||||
/// See RM0433 Rev 4 7.4
|
||||
#[cfg(any(pwr_h7rm0399, pwr_h7rm0455, pwr_h7rm0468, pwr_h7rs))]
|
||||
#[derive(PartialEq)]
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
pub enum SupplyConfig {
|
||||
/// Default power supply configuration.
|
||||
/// V CORE Power Domains are supplied from the LDO according to VOS.
|
||||
@ -180,6 +180,7 @@ pub enum SMPSSupplyVoltage {
|
||||
|
||||
/// Configuration of the core clocks
|
||||
#[non_exhaustive]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
pub hsi: Option<HSIPrescaler>,
|
||||
pub hse: Option<Hse>,
|
||||
|
@ -30,6 +30,7 @@ pub struct Hse {
|
||||
}
|
||||
|
||||
/// Clocks configuration
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
// base clock sources
|
||||
pub msi: Option<MSIRange>,
|
||||
|
@ -59,6 +59,7 @@ pub struct Pll {
|
||||
pub divr: Option<PllDiv>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
// base clock sources
|
||||
pub msi: Option<MSIRange>,
|
||||
|
@ -15,6 +15,7 @@ pub struct Hse {
|
||||
}
|
||||
|
||||
/// Clocks configuration
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Config {
|
||||
// base clock sources
|
||||
pub hsi: bool,
|
||||
|
@ -5,8 +5,8 @@ MEMORY
|
||||
BOOTLOADER_STATE : ORIGIN = 0x08006000, LENGTH = 4K
|
||||
FLASH : ORIGIN = 0x08008000, LENGTH = 64K
|
||||
DFU : ORIGIN = 0x08018000, LENGTH = 68K
|
||||
SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64
|
||||
RAM (rwx) : ORIGIN = 0x20000040, LENGTH = 32K - 64
|
||||
SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128
|
||||
RAM (rwx) : ORIGIN = 0x20000080, LENGTH = 32K - 128
|
||||
}
|
||||
|
||||
__bootloader_state_start = ORIGIN(BOOTLOADER_STATE) - ORIGIN(BOOTLOADER);
|
||||
@ -21,4 +21,4 @@ SECTIONS
|
||||
{
|
||||
*(.shared_data)
|
||||
} > SHARED_RAM
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ MEMORY
|
||||
{
|
||||
/* NOTE 1 K = 1 KiBi = 1024 bytes */
|
||||
FLASH : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64
|
||||
RAM (rwx) : ORIGIN = 0x20000040, LENGTH = 64K - 64
|
||||
SHARED_RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 128
|
||||
RAM (rwx) : ORIGIN = 0x20000080, LENGTH = 64K - 128
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
@ -12,4 +12,4 @@ SECTIONS
|
||||
{
|
||||
*(.shared_data)
|
||||
} > SHARED_RAM
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user