@@ -24,7 +24,7 @@ StartupManager ::~StartupManager() {}
2424FwSizeType StartupManager ::update_boot_count () {
2525 // Read the boot count file path from parameter and assert that it is either valid or the default value
2626 Fw::ParamValid is_valid;
27- auto boot_count_file = this ->paramGet_BOOT_COUNT_FILE (0 , is_valid);
27+ auto boot_count_file = this ->paramGet_BOOT_COUNT_FILE (is_valid);
2828 FW_ASSERT (is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
2929
3030 // Open the boot count file and read the current boot count
@@ -47,7 +47,8 @@ FwSizeType StartupManager ::update_boot_count() {
4747 }
4848 file.close ();
4949 }
50- boot_count = boot_count + 1 ;
50+ // Boot count of zero is a flag value, so ensure a minimum boot count of 1
51+ boot_count = FW_MAX (1 , boot_count + 1 );
5152
5253 // Open the file for writing the boot count
5354 status = file.open (boot_count_file.toChar (), Os::File::OPEN_CREATE, Os::File::OVERWRITE);
@@ -64,25 +65,80 @@ FwSizeType StartupManager ::update_boot_count() {
6465 return boot_count;
6566}
6667
67- void StartupManager ::run_handler (FwIndexType portNum, U32 context) {
68- // On the first call, update the boot count
69- if (this ->m_boot_count == 0 ) {
70- this ->m_boot_count = this ->update_boot_count ();
71- }
68+ Fw::Time StartupManager ::get_quiescence_start () {
69+ // Read the quiescence start time file path from parameter and assert that it is either valid or the default value
7270 Fw::ParamValid is_valid;
73- while (this ->m_boot_count == 1 && armed) {
74- armed = this ->paramGet_ARMED (is_valid);
75- }
7671
77- char buffer[Fw::TimeIntervalValue::SERIALIZED_SIZE];
72+ auto time_file = this ->paramGet_QUIESCENCE_START_FILE (is_valid);
73+ FW_ASSERT (is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
74+
75+ // Open the boot count file and read the current boot count
76+ Fw::Time time;
77+ Os::File file;
78+ Os::File::Status status = file.open (time_file.toChar (), Os::File::OPEN_READ);
79+ U8 buffer[Fw::Time::SERIALIZED_SIZE];
80+
81+ // If the file read ok, then we read the quiescence start time.
82+ if (status == Os::File::OP_OK) {
83+ FwSizeType size = sizeof (buffer);
84+ status = file.read (buffer, size);
85+ if (status == Os::File::OP_OK) {
86+ Fw::ExternalSerializeBuffer buffer_obj (buffer, sizeof (buffer));
87+ Fw::SerializeStatus serialization_status = buffer_obj.deserializeTo (time);
88+ if (serialization_status != Fw::SerializeStatus::FW_SERIALIZE_OK) {
89+ time = this ->getTime (); // Default to current time if deserialization fails
90+ }
91+ }
92+ (void )file.close ();
93+ }
94+ // Write quiescence start time if read failed
95+ if (status != Os::File::OP_OK) {
96+ FwSizeType size = sizeof (buffer);
97+ time = this ->getTime ();
98+ status = file.open (time_file.toChar (), Os::File::OPEN_CREATE, Os::File::OVERWRITE);
99+ if (status == Os::File::OP_OK) {
100+ Fw::ExternalSerializeBuffer buffer_obj (buffer, sizeof (Fw::Time::SERIALIZED_SIZE));
101+ Fw::SerializeStatus serialize_status = buffer_obj.serializeFrom (time);
102+ if (serialize_status == Fw::SerializeStatus::FW_SERIALIZE_OK) {
103+ (void )file.write (buffer, size);
104+ }
105+ }
106+ (void )file.close ();
107+ }
108+ return time;
109+ }
78110
79- Fw::ParamString bootCount =
111+ void StartupManager ::run_handler (FwIndexType portNum, U32 context) {
112+ Fw::ParamValid is_valid;
80113
81- Os::File file;
114+ // On the first call, update the boot count, set the quiescence start time, and dispatch the start-up sequence
115+ if (this ->m_boot_count == 0 ) {
116+ this ->m_boot_count = this ->update_boot_count ();
117+ this ->m_quiescence_start = this ->get_quiescence_start ();
82118
83- Os::File::Status status = file.open (, Os::File::OPEN_READ);
119+ Fw::ParamString first_sequence = this ->paramGet_STARTUP_SEQUENCE_FILE (is_valid);
120+ FW_ASSERT (is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
121+ this ->runSequence_out (0 , first_sequence);
122+ }
84123
85- this ->cmdResponse_out (this ->m_stored_opcode , this ->m_stored_sequence , Fw::CmdResponse::OK);
124+ // Are we waiting for quiescence?
125+ if (this ->m_waiting ) {
126+ // Check if the system is armed or if this is not the first boot. In both cases, we skip waiting.
127+ bool armed = this ->paramGet_ARMED (is_valid);
128+ FW_ASSERT (is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
129+
130+ Fw::TimeIntervalValue quiescence_period = this ->paramGet_QUIESCENCE_TIME (is_valid);
131+ Fw::Time quiescence_interval (quiescence_period.get_seconds (), quiescence_period.get_useconds ());
132+ FW_ASSERT (is_valid == Fw::ParamValid::VALID || is_valid == Fw::ParamValid::DEFAULT);
133+ Fw::Time end_time = Fw::Time::add (this ->m_quiescence_start , quiescence_interval);
134+
135+ // If not armed or this is not the first boot, we skip waiting
136+ if (!armed || end_time <= this ->getTime ()) {
137+ this ->m_waiting = false ;
138+ this ->cmdResponse_out (this ->m_stored_opcode , this ->m_stored_sequence , Fw::CmdResponse::OK);
139+ }
140+ }
141+ this ->tlmWrite_BootCount (this ->m_boot_count );
86142}
87143
88144// ----------------------------------------------------------------------
@@ -92,6 +148,7 @@ void StartupManager ::run_handler(FwIndexType portNum, U32 context) {
92148void StartupManager ::WAIT_FOR_QUIESCENCE_cmdHandler (FwOpcodeType opCode, U32 cmdSeq) {
93149 this ->m_stored_opcode = opCode;
94150 this ->m_stored_sequence = cmdSeq;
151+ this ->m_waiting = true ;
95152}
96153
97154} // namespace Components
0 commit comments