diff --git a/ci.sh b/ci.sh
index d17f4e13e..1393b9d47 100755
--- a/ci.sh
+++ b/ci.sh
@@ -149,6 +149,9 @@ cargo batch \
     --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h503rb,defmt,exti,time-driver-any,time \
     --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv8m.main-none-eabihf --features stm32h562ag,defmt,exti,time-driver-any,time \
     --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32wb35ce,defmt,exti,time-driver-any,time \
+    --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u031r8,defmt,exti,time-driver-any,time \
+    --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \
+    --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \
     --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\
     --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \
     --- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 93792ecf8..459d2e370 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -30,6 +30,7 @@ flavors = [
     { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" },
     { regex_feature = "stm32l4.*", target = "thumbv7em-none-eabi" },
     { regex_feature = "stm32l5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] },
+    { regex_feature = "stm32u0.*", target = "thumbv6m-none-eabi" },
     { regex_feature = "stm32u5.*", target = "thumbv8m.main-none-eabihf" },
     { regex_feature = "stm32wb.*", target = "thumbv7em-none-eabi" },
     { regex_feature = "stm32wba.*", target = "thumbv8m.main-none-eabihf" },
@@ -70,7 +71,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-0c4baf478324e19741c7a9795ab0aa8217c3691c" }
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d674277b78ca7400ecfeeb1b5af4e460a65c1a61" }
 
 vcell = "0.1.3"
 nb = "1.0.0"
@@ -96,7 +97,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-0c4baf478324e19741c7a9795ab0aa8217c3691c", default-features = false, features = ["metadata"]}
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d674277b78ca7400ecfeeb1b5af4e460a65c1a61", default-features = false, features = ["metadata"]}
 
 [features]
 default = ["rt"]
@@ -1419,6 +1420,38 @@ stm32l562qe = [ "stm32-metapac/stm32l562qe" ]
 stm32l562re = [ "stm32-metapac/stm32l562re" ]
 stm32l562ve = [ "stm32-metapac/stm32l562ve" ]
 stm32l562ze = [ "stm32-metapac/stm32l562ze" ]
+stm32u031c6 = [ "stm32-metapac/stm32u031c6" ]
+stm32u031c8 = [ "stm32-metapac/stm32u031c8" ]
+stm32u031f4 = [ "stm32-metapac/stm32u031f4" ]
+stm32u031f6 = [ "stm32-metapac/stm32u031f6" ]
+stm32u031f8 = [ "stm32-metapac/stm32u031f8" ]
+stm32u031g6 = [ "stm32-metapac/stm32u031g6" ]
+stm32u031g8 = [ "stm32-metapac/stm32u031g8" ]
+stm32u031k4 = [ "stm32-metapac/stm32u031k4" ]
+stm32u031k6 = [ "stm32-metapac/stm32u031k6" ]
+stm32u031k8 = [ "stm32-metapac/stm32u031k8" ]
+stm32u031r6 = [ "stm32-metapac/stm32u031r6" ]
+stm32u031r8 = [ "stm32-metapac/stm32u031r8" ]
+stm32u073c8 = [ "stm32-metapac/stm32u073c8" ]
+stm32u073cb = [ "stm32-metapac/stm32u073cb" ]
+stm32u073cc = [ "stm32-metapac/stm32u073cc" ]
+stm32u073h8 = [ "stm32-metapac/stm32u073h8" ]
+stm32u073hb = [ "stm32-metapac/stm32u073hb" ]
+stm32u073hc = [ "stm32-metapac/stm32u073hc" ]
+stm32u073k8 = [ "stm32-metapac/stm32u073k8" ]
+stm32u073kb = [ "stm32-metapac/stm32u073kb" ]
+stm32u073kc = [ "stm32-metapac/stm32u073kc" ]
+stm32u073m8 = [ "stm32-metapac/stm32u073m8" ]
+stm32u073mb = [ "stm32-metapac/stm32u073mb" ]
+stm32u073mc = [ "stm32-metapac/stm32u073mc" ]
+stm32u073r8 = [ "stm32-metapac/stm32u073r8" ]
+stm32u073rb = [ "stm32-metapac/stm32u073rb" ]
+stm32u073rc = [ "stm32-metapac/stm32u073rc" ]
+stm32u083cc = [ "stm32-metapac/stm32u083cc" ]
+stm32u083hc = [ "stm32-metapac/stm32u083hc" ]
+stm32u083kc = [ "stm32-metapac/stm32u083kc" ]
+stm32u083mc = [ "stm32-metapac/stm32u083mc" ]
+stm32u083rc = [ "stm32-metapac/stm32u083rc" ]
 stm32u535cb = [ "stm32-metapac/stm32u535cb" ]
 stm32u535cc = [ "stm32-metapac/stm32u535cc" ]
 stm32u535ce = [ "stm32-metapac/stm32u535ce" ]
@@ -1474,6 +1507,7 @@ stm32u599vj = [ "stm32-metapac/stm32u599vj" ]
 stm32u599zi = [ "stm32-metapac/stm32u599zi" ]
 stm32u599zj = [ "stm32-metapac/stm32u599zj" ]
 stm32u5a5aj = [ "stm32-metapac/stm32u5a5aj" ]
+stm32u5a5qi = [ "stm32-metapac/stm32u5a5qi" ]
 stm32u5a5qj = [ "stm32-metapac/stm32u5a5qj" ]
 stm32u5a5rj = [ "stm32-metapac/stm32u5a5rj" ]
 stm32u5a5vj = [ "stm32-metapac/stm32u5a5vj" ]
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 8d5dae436..224d51b84 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -27,11 +27,11 @@ fn cpu_regs() -> pac::exti::Exti {
     EXTI
 }
 
-#[cfg(not(any(exti_c0, exti_g0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50)))]
+#[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, gpio_v1, exti_u5, exti_h5, exti_h50)))]
 fn exticr_regs() -> pac::syscfg::Syscfg {
     pac::SYSCFG
 }
-#[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
+#[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
 fn exticr_regs() -> pac::exti::Exti {
     EXTI
 }
@@ -44,9 +44,9 @@ unsafe fn on_irq() {
     #[cfg(feature = "low-power")]
     crate::low_power::on_wakeup_irq();
 
-    #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))]
+    #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
     let bits = EXTI.pr(0).read().0;
-    #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
+    #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
     let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0;
 
     // We don't handle or change any EXTI lines above 16.
@@ -61,9 +61,9 @@ unsafe fn on_irq() {
     }
 
     // Clear pending
-    #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))]
+    #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
     EXTI.pr(0).write_value(Lines(bits));
-    #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
+    #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
     {
         EXTI.rpr(0).write_value(Lines(bits));
         EXTI.fpr(0).write_value(Lines(bits));
@@ -241,9 +241,9 @@ impl<'a> ExtiInputFuture<'a> {
             EXTI.ftsr(0).modify(|w| w.set_line(pin, falling));
 
             // clear pending bit
-            #[cfg(not(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50)))]
+            #[cfg(not(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50)))]
             EXTI.pr(0).write(|w| w.set_line(pin, true));
-            #[cfg(any(exti_c0, exti_g0, exti_l5, exti_u5, exti_h5, exti_h50))]
+            #[cfg(any(exti_c0, exti_g0, exti_u0, exti_l5, exti_u5, exti_h5, exti_h50))]
             {
                 EXTI.rpr(0).write(|w| w.set_line(pin, true));
                 EXTI.fpr(0).write(|w| w.set_line(pin, true));
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 9079ddd41..d7235ac7f 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -49,6 +49,7 @@ pub struct Config {
     pub sys: Sysclk,
     pub ahb_pre: AHBPrescaler,
     pub apb1_pre: APBPrescaler,
+    #[cfg(not(stm32u0))]
     pub apb2_pre: APBPrescaler,
     #[cfg(any(stm32wl5x, stm32wb))]
     pub core2_ahb_pre: AHBPrescaler,
@@ -75,6 +76,7 @@ impl Default for Config {
             sys: Sysclk::MSI,
             ahb_pre: AHBPrescaler::DIV1,
             apb1_pre: APBPrescaler::DIV1,
+            #[cfg(not(stm32u0))]
             apb2_pre: APBPrescaler::DIV1,
             #[cfg(any(stm32wl5x, stm32wb))]
             core2_ahb_pre: AHBPrescaler::DIV1,
@@ -130,7 +132,7 @@ pub const WPAN_DEFAULT: Config = Config {
 };
 
 fn msi_enable(range: MSIRange) {
-    #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
+    #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
     RCC.cr().modify(|w| {
         #[cfg(not(stm32wb))]
         w.set_msirgsel(crate::pac::rcc::vals::Msirgsel::CR);
@@ -240,7 +242,7 @@ pub(crate) unsafe fn init(config: Config) {
     let pll_input = PllInput {
         hse,
         hsi,
-        #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
+        #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
         msi,
     };
     let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
@@ -254,6 +256,10 @@ pub(crate) unsafe fn init(config: Config) {
         Sysclk::HSI => hsi.unwrap(),
         Sysclk::MSI => msi.unwrap(),
         Sysclk::PLL1_R => pll.r.unwrap(),
+        #[cfg(stm32u0)]
+        Sysclk::LSI | Sysclk::LSE => todo!(),
+        #[cfg(stm32u0)]
+        Sysclk::_RESERVED_6 | Sysclk::_RESERVED_7 => unreachable!(),
     };
 
     #[cfg(rcc_l4plus)]
@@ -263,6 +269,7 @@ pub(crate) unsafe fn init(config: Config) {
 
     let hclk1 = sys_clk / config.ahb_pre;
     let (pclk1, pclk1_tim) = super::util::calc_pclk(hclk1, config.apb1_pre);
+    #[cfg(not(stm32u0))]
     let (pclk2, pclk2_tim) = super::util::calc_pclk(hclk1, config.apb2_pre);
     #[cfg(any(stm32l4, stm32l5, stm32wlex))]
     let hclk2 = hclk1;
@@ -315,6 +322,13 @@ pub(crate) unsafe fn init(config: Config) {
         ..=64_000_000 => 3,
         _ => 4,
     };
+    #[cfg(stm32u0)]
+    let latency = match hclk1.0 {
+        // VOS RANGE1, others TODO.
+        ..=24_000_000 => 0,
+        ..=48_000_000 => 1,
+        _ => 2,
+    };
 
     #[cfg(stm32l1)]
     FLASH.acr().write(|w| w.set_acc64(true));
@@ -326,7 +340,11 @@ pub(crate) unsafe fn init(config: Config) {
     RCC.cfgr().modify(|w| {
         w.set_sw(config.sys);
         w.set_hpre(config.ahb_pre);
+        #[cfg(stm32u0)]
+        w.set_ppre(config.apb1_pre);
+        #[cfg(not(stm32u0))]
         w.set_ppre1(config.apb1_pre);
+        #[cfg(not(stm32u0))]
         w.set_ppre2(config.apb2_pre);
     });
     while RCC.cfgr().read().sws() != config.sys {}
@@ -353,8 +371,10 @@ pub(crate) unsafe fn init(config: Config) {
         #[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
         hclk3: Some(hclk3),
         pclk1: Some(pclk1),
+        #[cfg(not(stm32u0))]
         pclk2: Some(pclk2),
         pclk1_tim: Some(pclk1_tim),
+        #[cfg(not(stm32u0))]
         pclk2_tim: Some(pclk2_tim),
         #[cfg(stm32wl)]
         pclk3: Some(hclk3),
@@ -408,7 +428,7 @@ fn msirange_to_hertz(range: MSIRange) -> Hertz {
     Hertz(32_768 * (1 << (range as u8 + 1)))
 }
 
-#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
+#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
 fn msirange_to_hertz(range: MSIRange) -> Hertz {
     match range {
         MSIRange::RANGE100K => Hertz(100_000),
@@ -521,7 +541,7 @@ mod pll {
     }
 }
 
-#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl))]
+#[cfg(any(stm32l4, stm32l5, stm32wb, stm32wl, stm32u0))]
 mod pll {
     use super::{pll_enable, PllInstance};
     pub use crate::pac::rcc::vals::{
diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs
index d8604e07e..4b22a099d 100644
--- a/embassy-stm32/src/rcc/mco.rs
+++ b/embassy-stm32/src/rcc/mco.rs
@@ -52,7 +52,7 @@ macro_rules! impl_peri {
     };
 }
 
-#[cfg(any(rcc_c0, rcc_g0))]
+#[cfg(any(rcc_c0, rcc_g0, rcc_u0))]
 #[allow(unused_imports)]
 use self::{McoSource as Mco1Source, McoSource as Mco2Source};
 
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 5497bba07..a4e497fe7 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -25,7 +25,7 @@ pub use hsi48::*;
 #[cfg_attr(stm32g0, path = "g0.rs")]
 #[cfg_attr(stm32g4, path = "g4.rs")]
 #[cfg_attr(any(stm32h5, stm32h7), path = "h.rs")]
-#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl), path = "l.rs")]
+#[cfg_attr(any(stm32l0, stm32l1, stm32l4, stm32l5, stm32wb, stm32wl, stm32u0), path = "l.rs")]
 #[cfg_attr(stm32u5, path = "u5.rs")]
 #[cfg_attr(stm32wba, path = "wba.rs")]
 mod _version;
diff --git a/examples/stm32u0/.cargo/config.toml b/examples/stm32u0/.cargo/config.toml
new file mode 100644
index 000000000..688347084
--- /dev/null
+++ b/examples/stm32u0/.cargo/config.toml
@@ -0,0 +1,9 @@
+[target.'cfg(all(target_arch = "arm", target_os = "none"))']
+# replace stm32u083rctx with your chip as listed in `probe-rs chip list`
+runner = "probe-rs run --chip stm32u083rctx"
+
+[build]
+target = "thumbv6m-none-eabi"
+
+[env]
+DEFMT_LOG = "trace"
diff --git a/examples/stm32u0/Cargo.toml b/examples/stm32u0/Cargo.toml
new file mode 100644
index 000000000..495be3e75
--- /dev/null
+++ b/examples/stm32u0/Cargo.toml
@@ -0,0 +1,25 @@
+[package]
+edition = "2021"
+name = "embassy-stm32u0-examples"
+version = "0.1.0"
+license = "MIT OR Apache-2.0"
+
+[dependencies]
+# Change stm32u083rc to your chip name, if necessary.
+embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "time-driver-any", "stm32u083rc", "memory-x", "unstable-pac", "exti"]  }
+embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
+embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] }
+embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
+
+defmt = "0.3"
+defmt-rtt = "0.4"
+
+cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] }
+cortex-m-rt = "0.7.0"
+embedded-hal = "0.2.6"
+panic-probe = { version = "0.3", features = ["print-defmt"] }
+futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
+heapless = { version = "0.8", default-features = false }
+
+[profile.release]
+debug = 2
diff --git a/examples/stm32u0/build.rs b/examples/stm32u0/build.rs
new file mode 100644
index 000000000..8cd32d7ed
--- /dev/null
+++ b/examples/stm32u0/build.rs
@@ -0,0 +1,5 @@
+fn main() {
+    println!("cargo:rustc-link-arg-bins=--nmagic");
+    println!("cargo:rustc-link-arg-bins=-Tlink.x");
+    println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
+}
diff --git a/examples/stm32u0/src/bin/blinky.rs b/examples/stm32u0/src/bin/blinky.rs
new file mode 100644
index 000000000..90e479aae
--- /dev/null
+++ b/examples/stm32u0/src/bin/blinky.rs
@@ -0,0 +1,26 @@
+#![no_std]
+#![no_main]
+
+use defmt::*;
+use embassy_executor::Spawner;
+use embassy_stm32::gpio::{Level, Output, Speed};
+use embassy_time::Timer;
+use {defmt_rtt as _, panic_probe as _};
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+    let p = embassy_stm32::init(Default::default());
+    info!("Hello World!");
+
+    let mut led = Output::new(p.PA5, Level::High, Speed::Low);
+
+    loop {
+        info!("high");
+        led.set_high();
+        Timer::after_millis(300).await;
+
+        info!("low");
+        led.set_low();
+        Timer::after_millis(300).await;
+    }
+}
diff --git a/examples/stm32u0/src/bin/button.rs b/examples/stm32u0/src/bin/button.rs
new file mode 100644
index 000000000..8017f0274
--- /dev/null
+++ b/examples/stm32u0/src/bin/button.rs
@@ -0,0 +1,24 @@
+#![no_std]
+#![no_main]
+
+use cortex_m_rt::entry;
+use defmt::*;
+use embassy_stm32::gpio::{Input, Pull};
+use {defmt_rtt as _, panic_probe as _};
+
+#[entry]
+fn main() -> ! {
+    info!("Hello World!");
+
+    let p = embassy_stm32::init(Default::default());
+
+    let button = Input::new(p.PC13, Pull::Up);
+
+    loop {
+        if button.is_high() {
+            info!("high");
+        } else {
+            info!("low");
+        }
+    }
+}
diff --git a/examples/stm32u0/src/bin/button_exti.rs b/examples/stm32u0/src/bin/button_exti.rs
new file mode 100644
index 000000000..34a08bbc6
--- /dev/null
+++ b/examples/stm32u0/src/bin/button_exti.rs
@@ -0,0 +1,25 @@
+#![no_std]
+#![no_main]
+
+use defmt::*;
+use embassy_executor::Spawner;
+use embassy_stm32::exti::ExtiInput;
+use embassy_stm32::gpio::Pull;
+use {defmt_rtt as _, panic_probe as _};
+
+#[embassy_executor::main]
+async fn main(_spawner: Spawner) {
+    let p = embassy_stm32::init(Default::default());
+    info!("Hello World!");
+
+    let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up);
+
+    info!("Press the USER button...");
+
+    loop {
+        button.wait_for_falling_edge().await;
+        info!("Pressed!");
+        button.wait_for_rising_edge().await;
+        info!("Released!");
+    }
+}