diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 653a376bd..93a30c5c5 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -72,7 +72,7 @@ rand_core = "0.6.3"
 sdio-host = "0.5.0"
 critical-section = "1.1"
 #stm32-metapac = { version = "15" }
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-823168933f3860770111f7bde2a82b912eac58c0" }
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-37a0941112fd16fee53aaa2005fd67b77adab59c" }
 
 vcell = "0.1.3"
 nb = "1.0.0"
@@ -98,7 +98,7 @@ proc-macro2 = "1.0.36"
 quote = "1.0.15"
 
 #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-823168933f3860770111f7bde2a82b912eac58c0", default-features = false, features = ["metadata"]}
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-37a0941112fd16fee53aaa2005fd67b77adab59c", default-features = false, features = ["metadata"]}
 
 [features]
 default = ["rt"]
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index 67fceda56..49ffef217 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -49,6 +49,8 @@ fn main() {
     .unwrap()
     .to_ascii_lowercase();
 
+    eprintln!("chip: {chip_name}");
+
     for p in METADATA.peripherals {
         if let Some(r) = &p.registers {
             println!("cargo:rustc-cfg={}", r.kind);
@@ -1321,17 +1323,7 @@ fn main() {
     let mut interrupts_table: Vec<Vec<String>> = Vec::new();
     let mut peripherals_table: Vec<Vec<String>> = Vec::new();
     let mut pins_table: Vec<Vec<String>> = Vec::new();
-    let mut adc_common_table: Vec<Vec<String>> = Vec::new();
-
-    /*
-        If ADC3_COMMON exists, ADC3 and higher are assigned to it
-        All other ADCs are assigned to ADC_COMMON
-
-        ADC3 and higher are assigned to the adc34 clock in the table
-        The adc3_common cfg directive is added if ADC3_COMMON exists
-    */
-    let has_adc3 = METADATA.peripherals.iter().any(|p| p.name == "ADC3_COMMON");
-    let set_adc345 = HashSet::from(["ADC3", "ADC4", "ADC5"]);
+    let mut adc_table: Vec<Vec<String>> = Vec::new();
 
     for m in METADATA
         .memory
@@ -1388,14 +1380,18 @@ fn main() {
             }
 
             if regs.kind == "adc" {
-                let (adc_common, adc_clock) = if set_adc345.contains(p.name) && has_adc3 {
-                    ("ADC3_COMMON", "adc34")
-                } else {
-                    ("ADC_COMMON", "adc")
-                };
-
-                let row = vec![p.name.to_string(), adc_common.to_string(), adc_clock.to_string()];
-                adc_common_table.push(row);
+                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 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()];
+                adc_table.push(row);
             }
 
             for irq in p.interrupts {
@@ -1441,6 +1437,7 @@ 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())}),
             _ => panic!("bad dma channel kind {}", bi.kind),
         };
 
