FuSa 8-Bit Libraries Safety Framework
Loading...
Searching...
No Matches
midware_memory_manager_diag.c
Go to the documentation of this file.
1
22
23// Standard Library Includes
24#include <stdbool.h>
25#include <stddef.h>
26#include <stdint.h>
27
28// Framework Includes
29#include <driver_cpuctrl.h>
30#include <driver_errctrl.h>
31#include <driver_nvmctrl.h>
32#include <driver_ramctrl.h>
36
37// Device-specific Includes
38#include <xc.h>
39
40// RAM variable to reserve address used for memory reads
41static volatile uint8_t tempDiagData = 0U;
42
43// Error Controller bitmasks used when reading the error channel register
44static const uint32_t buserrChMask = 1UL << ERRCTRL_ESF_1_bp;
45static const uint32_t ram2ChMask = 1UL << ERRCTRL_ESF_2_bp;
46static const uint32_t flash2ChMask = 1UL << ERRCTRL_ESF_3_bp;
47static const uint32_t opcChMask = 1UL << ERRCTRL_ESF_4_bp;
48static const uint32_t ram1ChMask = 1UL << ERRCTRL_ESF_6_bp;
49static const uint32_t flash1ChMask = 1UL << ERRCTRL_ESF_7_bp;
50static const uint32_t eepromChMask = 1UL << ERRCTRL_ESF_14_bp;
51
52// Private function prototypes
53static void DisableRamParityChannels(void);
54static void RestoreRamParityChannels(uint8_t buserrCfg);
55static void DisableNvmParityChannels(void);
56static void RestoreNvmParityChannels(uint8_t buserrCfg, uint8_t opcCfg);
57
58static bool InjectCpuDataParityErrorOnRam(void);
59static bool InjectCpuAddressParityErrorOnRam(void);
60static bool InjectCpuControlParityErrorOnRam(void);
61static bool InjectNvmDataParityErrorOnCpu(void);
62static bool InjectNvmInstrParityErrorOnCpu(void);
63static bool InjectCpuDataParityErrorOnNvm(void);
64static bool InjectCpuAddressParityErrorOnNvm(void);
65static bool InjectCpuControlParityErrorOnNvm(void);
66
67static void DisableRamEccChannels(void);
68static void RestoreRamEccChannels(uint8_t buserrCfg, uint8_t ram1Cfg, uint8_t ram2Cfg);
69static void DisableFlashEccChannels(void);
70static void RestoreFlashEccChannels(uint8_t buserrCfg, uint8_t flash1Cfg, uint8_t flash2Cfg);
71static void DisableEepromEccChannels(void);
72static void RestoreEepromEccChannels(uint8_t buserrCfg, uint8_t eepromCfg);
73
74static bool InjectEccCompErrorOnRam(void);
75static bool InjectEcc1ErrorOnRam(void);
76static bool InjectEcc2ErrorOnRam(void);
77static bool InjectEccCompErrorOnFlash(void);
78static bool InjectEcc1ErrorOnFlash(void);
79static bool InjectEcc2ErrorOnFlash(void);
80static bool InjectEcc1ErrorOnEeprom(void);
81static bool InjectEcc2ErrorOnEeprom(void);
82
84{
85 // Check if there are any unhandled errors and ensure the Error Controller is in NORMAL state
86 const uint32_t errorChMask = buserrChMask;
87 const bool isConfigurable = IsErrChConfigurable(errorChMask);
88 if (!isConfigurable)
89 {
90 /* cppcheck-suppress misra-c2012-15.5 */
91 return ERROR;
92 }
93
94 // Disable and backup global interrupts configuration
96
97 // The error injection will trigger a Non-maskable Interrupt (NMI) unless temporarily disabled
98 CPUCTRL_SetControlA((uint8_t)CPU_NMIDIS_bm);
99
100 // Prevent error injection from triggering a real error response
101 uint8_t buserrChBackup = ERRCTRL_ReadConfigBuserr();
102 DisableRamParityChannels(); // Disables float and sets channel to NOTIFICATION
103
104 // Perform error injections to test each RAM parity checker
105 const bool isCpuDataDiagPassed = InjectCpuDataParityErrorOnRam();
106 const bool isCpuAddrDiagPassed = InjectCpuAddressParityErrorOnRam();
107 const bool isCpuCtrlDiagPassed = InjectCpuControlParityErrorOnRam();
108 const bool isDiagPassed = (isCpuDataDiagPassed && isCpuAddrDiagPassed && isCpuCtrlDiagPassed);
109
110 RestoreRamParityChannels(buserrChBackup);
111
112 // Re-enable NMI
113 CPUCTRL_ClearControlA((uint8_t)CPU_NMIDIS_bm);
114
115 // Restore global interrupts configuration
117
118 errFlag_t diagResult = ERROR;
119 if (isDiagPassed)
120 {
121 diagResult = NO_ERROR;
122 }
123 return diagResult;
124}
125
127{
128 // Check if there are any unhandled errors and ensure the Error Controller is in NORMAL state
129 const uint32_t errorChMask = buserrChMask | opcChMask;
130 const bool isConfigurable = IsErrChConfigurable(errorChMask);
131 if (!isConfigurable)
132 {
133 /* cppcheck-suppress misra-c2012-15.5 */
134 return ERROR;
135 }
136
137 // Disable and backup global interrupts configuration
139
140 // The error injection will trigger a Non-maskable Interrupt (NMI) unless temporarily disabled
141 CPUCTRL_SetControlA((uint8_t)CPU_NMIDIS_bm);
142
143 // Prevent error injection from triggering a real error response
144 const uint8_t buserrChBackup = ERRCTRL_ReadConfigBuserr();
145 const uint8_t opcChBackup = ERRCTRL_ReadConfigOpc();
146 DisableNvmParityChannels(); // Disables float and sets channels to NOTIFICATION
147
148 // Perform error injections to test each NVM and CPU parity checker
149 const bool isNvmDataDiagPassed = InjectNvmDataParityErrorOnCpu();
150 const bool isNvmInstrDiagPassed = InjectNvmInstrParityErrorOnCpu();
151 const bool isNvmDiagPassed = isNvmDataDiagPassed && isNvmInstrDiagPassed;
152
153 const bool isCpuDataDiagPassed = InjectCpuDataParityErrorOnNvm();
154 const bool isCpuAddrDiagPassed = InjectCpuAddressParityErrorOnNvm();
155 const bool isCpuCtrlDiagPassed = InjectCpuControlParityErrorOnNvm();
156 const bool isCpuDiagPassed
157 = (isCpuDataDiagPassed && isCpuAddrDiagPassed && isCpuCtrlDiagPassed);
158
159 const bool isDiagPassed = (isNvmDiagPassed && isCpuDiagPassed);
160
161 RestoreNvmParityChannels(buserrChBackup, opcChBackup);
162
163 // Re-enable NMI
164 CPUCTRL_ClearControlA((uint8_t)CPU_NMIDIS_bm);
165
166 // Restore global interrupts configuration
168
169 errFlag_t diagResult = ERROR;
170 if (isDiagPassed)
171 {
172 diagResult = NO_ERROR;
173 }
174 return diagResult;
175}
176
178{
179 // Check if there are any unhandled errors and ensure the Error Controller is in NORMAL state
180 const uint32_t errorChMask = buserrChMask | ram1ChMask | ram2ChMask;
181 const bool isConfigurable = IsErrChConfigurable(errorChMask);
182 if (!isConfigurable)
183 {
184 /* cppcheck-suppress misra-c2012-15.5 */
185 return ERROR;
186 }
187
188 // Disable and backup global interrupts configuration
190
191 // The error injection will trigger a Non-maskable Interrupt (NMI) unless temporarily disabled
192 CPUCTRL_SetControlA((uint8_t)CPU_NMIDIS_bm);
193
194 // Prevent error injection from triggering a real error response
195 const uint8_t buserrChBackup = ERRCTRL_ReadConfigBuserr();
196 const uint8_t ram1ChBackup = ERRCTRL_ReadConfigRam1();
197 const uint8_t ram2ChBackup = ERRCTRL_ReadConfigRam2();
198 DisableRamEccChannels(); // Disables float and sets channels to NOTIFICATION
199
200 // Perform error injections to test each RAM ECC checker
201 const bool isCompDiagPassed = InjectEccCompErrorOnRam();
202 const bool isEcc1DiagPassed = InjectEcc1ErrorOnRam();
203 const bool isEcc2DiagPassed = InjectEcc2ErrorOnRam();
204 const bool isDiagPassed = (isCompDiagPassed && isEcc1DiagPassed && isEcc2DiagPassed);
205
206 RestoreRamEccChannels(buserrChBackup, ram1ChBackup, ram2ChBackup);
207
208 // Re-enable NMI
209 CPUCTRL_ClearControlA((uint8_t)CPU_NMIDIS_bm);
210
211 // Restore global interrupts configuration
213
214 errFlag_t diagResult = ERROR;
215 if (isDiagPassed)
216 {
217 diagResult = NO_ERROR;
218 }
219 return diagResult;
220}
221
223{
224 // Check if there are any unhandled errors and ensure the Error Controller is in NORMAL state
225 const uint32_t errorChMask = buserrChMask | flash1ChMask | flash2ChMask;
226 const bool isConfigurable = IsErrChConfigurable(errorChMask);
227 if (!isConfigurable)
228 {
229 /* cppcheck-suppress misra-c2012-15.5 */
230 return ERROR;
231 }
232
233 // Disable and backup global interrupts configuration
235
236 // The error injection will trigger a Non-maskable Interrupt (NMI) unless temporarily disabled
237 CPUCTRL_SetControlA((uint8_t)CPU_NMIDIS_bm);
238
239 // Prevent error injection from triggering a real error response
240 const uint8_t buserrChBackup = ERRCTRL_ReadConfigBuserr();
241 const uint8_t flash1ChBackup = ERRCTRL_ReadConfigFlash1();
242 const uint8_t flash2ChBackup = ERRCTRL_ReadConfigFlash2();
243 DisableFlashEccChannels(); // Disables float and sets channels to NOTIFICATION
244
245 // Perform error injections to test each NVM ECC checker on Flash
246 const bool isCompDiagPassed = InjectEccCompErrorOnFlash();
247 const bool isEcc1DiagPassed = InjectEcc1ErrorOnFlash();
248 const bool isEcc2DiagPassed = InjectEcc2ErrorOnFlash();
249 const bool isDiagPassed = (isCompDiagPassed && isEcc1DiagPassed && isEcc2DiagPassed);
250
251 RestoreFlashEccChannels(buserrChBackup, flash1ChBackup, flash2ChBackup);
252
253 // Re-enable NMI
254 CPUCTRL_ClearControlA((uint8_t)CPU_NMIDIS_bm);
255
256 // Restore global interrupts configuration
258
259 errFlag_t diagResult = ERROR;
260 if (isDiagPassed)
261 {
262 diagResult = NO_ERROR;
263 }
264 return diagResult;
265}
266
268{
269 // Check if there are any unhandled errors and ensure the Error Controller is in NORMAL state
270 const uint32_t errorChMask = buserrChMask | eepromChMask;
271 const bool isConfigurable = IsErrChConfigurable(errorChMask);
272 if (!isConfigurable)
273 {
274 /* cppcheck-suppress misra-c2012-15.5 */
275 return ERROR;
276 }
277
278 // Disable and backup global interrupts configuration
280
281 // The error injection will trigger a Non-maskable Interrupt (NMI) unless temporarily disabled
282 CPUCTRL_SetControlA((uint8_t)CPU_NMIDIS_bm);
283
284 // Prevent error injection from triggering a real error response
285 const uint8_t buserrChBackup = ERRCTRL_ReadConfigBuserr();
286 const uint8_t eepromChBackup = ERRCTRL_ReadConfigEeprom();
287 DisableEepromEccChannels(); // Disables float and sets channels to NOTIFICATION
288
289 // Perform error injections to test each NVM ECC checker on EEPROM
290 const bool isEcc1DiagPassed = InjectEcc1ErrorOnEeprom();
291 const bool isEcc2DiagPassed = InjectEcc2ErrorOnEeprom();
292 const bool isDiagPassed = (isEcc1DiagPassed && isEcc2DiagPassed);
293
294 RestoreEepromEccChannels(buserrChBackup, eepromChBackup);
295
296 // Re-enable NMI
297 CPUCTRL_ClearControlA((uint8_t)CPU_NMIDIS_bm);
298
299 // Restore global interrupts configuration
301
302 errFlag_t diagResult = ERROR;
303 if (isDiagPassed)
304 {
305 diagResult = NO_ERROR;
306 }
307 return diagResult;
308}
309
310// Sets the BUSSERR Error Channel to NOTIFICATION severity and disables I/O float
311static void DisableRamParityChannels(void)
312{
313 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
314 const uint8_t floatConfig = 0U << ERRCTRL_FLOAT_bp; // Disable I/O float
315 const uint8_t severityConfig = (uint8_t)ERRCTRL_ERRLVL_NOTIFICATION_gc;
316 const uint8_t disableChConfig = (floatConfig | severityConfig);
317
318 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
319 ERRCTRL_WriteConfigBuserr(disableChConfig);
320 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
321}
322
323// Restores the BUSERR Error Channel config to its backed up configuration
324static void RestoreRamParityChannels(uint8_t buserrCfg)
325{
326 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
327 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
328 ERRCTRL_WriteConfigBuserr(buserrCfg);
329 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
330}
331
332// Sets the BUSSERR and OPC Error Channels to NOTIFICATION severity and disables I/O float
333static void DisableNvmParityChannels(void)
334{
335 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
336 const uint8_t floatConfig = 0U << ERRCTRL_FLOAT_bp; // Disable I/O float
337 const uint8_t severityConfig = (uint8_t)ERRCTRL_ERRLVL_NOTIFICATION_gc;
338 const uint8_t disableChConfig = (floatConfig | severityConfig);
339
340 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
341 ERRCTRL_WriteConfigBuserr(disableChConfig);
342 ERRCTRL_WriteConfigOpc(disableChConfig);
343 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
344}
345
346// Restores the BUSERR and OPC Error Channels config to its backed up configuration
347static void RestoreNvmParityChannels(uint8_t buserrCfg, uint8_t opcCfg)
348{
349 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
350 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
351 ERRCTRL_WriteConfigBuserr(buserrCfg);
353 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
354}
355
356// Sets the BUSSERR and RAM1/2 Error Channels to NOTIFICATION severity and disables I/O float
357static void DisableRamEccChannels(void)
358{
359 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
360 const uint8_t floatConfig = 0U << ERRCTRL_FLOAT_bp; // Disable I/O float
361 const uint8_t severityConfig = (uint8_t)ERRCTRL_ERRLVL_NOTIFICATION_gc;
362 const uint8_t disableChConfig = (floatConfig | severityConfig);
363
364 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
365 ERRCTRL_WriteConfigBuserr(disableChConfig);
366 ERRCTRL_WriteConfigRam1(disableChConfig);
367 ERRCTRL_WriteConfigRam2(disableChConfig);
368 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
369}
370
371// Restores the BUSERR and RAM1/2 Error Channels config to its backed up configuration
372static void RestoreRamEccChannels(uint8_t buserrCfg, uint8_t ram1Cfg, uint8_t ram2Cfg)
373{
374 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
375 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
376 ERRCTRL_WriteConfigBuserr(buserrCfg);
379 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
380}
381
382// Sets the BUSSERR and FLASH1/2 Error Channels to NOTIFICATION severity and disables I/O float
383static void DisableFlashEccChannels(void)
384{
385 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
386 const uint8_t floatConfig = 0U << ERRCTRL_FLOAT_bp; // Disable I/O float
387 const uint8_t severityConfig = (uint8_t)ERRCTRL_ERRLVL_NOTIFICATION_gc;
388 const uint8_t disableChConfig = (floatConfig | severityConfig);
389
390 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
391 ERRCTRL_WriteConfigBuserr(disableChConfig);
392 ERRCTRL_WriteConfigFlash1(disableChConfig);
393 ERRCTRL_WriteConfigFlash2(disableChConfig);
394 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
395}
396
397// Restores the BUSERR and FLASH1/2 Error Channels config to its backed up configuration
398static void RestoreFlashEccChannels(uint8_t buserrCfg, uint8_t flash1Cfg, uint8_t flash2Cfg)
399{
400 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
401 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
402 ERRCTRL_WriteConfigBuserr(buserrCfg);
403 ERRCTRL_WriteConfigFlash1(flash1Cfg);
404 ERRCTRL_WriteConfigFlash2(flash2Cfg);
405 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
406}
407
408// Sets the BUSSERR and EEPROM Error Channels to NOTIFICATION severity and disables I/O float
409static void DisableEepromEccChannels(void)
410{
411 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
412 const uint8_t floatConfig = 0U << ERRCTRL_FLOAT_bp; // Disable I/O float
413 const uint8_t severityConfig = (uint8_t)ERRCTRL_ERRLVL_NOTIFICATION_gc;
414 const uint8_t disableChConfig = (floatConfig | severityConfig);
415
416 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
417 ERRCTRL_WriteConfigBuserr(disableChConfig);
418 ERRCTRL_WriteConfigEeprom(disableChConfig);
419 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
420}
421
422// Restores the BUSERR and EEPROM Error Channels config to its backed up configuration
423static void RestoreEepromEccChannels(uint8_t buserrCfg, uint8_t eepromCfg)
424{
425 const uint8_t stateMask = (uint8_t)ERRCTRL_STATE_gm;
426 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_CONFIG_gc);
427 ERRCTRL_WriteConfigBuserr(buserrCfg);
428 ERRCTRL_WriteConfigEeprom(eepromCfg);
429 ERRCTRL_ModifyControlA(stateMask, (uint8_t)ERRCTRL_STATE_NORMAL_gc);
430}
431
432static bool InjectCpuDataParityErrorOnRam(void)
433{
434 // Inject and trigger data parity error
436
437 // Check if all correct flags are set after injection
438 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
439 const uint8_t ramParityMask = (uint8_t)RAMCTRL_PARITYD_bm;
440 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
441
442 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
443 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
444 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
445
446 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
447 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
448
449 const bool isDiagPassed = (isRamFlagSet && isCpuFlagSet && isErrorChSet);
450
451 // Write to error flags and error channel to clear them
452 CPUCTRL_WriteIntFlags(cpuBuserrMask);
453 RAMCTRL_WriteIntFlags(ramParityMask);
454 ERRCTRL_WriteChannelStatus(buserrChMask);
455
456 return isDiagPassed;
457}
458
459static bool InjectCpuAddressParityErrorOnRam(void)
460{
461 // Inject and trigger address parity error
463
464 // Check if all correct flags are set after injection
465 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
466 const uint8_t ramParityMask = (uint8_t)RAMCTRL_PARITYA_bm;
467 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
468
469 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
470 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
471 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
472
473 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
474 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
475
476 const bool isDiagPassed = (isRamFlagSet && isCpuFlagSet && isErrorChSet);
477
478 // Write to error flags and error channel to clear them
479 CPUCTRL_WriteIntFlags(cpuBuserrMask);
480 RAMCTRL_WriteIntFlags(ramParityMask);
481 ERRCTRL_WriteChannelStatus(buserrChMask);
482
483 return isDiagPassed;
484}
485
486static bool InjectCpuControlParityErrorOnRam(void)
487{
488 // Inject and trigger control parity error
490
491 // Check if all correct flags are set after injection
492 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
493 const uint8_t ramParityMask = (uint8_t)RAMCTRL_PARITYC_bm;
494 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
495
496 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
497 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
498 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
499
500 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
501 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
502
503 const bool isDiagPassed = (isRamFlagSet && isCpuFlagSet && isErrorChSet);
504
505 // Write to error flags and error channel to clear them
506 CPUCTRL_WriteIntFlags(cpuBuserrMask);
507 RAMCTRL_WriteIntFlags(ramParityMask);
508 ERRCTRL_WriteChannelStatus(buserrChMask);
509
510 return isDiagPassed;
511}
512
513static bool InjectNvmDataParityErrorOnCpu(void)
514{
515 // Inject and trigger data parity error
516 /* cppcheck-suppress misra-c2012-11.4 */
518
519 // Check if all correct flags are set after injection
520 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
521 const uint8_t cpuParityMask = (uint8_t)CPU_PARITYD_bm;
522 const bool isCpuDataParitySet = ((cpuIntFlags & cpuParityMask) == cpuParityMask);
523
524 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
525 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
526
527 const bool isDiagPassed = (isCpuDataParitySet && isErrorChSet);
528
529 // Write to error flags and error channel to clear them
530 CPUCTRL_WriteIntFlags(cpuParityMask);
531 ERRCTRL_WriteChannelStatus(buserrChMask);
532
533 return isDiagPassed;
534}
535
536static bool InjectNvmInstrParityErrorOnCpu(void)
537{
538 // Inject and trigger data parity error
540
541 // Check if all correct flags are set after injection
542 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
543 const uint8_t cpuParityMask = (uint8_t)CPU_PARITYI_bm;
544 const bool isCpuInstructionParitySet = ((cpuIntFlags & cpuParityMask) == cpuParityMask);
545
546 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
547 const bool isErrorChSet = ((chStatus & opcChMask) == opcChMask);
548
549 const bool isDiagPassed = (isCpuInstructionParitySet && isErrorChSet);
550
551 // Write to error flags and error channel to clear them
552 CPUCTRL_WriteIntFlags(cpuParityMask);
554
555 return isDiagPassed;
556}
557
558static bool InjectCpuDataParityErrorOnNvm(void)
559{
560 // Inject and trigger data parity error
561 /* cppcheck-suppress misra-c2012-11.4 */
563
564 // Check if all correct flags are set after injection
565 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
566 const uint8_t nvmIntMask = (uint8_t)NVMCTRL_PARITYD_bm;
567 const bool isNvmFlagSet = ((nvmIntFlags & nvmIntMask) == nvmIntMask);
568
569 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
570 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
571 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
572
573 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
574 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
575
576 const bool isDiagPassed = (isNvmFlagSet && isCpuFlagSet && isErrorChSet);
577
578 // Write to error flags and error channel to clear them
579 CPUCTRL_WriteIntFlags(cpuBuserrMask);
580 NVMCTRL_WriteIntFlagsB(nvmIntMask);
581 ERRCTRL_WriteChannelStatus(buserrChMask);
582
583 return isDiagPassed;
584}
585
586static bool InjectCpuAddressParityErrorOnNvm(void)
587{
588 // Inject and trigger data parity error
589 /* cppcheck-suppress misra-c2012-11.4 */
591
592 // Check if all correct flags are set after injection
593 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
594 const uint8_t nvmIntMask = (uint8_t)NVMCTRL_PARITYA_bm;
595 const bool isNvmFlagSet = ((nvmIntFlags & nvmIntMask) == nvmIntMask);
596
597 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
598 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
599 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
600
601 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
602 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
603
604 const bool isDiagPassed = (isNvmFlagSet && isCpuFlagSet && isErrorChSet);
605
606 // Write to error flags and error channel to clear them
607 CPUCTRL_WriteIntFlags(cpuBuserrMask);
608 NVMCTRL_WriteIntFlagsB(nvmIntMask);
609 ERRCTRL_WriteChannelStatus(buserrChMask);
610
611 return isDiagPassed;
612}
613
614static bool InjectCpuControlParityErrorOnNvm(void)
615{
616 // Inject and trigger data parity error
617 /* cppcheck-suppress misra-c2012-11.4 */
619
620 // Check if all correct flags are set after injection
621 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
622 const uint8_t nvmIntMask = (uint8_t)NVMCTRL_PARITYC_bm;
623 const bool isNvmFlagSet = ((nvmIntFlags & nvmIntMask) == nvmIntMask);
624
625 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
626 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
627 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
628
629 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
630 const bool isErrorChSet = ((chStatus & buserrChMask) == buserrChMask);
631
632 const bool isDiagPassed = (isNvmFlagSet && isCpuFlagSet && isErrorChSet);
633
634 // Write to error flags and error channel to clear them
635 CPUCTRL_WriteIntFlags(cpuBuserrMask);
636 NVMCTRL_WriteIntFlagsB(nvmIntMask);
637 ERRCTRL_WriteChannelStatus(buserrChMask);
638
639 return isDiagPassed;
640}
641
642static bool InjectEccCompErrorOnRam(void)
643{
644 // Inject and trigger ECC comparator error
646
647 // Check if all correct flags are set after injection
648 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
649 const uint8_t ramParityMask = (uint8_t)RAMCTRL_COMP_bm;
650 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
651
652 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
653 const bool isErrorChSet = ((chStatus & ram2ChMask) == ram2ChMask);
654
655 const bool isDiagPassed = (isRamFlagSet && isErrorChSet);
656
657 // Write to error flags and error channel to clear them
658 RAMCTRL_WriteIntFlags(ramParityMask);
659 ERRCTRL_WriteChannelStatus(ram2ChMask);
660
661 return isDiagPassed;
662}
663
664static bool InjectEcc1ErrorOnRam(void)
665{
666 // Inject and trigger 1-bit ECC error
667 tempDiagData = 0x55U;
668 ASM_InjectRamEcc1(&tempDiagData);
669
670 // Check if all correct flags are set after injection
671 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
672 const uint8_t ramParityMask = (uint8_t)RAMCTRL_ECC1_bm;
673 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
674
675 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
676 const bool isErrorChSet = ((chStatus & ram1ChMask) == ram1ChMask);
677
678 const bool isDiagPassed = (isRamFlagSet && isErrorChSet);
679
680 // Write to error flags and error channel to clear them
681 RAMCTRL_WriteIntFlags(ramParityMask);
682 ERRCTRL_WriteChannelStatus(ram1ChMask);
683
684 return isDiagPassed;
685}
686
687static bool InjectEcc2ErrorOnRam(void)
688{
689 // Inject and trigger 2-bit ECC error
690 tempDiagData = 0x55U;
691 ASM_InjectRamEcc2(&tempDiagData);
692
693 // Check if all correct flags are set after injection
694 const uint8_t ramIntFlags = RAMCTRL_ReadIntFlags();
695 const uint8_t ramParityMask = (uint8_t)RAMCTRL_ECC2_bm;
696 const bool isRamFlagSet = ((ramIntFlags & ramParityMask) == ramParityMask);
697
698 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
699 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
700 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
701
702 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
703 const uint32_t errChMask = buserrChMask | ram2ChMask;
704 const bool isErrorChSet = ((chStatus & errChMask) == errChMask);
705
706 const bool isDiagPassed = (isRamFlagSet && isCpuFlagSet && isErrorChSet);
707
708 // Write to error flags and error channel to clear them
709 CPUCTRL_WriteIntFlags(cpuBuserrMask);
710 RAMCTRL_WriteIntFlags(ramParityMask);
712
713 return isDiagPassed;
714}
715
716static bool InjectEccCompErrorOnFlash(void)
717{
718 // Inject ECC comparator error, trigger by reading from Flash.
719 NVMCTRL_SetControlD((uint8_t)NVMCTRL_COMP_bm);
720 /* cppcheck-suppress misra-c2012-11.4 */
721 tempDiagData = *(uint8_t*)DIAG_FLASH_ADDRESS; // No need to check FBUSY flag for Flash read.
722
723 // Check if all correct flags are set after injection
724 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
725 const uint8_t nvmCompMask = (uint8_t)NVMCTRL_COMP_bm;
726 const bool isRamFlagSet = ((nvmIntFlags & nvmCompMask) == nvmCompMask);
727
728 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
729 const bool isErrorChSet = ((chStatus & flash2ChMask) == flash2ChMask);
730
731 const bool isDiagPassed = (isRamFlagSet && isErrorChSet);
732
733 // Write to error flags and error channel to clear them
734 NVMCTRL_WriteIntFlagsB(nvmCompMask);
735 ERRCTRL_WriteChannelStatus(flash2ChMask);
736
737 return isDiagPassed;
738}
739
740static bool InjectEcc1ErrorOnFlash(void)
741{
742 // Inject 1-bit ECC error, trigger by reading from Flash.
743 NVMCTRL_SetControlD((uint8_t)NVMCTRL_ECC1_bm);
744 /* cppcheck-suppress misra-c2012-11.4 */
745 tempDiagData = *(uint8_t*)DIAG_FLASH_ADDRESS; // No need to check FBUSY flag for Flash read.
746
747 // Check if all correct flags are set after injection
748 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
749 const uint8_t nvmEccMask = (uint8_t)NVMCTRL_FECC1_bm;
750 const bool isNvmFlagSet = ((nvmIntFlags & nvmEccMask) == nvmEccMask);
751
752 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
753 const bool isErrorChSet = ((chStatus & flash1ChMask) == flash1ChMask);
754
755 const bool isDiagPassed = (isNvmFlagSet && isErrorChSet);
756
757 // Write to error flags and error channel to clear them
758 NVMCTRL_WriteIntFlagsB(nvmEccMask);
759 ERRCTRL_WriteChannelStatus(flash1ChMask);
760
761 return isDiagPassed;
762}
763
764static bool InjectEcc2ErrorOnFlash(void)
765{
766 // Inject 2-bit ECC error, trigger by reading from Flash.
767 NVMCTRL_SetControlD((uint8_t)NVMCTRL_ECC2_bm);
768 /* cppcheck-suppress misra-c2012-11.4 */
769 tempDiagData = *(uint8_t*)DIAG_FLASH_ADDRESS; // No need to check FBUSY flag for Flash read.
770
771 // Check if all correct flags are set after injection
772 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
773 const uint8_t nvmEccMask = (uint8_t)NVMCTRL_FECC2_bm;
774 const bool isNvmFlagSet = ((nvmIntFlags & nvmEccMask) == nvmEccMask);
775
776 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
777 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
778 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
779
780 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
781 const uint32_t errChMask = buserrChMask | flash2ChMask;
782 const bool isErrorChSet = ((chStatus & errChMask) == errChMask);
783
784 const bool isDiagPassed = (isNvmFlagSet && isCpuFlagSet && isErrorChSet);
785
786 // Write to error flags and error channel to clear them
787 CPUCTRL_WriteIntFlags(cpuBuserrMask);
788 NVMCTRL_WriteIntFlagsB(nvmEccMask);
790
791 return isDiagPassed;
792}
793
794static bool InjectEcc1ErrorOnEeprom(void)
795{
796 // Inject 1-bit ECC error, trigger by reading from EEPROM.
797 NVMCTRL_SetControlD((uint8_t)NVMCTRL_ECC1_bm);
798 /* cppcheck-suppress misra-c2012-11.4 */
799 tempDiagData = *(uint8_t*)DIAG_EEPROM_ADDRESS; // No need to check EEBUSY flag for EEPROM read.
800
801 // Check if all correct flags are set after injection
802 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
803 const uint8_t nvmEccMask = (uint8_t)NVMCTRL_EECC1_bm;
804 const bool isNvmFlagSet = ((nvmIntFlags & nvmEccMask) == nvmEccMask);
805
806 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
807 const bool isErrorChSet = ((chStatus & eepromChMask) == eepromChMask);
808
809 const bool isDiagPassed = (isNvmFlagSet && isErrorChSet);
810
811 // Write to error flags and error channel to clear them
812 NVMCTRL_WriteIntFlagsB(nvmEccMask);
813 ERRCTRL_WriteChannelStatus(eepromChMask);
814
815 return isDiagPassed;
816}
817
818static bool InjectEcc2ErrorOnEeprom(void)
819{
820 // Inject 2-bit ECC error, trigger by reading from EEPROM.
821 NVMCTRL_SetControlD((uint8_t)NVMCTRL_ECC2_bm);
822 /* cppcheck-suppress misra-c2012-11.4 */
823 tempDiagData = *(uint8_t*)DIAG_EEPROM_ADDRESS; // No need to check EEREADY flag for EEPROM read.
824
825 // Check if all correct flags are set after injection
826 const uint8_t nvmIntFlags = NVMCTRL_ReadIntFlagsB();
827 const uint8_t nvmIntMask = (uint8_t)NVMCTRL_EECC2_bm;
828 const bool isNvmFlagSet = ((nvmIntFlags & nvmIntMask) == nvmIntMask);
829
830 const uint8_t cpuIntFlags = CPUCTRL_ReadIntFlags();
831 const uint8_t cpuBuserrMask = (uint8_t)CPU_BUSERR_bm;
832 const bool isCpuFlagSet = ((cpuIntFlags & cpuBuserrMask) == cpuBuserrMask);
833
834 const uint32_t chStatus = ERRCTRL_ReadChannelStatus();
835 const uint32_t errChMask = buserrChMask | eepromChMask;
836 const bool isErrorChSet = ((chStatus & errChMask) == errChMask);
837
838 const bool isDiagPassed = (isNvmFlagSet && isCpuFlagSet && isErrorChSet);
839
840 // Write to error flags and error channel to clear them
841 CPUCTRL_WriteIntFlags(cpuBuserrMask);
842 NVMCTRL_WriteIntFlagsB(nvmIntMask);
844
845 return isDiagPassed;
846}
errFlag_t
Defines the error flag used by Middleware services to indicate error detection.
@ NO_ERROR
void CPUCTRL_ClearControlA(uint8_t bitmask)
Clears specific bits in the CTRLA register.
void CPUCTRL_SetControlA(uint8_t bitmask)
Sets specific bits in the CTRLA register.
uint8_t CPUCTRL_ReadIntFlags(void)
Reads the INTFLAGS register value.
void CPUCTRL_WriteIntFlags(uint8_t value)
Overwrites the INTFLAGS register value.
uint8_t ERRCTRL_ReadConfigFlash1(void)
Reads the ESCFLASH1 register value.
void ERRCTRL_WriteConfigRam1(uint8_t value)
Overwrites the ESCRAM1 register value.
void ERRCTRL_WriteConfigEeprom(uint8_t value)
Overwrites the ESCEEPROM register value.
uint8_t ERRCTRL_ReadConfigBuserr(void)
Reads the ESCBUSERR register value.
void ERRCTRL_WriteConfigBuserr(uint8_t value)
Overwrites the ESCBUSERR register value.
uint32_t ERRCTRL_ReadChannelStatus(void)
Reads the ESF register value.
uint8_t ERRCTRL_ReadConfigFlash2(void)
Reads the ESCFLASH2 register value.
void ERRCTRL_WriteConfigRam2(uint8_t value)
Overwrites the ESCRAM2 register value.
void ERRCTRL_WriteConfigFlash2(uint8_t value)
Overwrites the ESCFLASH2 register value.
uint8_t ERRCTRL_ReadConfigOpc(void)
Reads the ESCOPC register value.
void ERRCTRL_WriteConfigFlash1(uint8_t value)
Overwrites the ESCFLASH1 register value.
uint8_t ERRCTRL_ReadConfigRam1(void)
Reads the ESCRAM1 register value.
uint8_t ERRCTRL_ReadConfigEeprom(void)
Reads the ESCEEPROM register value.
uint8_t ERRCTRL_ReadConfigRam2(void)
Reads the ESCRAM2 register value.
void ERRCTRL_WriteConfigOpc(uint8_t value)
Overwrites the ESCOPC register value.
void ERRCTRL_WriteChannelStatus(uint32_t value)
Overwrites the ESF register value.
void ERRCTRL_ModifyControlA(uint8_t groupMask, uint8_t groupConfig)
Modifies specific bit field(s) in the CTRLA register.
void ASM_InjectCpuAddressParityNvm(uint8_t *flashDiagAddr)
This function makes the CPU inject a parity error in the address of the following NVM (Flash) read,...
errFlag_t MW_DiagNvmEepromEcc(void)
This function performs error injection diagnostic to detect faults in the NVMCTRL ECC checkers with E...
#define DIAG_FLASH_ADDRESS
Defines an address in Flash used in diagnostics to trigger Flash read.
errFlag_t MW_DiagRamEcc(void)
This function performs error injection diagnostic to detect faults in the redundant RAMCTRL ECC check...
errFlag_t MW_DiagRamParity(void)
This function performs error injection diagnostic to detect faults in the RAM parity checker triggere...
void ASM_InjectNvmInstructionParity(void)
This function makes the NVMCTRL inject a parity error in the instruction of the following NVM fetch,...
void ASM_InjectRamEcc2(volatile uint8_t *ramDiagAddr)
This function makes the RAM controller inject a 2-bit ECC error in the following RAM read,...
void ASM_InjectRamEccComp(void)
This function makes the RAM controller inject a comparator error in the following RAM read,...
void ASM_InjectCpuAddressParityRam(void)
This function makes the CPU inject a parity error in the address of the following RAM read,...
void ASM_InjectRamEcc1(volatile uint8_t *ramDiagAddr)
This function makes the RAM controller inject a 1-bit ECC error in the following RAM read,...
void ASM_InjectCpuControlParityRam(void)
This function makes the CPU inject a parity error in the control of the following RAM read,...
errFlag_t MW_DiagNvmParity(void)
This function performs error injection diagnostic to detect faults in the CPU and NVM bus parity chec...
#define DIAG_EEPROM_ADDRESS
Reserves an address in EEPROM used in diagnostics to trigger EEPROM read and write.
void ASM_InjectCpuDataParityRam(void)
This function makes the CPU inject a parity error in the data of the following RAM write,...
void ASM_InjectNvmDataParity(uint8_t *flashDiagAddr)
This function makes the NVMCTRL inject a parity error in the data of the following NVM (Flash) read,...
void ASM_InjectCpuDataParityNvm(uint8_t *eepromDiagAddr)
This function makes the CPU inject a parity error in the data of the following NVM (EEPROM) write,...
void ASM_InjectCpuControlParityNvm(uint8_t *flashDiagAddr)
This function makes the CPU inject a parity error in the control of the following NVM (Flash) read,...
errFlag_t MW_DiagNvmFlashEcc(void)
This function performs error injection diagnostic to detect faults in the NVMCTRL ECC checkers with F...
void NVMCTRL_SetControlD(uint8_t bitmask)
Sets specific bits in the CTRLD register.
uint8_t NVMCTRL_ReadIntFlagsB(void)
Reads the INTFLAGSB register value.
void NVMCTRL_WriteIntFlagsB(uint8_t value)
Overwrites the INTFLAGSB register value.
uint8_t RAMCTRL_ReadIntFlags(void)
Reads the INTFLAGS register value.
void RAMCTRL_WriteIntFlags(uint8_t value)
Overwrites the INTFLAGS register value.
void AtomicSectionStart(void)
Backup and disable global interrupts.
void AtomicSectionEnd(void)
Restore global interrupts if previously enabled.
bool IsErrChConfigurable(uint32_t channelMask)
Check Error Controller state and error channels indicated by the channel mask input.
Contains API prototypes for the Memory Manager Diagnostics.
Contains assembly APIs for the Memory Manager Diagnostics.