Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions embassy-mspm0/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- feat: add MSPM0H3216 support
- feat: Add i2c target implementation (#4605)
- fix: group irq handlers must check for NO_INTR (#4785)
- feat: Add read_reset_cause function
4 changes: 2 additions & 2 deletions embassy-mspm0/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ cortex-m = "0.7.6"
critical-section = "1.2.0"

# mspm0-metapac = { version = "" }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-e7de4103a0713772695ffcad52c3c2f07414dc29" }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-8542f260cc89645a983b7f1a874c87b21822279e" }

[build-dependencies]
proc-macro2 = "1.0.94"
quote = "1.0.40"
cfg_aliases = "0.2.1"

# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-e7de4103a0713772695ffcad52c3c2f07414dc29", default-features = false, features = ["metadata"] }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-8542f260cc89645a983b7f1a874c87b21822279e", default-features = false, features = ["metadata"] }

[features]
default = ["rt"]
Expand Down
111 changes: 111 additions & 0 deletions embassy-mspm0/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,114 @@ impl Iterator for BitIter {
}
}
}

/// Reset cause values from SYSCTL.RSTCAUSE register.
/// Based on MSPM0 L-series Technical Reference Manual Table 2-9 and
/// MSPM0 G-series Technical Reference Manual Table 2-12.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ResetCause {
/// No reset since last read
NoReset,
/// VDD < POR- violation, PMU trim parity fault, or SHUTDNSTOREx parity fault
PorHwFailure,
/// NRST pin reset (>1s)
PorExternalNrst,
/// Software-triggered POR
PorSwTriggered,
/// VDD < BOR- violation
BorSupplyFailure,
/// Wake from SHUTDOWN
BorWakeFromShutdown,
/// Non-PMU trim parity fault
#[cfg(not(any(
mspm0c110x,
mspm0c1105_c1106,
mspm0g110x,
mspm0g150x,
mspm0g151x,
mspm0g310x,
mspm0g350x,
mspm0g351x
)))]
BootrstNonPmuParityFault,
/// Fatal clock fault
BootrstClockFault,
/// Software-triggered BOOTRST
BootrstSwTriggered,
/// NRST pin reset (<1s)
BootrstExternalNrst,
/// WWDT0 violation
BootrstWwdt0Violation,
/// WWDT1 violation (G-series only)
#[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))]
SysrstWwdt1Violation,
/// BSL exit (if present)
SysrstBslExit,
/// BSL entry (if present)
SysrstBslEntry,
/// Uncorrectable flash ECC error (if present)
#[cfg(not(any(mspm0c110x, mspm0c1105_c1106, mspm0g351x, mspm0g151x)))]
SysrstFlashEccError,
/// CPU lockup violation
SysrstCpuLockupViolation,
/// Debug-triggered SYSRST
SysrstDebugTriggered,
/// Software-triggered SYSRST
SysrstSwTriggered,
/// Debug-triggered CPURST
CpurstDebugTriggered,
/// Software-triggered CPURST
CpurstSwTriggered,
}

/// Read the reset cause from the SYSCTL.RSTCAUSE register.
///
/// This function reads the reset cause register which indicates why the last
/// system reset occurred. The register is automatically cleared after being read,
/// so this should be called only once per application startup.
///
/// If the reset cause is not recognized, an `Err` containing the raw value is returned.
#[must_use = "Reading reset cause will clear it"]
pub fn read_reset_cause() -> Result<ResetCause, u8> {
Copy link
Member

@i509VCB i509VCB Nov 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Last comment is relating to return value. We do exhaustively measure each value hardware can produce, so we could mark other values as unreachable.

unreachable_unchecked is technically valid but would cause undefined behavior when new chips are added and this code isn't updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather err (haha) on the side of caution and keep the Err return to avoid undefined behavior. A runtime panic is better than undefined behavior.

let cause_raw = pac::SYSCTL.rstcause().read().id();

use ResetCause::*;
use pac::sysctl::vals::Id;

match cause_raw {
Id::NORST => Ok(NoReset),
Id::PORHWFAIL => Ok(PorHwFailure),
Id::POREXNRST => Ok(PorExternalNrst),
Id::PORSW => Ok(PorSwTriggered),
Id::BORSUPPLY => Ok(BorSupplyFailure),
Id::BORWAKESHUTDN => Ok(BorWakeFromShutdown),
#[cfg(not(any(
mspm0c110x,
mspm0c1105_c1106,
mspm0g110x,
mspm0g150x,
mspm0g151x,
mspm0g310x,
mspm0g350x,
mspm0g351x
)))]
Id::BOOTNONPMUPARITY => Ok(BootrstNonPmuParityFault),
Id::BOOTCLKFAIL => Ok(BootrstClockFault),
Id::BOOTSW => Ok(BootrstSwTriggered),
Id::BOOTEXNRST => Ok(BootrstExternalNrst),
Id::BOOTWWDT0 => Ok(BootrstWwdt0Violation),
Id::SYSBSLEXIT => Ok(SysrstBslExit),
Id::SYSBSLENTRY => Ok(SysrstBslEntry),
#[cfg(any(mspm0g110x, mspm0g150x, mspm0g151x, mspm0g310x, mspm0g350x, mspm0g351x))]
Id::SYSWWDT1 => Ok(SysrstWwdt1Violation),
#[cfg(not(any(mspm0c110x, mspm0c1105_c1106, mspm0g351x, mspm0g151x)))]
Id::SYSFLASHECC => Ok(SysrstFlashEccError),
Id::SYSCPULOCK => Ok(SysrstCpuLockupViolation),
Id::SYSDBG => Ok(SysrstDebugTriggered),
Id::SYSSW => Ok(SysrstSwTriggered),
Id::CPUDBG => Ok(CpurstDebugTriggered),
Id::CPUSW => Ok(CpurstSwTriggered),
other => Err(other as u8),
}
}