diff --git a/embassy-stm32/src/can/enums.rs b/embassy-stm32/src/can/enums.rs
index 4d89c84d1..a5cca424d 100644
--- a/embassy-stm32/src/can/enums.rs
+++ b/embassy-stm32/src/can/enums.rs
@@ -29,6 +29,24 @@ pub enum BusError {
     BusWarning,
 }
 
+/// Bus error modes.
+///
+/// Contrary to the `BusError` enum which also includes last-seen acute protocol
+/// errors, this enum includes only the mutually exclusive bus error modes.
+#[derive(Debug)]
+#[cfg_attr(feature = "defmt", derive(defmt::Format))]
+pub enum BusErrorMode {
+    /// Error active mode (default). Controller will transmit an active error
+    /// frame upon protocol error.
+    ErrorActive,
+    /// Error passive mode. An error counter exceeded 127. Controller will
+    /// transmit a passive error frame upon protocol error.
+    ErrorPassive,
+    /// Bus off mode. The transmit error counter exceeded 255. Controller is not
+    /// participating in bus traffic.
+    BusOff,
+}
+
 /// Frame Create Errors
 #[derive(Debug)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs
index 0df74a778..faf8a1176 100644
--- a/embassy-stm32/src/can/fdcan.rs
+++ b/embassy-stm32/src/can/fdcan.rs
@@ -859,9 +859,17 @@ impl<T: Instance> Properties<T> {
         T::registers().regs.ecr().read().tec()
     }
 
-    /// Get the current Bus-Off state
-    pub fn bus_off(&self) -> bool {
-        T::registers().regs.psr().read().bo()
+    /// Get the current bus error mode
+    pub fn bus_error_mode(&self) -> BusErrorMode {
+        // This read will clear LEC and DLEC. This is not ideal, but protocol
+        // error reporting in this driver should have a big ol' FIXME on it
+        // anyway!
+        let psr = T::regs().psr().read();
+        match (psr.bo(), psr.ep()) {
+            (false, false) => BusErrorMode::ErrorActive,
+            (false, true) => BusErrorMode::ErrorPassive,
+            (true, _) => BusErrorMode::BusOff,
+        }
     }
 }