10template <
typename BusType>
12 : bus_(bus), address_(address), initialized_(
false), error_flags_(0) {}
14template <
typename BusType>
16 if (bus_ ==
nullptr) {
17 setError(Error::InvalidParam);
20 const uint8_t data = value;
21 if (!bus_->Write(address_, reg, &data, 1)) {
22 setError(Error::I2cWrite);
28template <
typename BusType>
29bool PF1550<BusType>::readReg8(uint8_t reg, uint8_t& value)
noexcept {
30 if (bus_ ==
nullptr) {
31 setError(Error::InvalidParam);
34 if (!bus_->Read(address_, reg, &value, 1)) {
35 setError(Error::I2cRead);
41template <
typename BusType>
46 if (bus_ ==
nullptr || !bus_->EnsureInitialized()) {
47 setError(Error::NotInitialized);
50 if (!VerifyDevice()) {
54 ClearErrorFlags(
static_cast<uint16_t
>(Error::NotInitialized));
58template <
typename BusType>
66template <
typename BusType>
69 if (!ReadDeviceId(
id)) {
70 setError(Error::DeviceNotFound);
74 setError(Error::WrongDeviceId);
80template <
typename BusType>
82 return readReg8(
static_cast<uint8_t
>(reg), value);
85template <
typename BusType>
87 return writeReg8(
static_cast<uint8_t
>(reg), value);
90template <
typename BusType>
92 if (bus_ ==
nullptr || !bus_->EnsureInitialized()) {
93 setError(Error::NotInitialized);
97 for (
const auto& entry : profile) {
98 if (!writeReg8(entry.reg, entry.value)) {
99 setError(Error::ProfileApply);
102 if (entry.delay_us > 0) {
103 bus_->DelayUs(entry.delay_us);
109template <
typename BusType>
114template <
typename BusType>
119template <
typename BusType>
121 if (bus_ ==
nullptr) {
122 setError(Error::InvalidParam);
133 setError(Error::InvalidParam);
139template <
typename BusType>
141 if (bus_ ==
nullptr) {
142 setError(Error::InvalidParam);
150template <
typename BusType>
155template <
typename BusType>
158 if (!ReadPmicStatus(raw)) {
166template <
typename BusType>
173 if (raw_reg !=
nullptr) {
180template <
typename BusType>
195template <
typename BusType>
197 if (buffer ==
nullptr || len == 0) {
198 setError(Error::InvalidParam);
201 for (
size_t i = 0; i < len; ++i) {
202 const uint8_t addr =
static_cast<uint8_t
>(start + i);
204 setError(Error::InvalidParam);
207 if (!ReadOtpByte(addr, buffer[i])) {
214template <
typename BusType>
219template <
typename BusType>
223 if ((sw_index != 1U && sw_index != 2U) || !sw_dvs_enabled_[sw_index - 1U]) {
224 setError(Error::InvalidParam);
229 setError(Error::InvalidParam);
233 return writeReg8(
static_cast<uint8_t
>(volt_reg), code);
236template <
typename BusType>
250 setError(Error::InvalidParam);
253 return writeReg8(
static_cast<uint8_t
>(volt_reg),
static_cast<uint8_t
>(code));
256template <
typename BusType>
259 if (value == 0xFFU) {
260 setError(Error::InvalidParam);
270template <
typename BusType>
275template <
typename BusType>
278 uint8_t sw0 = 0, sw1 = 0, ldo0 = 0, temp0 = 0, misc0 = 0, chg = 0, vbus = 0;
279 bool any_fail =
false;
310 setError(Error::DiagnosticRead);
316template <
typename BusType>
318 const uint8_t kClearAll = 0xFFU;
331template <
typename BusType>
333 const uint8_t mask_value = masked ? 0xFFU : 0x00U;
350template <
typename BusType>
359 static constexpr RailMap kMap[] = {
368 for (
const auto& m : kMap) {
369 auto& d = snap.rails[
static_cast<size_t>(m.id)];
370 if (!readReg8(
static_cast<uint8_t
>(m.volt_reg), d.volt_reg)) { ok =
false;
continue; }
371 if (!readReg8(
static_cast<uint8_t
>(m.ctrl_reg), d.ctrl_reg)) { ok =
false;
continue; }
374 }
else if (m.is_sw) {
375 const bool dvs = sw_dvs_enabled_[m.id ==
RailId::Sw1 ? 0U : 1U];
384 auto& vsnvs = snap.rails[
static_cast<size_t>(
RailId::Vsnvs)];
387 vsnvs.enabled_run =
true;
388 vsnvs.enabled_stby =
true;
395template <
typename BusType>
396bool PF1550<BusType>::fillFaultSnapshot(DiagnosticSnapshot& snap)
noexcept {
397 if (!ReadLatchedFaults(snap.faults)) {
401 uint8_t sw_sense0 = 0, sw_sense1 = 0, ldo_sense = 0;
406 auto mark = [&](
RailId id,
bool latched,
bool live) {
407 auto& d = snap.rails[
static_cast<size_t>(id)];
408 d.stat_latched = latched;
429template <
typename BusType>
442 out.chg_sense_reg = chg_raw;
449 uint8_t vbus_lim_reg = 0;
454 ok &= fillRailSnapshot(out);
455 ok &= fillFaultSnapshot(out);
459 setError(Error::DiagnosticRead);
464template <
typename BusType>
472 snap.chg_sense_reg = chg_raw;
478 ok &= fillFaultSnapshot(snap);
481 setError(Error::DiagnosticRead);
486template <
typename BusType>
491 if (!ReadDiagnosticSnapshot(out.snapshot)) {
493 setError(Error::SelfTestFailed);
500 out.all_rails_enabled =
true;
501 for (
size_t i = 0; i < static_cast<size_t>(
RailId::COUNT); ++i) {
504 if (!out.snapshot.rails[i].enabled_run) {
505 out.all_rails_enabled =
false;
510 out.faults = out.snapshot.faults;
514 return static_cast<uint8_t
>(s);
517 if (sev_val(out.worst_severity) < sev_val(target)) {
518 out.worst_severity = target;
527 setError(Error::SelfTestFailed);
CRTP-based PF1550 PMIC driver.
Definition pf1550.hpp:62
bool SetPowerMode(PowerMode mode) noexcept
Drive the STANDBY strap pin to RUN or STANDBY.
Definition pf1550.ipp:120
bool ReadOtpByte(uint8_t otp_addr, uint8_t &value) noexcept
Read a single OTP byte via FMRADDR/FMRDATA indirection.
Definition pf1550.ipp:181
bool ReadDeviceId(uint8_t &id) noexcept
Read DEVICE_ID (Reg 0x00).
Definition pf1550.ipp:59
bool ReadRegister(Register reg, uint8_t &value) noexcept
Read any PF1550 register by enumerated address.
Definition pf1550.ipp:81
bool ReadPmicStatus(uint8_t &status) noexcept
Read STATE_INFO (Reg 0x67) and return the raw byte.
Definition pf1550.ipp:151
bool RefreshStatusSnapshot(DiagnosticSnapshot &snap) noexcept
Refresh only the status part of a snapshot (≈14 register reads).
Definition pf1550.ipp:465
bool ReadPmicState(PmicState &state) noexcept
Decoded variant of ReadPmicStatus.
Definition pf1550.ipp:156
bool ClearLatchedFaults() noexcept
Write 0xFF to every category STAT register to clear all RW1C bits.
Definition pf1550.ipp:317
bool ReadLatchedFaults(FaultFlags &faults) noexcept
Read every category STAT register and aggregate latched faults.
Definition pf1550.ipp:276
bool ApplyPortentaH7CarrierProfile() noexcept
Apply the Portenta-H7-on-carrier profile.
Definition pf1550.ipp:115
bool ReadChargerState(ChargerState &state, uint8_t *raw_reg=nullptr) noexcept
Read CHG_SNS (Reg 0x87) — charger sub-state. Returns decoded enum.
Definition pf1550.ipp:167
bool ReadDiagnosticSnapshot(DiagnosticSnapshot &out) noexcept
Build a full diagnostic snapshot (≈30 register reads).
Definition pf1550.ipp:430
bool SetSwVoltageMv(uint8_t sw_index, uint16_t mv) noexcept
Set the RUN voltage of a DVS-enabled SW1 or SW2 in millivolts.
Definition pf1550.ipp:220
bool WriteRegister(Register reg, uint8_t value) noexcept
Write any PF1550 register by enumerated address.
Definition pf1550.ipp:86
bool ApplyPortentaH7DefaultProfile() noexcept
Apply the legacy VFR-heritage Portenta H7 default profile.
Definition pf1550.ipp:110
bool ReadInterruptCategory(uint8_t &category) noexcept
Read INT_CATEGORY (Reg 0x06).
Definition pf1550.ipp:271
PF1550(BusType *bus, uint8_t address=kDefaultI2cAddress) noexcept
Construct a driver instance bound to a CRTP bus adapter.
Definition pf1550.ipp:11
bool RunPowerSelfTest(SelfTestResult &out) noexcept
Boot-time self-test.
Definition pf1550.ipp:487
bool SetSwVoltage(uint8_t sw_index, SwVoltageCode run_code) noexcept
Set the RUN voltage of SW1 or SW2 from a SwVoltageCode.
Definition pf1550.ipp:215
bool VerifyDevice() noexcept
Read DEVICE_ID and assert it matches kExpectedDeviceId.
Definition pf1550.ipp:67
bool SetLdoVoltage(uint8_t ldo_index, LdoVoltageCode code) noexcept
Write LDOn_VOLT for n=1..3. Returns false if ldo_index is invalid.
Definition pf1550.ipp:237
bool EnsureInitialized() noexcept
Idempotently initialise the bus and verify the device.
Definition pf1550.ipp:42
bool SetVbusCurrentLimitMa(uint16_t limit_ma) noexcept
Convenience: write VBUS_IN_LIM_CNFG (0x94) from a mA value.
Definition pf1550.ipp:257
bool ApplyProfile(std::span< const profiles::RegisterWrite > profile) noexcept
Apply an arbitrary profile (sequence of register writes).
Definition pf1550.ipp:91
bool ReadOtpRegion(uint8_t *buffer, size_t len, uint8_t start=OtpRegion::kStart) noexcept
Read a contiguous region of OTP memory (default: full 0x1C..0x36 range).
Definition pf1550.ipp:196
bool SetInterruptMaskAll(bool masked) noexcept
Mask (1) or unmask (0) all interrupt categories at once.
Definition pf1550.ipp:332
bool SetUsbRails(bool vbus_en, bool otg_en) noexcept
Drive USB_VBUS_EN and USB_OTG_EN straps (HIGH = enabled on Portenta).
Definition pf1550.ipp:140
constexpr std::array< RegisterWrite, 14 > kPortentaH7Default
Portenta H7 eval MCU-domain profile (VFR heritage).
Definition pf1550_profiles.hpp:39
constexpr std::array< RegisterWrite, 14 > kPortentaH7Carrier
Portenta H7 + carrier bring-up profile (SW1-first, full SW2 enable).
Definition pf1550_profiles.hpp:73
Register
Symbolic register addresses used by the PF1550 driver.
Definition pf1550_registers.hpp:51
@ ChgSense
CHG_SNS — Table 154. Charger mode (precharge, fast-cc, fast-cv, eoc …).
@ SwIntStat1
SW_INT_STAT1 — high-side current limits.
@ OnKeyIntMask0
ONKEY_INT_MASK0.
@ LdoIntStat0
LDO_INT_STAT0 — Table 99. LDO1/2/3 current-limit faults.
@ MiscIntStat0
MISC_INT_STAT0 — Table 108. PWRON / VSYS / RESETBMCU events.
@ SwIntStat2
SW_INT_STAT2 — DVS done.
@ SwIntSense0
SW_INT_SENSE0.
@ FmrData
FRMDATA — OTP indirect data.
@ LdoIntMask0
LDO_INT_MASK0.
@ Sw2Volt
SW2_VOLT — Table 117.
@ FmrAddr
FMRADDR — OTP indirect address.
@ SwIntStat0
SW_INT_STAT0 — low-side current limits (SW1/2/3).
@ TempIntMask0
TEMP_INT_MASK0.
@ StateInfo
STATE_INFO — Table 146. STATE[5:0] = Wait/RUN/STANDBY/SLEEP/REGS_DISABLE.
@ LdoIntSense0
LDO_INT_SENSE0.
@ Sw2Ctrl
SW2_CTRL — Table 120.
@ Sw3Volt
SW3_VOLT — Table 122.
@ ChgIntMask
CHG_INT_MASK.
@ SwIntMask2
SW_INT_MASK2.
@ OtpFlavor
OTP_FLAVOR — Table 87. 0x00 = OTP not burned (A0EP).
@ ChgInt
CHG_INT — Table 150. SUP_I/BAT2SOC_I/CHGREV_I/CHG_I.
@ Sw1Ctrl
SW1_CTRL — EN/STBY_EN/OMODE/LPWR/DVSSPEED/FPWM/RDIS_ENB.
@ SwIntMask0
SW_INT_MASK0.
@ SwIntSense1
SW_INT_SENSE1.
@ IntCategory
INT_CATEGORY — Table 89. CHG/SW1/SW2/SW3/LDO/ONKEY/TEMP/MISC summary.
@ Sw1Volt
SW1_VOLT — RUN-mode voltage code (Table 31).
@ SiliconRev
SILICON_REV — Table 88. Metal/full-layer/fab-fin identifiers.
@ DeviceId
DEVICE_ID — Table 86. Bits[2:0] = family, [7:3] = 01111 for PF1550.
@ Ldo2Ctrl
LDO2_CTRL — must be written last in Portenta profile.
@ OnKeyIntStat0
ONKEY_INT_STAT0 — Table 105. Push / 1s/2s/3s/4s/8s long-press.
@ VbusSns
VBUS_SNS — Table 153. VBUS_VALID, DPM_SNS, OVLO, UVLO.
@ VsnvsCtrl
VSNVS_CTRL — Table 127. RTC/SNVS backup LDO control.
@ TempIntStat0
TEMP_INT_STAT0 — Table 102. Junction-temperature events.
@ VbusInCurrentLimit
VBUS input current limit ((mA/50) << 3 — Portenta uses 1500 mA → 0xA0).
@ MiscIntMask0
MISC_INT_MASK0.
@ SwIntMask1
SW_INT_MASK1.
RailId
Logical identifier for each independently-controllable PF1550 output.
Definition pf1550_diagnostics.hpp:43
@ Ldo3
LDO3 — Portenta +1V2 (STM32 DSI, ETH PHY).
@ Sw2
SW2 / BUCK2 — Portenta +3V3 / carrier VOUT.
@ Sw3
SW3 / BUCK3 — Portenta +3V1 VCORE (MCU + QSPI).
@ Ldo2
LDO2 — Portenta +1V8 (USB PHY, MIPI).
@ Sw1
SW1 / BUCK1 — Portenta +3V1SW (feeds LDO inputs).
@ Vsnvs
VSNVS — RTC / backup LDO (≤2 mA).
@ Ldo1
LDO1 — Portenta +1V0 (MIPI bridge analog).
LdoVoltageCode
Common LDO output voltage codes used on Portenta H7 (Table 41).
Definition pf1550_registers.hpp:274
constexpr uint8_t SwDvsMillivoltsToCode(uint16_t mv) noexcept
Encode a DVS-enabled SW1 / SW2 voltage (Table 31, left column).
Definition pf1550_voltage_tables.hpp:69
constexpr ChargerState DecodeChargerSense(uint8_t reg) noexcept
Convert CHG_SNS (0x87) into a typed ChargerState.
Definition pf1550_voltage_tables.hpp:236
constexpr uint16_t VbusLimitRegToMilliamps(uint8_t reg_value) noexcept
Decode VBUS_IN_LIM_CNFG (absolute address 0x94) register byte to mA.
Definition pf1550_voltage_tables.hpp:158
constexpr uint16_t SwCodeToMillivolts(uint8_t code) noexcept
SW1 / SW2 output voltage, DVS disabled (OTP_SWx_DVS_SEL = 1).
Definition pf1550_voltage_tables.hpp:47
constexpr uint16_t LdoCodeToMillivolts(uint8_t code, bool is_ldo2) noexcept
Decode a 5-bit LDO voltage register field to millivolts.
Definition pf1550_voltage_tables.hpp:118
FaultSeverity
Severity classification for a fault.
Definition pf1550_diagnostics.hpp:65
constexpr uint8_t kExpectedDeviceId
Expected DEVICE_ID[2:0] family identifier (PF1550 family = 100b).
Definition pf1550_registers.hpp:35
constexpr uint16_t SwDvsCodeToMillivolts(uint8_t code) noexcept
SW1 / SW2 output voltage, DVS enabled (OTP_SWx_DVS_SEL = 0): 0.6000 V + 12.5 mV × code (Table 31,...
Definition pf1550_voltage_tables.hpp:57
constexpr uint16_t Sw3CodeToMillivolts(uint8_t code) noexcept
SW3 output voltage (Table 37): 1.80 V + 100 mV × SW3_VOLT[3:0].
Definition pf1550_voltage_tables.hpp:82
PmicState
STATE_INFO[5:0] values (Reg 0x67) describing the PMIC state machine.
Definition pf1550_registers.hpp:226
@ Run
RUN — all OTP-sequenced regulators enabled.
constexpr uint16_t kVsnvsMillivolts
VSNVS output voltage: fixed 3.0 V (VSNVS_CTRL has no voltage field, Table 127).
Definition pf1550_registers.hpp:38
ChargerState
CHG_SNS[3:0] values (Reg 0x87) describing the charger sub-state.
Definition pf1550_registers.hpp:236
constexpr uint8_t VbusLimitMilliampsToReg(uint16_t mA) noexcept
Encode mA → VBUS_IN_LIM_CNFG (0x94) register byte (bits 7:3).
Definition pf1550_voltage_tables.hpp:188
SwVoltageCode
Common SW buck output voltage codes (RUN mode).
Definition pf1550_registers.hpp:265
constexpr FaultSeverity WorstSeverityPortentaH7(FaultFlags fl) noexcept
Return the worst-case severity across an aggregated bitmask.
Definition pf1550_diagnostics.hpp:240
constexpr PmicState DecodeStateInfo(uint8_t reg) noexcept
Convert STATE_INFO (0x67) full byte into a typed PmicState.
Definition pf1550_voltage_tables.hpp:224
PowerMode
Definition pf1550_i2c_interface.hpp:35
Full diagnostic snapshot returned by PF1550::ReadDiagnosticSnapshot().
Definition pf1550_diagnostics.hpp:140
Bitset of latched fault flags.
Definition pf1550_diagnostics.hpp:79
static constexpr uint32_t kTempShdn
THERM125I: die crossed 125 °C.
Definition pf1550_diagnostics.hpp:97
static constexpr uint32_t kLdo3Fault
Definition pf1550_diagnostics.hpp:93
static constexpr uint32_t kSw1Ls
Definition pf1550_diagnostics.hpp:83
static constexpr uint32_t kVbusInval
Definition pf1550_diagnostics.hpp:108
static constexpr uint32_t kSw3Ls
Definition pf1550_diagnostics.hpp:87
static constexpr uint32_t kVsysLow
LOW_SYS_WARN_I: VSYS crossed LOW_SYS_WARN.
Definition pf1550_diagnostics.hpp:101
static constexpr uint32_t kChgFault
Definition pf1550_diagnostics.hpp:107
static constexpr uint32_t kTempWarn
THERM110I: die crossed 110 °C.
Definition pf1550_diagnostics.hpp:96
static constexpr uint32_t kLdo1Fault
Definition pf1550_diagnostics.hpp:91
static constexpr uint32_t kLdo2Fault
Definition pf1550_diagnostics.hpp:92
static constexpr uint32_t kSw2Hs
Definition pf1550_diagnostics.hpp:86
static constexpr uint32_t kPwrOn
PWRON_I: power-on button event.
Definition pf1550_diagnostics.hpp:100
static constexpr uint32_t kSw1Hs
Definition pf1550_diagnostics.hpp:84
static constexpr uint32_t kI2cReadFail
Definition pf1550_diagnostics.hpp:112
static constexpr uint32_t kVsysOv
SYS_OVLO_I: VSYS crossed SYS_OVLO.
Definition pf1550_diagnostics.hpp:102
static constexpr uint32_t kSw3Hs
Definition pf1550_diagnostics.hpp:88
static constexpr uint32_t kSw2Ls
Definition pf1550_diagnostics.hpp:85
static constexpr uint8_t kLdo3Fault
LDO3 fault.
Definition pf1550_registers.hpp:199
static constexpr uint8_t kLdo2Fault
LDO2 fault.
Definition pf1550_registers.hpp:198
static constexpr uint8_t kLdo1Fault
LDO1 fault.
Definition pf1550_registers.hpp:197
static constexpr uint8_t kLowSysWarn
LOW_SYS_WARN_I — VSYS crossed the LOW_SYS_WARN threshold.
Definition pf1550_registers.hpp:215
static constexpr uint8_t kSysOvlo
SYS_OVLO_I — VSYS crossed the SYS_OVLO threshold.
Definition pf1550_registers.hpp:216
static constexpr uint8_t kPwrOn
PWRON_I — power-on button event.
Definition pf1550_registers.hpp:214
static constexpr uint8_t kEndExclusive
One past the last OTP byte address.
Definition pf1550_registers.hpp:327
static constexpr uint8_t kKey3Val
Definition pf1550_registers.hpp:321
static constexpr uint8_t kKey2Reg
Definition pf1550_registers.hpp:318
static constexpr uint8_t kKey1Val
Definition pf1550_registers.hpp:317
static constexpr uint8_t kKey1Reg
Definition pf1550_registers.hpp:316
static constexpr uint8_t kKey3Reg
Definition pf1550_registers.hpp:320
static constexpr uint8_t kKey2Val
Definition pf1550_registers.hpp:319
Result of a power self-test pass.
Definition pf1550_diagnostics.hpp:162
bool ran
Definition pf1550_diagnostics.hpp:163
static constexpr uint8_t kStbyEn
SW_STBY_EN — enable in STANDBY.
Definition pf1550_registers.hpp:294
static constexpr uint8_t kEn
SW_EN — enable in RUN.
Definition pf1550_registers.hpp:293
static constexpr uint8_t kSw3Ls
SW3_LS_I — SW3 low-side current limit.
Definition pf1550_registers.hpp:184
static constexpr uint8_t kSw2Ls
SW2_LS_I — SW2 low-side current limit.
Definition pf1550_registers.hpp:183
static constexpr uint8_t kSw1Ls
SW1_LS_I — SW1 low-side current limit (Table 90).
Definition pf1550_registers.hpp:182
static constexpr uint8_t kSw2Hs
SW2_HS_I — SW2 high-side current limit.
Definition pf1550_registers.hpp:191
static constexpr uint8_t kSw1Hs
SW1_HS_I — SW1 high-side current limit.
Definition pf1550_registers.hpp:190
static constexpr uint8_t kSw3Hs
SW3_HS_I — SW3 high-side current limit.
Definition pf1550_registers.hpp:192
static constexpr uint8_t kTherm110
THERM110I — die temperature crossed 110 °C (either way).
Definition pf1550_registers.hpp:204
static constexpr uint8_t kTherm125
THERM125I — die temperature crossed 125 °C (either way).
Definition pf1550_registers.hpp:205