FuSa 8-Bit Libraries Safety Framework
Loading...
Searching...
No Matches
tasks_pre_startup.c
Go to the documentation of this file.
1
22
23// Standard Library Includes
24#include <stdbool.h>
25#include <stdint.h>
26
27// Framework Includes
34#include <tasks_config.h>
35#include <tasks_pre_startup.h>
36
42typedef enum
43{
44 FSM_STATE_START = ERRINJ_RESET_NONE,
45 FSM_STATE_CONTINUE = ERRINJ_RESET_CPU,
46 FSM_STATE_COMPLETE = ERRINJ_RESET_WDT,
47 FSM_STATE_CORRUPT = ERRINJ_RESET_CORRUPT
48} fsmState_t;
49
50// Private function prototypes
51static errInjectReset_t DetermineErrorInjection(resetReason_t reason);
52static fsmState_t DetermineState(void);
53static void RunDiagSwdtExpire(void);
54static void ResetFsm(void);
55static void AbortFsm(void);
56
58{
60
61 // I/O Pins not floated (tri-Stated)
62 bool isIoUnsafe = (flag != NO_ERROR);
63 if (isIoUnsafe)
64 {
65 MW_EnableForceFloat(); // Force tri-stating of all I/O pins
67 }
68 else
69 {
70 /* Intentional misra-c2012-2.2/14.3 deviation */
72 {
74 }
75 }
76}
77
79{
81 errInjectReset_t errInjState = DetermineErrorInjection(reason);
82
83 /*
84 * Only store the reset reason if it is the true reset reason and not an error injection as part
85 * of the pre-startup sequence
86 */
87 if (errInjState != ERRINJ_RESET_NONE)
88 {
89 uint8_t errInjStateVal = (uint8_t)errInjState;
90 // Store reason for reset due to error injection, to complete the pre-startup sequence
92 }
93 else
94 {
95 uint8_t reasonVal = (uint8_t)reason;
96 // Store device reset reason, for later handling in the startup sequence
98 }
99}
100
101// Checks the error injection ongoing flag to determine if the reset was due to an error injection
102static errInjectReset_t DetermineErrorInjection(resetReason_t reason)
103{
104 bool isErrInjOngoing = MW_GetPersistentFlag(PFLAG_ERRINJ_ONGOING);
105 errInjectReset_t errorInjectionReason = ERRINJ_RESET_NONE;
106
107 if (isErrInjOngoing)
108 {
109 if (reason == RSTRSN_MCHK_DCLS)
110 {
111 errorInjectionReason = ERRINJ_RESET_CPU;
112 }
113
114 if (reason == RSTRSN_WDT_TIMEOUT)
115 {
116 errorInjectionReason = ERRINJ_RESET_WDT;
117 }
118 }
119 return errorInjectionReason;
120}
121
123{
124 fsmState_t state = DetermineState(); // Read persistent memory to figure out the FSM state
125 bool isDiagFailure = false; // Diagnostics pass by default if the expected reset occured
126
127 // Initial state, perform CPU lockstep error injection
128 if (state == FSM_STATE_START)
129 {
130 // Prevent the system from treating the error injection reset as a real fault
132 (void)MW_DiagCpuLockstep(); // Always returns ERROR
133
134 // Diagnostic failed to reset the device: go to the next state and report failure
135 isDiagFailure = true;
136 state = FSM_STATE_CONTINUE;
137 }
138
139 // After CPU error injection, store result and perform error injection for watchdogs
140 if (state == FSM_STATE_CONTINUE)
141 {
143
144 RunDiagSwdtExpire(); // Does not reset the device, but will enable the SWDT until next reset
145
146 (void)MW_DiagWdtExpire(); // Always returns ERROR
147
148 // Diagnostic failed to reset the device: go to the next state and report failure
149 isDiagFailure = true;
150 state = FSM_STATE_COMPLETE;
151 }
152
153 // After WDT error injection, store result and reset FSM
154 if (state == FSM_STATE_COMPLETE)
155 {
157 ResetFsm(); // Clear error injection reason and error injection flag
158 }
159
160 // If the FSM is corrupted, abort execution to avoid infinite reset loops.
161 if (state == FSM_STATE_CORRUPT)
162 {
163 AbortFsm(); // Set error injection reason to corrupted
164 }
165}
166
167/*
168 * Reads the error injection reset reason to determine which state the T_RunResetDiagnosticFsm is
169 * in. It is assumed that the reason is stored in persistent memory by another part of the system
170 * during determination of the reset reason if the PFLAG_ERRINJ_ONGOING flag is set. The persistent
171 * memory can store data between resets, except for POR / BOR resets, in which the FSM is set back
172 * to the initial state automatically.
173 */
174static fsmState_t DetermineState(void)
175{
176 const uint8_t errInjReasonVal = MW_GetPersistentVal(PVAL_ERRINJ_REASON);
177
178 /* Intentional misra-c2012-10.5 deviation */
179 const errInjectReset_t errInjReason = (errInjectReset_t)errInjReasonVal;
180
181 /* Intentional misra-c2012-10.5 deviation */
182 fsmState_t state = (fsmState_t)errInjReason;
183
184 const bool invalidReasonVal = (errInjReason > ERRINJ_RESET_CORRUPT);
185 const bool flagsCorrupted = MW_IsPersistentFlagsCorrupt();
186
187 // Check if a single bit flip has occured in the reset reason data
188 const bool errInjOngoing = MW_GetPersistentFlag(PFLAG_ERRINJ_ONGOING);
189 const bool stateCorrupted = ((errInjOngoing == false) && (state != FSM_STATE_START));
190
191 // If persistent data used by the FSM is corrupted, the FSM state itself is corrupted
192 if (invalidReasonVal || flagsCorrupted || stateCorrupted)
193 {
194 state = FSM_STATE_CORRUPT;
195 }
196
197 return state;
198}
199
200// Performs the Syncronous Watchdog Expire diagnostic and stores the result in persistent memory.
201static void RunDiagSwdtExpire(void)
202{
204 bool isDiagFailure = true;
205
206 if (result == NO_ERROR)
207 {
208 isDiagFailure = false;
209 }
210
212}
213
214// Reset FSM by clearing the reason and error injection flag
215static void ResetFsm(void)
216{
217 const errInjectReset_t fsmReset = ERRINJ_RESET_NONE;
218 const uint8_t fsmResetVal = (uint8_t)fsmReset;
221}
222
223/*
224 * Report that the FSM was aborted for later handling by setting the error injection reason to
225 * corrupt, indicating that the stored true reset reason cannot be trusted, since it is not possible
226 * to know if it is the true reset reason or if it was overwritten by an error injection reset.
227 */
228static void AbortFsm(void)
229{
230 const errInjectReset_t fsmAborted = ERRINJ_RESET_CORRUPT;
231 const uint8_t fsmAbortedVal = (uint8_t)fsmAborted;
233}
errFlag_t
Defines the error flag used by Middleware services to indicate error detection.
@ NO_ERROR
Defines type for storing the reason of a device reset caused by an error injection.
errInjectReset_t
Defines possible reasons for a device reset due to an error injection.
errFlag_t MW_DiagCpuLockstep(void)
Performs error injection diagnostic to detect faults in the CPU lockstep mechanism.
errFlag_t MW_CheckIoSafe(void)
Checks if all I/O pins are floated (tri-stated).
void MW_EnableForceFloat(void)
Enables forced floating (tri-stating) of all I/O pins.
void MW_StorePersistentVal(persistentVal_t valueType, uint8_t value)
Stores a value in General Purpose Registers (GPR) for perserving data between resets.
void MW_StorePersistentFlag(persistentFlag_t flagType, bool flag)
Stores two redundant boolean flags in General Purpose Registers (GPR) for perserving data between res...
bool MW_GetPersistentFlag(persistentFlag_t flagType)
Reads two redundant bits for each boolean flags in General Purpose Registers (GPR) that is stored for...
bool MW_IsPersistentFlagsCorrupt(void)
Compares two redundant bits for each boolean flags in General Purpose Registers (GPR) and checks if a...
uint8_t MW_GetPersistentVal(persistentVal_t valueType)
Reads a value in General Purpose Registers (GPR) that is stored for preserving data between resets.
@ PVAL_RESET_REASON
@ PVAL_ERRINJ_REASON
@ PFLAG_WDT_INJ_FAULT
@ PFLAG_ERRINJ_ONGOING
@ PFLAG_IO_FLOAT_FAULT
@ PFLAG_CPU_INJ_FAULT
@ PFLAG_SWDT_INJ_FAULT
void T_DetermineResetReason(void)
Determines the reason for the last device reset and stores it for later handling.
void T_RunResetDiagnosticFsm(void)
Implements an FSM for performing error injection diagnostics leading to device resets.
void T_EnsureSafeState(void)
Ensures the device is in a Safe State by making sure io pins are floated.
resetReason_t MW_GetClearResetReason(void)
Reads and clears the reset flag registers.
resetReason_t
Type defines for all possible reset sources.
@ RSTRSN_WDT_TIMEOUT
@ RSTRSN_MCHK_DCLS
#define STRICT_SAFE_STATE
Configures whether to use a strict Safe State to Mission Mode transition in TM_PreStartup and TM_Star...
#define PRE_STARTUP_SWDT_RESET_VAL
Configures the new SWDT reset value after performing the SWDT Expire diagnostic in T_RunResetDiagnost...
#define ENABLED
Used to enable optional Task features through macro configurations.
errFlag_t MW_DiagWdtExpire(void)
Performs error injection diagnostic to detect faults in the Watchdog Timer (WDT) Expire mechanism.
errFlag_t MW_DiagSwdtExpire(uint32_t newReset)
Performs error injection diagnostic to detect faults in the Synchronous Watchdog Timer (SWDT) Expire ...
Contains API prototypes for the Watchdog Manager diagnostics.