Skip to content
Draft
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
261 changes: 234 additions & 27 deletions FprimeZephyrReference/Components/ModeManager/ModeManager.cpp

Large diffs are not rendered by default.

67 changes: 62 additions & 5 deletions FprimeZephyrReference/Components/ModeManager/ModeManager.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,18 @@ module Components {

@ System mode enumeration
enum SystemMode {
NORMAL = 0 @< Normal operational mode
SAFE_MODE = 1 @< Safe mode with non-critical components powered off
NORMAL = 2 @< Normal operational mode
}

@ Reason for entering safe mode (used for recovery decision logic)
enum SafeModeReason {
NONE = 0 @< Not in safe mode or reason cleared
LOW_BATTERY = 1 @< Entered due to low voltage condition
SYSTEM_FAULT = 2 @< Entered due to unintended reboot/system fault
GROUND_COMMAND = 3 @< Entered via ground command
EXTERNAL_REQUEST = 4 @< Entered via external component request
LORA = 5 @< Entered due to LoRa communication timeout or fault
}

@ Port for notifying about mode changes
Expand All @@ -12,6 +22,10 @@ module Components {
@ Port for querying the current system mode
port GetSystemMode -> SystemMode

@ Port for forcing safe mode with a reason
@ Pass NONE as reason to default to EXTERNAL_REQUEST
port ForceSafeModeWithReason(reason: SafeModeReason)

@ Component to manage system modes and orchestrate safe mode transitions
@ based on voltage, watchdog faults, and communication timeouts
active component ModeManager {
Expand All @@ -24,22 +38,26 @@ module Components {
sync input port run: Svc.Sched

@ Port to force safe mode entry (callable by other components)
async input port forceSafeMode: Fw.Signal
@ Accepts SafeModeReason - pass NONE to default to EXTERNAL_REQUEST
async input port forceSafeMode: Components.ForceSafeModeWithReason

@ Port to query the current system mode
sync input port getMode: Components.GetSystemMode

@ Port called before intentional reboot to set clean shutdown flag
sync input port prepareForReboot: Fw.Signal

# ----------------------------------------------------------------------
# Output Ports
# ----------------------------------------------------------------------

@ Port to notify other components of mode changes (with current mode)
output port modeChanged: Components.SystemModeChanged

@ Ports to turn on LoadSwitch instances (8 total)
@ Ports to turn on LoadSwitch instances (6 face switches + 2 payload switches)
output port loadSwitchTurnOn: [8] Fw.Signal

@ Ports to turn off LoadSwitch instances (8 total)
@ Ports to turn off LoadSwitch instances (6 face switches + 2 payload switches)
output port loadSwitchTurnOff: [8] Fw.Signal

@ Port to get system voltage from INA219 manager
Expand Down Expand Up @@ -83,7 +101,6 @@ module Components {
severity warning high \
format "External fault detected - external component forced safe mode"


@ Event emitted when command validation fails
event CommandValidationFailed(
cmdName: string size 50 @< Command that failed validation
Expand All @@ -100,6 +117,31 @@ module Components {
severity warning low \
format "State persistence {} failed with status {}"

@ Event emitted when automatically entering safe mode due to low voltage
event AutoSafeModeEntry(
reason: SafeModeReason @< Reason for entering safe mode
voltage: F32 @< Voltage that triggered the entry (0 if N/A)
) \
severity warning high \
format "AUTO SAFE MODE ENTRY: reason={} voltage={}V"

@ Event emitted when automatically exiting safe mode due to voltage recovery
event AutoSafeModeExit(
voltage: F32 @< Voltage that triggered recovery
) \
severity activity high \
format "AUTO SAFE MODE EXIT: Voltage recovered to {}V"

@ Event emitted when unintended reboot is detected
event UnintendedRebootDetected() \
severity warning high \
format "UNINTENDED REBOOT DETECTED: Entering safe mode"

@ Event emitted when preparing for intentional reboot
event PreparingForReboot() \
severity activity high \
format "Preparing for intentional reboot - setting clean shutdown flag"

# ----------------------------------------------------------------------
# Telemetry
# ----------------------------------------------------------------------
Expand All @@ -110,6 +152,21 @@ module Components {
@ Number of times safe mode has been entered
telemetry SafeModeEntryCount: U32

@ Current safe mode reason (NONE if not in safe mode)
telemetry CurrentSafeModeReason: SafeModeReason

# ----------------------------------------------------------------------
# Parameters
# ----------------------------------------------------------------------

@ Voltage threshold for safe mode entry (V)
param SafeModeEntryVoltage: F32 default 6.7

@ Voltage threshold for safe mode recovery (V)
param SafeModeRecoveryVoltage: F32 default 8.0

@ Debounce time for voltage transitions (seconds)
param SafeModeDebounceSeconds: U32 default 10

###############################################################################
# Standard AC Ports: Required for Channels, Events, Commands, and Parameters #
Expand Down
36 changes: 28 additions & 8 deletions FprimeZephyrReference/Components/ModeManager/ModeManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ class ModeManager : public ModeManagerComponentBase {
//! Handler implementation for forceSafeMode
//!
//! Port to force safe mode entry (callable by other components)
void forceSafeMode_handler(FwIndexType portNum //!< The port number
//! @param reason The reason for entering safe mode (NONE defaults to EXTERNAL_REQUEST)
void forceSafeMode_handler(FwIndexType portNum, //!< The port number
const Components::SafeModeReason& reason //!< The safe mode reason
) override;

//! Handler implementation for getMode
Expand All @@ -56,6 +58,12 @@ class ModeManager : public ModeManagerComponentBase {
Components::SystemMode getMode_handler(FwIndexType portNum //!< The port number
) override;

//! Handler implementation for prepareForReboot
//!
//! Port called before intentional reboot to set clean shutdown flag
void prepareForReboot_handler(FwIndexType portNum //!< The port number
) override;

// ----------------------------------------------------------------------
// Handler implementations for commands
// ----------------------------------------------------------------------
Expand All @@ -81,12 +89,15 @@ class ModeManager : public ModeManagerComponentBase {
//! Save persistent state to file
void saveState();

//! Enter safe mode with optional reason override
void enterSafeMode(const char* reason = nullptr);
//! Enter safe mode with specified reason
void enterSafeMode(Components::SafeModeReason reason);

//! Exit safe mode
//! Exit safe mode (manual command)
void exitSafeMode();

//! Exit safe mode automatically due to voltage recovery
void exitSafeModeAutomatic(F32 voltage);

//! Turn off non-critical components
void turnOffNonCriticalComponents();

Expand All @@ -104,21 +115,30 @@ class ModeManager : public ModeManagerComponentBase {
// ----------------------------------------------------------------------

//! System mode enumeration
enum class SystemMode : U8 { NORMAL = 0, SAFE_MODE = 1 };
enum class SystemMode : U8 { SAFE_MODE = 1, NORMAL = 2 };

//! Persistent state structure
struct PersistentState {
U8 mode; //!< Current mode (SystemMode)
U32 safeModeEntryCount; //!< Number of times safe mode entered
U8 safeModeReason; //!< Reason for safe mode entry (SafeModeReason)
U8 cleanShutdown; //!< Clean shutdown flag (1 = clean, 0 = unclean)
};

// ----------------------------------------------------------------------
// Private member variables
// ----------------------------------------------------------------------

SystemMode m_mode; //!< Current system mode
U32 m_safeModeEntryCount; //!< Counter for safe mode entries
U32 m_runCounter; //!< Counter for run handler calls (1Hz)
SystemMode m_mode; //!< Current system mode
U32 m_safeModeEntryCount; //!< Counter for safe mode entries
U32 m_runCounter; //!< Counter for run handler calls (1Hz)
Components::SafeModeReason m_safeModeReason; //!< Current safe mode reason
U32 m_safeModeVoltageCounter; //!< Counter for low voltage in NORMAL mode
U32 m_recoveryVoltageCounter; //!< Counter for voltage recovery in SAFE_MODE

// ----------------------------------------------------------------------
// Constants
// ----------------------------------------------------------------------

static constexpr const char* STATE_FILE_PATH = "/mode_state.bin"; //!< State file path
};
Expand Down
Loading
Loading