@@ -1535,7 +1532,7 @@ fn main() {
     make_table(&mut m, "foreach_interrupt", &interrupts_table);
     make_table(&mut m, "foreach_peripheral", &peripherals_table);
     make_table(&mut m, "foreach_pin", &pins_table);
-    make_table(&mut m, "foreach_adc", &adc_common_table);
+    make_table(&mut m, "foreach_adc", &adc_table);
 
     let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
     let out_file = out_dir.join("_macros.rs").to_string_lossy().to_string();
@@ -1568,13 +1565,6 @@ fn main() {
         println!("cargo:rustc-cfg={}_{}", &chip_name[..chip_name.len() - 2], core);
     }
 
-    // =======
-    // ADC3_COMMON is present
-    #[allow(clippy::print_literal)]
-    if has_adc3 {
-        println!("cargo:rustc-cfg={}", "adc3_common");
-    }
-
     // =======
     // Features for targeting groups of chips
 
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index 1dda28cf2..f17522076 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -9,7 +9,7 @@ use stm32_metapac::adc::vals::Ckmode;
 use super::blocking_delay_us;
 use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
 use crate::interrupt::typelevel::Interrupt;
-use crate::peripherals::ADC;
+use crate::peripherals::ADC1;
 use crate::{interrupt, Peripheral};
 
 pub const VDDA_CALIB_MV: u32 = 3300;
@@ -36,26 +36,26 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 pub struct Vbat;
 
 #[cfg(not(adc_l0))]
-impl AdcPin<ADC> for Vbat {}
+impl AdcPin<ADC1> for Vbat {}
 
 #[cfg(not(adc_l0))]
-impl super::SealedAdcPin<ADC> for Vbat {
+impl super::SealedAdcPin<ADC1> for Vbat {
     fn channel(&self) -> u8 {
         18
     }
 }
 
 pub struct Vref;
-impl AdcPin<ADC> for Vref {}
-impl super::SealedAdcPin<ADC> for Vref {
+impl AdcPin<ADC1> for Vref {}
+impl super::SealedAdcPin<ADC1> for Vref {
     fn channel(&self) -> u8 {
         17
     }
 }
 
 pub struct Temperature;
-impl AdcPin<ADC> for Temperature {}
-impl super::SealedAdcPin<ADC> for Temperature {
+impl AdcPin<ADC1> for Temperature {}
+impl super::SealedAdcPin<ADC1> for Temperature {
     fn channel(&self) -> u8 {
         16
     }
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
index 26298a08b..8a748ad72 100644
--- a/embassy-stm32/src/dac/mod.rs
+++ b/embassy-stm32/src/dac/mod.rs
@@ -368,7 +368,7 @@ impl<'d, T: Instance, const N: u8, DMA> Drop for DacChannel<'d, T, N, DMA> {
 ///
 /// ```ignore
 /// // Pins may need to be changed for your specific device.
-/// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC, NoDma, NoDma, p.PA4, p.PA5).split();
+/// let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, NoDma, NoDma, p.PA4, p.PA5).split();
 /// ```
 pub struct Dac<'d, T: Instance, DMACh1 = NoDma, DMACh2 = NoDma> {
     ch1: DacChannel<'d, T, 1, DMACh1>,
diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs
index ef03970ef..a3717e67b 100644
--- a/embassy-stm32/src/dma/gpdma.rs
+++ b/embassy-stm32/src/dma/gpdma.rs
@@ -32,7 +32,7 @@ impl Default for TransferOptions {
     }
 }
 
-impl From<WordSize> for vals::ChTr1Dw {
+impl From<WordSize> for vals::Dw {
     fn from(raw: WordSize) -> Self {
         match raw {
             WordSize::OneByte => Self::BYTE,
@@ -235,8 +235,8 @@ impl<'a> Transfer<'a> {
         });
         ch.tr2().write(|w| {
             w.set_dreq(match dir {
-                Dir::MemoryToPeripheral => vals::ChTr2Dreq::DESTINATIONPERIPHERAL,
-                Dir::PeripheralToMemory => vals::ChTr2Dreq::SOURCEPERIPHERAL,
+                Dir::MemoryToPeripheral => vals::Dreq::DESTINATIONPERIPHERAL,
+                Dir::PeripheralToMemory => vals::Dreq::SOURCEPERIPHERAL,
             });
             w.set_reqsel(request);
         });
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index c6e015022..37f460574 100644
--- a/embassy-stm32/src/eth/v2/mod.rs
+++ b/embassy-stm32/src/eth/v2/mod.rs
@@ -94,8 +94,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
 
         #[cfg(rcc_h5)]
         critical_section::with(|_| {
-            crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true));
-
             crate::pac::RCC.ahb1enr().modify(|w| {
                 w.set_ethen(true);
                 w.set_ethtxen(true);
@@ -161,8 +159,6 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> {
 
         #[cfg(rcc_h5)]
         critical_section::with(|_| {
-            crate::pac::RCC.apb3enr().modify(|w| w.set_sbsen(true));
-
             crate::pac::RCC.ahb1enr().modify(|w| {
                 w.set_ethen(true);
                 w.set_ethtxen(true);
diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs
index 215f8a3d2..f33351e74 100644
--- a/embassy-stm32/src/rcc/f013.rs
+++ b/embassy-stm32/src/rcc/f013.rs
@@ -299,54 +299,66 @@ pub(crate) unsafe fn init(config: Config) {
 
     let rtc = config.ls.init();
 
+    // TODO: all this ADC stuff should probably go into the ADC module, not here.
+    // Most STM32s manage ADC clocks in a similar way with ADCx_COMMON.
     #[cfg(all(stm32f3, not(rcc_f37)))]
     use crate::pac::adccommon::vals::Ckmode;
 
     #[cfg(all(stm32f3, not(rcc_f37)))]
-    let adc = match config.adc {
-        AdcClockSource::Pll(adcpres) => {
-            RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres));
-            crate::pac::ADC_COMMON
-                .ccr()
-                .modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
+    let adc = {
+        #[cfg(peri_adc1_common)]
+        let common = crate::pac::ADC1_COMMON;
+        #[cfg(peri_adc12_common)]
+        let common = crate::pac::ADC12_COMMON;
 
-            unwrap!(pll) / adcpres
-        }
-        AdcClockSource::Hclk(adcpres) => {
-            assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
+        match config.adc {
+            AdcClockSource::Pll(adcpres) => {
+                RCC.cfgr2().modify(|w| w.set_adc12pres(adcpres));
+                common.ccr().modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
 
-            let (div, ckmode) = match adcpres {
-                AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
-                AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
-                AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
-            };
-            crate::pac::ADC_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
+                unwrap!(pll) / adcpres
+            }
+            AdcClockSource::Hclk(adcpres) => {
+                assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
 
-            hclk / div
+                let (div, ckmode) = match adcpres {
+                    AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
+                    AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
+                    AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
+                };
+                common.ccr().modify(|w| w.set_ckmode(ckmode));
+
+                hclk / div
+            }
         }
     };
 
     #[cfg(all(stm32f3, not(rcc_f37), adc3_common))]
-    let adc34 = match config.adc34 {
-        AdcClockSource::Pll(adcpres) => {
-            RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres));
-            crate::pac::ADC3_COMMON
-                .ccr()
-                .modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
+    let adc34 = {
+        #[cfg(peri_adc3_common)]
+        let common = crate::pac::ADC3_COMMON;
+        #[cfg(peri_adc34_common)]
+        let common = crate::pac::ADC34_COMMON;
 
-            unwrap!(pll) / adcpres
-        }
-        AdcClockSource::Hclk(adcpres) => {
-            assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
+        match config.adc34 {
+            AdcClockSource::Pll(adcpres) => {
+                RCC.cfgr2().modify(|w| w.set_adc34pres(adcpres));
+                common.ccr().modify(|w| w.set_ckmode(Ckmode::ASYNCHRONOUS));
 
-            let (div, ckmode) = match adcpres {
-                AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
-                AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
-                AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
-            };
-            crate::pac::ADC3_COMMON.ccr().modify(|w| w.set_ckmode(ckmode));
+                unwrap!(pll) / adcpres
+            }
+            AdcClockSource::Hclk(adcpres) => {
+                assert!(!(adcpres == AdcHclkPrescaler::Div1 && config.ahb_pre != AHBPrescaler::DIV1));
 
-            hclk / div
+                let (div, ckmode) = match adcpres {
+                    AdcHclkPrescaler::Div1 => (1u32, Ckmode::SYNCDIV1),
+                    AdcHclkPrescaler::Div2 => (2u32, Ckmode::SYNCDIV2),
+                    AdcHclkPrescaler::Div4 => (4u32, Ckmode::SYNCDIV4),
+                };
+                common.ccr().modify(|w| w.set_ckmode(ckmode));
+
+                hclk / div
+            }
         }
     };
 
diff --git a/examples/stm32f0/src/bin/adc.rs b/examples/stm32f0/src/bin/adc.rs
index a5a4186ea..8825e2687 100644
--- a/examples/stm32f0/src/bin/adc.rs
+++ b/examples/stm32f0/src/bin/adc.rs
@@ -4,13 +4,13 @@
 use defmt::*;
 use embassy_executor::Spawner;
 use embassy_stm32::adc::{Adc, SampleTime};
-use embassy_stm32::peripherals::ADC;
+use embassy_stm32::peripherals::ADC1;
 use embassy_stm32::{adc, bind_interrupts};
 use embassy_time::Timer;
 use {defmt_rtt as _, panic_probe as _};
 
 bind_interrupts!(struct Irqs {
-    ADC1_COMP => adc::InterruptHandler<ADC>;
+    ADC1_COMP => adc::InterruptHandler<ADC1>;
 });
 
 #[embassy_executor::main]
@@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) {
     let p = embassy_stm32::init(Default::default());
     info!("Hello World!");
 
-    let mut adc = Adc::new(p.ADC, Irqs);
+    let mut adc = Adc::new(p.ADC1, Irqs);
     adc.set_sample_time(SampleTime::CYCLES71_5);
     let mut pin = p.PA1;
 
diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs
index 9c7754c4f..dd2a45718 100644
--- a/examples/stm32f4/src/bin/dac.rs
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -12,7 +12,7 @@ async fn main(_spawner: Spawner) -> ! {
     let p = embassy_stm32::init(Default::default());
     info!("Hello World, dude!");
 
-    let mut dac = DacCh1::new(p.DAC, NoDma, p.PA4);
+    let mut dac = DacCh1::new(p.DAC1, NoDma, p.PA4);
 
     loop {
         for v in 0..=255 {
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs
index 507c3204a..9dd09bc45 100644
--- a/examples/stm32l0/src/bin/adc.rs
+++ b/examples/stm32l0/src/bin/adc.rs
@@ -4,13 +4,13 @@
 use defmt::*;
 use embassy_executor::Spawner;
 use embassy_stm32::adc::{Adc, SampleTime};
-use embassy_stm32::peripherals::ADC;
+use embassy_stm32::peripherals::ADC1;
 use embassy_stm32::{adc, bind_interrupts};
 use embassy_time::Timer;
 use {defmt_rtt as _, panic_probe as _};
 
 bind_interrupts!(struct Irqs {
-    ADC1_COMP => adc::InterruptHandler<ADC>;
+    ADC1_COMP => adc::InterruptHandler<ADC1>;
 });
 
 #[embassy_executor::main]
@@ -18,7 +18,7 @@ async fn main(_spawner: Spawner) {
     let p = embassy_stm32::init(Default::default());
     info!("Hello World!");
 
-    let mut adc = Adc::new(p.ADC, Irqs);
+    let mut adc = Adc::new(p.ADC1, Irqs);
     adc.set_sample_time(SampleTime::CYCLES79_5);
     let mut pin = p.PA1;
 
diff --git a/tests/stm32/src/bin/dac_l1.rs b/tests/stm32/src/bin/dac_l1.rs
index f8b00aaef..d5e9c9722 100644
--- a/tests/stm32/src/bin/dac_l1.rs
+++ b/tests/stm32/src/bin/dac_l1.rs
@@ -19,7 +19,7 @@ use micromath::F32Ext;
 use {defmt_rtt as _, panic_probe as _};
 
 bind_interrupts!(struct Irqs {
-    ADC1 => embassy_stm32::adc::InterruptHandler<peripherals::ADC>;
+    ADC1 => embassy_stm32::adc::InterruptHandler<peripherals::ADC1>;
 });
 
 #[embassy_executor::main]
diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs
index 0e555efc8..24d33dc3b 100644
--- a/tests/stm32/src/common.rs
+++ b/tests/stm32/src/common.rs
@@ -120,7 +120,7 @@ define_peris!(
 define_peris!(
     UART = USART6, UART_TX = PG14, UART_RX = PG9, UART_TX_DMA = DMA2_CH6, UART_RX_DMA = DMA2_CH1,
     SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA2_CH3, SPI_RX_DMA = DMA2_CH2,
-    ADC = ADC1, DAC = DAC, DAC_PIN = PA4,
+    ADC = ADC1, DAC = DAC1, DAC_PIN = PA4,
     CAN = CAN1, CAN_RX = PD0, CAN_TX = PD1,
     @irq UART = {USART6 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART6>;},
 );
@@ -128,7 +128,7 @@ define_peris!(
 define_peris!(
     UART = USART1, UART_TX = PA9, UART_RX = PA10, UART_TX_DMA = DMA2_CH7, UART_RX_DMA = DMA2_CH5,
     SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA2_CH3, SPI_RX_DMA = DMA2_CH2,
-    ADC = ADC1, DAC = DAC, DAC_PIN = PA4,
+    ADC = ADC1, DAC = DAC1, DAC_PIN = PA4,
     CAN = CAN1, CAN_RX = PA11, CAN_TX = PA12,
     @irq UART = {USART1 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART1>;},
 );
@@ -210,7 +210,7 @@ define_peris!(
 define_peris!(
     UART = USART3, UART_TX = PB10, UART_RX = PB11, UART_TX_DMA = DMA1_CH2, UART_RX_DMA = DMA1_CH3,
     SPI = SPI1, SPI_SCK = PA5, SPI_MOSI = PA7, SPI_MISO = PA6, SPI_TX_DMA = DMA1_CH3, SPI_RX_DMA = DMA1_CH2,
-    ADC = ADC, DAC = DAC, DAC_PIN = PA4,
+    ADC = ADC1, DAC = DAC1, DAC_PIN = PA4,
     @irq UART = {USART3 => embassy_stm32::usart::InterruptHandler<embassy_stm32::peripherals::USART3>;},
 );
 #[cfg(feature = "stm32l552ze")]