diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 27f26df28..552ec19cc 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -97,6 +97,7 @@ build = [ {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32wba55ug", "time", "time-driver-any"]}, {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32wba62cg", "time", "time-driver-any"]}, {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "low-power", "stm32wba65ri", "time", "time-driver-any"]}, + {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u385rg", "time", "time-driver-any"]}, {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5f9zj", "time", "time-driver-any"]}, {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32u5g9nj", "time", "time-driver-any"]}, {target = "thumbv8m.main-none-eabihf", features = ["defmt", "exti", "stm32n657x0", "time", "time-driver-any"]}, @@ -135,6 +136,7 @@ flavors = [ { regex_feature = "stm32l5...e", target = "thumbv8m.main-none-eabihf", features = ["low-power", "dual-bank"] }, { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] }, { regex_feature = "stm32u0.*", target = "thumbv6m-none-eabi" }, + { regex_feature = "stm32u3.*", target = "thumbv8m.main-none-eabihf"}, { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" }, { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" }, { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" }, @@ -200,11 +202,13 @@ aligned = "0.4.1" heapless = "0.9.1" #stm32-metapac = { version = "18" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-658588478e426d68090a59ff8385bce5b407c2bc" } +stm32-metapac = { path = "../../stm32-data/build/stm32-metapac" } +# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2" } [build-dependencies] #stm32-metapac = { version = "18", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-658588478e426d68090a59ff8385bce5b407c2bc", default-features = false, features = ["metadata"] } +# stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-b77c8d968f53b18d6bdcd052e354b5070ec2bbc2", default-features = false, features = ["metadata"] } +stm32-metapac = { path = "../../stm32-data/build/stm32-metapac" , default-features = false, features = ["metadata"] } proc-macro2 = "1.0.36" quote = "1.0.15" @@ -1701,6 +1705,18 @@ stm32u083hc = [ "stm32-metapac/stm32u083hc" ] stm32u083kc = [ "stm32-metapac/stm32u083kc" ] stm32u083mc = [ "stm32-metapac/stm32u083mc" ] stm32u083rc = [ "stm32-metapac/stm32u083rc" ] +stm32u375ce = [ "stm32-metapac/stm32u375ce" ] +stm32u375cg = [ "stm32-metapac/stm32u375cg" ] +stm32u375ke = [ "stm32-metapac/stm32u375ke" ] +stm32u375kg = [ "stm32-metapac/stm32u375kg" ] +stm32u375re = [ "stm32-metapac/stm32u375re" ] +stm32u375rg = [ "stm32-metapac/stm32u375rg" ] +stm32u375ve = [ "stm32-metapac/stm32u375ve" ] +stm32u375vg = [ "stm32-metapac/stm32u375vg" ] +stm32u385cg = [ "stm32-metapac/stm32u385cg" ] +stm32u385kg = [ "stm32-metapac/stm32u385kg" ] +stm32u385rg = [ "stm32-metapac/stm32u385rg" ] +stm32u385vg = [ "stm32-metapac/stm32u385vg" ] stm32u535cb = [ "stm32-metapac/stm32u535cb" ] stm32u535cc = [ "stm32-metapac/stm32u535cc" ] stm32u535ce = [ "stm32-metapac/stm32u535ce" ] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index a3b863340..f25255297 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -97,12 +97,10 @@ fn main() { match (single_bank_selected, dual_bank_selected) { (true, true) => panic!("Both 'single-bank' and 'dual-bank' features enabled"), - (true, false) => { - single_bank_memory.expect("The 'single-bank' feature is not supported on this dual bank chip") - } - (false, true) => { - dual_bank_memory.expect("The 'dual-bank' feature is not supported on this single bank chip") - } + (true, false) => single_bank_memory + .expect("The 'single-bank' feature is not supported on this dual bank chip"), + (false, true) => dual_bank_memory + .expect("The 'dual-bank' feature is not supported on this single bank chip"), (false, false) => { if METADATA.memory.len() != 1 { panic!( @@ -350,8 +348,8 @@ fn main() { }; for tim in [ - "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", "tim22", "tim23", - "tim24", + "tim1", "tim2", "tim3", "tim4", "tim5", "tim8", "tim9", "tim12", "tim15", "tim20", "tim21", + "tim22", "tim23", "tim24", ] { cfgs.declare(format!("time_driver_{}", tim)); } @@ -514,7 +512,12 @@ fn main() { .filter_map(|p| p.registers.as_ref()) .find(|r| r.kind == "rcc") .unwrap(); - let rcc_block = rcc_registers.ir.blocks.iter().find(|b| b.name == "Rcc").unwrap(); + let rcc_block = rcc_registers + .ir + .blocks + .iter() + .find(|b| b.name == "Rcc") + .unwrap(); // ======== // Generate RccPeripheral impls @@ -570,7 +573,7 @@ fn main() { }, ); } - if chip_name.starts_with("stm32u5") { + if chip_name.starts_with("stm32u5") || chip_name.starts_with("stm32U3") { clock_gen.chained_muxes.insert( "ICLK", &PeripheralRccRegister { @@ -669,7 +672,11 @@ fn main() { .find(|i| i.name.eq_ignore_ascii_case(&fieldset_name)) .unwrap(); let field_name = mux.field.to_ascii_lowercase(); - let field = fieldset.fields.iter().find(|i| i.name == field_name).unwrap(); + let field = fieldset + .fields + .iter() + .find(|i| i.name == field_name) + .unwrap(); let enum_name = field.enumm.unwrap(); let enumm = ir.enums.iter().find(|i| i.name == enum_name).unwrap(); @@ -757,7 +764,10 @@ fn main() { }; let enable_offset_and_bit = get_offset_and_bit(en_reg); - let needs_refcount = *rcc_field_count.get(&(en_reg.register, en_reg.field)).unwrap() > 1; + let needs_refcount = *rcc_field_count + .get(&(en_reg.register, en_reg.field)) + .unwrap() + > 1; let refcount_idx = if needs_refcount { let next_refcount_idx = refcount_idxs.len() as u8; let refcount_idx = *refcount_idxs @@ -853,7 +863,11 @@ fn main() { }) } - let enum_names: BTreeSet<_> = clock_gen.muxes.iter().map(|(_, _, enum_name)| enum_name).collect(); + let enum_names: BTreeSet<_> = clock_gen + .muxes + .iter() + .map(|(_, _, enum_name)| enum_name) + .collect(); g.extend(quote! { pub mod mux { @@ -899,7 +913,11 @@ fn main() { clock_gen.clock_names.insert("plli2s1_r".to_string()); } - let clock_idents: Vec<_> = clock_gen.clock_names.iter().map(|n| format_ident!("{}", n)).collect(); + let clock_idents: Vec<_> = clock_gen + .clock_names + .iter() + .map(|n| format_ident!("{}", n)) + .collect(); g.extend(quote! { #[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -1471,7 +1489,9 @@ fn main() { let pin_name = { // If we encounter a _C pin but the split_feature for this pin is not enabled, skip it - if pin.pin.ends_with("_C") && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) { + if pin.pin.ends_with("_C") + && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) + { continue; } @@ -1538,12 +1558,13 @@ fn main() { } else { let reg = format_ident!("{}", afio.register.to_lowercase()); let setter = format_ident!("set_{}", afio.field.to_lowercase()); - let type_and_values = if is_bool_field("AFIO", afio.register, afio.field) { - let values = values.iter().map(|&v| v > 0); - quote!(AfioRemapBool, [#(#values),*]) - } else { - quote!(AfioRemap, [#(#values),*]) - }; + let type_and_values = + if is_bool_field("AFIO", afio.register, afio.field) { + let values = values.iter().map(|&v| v > 0); + quote!(AfioRemapBool, [#(#values),*]) + } else { + quote!(AfioRemap, [#(#values),*]) + }; Some(quote! { pin_trait_afio_impl!(#tr, #peri, #pin_name, {#reg, #setter, #type_and_values}); @@ -1562,11 +1583,12 @@ fn main() { "LPUART", "TIM", ]; - let not_applicable = if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { - quote!(, crate::gpio::AfioRemapNotApplicable) - } else { - quote!() - }; + let not_applicable = + if peripherals_with_afio.iter().any(|&x| p.name.starts_with(x)) { + quote!(, crate::gpio::AfioRemapNotApplicable) + } else { + quote!() + }; Some(quote!(pin_trait_impl!(#tr, #peri, #pin_name, #af #not_applicable);)) }; @@ -1583,7 +1605,9 @@ fn main() { let peri = format_ident!("{}", p.name); let pin_name = { // If we encounter a _C pin but the split_feature for this pin is not enabled, skip it - if pin.pin.ends_with("_C") && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) { + if pin.pin.ends_with("_C") + && !split_features.iter().any(|x| x.pin_name_with_c == pin.pin) + { continue; } format_ident!("{}", pin.pin) @@ -1591,27 +1615,49 @@ fn main() { // H7 has differential voltage measurements let ch: Option<(u8, bool)> = if pin.signal.starts_with("INP") { - Some((pin.signal.strip_prefix("INP").unwrap().parse().unwrap(), false)) + Some(( + pin.signal.strip_prefix("INP").unwrap().parse().unwrap(), + false, + )) } else if pin.signal.starts_with("INN") { - Some((pin.signal.strip_prefix("INN").unwrap().parse().unwrap(), true)) + Some(( + pin.signal.strip_prefix("INN").unwrap().parse().unwrap(), + true, + )) } else if pin.signal.starts_with("IN") && pin.signal.ends_with('b') { // we number STM32L1 ADC bank 1 as 0..=31, bank 2 as 32..=63 - let signal = pin.signal.strip_prefix("IN").unwrap().strip_suffix('b').unwrap(); + let signal = pin + .signal + .strip_prefix("IN") + .unwrap() + .strip_suffix('b') + .unwrap(); Some((32u8 + signal.parse::().unwrap(), false)) } else if pin.signal.starts_with("IN") { - Some((pin.signal.strip_prefix("IN").unwrap().parse().unwrap(), false)) + Some(( + pin.signal.strip_prefix("IN").unwrap().parse().unwrap(), + false, + )) } else { None }; if let Some((ch, false)) = ch { - adc_pairs.entry(ch).or_insert((None, None)).0.replace(pin_name.clone()); + adc_pairs + .entry(ch) + .or_insert((None, None)) + .0 + .replace(pin_name.clone()); g.extend(quote! { impl_adc_pin!( #peri, #pin_name, #ch); }) } if let Some((ch, true)) = ch { - adc_pairs.entry(ch).or_insert((None, None)).1.replace(pin_name.clone()); + adc_pairs + .entry(ch) + .or_insert((None, None)) + .1 + .replace(pin_name.clone()); } } @@ -1711,7 +1757,7 @@ fn main() { (("timer", "CH3"), quote!(crate::timer::Dma)), (("timer", "CH4"), quote!(crate::timer::Dma)), (("cordic", "WRITE"), quote!(crate::cordic::WriteDma)), // FIXME: stm32u5a crash on Cordic driver - (("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver + (("cordic", "READ"), quote!(crate::cordic::ReadDma)), // FIXME: stm32u5a crash on Cordic driver ] .into(); @@ -1787,13 +1833,15 @@ fn main() { let register = format_ident!("{}", remap_info.register.to_lowercase()); let setter = format_ident!("set_{}", remap_info.field.to_lowercase()); - let value = if is_bool_field("SYSCFG", &remap_info.register, &remap_info.field) { - let bool_value = format_ident!("{}", remap_info.value > 0); - quote!(#bool_value) - } else { - let value = remap_info.value; - quote!(#value.into()) - }; + let value = + if is_bool_field("SYSCFG", &remap_info.register, &remap_info.field) + { + let bool_value = format_ident!("{}", remap_info.value > 0); + quote!(#bool_value) + } else { + let value = remap_info.value; + quote!(#value.into()) + }; remap.extend(quote!(crate::pac::SYSCFG.#register().modify(|w| w.#setter(#value));)); } @@ -1828,9 +1876,16 @@ fn main() { fn is_rcc_name(e: &str) -> bool { match e { - "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" | "Prediv2" | "Hpre5" => true, + "Pllp" | "Pllq" | "Pllr" | "Plldivst" | "Pllm" | "Plln" | "Prediv1" + | "Prediv2" | "Hpre5" => true, "Timpre" | "Pllrclkpre" => false, - e if e.ends_with("pre") || e.ends_with("pres") || e.ends_with("div") || e.ends_with("mul") => true, + e if e.ends_with("pre") + || e.ends_with("pres") + || e.ends_with("div") + || e.ends_with("mul") => + { + true + } _ => false, } } @@ -1850,7 +1905,8 @@ fn main() { Err(()) } - if (kind == "rcc" && is_rcc_name(e.name)) || ((kind == "adccommon" || kind == "adc") && is_adc_name(e.name)) + if (kind == "rcc" && is_rcc_name(e.name)) + || ((kind == "adccommon" || kind == "adc") && is_adc_name(e.name)) { let kind = format_ident!("{}", kind); let enum_name = format_ident!("{}", e.name); @@ -1858,7 +1914,10 @@ fn main() { let mut divs = Vec::new(); for v in e.variants { let Ok(val) = parse_num(v.name) else { - panic!("could not parse mul/div. enum={} variant={}", e.name, v.name) + panic!( + "could not parse mul/div. enum={} variant={}", + e.name, v.name + ) }; let variant_name = format_ident!("{}", v.name); let variant = quote!(crate::pac::#kind::vals::#enum_name::#variant_name); @@ -1951,7 +2010,11 @@ fn main() { for pin in METADATA.pins { let port_letter = pin.name.chars().nth(1).unwrap(); let pname = format!("GPIO{}", port_letter); - let p = METADATA.peripherals.iter().find(|p| p.name == pname).unwrap(); + let p = METADATA + .peripherals + .iter() + .find(|p| p.name == pname) + .unwrap(); assert_eq!(0, (p.address as u32 - gpio_base) % gpio_stride); let port_num = (p.address as u32 - gpio_base) / gpio_stride; let pin_num: u32 = pin.name[2..].parse().unwrap(); @@ -1988,14 +2051,22 @@ fn main() { let adc_num = p.name.strip_prefix("ADC").unwrap(); let mut adc_common = None; for p2 in METADATA.peripherals { - if let Some(common_nums) = p2.name.strip_prefix("ADC").and_then(|s| s.strip_suffix("_COMMON")) { + if let Some(common_nums) = p2 + .name + .strip_prefix("ADC") + .and_then(|s| s.strip_suffix("_COMMON")) + { if common_nums.contains(adc_num) { adc_common = Some(p2); } } } let adc_common = adc_common.map(|p| p.name).unwrap_or("none"); - let row = vec![p.name.to_string(), adc_common.to_string(), "adc".to_string()]; + let row = vec![ + p.name.to_string(), + adc_common.to_string(), + "adc".to_string(), + ]; adc_table.push(row); } @@ -2053,7 +2124,10 @@ fn main() { #[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()); + dma_ch_to_irq + .entry(channel) + .or_default() + .push(irq.to_string()); } } @@ -2098,7 +2172,9 @@ fn main() { "dma" => quote!(crate::dma::DmaInfo::Dma(crate::pac::#dma)), "bdma" => quote!(crate::dma::DmaInfo::Bdma(crate::pac::#dma)), "gpdma" => quote!(crate::pac::#dma), - "lpdma" => quote!(unsafe { crate::pac::gpdma::Gpdma::from_ptr(crate::pac::#dma.as_ptr())}), + "lpdma" => { + quote!(unsafe { crate::pac::gpdma::Gpdma::from_ptr(crate::pac::#dma.as_ptr())}) + } _ => panic!("bad dma channel kind {}", bi.kind), }; @@ -2166,7 +2242,12 @@ fn main() { // ======== // Generate gpio_block() function - let gpio_base = METADATA.peripherals.iter().find(|p| p.name == "GPIOA").unwrap().address as usize; + let gpio_base = METADATA + .peripherals + .iter() + .find(|p| p.name == "GPIOA") + .unwrap() + .address as usize; let gpio_stride = 0x400 as usize; for p in METADATA.peripherals { @@ -2231,8 +2312,10 @@ fn main() { cfgs.declare("eeprom"); - let eeprom_memory_regions: Vec<&MemoryRegion> = - memory.iter().filter(|x| x.kind == MemoryRegionKind::Eeprom).collect(); + let eeprom_memory_regions: Vec<&MemoryRegion> = memory + .iter() + .filter(|x| x.kind == MemoryRegionKind::Eeprom) + .collect(); if !eeprom_memory_regions.is_empty() { cfgs.enable("eeprom"); @@ -2252,7 +2335,11 @@ fn main() { "EEPROM regions for chip {} are not contiguous, which is unexpected for L0/L1 series. \ First region: '{}' at {:#X}. Found next non-contiguous region: '{}' at {:#X}. \ Please verify chip metadata. Embassy currently assumes contiguous EEPROM for these series.", - chip_name, sorted_eeprom_regions[0].name, first_eeprom_address, region.name, region.address + chip_name, + sorted_eeprom_regions[0].name, + first_eeprom_address, + region.name, + region.address ); } total_eeprom_size += region.size; @@ -2485,7 +2572,10 @@ fn gen_memory_x(memory: &[MemoryRegion], out_dir: &Path) { } fn get_memory_range(memory: &[MemoryRegion], kind: MemoryRegionKind) -> (u32, u32, String) { - let mut mems: Vec<_> = memory.iter().filter(|m| m.kind == kind && m.size != 0).collect(); + let mut mems: Vec<_> = memory + .iter() + .filter(|m| m.kind == kind && m.size != 0) + .collect(); mems.sort_by_key(|m| m.address); let mut start = u32::MAX; @@ -2524,7 +2614,8 @@ fn mem_filter(chip: &str, region: &str) -> bool { return false; } - if region.starts_with("SDRAM_") || region.starts_with("FMC_") || region.starts_with("OCTOSPI_") { + if region.starts_with("SDRAM_") || region.starts_with("FMC_") || region.starts_with("OCTOSPI_") + { return false; } diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 17b1dae77..2de3c1b81 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -12,7 +12,7 @@ #[cfg_attr(adc_l0, path = "v1.rs")] #[cfg_attr(adc_v2, path = "v2.rs")] #[cfg_attr(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0), path = "v3.rs")] -#[cfg_attr(any(adc_v4, adc_u5), path = "v4.rs")] +#[cfg_attr(any(adc_v4, adc_u5, adc_u3), path = "v4.rs")] #[cfg_attr(adc_g4, path = "g4.rs")] #[cfg_attr(adc_c0, path = "c0.rs")] mod _version; @@ -126,7 +126,7 @@ trait SealedInstance: BasicInstance { } pub(crate) trait SealedAdcChannel { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] + #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_u3, adc_wba))] fn setup(&mut self) {} #[allow(unused)] @@ -138,7 +138,7 @@ pub(crate) trait SealedAdcChannel { } } -#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5))] +#[cfg(any(adc_c0, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3))] /// Number of samples used for averaging. #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -152,18 +152,20 @@ pub enum Averaging { Samples64, Samples128, Samples256, - #[cfg(any(adc_c0, adc_v4, adc_u5))] + #[cfg(any(adc_c0, adc_v4, adc_u5, adc_u3))] Samples512, - #[cfg(any(adc_c0, adc_v4, adc_u5))] + #[cfg(any(adc_c0, adc_v4, adc_u5, adc_u3))] Samples1024, } #[cfg(any( - adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0 + adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0 ))] pub(crate) enum ConversionMode { // Should match the cfg on "read" below - #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] + #[cfg(any( + adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0 + ))] Singular, // Should match the cfg on "into_ring_buffered" below #[cfg(any(adc_v2, adc_g4, adc_v3, adc_g0, adc_u0))] @@ -184,7 +186,7 @@ pub enum RegularConversionMode { impl<'d, T: Instance> Adc<'d, T> { #[cfg(any( - adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u5, adc_v3, adc_v4, adc_wba, adc_c0 + adc_v2, adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_u3, adc_u5, adc_v3, adc_v4, adc_wba, adc_c0 ))] /// Read an ADC pin. pub fn blocking_read( @@ -192,12 +194,12 @@ impl<'d, T: Instance> Adc<'d, T> { channel: &mut impl AdcChannel, sample_time: ::SampleTime, ) -> u16 { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] + #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba))] channel.setup(); // Ensure no conversions are ongoing T::regs().stop(); - #[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u5, adc_wba, adc_c0))] + #[cfg(any(adc_v2, adc_v3, adc_g0, adc_h7rs, adc_u0, adc_u3, adc_u5, adc_wba, adc_c0))] T::regs().enable(); T::regs().configure_sequence([((channel.channel(), channel.is_differential()), sample_time)].into_iter()); @@ -211,7 +213,9 @@ impl<'d, T: Instance> Adc<'d, T> { unsafe { core::ptr::read_volatile(T::regs().data()) } } - #[cfg(any(adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] + #[cfg(any( + adc_g4, adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_u3, adc_wba, adc_c0 + ))] /// Read one or multiple ADC regular channels using DMA. /// /// `readings` must have a length that is a multiple of the length of the `sequence` iterator. @@ -263,7 +267,7 @@ impl<'d, T: Instance> Adc<'d, T> { // Ensure no conversions are ongoing T::regs().stop(); - #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u5, adc_wba, adc_c0))] + #[cfg(any(adc_g0, adc_v3, adc_h7rs, adc_u0, adc_v4, adc_u3, adc_u5, adc_wba, adc_c0))] T::regs().enable(); T::regs().configure_sequence( @@ -401,7 +405,7 @@ impl SpecialChannel for Dac {} /// ADC instance. #[cfg(not(any( adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, - adc_u5, adc_c0, adc_wba, + adc_u5, adc_u3, adc_c0, adc_wba, )))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType { @@ -410,7 +414,7 @@ pub trait Instance: SealedInstance + crate::PeripheralType { /// ADC instance. #[cfg(any( adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, - adc_u5, adc_c0, adc_wba, + adc_u5, adc_u3, adc_c0, adc_wba, ))] #[allow(private_bounds)] pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral { @@ -425,7 +429,7 @@ pub trait AdcChannel: SealedAdcChannel + Sized { where Self: 'a, { - #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] + #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba))] self.setup(); AnyAdcChannel { @@ -600,7 +604,9 @@ macro_rules! impl_adc_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::adc::AdcChannel for crate::Peri<'_, crate::peripherals::$pin> {} impl crate::adc::SealedAdcChannel for crate::Peri<'_, crate::peripherals::$pin> { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] + #[cfg(any( + adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba + ))] fn setup(&mut self) { ::set_as_analog(self); } @@ -628,7 +634,7 @@ macro_rules! impl_adc_pair { crate::Peri<'_, crate::peripherals::$npin>, ) { - #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u5, adc_wba))] + #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v3, adc_v4, adc_u3, adc_u5, adc_wba))] fn setup(&mut self) { ::set_as_analog(&mut self.0); ::set_as_analog(&mut self.1); diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 962816194..69d406b7e 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -1,7 +1,10 @@ -#[cfg(not(stm32u5))] +#[cfg(not(stm32u3))] +use pac::adc::vals::Difsel; +#[cfg(not(any(stm32u5, stm32u3)))] use pac::adc::vals::{Adcaldif, Boost}; #[allow(unused)] -use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; +use pac::adc::vals::{Adstp, Dmngt, Exten, Pcsel}; +#[cfg(not(stm32u3))] use pac::adccommon::vals::Presc; use super::{Adc, Averaging, Instance, Resolution, SampleTime, Temperature, Vbat, VrefInt, blocking_delay_us}; @@ -23,6 +26,8 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); #[cfg(stm32u5)] const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); +#[cfg(stm32u3)] +const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(48); #[cfg(stm32g4)] impl super::SealedSpecialConverter for T { @@ -43,12 +48,12 @@ impl super::SealedSpecialConverter for T { } // TODO this should be 14 for H7a/b/35 -#[cfg(not(stm32u5))] +#[cfg(not(any(stm32u5, stm32u3)))] impl super::SealedSpecialConverter for T { const CHANNEL: u8 = 17; } -#[cfg(stm32u5)] +#[cfg(any(stm32u5, stm32u3))] impl super::SealedSpecialConverter for T { const CHANNEL: u8 = 0; } @@ -61,6 +66,17 @@ impl super::SealedSpecialConverter for T { const CHANNEL: u8 = 18; } +#[cfg(stm32u3)] +impl super::SealedSpecialConverter for T { + const CHANNEL: u8 = 16; +} + +#[cfg(stm32u3)] +impl super::SealedSpecialConverter for T { + const CHANNEL: u8 = 17; +} + +#[cfg(not(stm32u3))] fn from_ker_ck(frequency: Hertz) -> Presc { let raw_prescaler = rcc::raw_prescaler(frequency.0, MAX_ADC_CLK_FREQ.0); match raw_prescaler { @@ -163,7 +179,7 @@ impl AdcRegs for crate::pac::adc::Adc { self.smpr(1).modify(|reg| reg.set_smp((channel - 10) as _, sample_time)); } - #[cfg(any(stm32h7, stm32u5))] + #[cfg(any(stm32h7, stm32u5, stm32u3))] { self.cfgr2().modify(|w| w.set_lshift(0)); self.pcsel().modify(|w| w.set_pcsel(channel as _, Pcsel::PRESELECTED)); @@ -202,7 +218,9 @@ impl<'d, T: Instance> Adc<'d, T> { // Set the ADC resolution. if let Some(resolution) = config.resolution { - T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); + T::regs() + .cfgr() + .modify(|reg| reg.set_res(resolution.into())); } // Set hardware averaging. @@ -235,11 +253,16 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: Peri<'d, T>) -> Self { rcc::enable_and_reset::(); + #[cfg(not(stm32u3))] let prescaler = from_ker_ck(T::frequency()); - + #[cfg(not(stm32u3))] T::common_regs().ccr().modify(|w| w.set_presc(prescaler)); - + #[cfg(not(stm32u3))] let frequency = T::frequency() / prescaler; + + #[cfg(stm32u3)] + let frequency = T::frequency(); + info!("ADC frequency set to {}", frequency); if frequency > MAX_ADC_CLK_FREQ { @@ -270,12 +293,14 @@ impl<'d, T: Instance> Adc<'d, T> { blocking_delay_us(10); + #[cfg(not(stm32u3))] T::regs().difsel().modify(|w| { for n in 0..20 { w.set_difsel(n, Difsel::SINGLE_ENDED); } }); + #[cfg(not(stm32u3))] T::regs().cr().modify(|w| { #[cfg(not(adc_u5))] w.set_adcaldif(Adcaldif::SINGLE_ENDED); diff --git a/embassy-stm32/src/dac/tsel.rs b/embassy-stm32/src/dac/tsel.rs index 1877954b9..9fe9428dd 100644 --- a/embassy-stm32/src/dac/tsel.rs +++ b/embassy-stm32/src/dac/tsel.rs @@ -160,7 +160,7 @@ pub enum TriggerSel { } /// Trigger selection for L4+, L5, U5, H7. -#[cfg(any(stm32l4_plus, stm32l5, stm32u5, stm32h7))] +#[cfg(any(stm32l4_plus, stm32l5, stm32u5, stm32u3, stm32h7))] #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum TriggerSel { @@ -168,9 +168,11 @@ pub enum TriggerSel { Tim1 = 1, Tim2 = 2, Tim4 = 3, + #[cfg(not(stm32u3))] Tim5 = 4, Tim6 = 5, Tim7 = 6, + #[cfg(not(stm32u3))] Tim8 = 7, Tim15 = 8, #[cfg(all(stm32h7, hrtim))] @@ -178,9 +180,9 @@ pub enum TriggerSel { #[cfg(all(stm32h7, hrtim))] Hrtim1DacTrg2 = 10, Lptim1 = 11, - #[cfg(not(stm32u5))] + #[cfg(not(any(stm32u5, stm32u3)))] Lptim2 = 12, - #[cfg(stm32u5)] + #[cfg(any(stm32u5, stm32u3))] Lptim3 = 12, Exti9 = 13, #[cfg(any(stm32h7ax, stm32h7bx))] diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 458174b5d..5aa3982c5 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -34,11 +34,13 @@ fn cpu_regs() -> pac::exti::Exti { EXTI } -#[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50, exti_n6)))] +#[cfg(not(any( + exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6 +)))] fn exticr_regs() -> pac::syscfg::Syscfg { pac::SYSCFG } -#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))] +#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6))] fn exticr_regs() -> pac::exti::Exti { EXTI } @@ -48,9 +50,9 @@ fn exticr_regs() -> pac::afio::Afio { } unsafe fn on_irq() { - #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6)))] + #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6)))] let bits = EXTI.pr(0).read().0; - #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))] + #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6))] let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0; // We don't handle or change any EXTI lines above 16. @@ -65,9 +67,9 @@ unsafe fn on_irq() { } // Clear pending - #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6)))] + #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6)))] EXTI.pr(0).write_value(Lines(bits)); - #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50, exti_n6))] + #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_u3, exti_h5, exti_h50, exti_n6))] { EXTI.rpr(0).write_value(Lines(bits)); EXTI.fpr(0).write_value(Lines(bits)); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index a0b2f045c..dfa3d934e 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -271,11 +271,11 @@ pub struct Config { /// which needs to be enabled before these pins can be used. /// /// May increase power consumption. Defaults to true. - #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] + #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u3, stm32wba))] pub enable_independent_io_supply: bool, /// On the U5 series all analog peripherals are powered by a separate supply. - #[cfg(stm32u5)] + #[cfg(any(stm32u5, stm32u3))] pub enable_independent_analog_supply: bool, /// BDMA interrupt priority. @@ -319,9 +319,9 @@ impl Default for Config { min_stop_pause: embassy_time::Duration::from_millis(250), #[cfg(dbgmcu)] enable_debug_during_sleep: true, - #[cfg(any(stm32l4, stm32l5, stm32u5, stm32wba))] + #[cfg(any(stm32l4, stm32l5, stm32u5, stm32u3, stm32wba))] enable_independent_io_supply: true, - #[cfg(stm32u5)] + #[cfg(any(stm32u5, stm32u3))] enable_independent_analog_supply: true, #[cfg(bdma)] bdma_interrupt_priority: Priority::P0, @@ -393,7 +393,10 @@ mod dual_core { /// /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs /// for more information on its requirements. - pub fn init_primary(config: Config, shared_data: &'static MaybeUninit) -> Peripherals { + pub fn init_primary( + config: Config, + shared_data: &'static MaybeUninit, + ) -> Peripherals { let shared_data = unsafe { shared_data.assume_init_ref() }; // Write the flag as soon as possible. Reading this flag uninitialized in the `init_secondary` @@ -406,7 +409,9 @@ mod dual_core { unsafe { *shared_data.config.get() }.write(config.into()); - shared_data.init_flag.store(INIT_DONE_FLAG, Ordering::SeqCst); + shared_data + .init_flag + .store(INIT_DONE_FLAG, Ordering::SeqCst); p } @@ -420,7 +425,9 @@ mod dual_core { /// /// The `shared_data` is used to coordinate the init with the second core. Read the [SharedData] docs /// for more information on its requirements. - pub fn try_init_secondary(shared_data: &'static MaybeUninit) -> Option { + pub fn try_init_secondary( + shared_data: &'static MaybeUninit, + ) -> Option { let shared_data = unsafe { shared_data.assume_init_ref() }; if shared_data.init_flag.load(Ordering::SeqCst) != INIT_DONE_FLAG { @@ -536,14 +543,17 @@ fn init_hw(config: Config) -> Peripherals { cr.set_stop(config.enable_debug_during_sleep); cr.set_standby(config.enable_debug_during_sleep); } - #[cfg(any(dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u0, dbgmcu_u5, dbgmcu_wba, dbgmcu_l5))] + #[cfg(any( + dbgmcu_f0, dbgmcu_c0, dbgmcu_g0, dbgmcu_u0, dbgmcu_u3, dbgmcu_u5, dbgmcu_wba, + dbgmcu_l5 + ))] { cr.set_dbg_stop(config.enable_debug_during_sleep); cr.set_dbg_standby(config.enable_debug_during_sleep); } #[cfg(any( - dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, dbgmcu_l0, dbgmcu_l1, - dbgmcu_l4, dbgmcu_wb, dbgmcu_wl, dbgmcu_n6 + dbgmcu_f1, dbgmcu_f2, dbgmcu_f3, dbgmcu_f4, dbgmcu_f7, dbgmcu_g4, dbgmcu_f7, + dbgmcu_l0, dbgmcu_l1, dbgmcu_l4, dbgmcu_wb, dbgmcu_wl, dbgmcu_n6 ))] { cr.set_dbg_sleep(config.enable_debug_during_sleep); @@ -564,7 +574,10 @@ fn init_hw(config: Config) -> Peripherals { rcc::enable_and_reset_with_cs::(cs); #[cfg(not(any(stm32h5, stm32h7, stm32h7rs, stm32wb, stm32wl)))] rcc::enable_and_reset_with_cs::(cs); - #[cfg(all(flash, not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs))))] + #[cfg(all( + flash, + not(any(stm32f2, stm32f4, stm32f7, stm32l0, stm32h5, stm32h7, stm32h7rs)) + ))] rcc::enable_and_reset_with_cs::(cs); // Enable the VDDIO2 power supply on chips that have it. @@ -589,7 +602,7 @@ fn init_hw(config: Config) -> Peripherals { }); }); } - #[cfg(stm32u5)] + #[cfg(any(stm32u5, stm32u3))] { crate::pac::PWR.svmcr().modify(|w| { w.set_io2sv(config.enable_independent_io_supply); diff --git a/embassy-stm32/src/rcc/bd.rs b/embassy-stm32/src/rcc/bd.rs index 219be208f..6225b970c 100644 --- a/embassy-stm32/src/rcc/bd.rs +++ b/embassy-stm32/src/rcc/bd.rs @@ -25,7 +25,7 @@ pub struct LseConfig { pub frequency: Hertz, pub mode: LseMode, /// If peripherals other than RTC/TAMP or RCC functions need the lse this bit must be set - #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba))] + #[cfg(any(rcc_l5, rcc_u5, rcc_u3, rcc_wle, rcc_wl5, rcc_wba))] pub peripherals_clocked: bool, } @@ -71,10 +71,10 @@ fn unlock() { #[cfg(any(stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1))] let cr = crate::pac::PWR.cr(); #[cfg(not(any( - stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32h5, stm32wba, stm32n6 + stm32f0, stm32f1, stm32f2, stm32f3, stm32l0, stm32l1, stm32u5, stm32u3, stm32h5, stm32wba, stm32n6 )))] let cr = crate::pac::PWR.cr1(); - #[cfg(any(stm32u5, stm32h5, stm32wba, stm32n6))] + #[cfg(any(stm32u5, stm32u3, stm32h5, stm32wba, stm32n6))] let cr = crate::pac::PWR.dbpcr(); cr.modify(|w| w.set_dbp(true)); @@ -118,7 +118,7 @@ impl LsConfig { lse: Some(LseConfig { frequency: Hertz(32_768), mode: LseMode::Oscillator(LseDrive::MediumHigh), - #[cfg(any(rcc_l5, rcc_u5, rcc_wle, rcc_wl5, rcc_wba))] + #[cfg(any(rcc_l5, rcc_u5, rcc_u3, rcc_wle, rcc_wl5, rcc_wba))] peripherals_clocked: false, }), lsi: false, diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs index 50ac162a4..1e063aed5 100644 --- a/embassy-stm32/src/rcc/hsi48.rs +++ b/embassy-stm32/src/rcc/hsi48.rs @@ -39,9 +39,11 @@ pub(crate) fn init_hsi48(config: Hsi48Config) -> Hertz { }); // Enable HSI48 - #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0, stm32c071)))] + #[cfg(not(any( + stm32u5, stm32u3, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0, stm32c071 + )))] let r = RCC.crrcr(); - #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32c071))] + #[cfg(any(stm32u5, stm32u3, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32c071))] let r = RCC.cr(); #[cfg(any(stm32f0))] let r = RCC.cr2(); diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 0624fdf26..e66170909 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -4,6 +4,35 @@ use embassy_hal_internal::PeripheralType; use crate::gpio::{AfType, OutputType, Speed}; use crate::pac::RCC; +#[cfg(any( + rcc_f2, + rcc_f410, + rcc_f4, + rcc_f7, + rcc_h50, + rcc_h5, + rcc_h7ab, + rcc_h7rm0433, + rcc_h7, + rcc_h7rs, + rcc_n6 +))] +pub use crate::pac::rcc::vals::Mco1sel as Mco1Source; +#[cfg(any( + rcc_f2, + rcc_f410, + rcc_f4, + rcc_f7, + rcc_h50, + rcc_h5, + rcc_h7ab, + rcc_h7rm0433, + rcc_h7, + rcc_h7rs, + rcc_n6, + rcc_u3, +))] +pub use crate::pac::rcc::vals::Mco2sel as Mco2Source; #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; #[cfg(not(any( @@ -20,20 +49,7 @@ pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; rcc_n6 )))] pub use crate::pac::rcc::vals::Mcosel as McoSource; -#[cfg(any( - rcc_f2, - rcc_f410, - rcc_f4, - rcc_f7, - rcc_h50, - rcc_h5, - rcc_h7ab, - rcc_h7rm0433, - rcc_h7, - rcc_h7rs, - rcc_n6 -))] -pub use crate::pac::rcc::vals::{Mco1sel as Mco1Source, Mco2sel as Mco2Source}; + use crate::{Peri, peripherals}; #[cfg(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37))] @@ -61,9 +77,9 @@ macro_rules! impl_peri { type Source = $source; unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { - #[cfg(not(any(stm32u5, stm32wba, stm32n6)))] + #[cfg(not(any(stm32u3, stm32u5, stm32wba, stm32n6)))] let r = RCC.cfgr(); - #[cfg(any(stm32u5, stm32wba))] + #[cfg(any(stm32u3, stm32u5, stm32wba))] let r = RCC.cfgr1(); #[cfg(any(stm32n6))] let r = RCC.ccipr5(); diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 753ee1290..200f7fb19 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -28,6 +28,7 @@ pub use hsi48::*; #[cfg_attr(stm32g4, path = "g4.rs")] #[cfg_attr(any(stm32h5, stm32h7, stm32h7rs), path = "h.rs")] #[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")] +#[cfg_attr(stm32u3, path = "u3.rs")] #[cfg_attr(stm32u5, path = "u5.rs")] #[cfg_attr(stm32wba, path = "wba.rs")] #[cfg_attr(stm32n6, path = "n6.rs")] diff --git a/embassy-stm32/src/rcc/u3.rs b/embassy-stm32/src/rcc/u3.rs new file mode 100644 index 000000000..73d9b926a --- /dev/null +++ b/embassy-stm32/src/rcc/u3.rs @@ -0,0 +1,555 @@ +use stm32_metapac::rcc::vals::{Msikdiv, Msisdiv, Msissel}; + +// pub use crate::pac::pwr::vals::Vosr as VoltageScale; +pub use crate::pac::rcc::vals::{Hpre as AHBPrescaler, Ppre as APBPrescaler, Sw as Sysclk}; +use crate::pac::rcc::vals::{Hseext, Msipllsel, Msirgsel}; +use crate::pac::{FLASH, PWR, RCC}; +use crate::rcc::LSI_FREQ; +use crate::time::Hertz; + +/// HSI speed +pub const HSI_FREQ: Hertz = Hertz(16_000_000); + +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum VoltageScale { + /// High performance range (system clock freq up to 96MHz) + RANGE1, + /// Low power range (system clock freq up to 48MHz) + RANGE2, +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum MSIRange { + /// MSIRC0 + /// Range 0: 96 MHz + RANGE0_96MHZ, + /// Range 1: 48 MHz + RANGE1_48MHZ, + /// Range 2/4: 24 MHz + RANGE2_24MHZ, + /// Range 3/5: 12 MHz + RANGE3_12MHZ, + /// MSIRC1 + /// Range 4: 24 MHz + RANGE4_24MHZ, + /// Range 5: 12 MHz + RANGE5_12MHZ, + /// Range 6: 6 MHz + RANGE6_6MHZ, + /// Range 7: 3 MHz + RANGE7_3MHZ, +} + +impl From for Msisdiv { + fn from(range: MSIRange) -> Self { + match range { + MSIRange::RANGE0_96MHZ => Msisdiv::DIV1, + MSIRange::RANGE1_48MHZ => Msisdiv::DIV2, + MSIRange::RANGE2_24MHZ => Msisdiv::DIV4, + MSIRange::RANGE3_12MHZ => Msisdiv::DIV8, + MSIRange::RANGE4_24MHZ => Msisdiv::DIV1, + MSIRange::RANGE5_12MHZ => Msisdiv::DIV2, + MSIRange::RANGE6_6MHZ => Msisdiv::DIV4, + MSIRange::RANGE7_3MHZ => Msisdiv::DIV8, + } + } +} + +impl From for Msikdiv { + fn from(range: MSIRange) -> Self { + match range { + MSIRange::RANGE0_96MHZ => Msikdiv::DIV1, + MSIRange::RANGE1_48MHZ => Msikdiv::DIV2, + MSIRange::RANGE2_24MHZ => Msikdiv::DIV4, + MSIRange::RANGE3_12MHZ => Msikdiv::DIV8, + MSIRange::RANGE4_24MHZ => Msikdiv::DIV1, + MSIRange::RANGE5_12MHZ => Msikdiv::DIV2, + MSIRange::RANGE6_6MHZ => Msikdiv::DIV4, + MSIRange::RANGE7_3MHZ => Msikdiv::DIV8, + } + } +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub enum HseMode { + /// crystal/ceramic oscillator (HSEBYP=0) + Oscillator, + /// external analog clock (low swing) (HSEBYP=1, HSEEXT=0) + Bypass, + /// external digital clock (full swing) (HSEBYP=1, HSEEXT=1) + BypassDigital, +} + +#[derive(Clone, Copy, Eq, PartialEq)] +pub struct Hse { + /// HSE frequency. + pub freq: Hertz, + /// HSE mode. + pub mode: HseMode, +} + +#[derive(Clone, Copy, PartialEq)] +pub enum MsiAutoCalibration { + /// MSI auto-calibration is disabled + Disabled, + /// MSIS is given priority for auto-calibration + MSIS, + /// MSIK is given priority for auto-calibration + MSIK, + /// MSIS with fast mode (always on) + MsisFast, + /// MSIK with fast mode (always on) + MsikFast, +} + +impl MsiAutoCalibration { + const fn default() -> Self { + MsiAutoCalibration::Disabled + } + + fn base_mode(&self) -> Self { + match self { + MsiAutoCalibration::Disabled => MsiAutoCalibration::Disabled, + MsiAutoCalibration::MSIS => MsiAutoCalibration::MSIS, + MsiAutoCalibration::MSIK => MsiAutoCalibration::MSIK, + MsiAutoCalibration::MsisFast => MsiAutoCalibration::MSIS, + MsiAutoCalibration::MsikFast => MsiAutoCalibration::MSIK, + } + } + + fn is_fast(&self) -> bool { + matches!( + self, + MsiAutoCalibration::MsisFast | MsiAutoCalibration::MsikFast + ) + } +} + +impl Default for MsiAutoCalibration { + fn default() -> Self { + Self::default() + } +} + +#[derive(Clone, Copy)] +pub struct Config { + // base clock sources + pub msis: Option, + pub msik: Option, + pub hsi: bool, + pub hse: Option, + pub hsi48: Option, + + // sysclk, buses. + pub sys: Sysclk, + pub ahb_pre: AHBPrescaler, + pub apb1_pre: APBPrescaler, + pub apb2_pre: APBPrescaler, + pub apb3_pre: APBPrescaler, + + /// The voltage range influences the maximum clock frequencies for different parts of the + /// device. In particular, system clocks exceeding 48 MHz require `RANGE1`. + /// + /// See RM0487 § 10.2.3 for clock source frequency limits. + pub voltage_range: VoltageScale, + pub ls: super::LsConfig, + + /// Per-peripheral kernel clock selection muxes + pub mux: super::mux::ClockMux, + pub auto_calibration: MsiAutoCalibration, +} + +impl Config { + pub const fn new() -> Self { + Self { + msis: Some(MSIRange::RANGE5_12MHZ), + msik: Some(MSIRange::RANGE5_12MHZ), + hse: None, + hsi: false, + hsi48: Some(crate::rcc::Hsi48Config::new()), + sys: Sysclk::MSIS, + ahb_pre: AHBPrescaler::DIV1, + apb1_pre: APBPrescaler::DIV1, + apb2_pre: APBPrescaler::DIV1, + apb3_pre: APBPrescaler::DIV1, + voltage_range: VoltageScale::RANGE1, + ls: crate::rcc::LsConfig::new(), + mux: super::mux::ClockMux::default(), + auto_calibration: MsiAutoCalibration::default(), + } + } +} + +impl Default for Config { + fn default() -> Self { + Self::new() + } +} + +pub(crate) unsafe fn init(config: Config) { + // Set the requested power mode + // Voltage range enable bits must be at opposite values and can + // only be set once the current range is ready. See RM0487 § 9.5.4. + match config.voltage_range { + VoltageScale::RANGE1 => { + if PWR.vosr().read().r2en() { + while !PWR.vosr().read().r2rdy() {} + } + PWR.vosr().modify(|w| { + w.set_r1en(true); + w.set_r2en(false); + }); + while !PWR.vosr().read().r1rdy() {} + } + VoltageScale::RANGE2 => { + if PWR.vosr().read().r1en() { + while !PWR.vosr().read().r1rdy() {} + } + PWR.vosr().modify(|w| { + w.set_r2en(true); + w.set_r1en(false); + }); + while !PWR.vosr().read().r2rdy() {} + } + } + + let lse_calibration_freq = if config.auto_calibration != MsiAutoCalibration::Disabled { + // LSE must be configured and peripherals clocked for MSI auto-calibration + let lse_config = config + .ls + .lse + .clone() + .expect("LSE must be configured for MSI auto-calibration"); + assert!(lse_config.peripherals_clocked); + + // Expect less than +/- 5% deviation for LSE frequency + if (31_100..=34_400).contains(&lse_config.frequency.0) { + // Check that the calibration is applied to an active clock + match ( + config.auto_calibration.base_mode(), + config.msis.is_some(), + config.msik.is_some(), + ) { + (MsiAutoCalibration::MSIS, true, _) => { + // MSIS is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + (MsiAutoCalibration::MSIK, _, true) => { + // MSIK is active and using LSE for auto-calibration + Some(lse_config.frequency) + } + // improper configuration + _ => panic!( + "MSIx auto-calibration is enabled for a source that has not been configured." + ), + } + } else { + panic!( + "LSE frequency more than 5% off from 32.768 kHz, cannot use for MSI auto-calibration" + ); + } + } else { + None + }; + + let mut msis = config.msis.map(|range| { + // Check MSI output per RM0487 § 10.2.3 Table 98 + match config.voltage_range { + VoltageScale::RANGE2 => { + assert!(msirange_to_hertz(range).0 <= 48_000_000); + } + _ => {} + } + + // RM0487 § 10.5.2: spin until MSIS is off or MSIS is ready before setting its range + loop { + let cr = RCC.cr().read(); + if cr.msison() == false || cr.msisrdy() == true { + break; + } + } + + // Use MSIRC0 or MSIRC1 depending on requested range. + let msissel = if msirange_to_hertz(range).0 <= 24_000_000 { + Msissel::MSIRC1_24MHZ + } else { + Msissel::MSIRC0_96MHZ + }; + RCC.icscr1().modify(|w| { + w.set_msissel(msissel); + w.set_msisdiv(range.into()); + w.set_msirgsel(Msirgsel::RCC_ICSCR1); + }); + RCC.cr().write(|w| { + // Out of reset MSIPLLxEN and MSIPLLSEL are 0 + // and msison is true + w.set_msipll0en(false); + w.set_msipll1en(false); + w.set_msison(true); + }); + let msis = if let (Some(freq), MsiAutoCalibration::MSIS) = + (lse_calibration_freq, config.auto_calibration.base_mode()) + { + // Enable the MSIS auto-calibration feature + if msissel == Msissel::MSIRC0_96MHZ { + RCC.icscr1().modify(|w| w.set_msipll0sel(Msipllsel::LSE)); + RCC.cr().modify(|w| w.set_msipll0en(true)); + } else { + RCC.icscr1().modify(|w| w.set_msipll1sel(Msipllsel::LSE)); + RCC.cr().modify(|w| w.set_msipll1en(true)); + } + calculate_calibrated_msi_frequency(range, freq) + } else { + msirange_to_hertz(range) + }; + while !RCC.cr().read().msisrdy() {} + msis + }); + + let mut msik = config.msik.map(|range| { + // Check MSI output per RM0456 § 11.4.10 + match config.voltage_range { + VoltageScale::RANGE2 => { + assert!(msirange_to_hertz(range).0 <= 48_000_000); + } + _ => {} + } + + // RM0456 § 11.8.2: spin until MSIK is off or MSIK is ready before setting its range + loop { + let cr = RCC.cr().read(); + if cr.msikon() == false || cr.msikrdy() == true { + break; + } + } + + RCC.icscr1().modify(|w| { + w.set_msikdiv(range.into()); + w.set_msirgsel(Msirgsel::RCC_ICSCR1); + }); + RCC.cr().modify(|w| { + w.set_msikon(true); + }); + let msik = if let (Some(freq), MsiAutoCalibration::MSIK) = + (lse_calibration_freq, config.auto_calibration.base_mode()) + { + // Enable the MSIK auto-calibration feature + + // RCC.cr().modify(|w| w.set_msipllsel(Msipllsel::MSIK)); + // RCC.cr().modify(|w| w.set_msipllen(true)); + calculate_calibrated_msi_frequency(range, freq) + } else { + msirange_to_hertz(range) + }; + while !RCC.cr().read().msikrdy() {} + msik + }); + + if let Some(lse_freq) = lse_calibration_freq { + // If both MSIS and MSIK are enabled, we need to check if they are using the same internal source. + if let (Some(msis_range), Some(msik_range)) = (config.msis, config.msik) { + if msis_range == msik_range { + // Clock source is shared, both will be auto calibrated, recalculate other frequency + match config.auto_calibration.base_mode() { + MsiAutoCalibration::MSIS => { + msik = Some(calculate_calibrated_msi_frequency(msik_range, lse_freq)); + } + MsiAutoCalibration::MSIK => { + msis = Some(calculate_calibrated_msi_frequency(msis_range, lse_freq)); + } + _ => {} + } + } + } + // Check if Fast mode should be used + if config.auto_calibration.is_fast() { + RCC.cr().modify(|w| { + // TODO clean this up to select the correct MSIPLLxFAST bit + w.set_msipll0fast(true); + // w.set_msipllfast(Msipllfast::FAST); + }); + } + } + + let hsi = config.hsi.then(|| { + RCC.cr().modify(|w| w.set_hsion(true)); + while !RCC.cr().read().hsirdy() {} + + HSI_FREQ + }); + + let hse = config.hse.map(|hse| { + // Check frequency limits per RM456 § 11.4.10 + match config.voltage_range { + VoltageScale::RANGE1 => { + assert!(hse.freq.0 <= 50_000_000); + } + VoltageScale::RANGE2 => { + assert!(hse.freq.0 <= 48_000_000); + } + } + + // Enable HSE, and wait for it to stabilize + RCC.cr().modify(|w| { + w.set_hseon(true); + w.set_hsebyp(hse.mode != HseMode::Oscillator); + w.set_hseext(match hse.mode { + HseMode::Oscillator | HseMode::Bypass => Hseext::ANALOG, + HseMode::BypassDigital => Hseext::DIGITAL, + }); + }); + while !RCC.cr().read().hserdy() {} + + hse.freq + }); + + let hsi48 = config.hsi48.map(super::init_hsi48); + + // let pll_input = PllInput { hse, hsi, msi: msis }; + // let pll1 = init_pll(PllInstance::Pll1, config.pll1, &pll_input, config.voltage_range); + // let pll2 = init_pll(PllInstance::Pll2, config.pll2, &pll_input, config.voltage_range); + // let pll3 = init_pll(PllInstance::Pll3, config.pll3, &pll_input, config.voltage_range); + + let sys_clk = match config.sys { + Sysclk::HSE => hse.unwrap(), + Sysclk::HSI16 => hsi.unwrap(), + Sysclk::MSIS => msis.unwrap(), + Sysclk::_RESERVED_3 => unreachable!(), + // Sysclk:: => pll1.r.unwrap(), + }; + + // Do we need the EPOD booster to reach the target clock speed per § 10.5.4? + if sys_clk >= Hertz::mhz(24) { + // Enable the booster + PWR.vosr().modify(|w| w.set_boosten(true)); + while !PWR.vosr().read().boostrdy() {} + } + + // The clock source is ready + // Calculate and set the flash wait states + // TODO: add wait states for low power modes + let wait_states = match config.voltage_range { + // VOS 1 range VCORE 1.26V - 1.40V + VoltageScale::RANGE1 => match sys_clk.0 { + ..=32_000_000 => 0, + ..=64_000_000 => 1, + ..=96_000_000 => 2, + _ => 3, + }, + // VOS 2 range VCORE 1.15V - 1.26V + VoltageScale::RANGE2 => match sys_clk.0 { + ..=16_000_000 => 0, + ..=32_000_000 => 1, + ..=48_000_000 => 2, + _ => 3, + }, + }; + FLASH.acr().modify(|w| { + w.set_latency(wait_states); + }); + + // Switch the system clock source + RCC.cfgr1().modify(|w| w.set_sw(config.sys)); + while RCC.cfgr1().read().sw() != config.sys {} + + // Configure the bus prescalers + RCC.cfgr2().modify(|w| { + w.set_hpre(config.ahb_pre); + w.set_ppre1(config.apb1_pre); + w.set_ppre2(config.apb2_pre); + }); + RCC.cfgr3().modify(|w| { + w.set_ppre3(config.apb3_pre); + }); + + let hclk = sys_clk / config.ahb_pre; + + let hclk_max = match config.voltage_range { + VoltageScale::RANGE1 => Hertz::mhz(96), + VoltageScale::RANGE2 => Hertz::mhz(48), + }; + assert!(hclk <= hclk_max); + + let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk, config.apb1_pre); + let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk, config.apb2_pre); + let (pclk3, _) = super::util::calc_pclk(hclk, config.apb3_pre); + + let rtc = config.ls.init(); + let lse = config.ls.lse.map(|l| l.frequency); + let lsi = config.ls.lsi.then_some(LSI_FREQ); + + config.mux.init(); + + set_clocks!( + sys: Some(sys_clk), + hclk1: Some(hclk), + hclk2: Some(hclk), + hclk3: Some(hclk), + pclk1: Some(pclk1), + pclk2: Some(pclk2), + pclk3: Some(pclk3), + pclk1_tim: Some(pclk1_tim), + pclk2_tim: Some(pclk2_tim), + msik: msik, + hsi48: hsi48, + rtc: rtc, + lse: lse, + lsi: lsi, + hse: hse, + hsi: hsi, + + // TODO + audioclk: None, + shsi: None, + ); +} + +fn msirange_to_hertz(range: MSIRange) -> Hertz { + match range { + MSIRange::RANGE0_96MHZ => Hertz(96_000_000), + MSIRange::RANGE1_48MHZ => Hertz(48_000_000), + MSIRange::RANGE2_24MHZ => Hertz(24_000_000), + MSIRange::RANGE3_12MHZ => Hertz(12_000_000), + MSIRange::RANGE4_24MHZ => Hertz(12_000_000), + MSIRange::RANGE5_12MHZ => Hertz(12_000_000), + MSIRange::RANGE6_6MHZ => Hertz(6_000_000), + MSIRange::RANGE7_3MHZ => Hertz(3_000_000), + } +} + +/// Fraction structure for MSI auto-calibration +/// Represents the multiplier as numerator/denominator that LSE frequency is multiplied by +#[derive(Debug, Clone, Copy)] +struct MsiFraction { + numerator: u32, + denominator: u32, +} + +impl MsiFraction { + const fn new(numerator: u32, denominator: u32) -> Self { + Self { + numerator, + denominator, + } + } + + /// Calculate the calibrated frequency given an LSE frequency + fn calculate_frequency(&self, lse_freq: Hertz) -> Hertz { + Hertz(lse_freq.0 * self.numerator / self.denominator) + } +} + +fn get_msi_calibration_fraction(range: MSIRange) -> MsiFraction { + // Exploiting the MSIx internals to make calculations compact + let denominator = (range as u32 & 0x03) + 1; + // Base multipliers are deduced from Table 82: MSI oscillator characteristics in data sheet + let numerator = [1465, 122, 94, 12][range as usize >> 2]; + + MsiFraction::new(numerator, denominator) +} + +/// Calculate the calibrated MSI frequency for a given range and LSE frequency +fn calculate_calibrated_msi_frequency(range: MSIRange, lse_freq: Hertz) -> Hertz { + let fraction = get_msi_calibration_fraction(range); + fraction.calculate_frequency(lse_freq) +} diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index 62c751ac8..fb516679d 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -78,7 +78,7 @@ fn common_init() { while !crate::pac::PWR.csr2().read().usb33rdy() {} } - #[cfg(stm32u5)] + #[cfg(any(stm32u5, stm32u3))] { // Enable USB power critical_section::with(|_| { diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index d405e4802..df9ed4746 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -9,7 +9,8 @@ use embassy_hal_internal::PeripheralType; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver as driver; use embassy_usb_driver::{ - Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, + Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, + Event, Unsupported, }; use crate::pac::USBRAM; @@ -208,7 +209,9 @@ mod btable { pub(super) fn write_in_len_tx(index: usize, addr: u16, len: u16) { assert_eq!(addr & 0b11, 0); - USBRAM.mem(index * 2).write_value((addr as u32) | ((len as u32) << 16)); + USBRAM + .mem(index * 2) + .write_value((addr as u32) | ((len as u32) << 16)); } pub(super) fn write_in_len_rx(index: usize, addr: u16, len: u16) { @@ -266,7 +269,9 @@ impl EndpointBuffer { let val = u16::from_le_bytes(val); #[cfg(any(usbram_32_2048, usbram_32_1024))] let val = u32::from_le_bytes(val); - USBRAM.mem(self.addr as usize / USBRAM_ALIGN + i).write_value(val); + USBRAM + .mem(self.addr as usize / USBRAM_ALIGN + i) + .write_value(val); } } } @@ -321,7 +326,9 @@ impl<'d, T: Instance> Driver<'d, T> { }); // wait t_STARTUP = 1us - cortex_m::asm::delay(unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 1_000_000); + cortex_m::asm::delay( + unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 / 1_000_000, + ); #[cfg(not(usb_v4))] regs.btable().write(|w| w.set_btable(0)); @@ -647,7 +654,9 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { true => Stat::STALL, }; let mut w = invariant(r); - w.set_stat_tx(Stat::from_bits(r.stat_tx().to_bits() ^ want_stat.to_bits())); + w.set_stat_tx(Stat::from_bits( + r.stat_tx().to_bits() ^ want_stat.to_bits(), + )); reg.write_value(w); } } @@ -666,7 +675,9 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { true => Stat::STALL, }; let mut w = invariant(r); - w.set_stat_rx(Stat::from_bits(r.stat_rx().to_bits() ^ want_stat.to_bits())); + w.set_stat_rx(Stat::from_bits( + r.stat_rx().to_bits() ^ want_stat.to_bits(), + )); reg.write_value(w); } } @@ -1066,7 +1077,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } } - async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result { + async fn data_out( + &mut self, + buf: &mut [u8], + first: bool, + last: bool, + ) -> Result { let regs = T::regs(); // When a SETUP is received, Stat/Stat is set to NAK. @@ -1208,8 +1224,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let epr = regs.epr(0).read(); regs.epr(0).write(|w| { w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat::from_bits(epr.stat_rx().to_bits() ^ Stat::STALL.to_bits())); - w.set_stat_tx(Stat::from_bits(epr.stat_tx().to_bits() ^ Stat::VALID.to_bits())); + w.set_stat_rx(Stat::from_bits( + epr.stat_rx().to_bits() ^ Stat::STALL.to_bits(), + )); + w.set_stat_tx(Stat::from_bits( + epr.stat_tx().to_bits() ^ Stat::VALID.to_bits(), + )); w.set_ctr_rx(true); // don't clear w.set_ctr_tx(true); // don't clear }); @@ -1239,8 +1259,12 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { let epr = regs.epr(0).read(); regs.epr(0).write(|w| { w.set_ep_type(EpType::CONTROL); - w.set_stat_rx(Stat::from_bits(epr.stat_rx().to_bits() ^ Stat::STALL.to_bits())); - w.set_stat_tx(Stat::from_bits(epr.stat_tx().to_bits() ^ Stat::STALL.to_bits())); + w.set_stat_rx(Stat::from_bits( + epr.stat_rx().to_bits() ^ Stat::STALL.to_bits(), + )); + w.set_stat_tx(Stat::from_bits( + epr.stat_tx().to_bits() ^ Stat::STALL.to_bits(), + )); w.set_ctr_rx(true); // don't clear w.set_ctr_tx(true); // don't clear }); diff --git a/embassy-stm32/src/vrefbuf/mod.rs b/embassy-stm32/src/vrefbuf/mod.rs index 43dd9c800..0e3f1cec1 100644 --- a/embassy-stm32/src/vrefbuf/mod.rs +++ b/embassy-stm32/src/vrefbuf/mod.rs @@ -46,6 +46,11 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { use crate::pac::RCC; RCC.apb3enr().modify(|w| w.set_vrefen(true)); } + #[cfg(rcc_u3)] + { + use crate::pac::RCC; + RCC.apb1enr1().modify(|w| w.set_vrefen(true)); + } #[cfg(any(rcc_h7rs, rcc_h7rm0433, rcc_h7ab, rcc_h7))] { use crate::pac::RCC; @@ -64,7 +69,9 @@ impl<'d, T: Instance> VoltageReferenceBuffer<'d, T> { "Vrefbuf configured with voltage scale {} and impedance mode {}", voltage_scale as u8, impedance_mode as u8, ); - VoltageReferenceBuffer { vrefbuf: PhantomData } + VoltageReferenceBuffer { + vrefbuf: PhantomData, + } } }