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:
Dario Nieuwenhuis 2024-08-17 16:40:45 +00:00 committed by GitHub
commit e30a888823
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 108 additions and 28 deletions

View File

@ -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)| {

View File

@ -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);

View File

@ -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);

View File

@ -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);
});

View File

@ -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,

View File

@ -37,6 +37,7 @@ pub struct Hsi {
/// Clocks configutation
#[non_exhaustive]
#[derive(Clone, Copy)]
pub struct Config {
/// HSI Configuration
pub hsi: Option<Hsi>,

View File

@ -76,6 +76,7 @@ pub enum HrtimClockSource {
/// Clocks configutation
#[non_exhaustive]
#[derive(Clone, Copy)]
pub struct Config {
pub hsi: bool,
pub hse: Option<Hse>,

View File

@ -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>,

View File

@ -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,

View File

@ -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,

View File

@ -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>,

View File

@ -30,6 +30,7 @@ pub struct Hse {
}
/// Clocks configuration
#[derive(Clone, Copy)]
pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,

View File

@ -59,6 +59,7 @@ pub struct Pll {
pub divr: Option<PllDiv>,
}
#[derive(Clone, Copy)]
pub struct Config {
// base clock sources
pub msi: Option<MSIRange>,

View File

@ -15,6 +15,7 @@ pub struct Hse {
}
/// Clocks configuration
#[derive(Clone, Copy)]
pub struct Config {
// base clock sources
pub hsi: bool,

View File

@ -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
}
}

View File

@ -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
}
}