rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
error_handling.cpp
Go to the documentation of this file.
1/**
2 * @file error_handling.cpp
3 *
4 * @date Apr 1, 2014
5 * @author Andrey Belomutskiy, (c) 2012-2020
6 */
7
8#include "pch.h"
9#include "rusefi/efistringutil.h"
10#include "os_util.h"
11#include "backup_ram.h"
12#include "error_handling_led.h"
13#include "log_hard_fault.h"
14#include "rusefi/critical_error.h"
15#include "rusefi/efistring.h"
16
17#if EFI_USE_OPENBLT
18/* communication with OpenBLT that is plain C, not to modify external file */
19extern "C" {
21};
22#endif
23
24using namespace rusefi::stringutil;
25
26/**
27 * Executes the BKPT instruction that causes the debugger to stop.
28 */
29#define bkpt() __asm volatile("BKPT #0\n")
30
33static critical_msg_t configErrorMessageBuffer; // recoverable configuration error, non-critical
34
36/**
37 * not critical error: TS would display text error message until clearConfigErrorMessage() is invoked
38 */
39static bool hasConfigErrorFlag = false;
40static bool hasReportFile = false;
41
42// todo: revisit very questionable code!
43// todo: reuse hasCriticalFirmwareErrorFlag? something?
45
46const char *dbg_panic_file;
48
49// todo: need vararg version of 'firmwareError' to make this method vararg?
50void efiCriticalError(const char *message) {
51 criticalError(message);
52}
53
57
59 return hasConfigErrorFlag;
60}
61
65
67 return hasReportFile;
68}
69
70#if EFI_PROD_CODE
71
72#if EFI_BACKUP_SRAM
74static uint32_t bootCount = 0;
75#endif // EFI_BACKUP_SRAM
76
78#if EFI_BACKUP_SRAM
79 /* copy error state from backup RAM and clear it in backup RAM.
80 * so few users can access previous error state and we should not care about who sohuld clear backup ram. */
81 auto sramState = getBackupSram();
82 memcpy(&lastBootError, &sramState->err, sizeof(backupErrorState));
83 memset(&sramState->err, 0x00, sizeof(sramState->err));
84 // Reset cookie so we don't report it again.
85 sramState->err.Cookie = ErrorCookie::None;
86
87 // Cookie can be some random value at first power on
88 // reset to None to avoid generating 'Unknown' fail report
93 }
94
95 //bootcount
96 if (sramState->BootCountCookie != 0xdeadbeef) {
97 sramState->BootCountCookie = 0xdeadbeef;
98 sramState->BootCount = 0;
99 }
100 // save current bootcounter
101 bootCount = sramState->BootCount;
102
103 sramState->BootCount++;
104
107 if (err->Cookie == ErrorCookie::HardFault) {
108 criticalError("Last boot had hard fault type: %lx addr: %lx CSFR: %lx",
109 err->FaultType, err->FaultAddress, err->Csfr);
110 }
111 }
112
114 // if reset by watchdog, signal a fatal error
115 if ((cause == Reset_Cause_IWatchdog) || (cause == Reset_Cause_WWatchdog)) {
116 firmwareError(ObdCode::OBD_PCM_Processor_Fault, "Watchdog Reset detected! Check SD card for report file.");
117 }
118#endif // EFI_PROD_CODE
119
120 // see https://github.com/rusefi/rusefi/wiki/Resilience
121 addConsoleAction("chibi_fault", [](){ chDbgCheck(0); } );
122 addConsoleAction("soft_fault", [](){ firmwareError(ObdCode::RUNTIME_CRITICAL_TEST_ERROR, "firmwareError: %d", getRusEfiVersion()); });
123 addConsoleAction("hard_fault", [](){ causeHardFault(); } );
124}
125
127#if EFI_BACKUP_SRAM
129#else
130 return 0;
131#endif
132}
133
135{
136 switch (cookie) {
138 return "No error";
140 return "firmware";
142 return "HardFault";
144 return "ChibiOS panic";
145 }
146
147 return "Unknown";
148}
149
150#define printResetReason() \
151 PRINT("Reset Cause: %s", getMCUResetCause(getMCUResetCause()))
152
153#if EFI_USE_OPENBLT
154#define printWdResetCounter() \
155 do { \
156 uint8_t wd_counter = 0; \
157 SharedParamsReadByIndex(1, &wd_counter); \
158 PRINT("WD resets: %u", (unsigned int)wd_counter); \
159 } while (0)
160#else
161#define printWdResetCounter() \
162 do {} while(0)
163#endif
164
165
166#define printErrorState() \
167do { \
168 PRINT("Power cycle count: %lu", bootCount); \
169 \
170 if (cookie == ErrorCookie::None) { \
171 break; \
172 } \
173 \
174 PRINT("Last error type %s", errorCookieToName(err->Cookie)); \
175 \
176 switch (cookie) { \
177 case ErrorCookie::FirmwareError: \
178 { \
179 PRINT("%s", err->msg); \
180 } \
181 break; \
182 case ErrorCookie::HardFault: \
183 { \
184 PRINT("type: 0x%08lx addr: 0x%08lx CSFR: 0x%08lx", \
185 err->FaultType, err->FaultAddress, err->Csfr); \
186 \
187 auto ctx = &err->FaultCtx; \
188 PRINT("r0 0x%08lx", ctx->r0); \
189 PRINT("r1 0x%08lx", ctx->r1); \
190 PRINT("r2 0x%08lx", ctx->r2); \
191 PRINT("r3 0x%08lx", ctx->r3); \
192 PRINT("r12 0x%08lx", ctx->r12); \
193 PRINT("lr (thread) 0x%08lx", ctx->lr_thd); \
194 PRINT("pc 0x%08lx", ctx->pc); \
195 PRINT("xpsr 0x%08lx", ctx->xpsr); \
196 \
197 /* FPU registers - not very useful for debug */ \
198 if (0) { \
199 /* Print rest the context as a sequence of uintptr */ \
200 uintptr_t* data = reinterpret_cast<uintptr_t*>(&err->FaultCtx); \
201 for (size_t i = 8; i < sizeof(port_extctx) / sizeof(uintptr_t); i++) { \
202 PRINT("Fault ctx %d: 0x%08x", i, data[i]); \
203 } \
204 } \
205 } \
206 break; \
207 case ErrorCookie::ChibiOsPanic: \
208 { \
209 PRINT("msg %s", err->msg); \
210 PRINT("file %s", err->file); \
211 PRINT("line %d", err->line); \
212 } \
213 break; \
214 default: \
215 /* No cookie stored or invalid cookie (ie, backup RAM contains random garbage) */ \
216 break; \
217 } \
218} while(0)
219
220#define printErrorStack() \
221do { \
222 PRINT("SP 0x%08lx", err->sp); \
223 for (size_t i = 0; i < ERROR_STACK_DEPTH; i++) { \
224 uint32_t cur = err->stack[i]; \
225 if (cur != 0) { \
226 PRINT(" 0x%08lx: 0x%08lx", err->sp - i * 4, cur); \
227 } \
228 } \
229} while(0)
230
231// TODO: reuse this code for writing crash report file
233 //this is console print
234 #define PRINT(...) efiPrintf(__VA_ARGS__)
235
236 printResetReason();
237 printWdResetCounter();
238
239#if EFI_BACKUP_SRAM
241 ErrorCookie cookie = err->Cookie;
242
243 printErrorState();
244 printErrorStack();
245#endif // EFI_BACKUP_SRAM
246 #undef PRINT
247}
248
249#if EFI_FILE_LOGGING
250#include "ff.h"
251
252#define FAIL_REPORT_PREFIX "fail"
253
254PUBLIC_API_WEAK void onBoardWriteErrorFile(FIL *) {
255}
256
257static const char *errorHandlerGetErrorName(ErrorCookie cookie)
258{
259 switch (cookie) {
261 return "none";
263 return "FWerror";
265 return "HardFault";
267 return "OSpanic";
268 }
269
270 return "unknown";
271}
272
274
276#if EFI_BACKUP_SRAM
278 ErrorCookie cookie = err->Cookie;
279#else
281#endif
282
283 if (cookie != ErrorCookie::None) {
284 needErrorReportFile = true;
285 }
286
287 auto cause = getMCUResetCause();
288 // TODO: should we also report Unknown?
289 if ((cause != Reset_Cause_NRST_Pin) && (cause != Reset_Cause_BOR) &&
290 (cause != Reset_Cause_POR) && (cause != Reset_Cause_Unknown)) {
291 // not an expected cause
292 needErrorReportFile = true;
293 }
294
296 char fileName[_MAX_FILLER + 20];
297 memset(fd, 0, sizeof(FIL)); // clear the memory
298 //TODO: use date + time for file name?
299#if EFI_BACKUP_SRAM
300 sprintf(fileName, "%05ld_%s_%s.txt",
301 bootCount, FAIL_REPORT_PREFIX, errorHandlerGetErrorName(cookie));
302#else
303 sprintf(fileName, "last_%s_%s.txt",
304 FAIL_REPORT_PREFIX, errorHandlerGetErrorName(cookie));
305#endif
306
307 FRESULT ret = f_open(fd, fileName, FA_CREATE_ALWAYS | FA_WRITE);
308 if (ret == FR_OK) {
309 //this is file print
310 #define PRINT(format, ...) f_printf(fd, format "\r\n", __VA_ARGS__)
311 printResetReason();
312 printWdResetCounter();
313#if EFI_BACKUP_SRAM
314 printErrorState();
315 printErrorStack();
316#endif // EFI_BACKUP_SRAM
317 f_printf(fd, "rusEFI v%d@%u", getRusEfiVersion(), /*do we have a working way to print 64 bit values?!*/(int)SIGNATURE_HASH);
318 // additional board-specific data
320 // todo: figure out what else would be useful
321 f_close(fd);
323 }
324 }
325}
326
328 bool exist = false;
329 FRESULT fr; /* Return value */
330 DIR dj; /* Directory object */
331 FILINFO fno; /* File information */
332 TCHAR pattern[32];
333
334 sprintf(pattern, "*%s*", errorHandlerGetErrorName(cookie));
335
336 fr = f_findfirst(&dj, &fno, "", pattern);
337 exist = ((fr == FR_OK) && (fno.fname[0]));
338 f_closedir(&dj);
339
340 return exist;
341}
342
351
353 bool failed = false;
354 FRESULT fr; /* Return value */
355 DIR dj; /* Directory object */
356 FILINFO fno; /* File information */
357 TCHAR pattern[32];
358
359 sprintf(pattern, "*%s*", errorHandlerGetErrorName(cookie));
360
361 do {
362 fr = f_findfirst(&dj, &fno, "", pattern);
363 f_closedir(&dj);
364
365 if ((fr == FR_OK) && (fno.fname[0])) {
366 efiPrintf("deleting %s", fno.fname);
367 FRESULT ret = f_unlink(fno.fname);
368 if (ret != FR_OK) {
369 efiPrintf("Faield to delete %s: %d", fno.fname, ret);
370 failed = true;
371 } else {
372 efiPrintf("%s removed", fno.fname);
373 }
374 }
375 } while ((!failed) && (fr == FR_OK) && (fno.fname[0]));
376}
377
386
387#endif
388
389#if EFI_BACKUP_SRAM
390static void errorHandlerSaveStack(backupErrorState *err, uint32_t *sp)
391{
392 err->sp = (uint32_t)sp;
393 for (size_t i = 0; i < ERROR_STACK_DEPTH; i++) {
394 // avoid optimizatio and usage of __builtin_memcpy
395 // to avoid "error: '__builtin_memcpy' reading 128 bytes from a region of size 4"
396 err->stack[i] = *(volatile uint32_t *)sp;
397 sp++;
398 }
399}
400#endif // EFI_BACKUP_SRAM
401
402void logHardFault(uint32_t type, uintptr_t faultAddress, void* sp, port_extctx* ctx, uint32_t csfr) {
403 // todo: reuse hasCriticalFirmwareErrorFlag? something?
405 // Evidence first!
406#if EFI_BACKUP_SRAM
407 auto bkpram = getBackupSram();
408 auto err = &bkpram->err;
409 if (err->Cookie == ErrorCookie::None) {
410 err->FaultType = type;
411 err->FaultAddress = faultAddress;
412 err->Csfr = csfr;
413 memcpy(&err->FaultCtx, ctx, sizeof(port_extctx));
414 err->Cookie = ErrorCookie::HardFault;
415 // copy stack last as it can be corrupted and cause another exeption
416 errorHandlerSaveStack(err, (uint32_t *)sp);
417 }
418#endif // EFI_BACKUP_SRAM
419 // criticalShutdown() shutdown can cause cascaded fault.
420 // So we first save some valuable evidence and only after try to gracefully shutdown HW
421 criticalShutdown();
422}
423
424#endif /* EFI_PROD_CODE */
425
426#if EFI_SIMULATOR || EFI_PROD_CODE
427
428void chDbgPanic3(const char *msg, const char * file, int line) {
429#if EFI_PROD_CODE
430#if EFI_BACKUP_SRAM
431 // following is allocated on stack
432 // add some marker
433 uint32_t tmp = 0xfffffa11;
434#endif
435 // Attempt to break in to the debugger, if attached
436 if (CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk)
437 {
438 bkpt();
439 }
440#endif // EFI_PROD_CODE
441
442#if EFI_BACKUP_SRAM
443 auto bkpram = getBackupSram();
444 auto err = &bkpram->err;
445 if (err->Cookie == ErrorCookie::None) {
446 strlncpy(err->file, file, efi::size(err->file));
447 err->line = line;
448 strlncpy(err->msg, msg, efi::size(err->msg));
449 err->Cookie = ErrorCookie::ChibiOsPanic;
450 // copy stack last as it can be corrupted and cause another exeption
451 uint32_t *sp = &tmp;
452 errorHandlerSaveStack(err, sp);
453 }
454#endif // EFI_BACKUP_SRAM
455
456 if (hasOsPanicError())
457 return;
458 dbg_panic_file = file;
459 dbg_panic_line = line;
460#if CH_DBG_SYSTEM_STATE_CHECK
461 ch0.dbg.panic_msg = msg;
462#endif /* CH_DBG_SYSTEM_STATE_CHECK */
463
464#if !EFI_PROD_CODE
465 printf("chDbgPanic3 %s %s%d", msg, file, line);
466 exit(-1);
467#else // EFI_PROD_CODE
468
469 criticalError("assert fail %s %s:%d", msg, file, line);
470
471 // If on the main thread, longjmp back to the init process so we can keep USB alive
472 if (chThdGetSelfX()->threadId == 0) {
473 // Force unlock, since we may be throwing-under-lock
474 chSysUnconditionalUnlock();
475
476 // there was a port_disable in chSysHalt, reenable interrupts so USB works
477 port_enable();
478
479 __NO_RETURN void onAssertionFailure();
481 } else {
482 // Not the main thread.
483 // All hope is now lost.
484
485 // Reboot!
486 NVIC_SystemReset();
487 }
488
489#endif // EFI_PROD_CODE
490}
491#endif /* EFI_SIMULATOR || EFI_PROD_CODE */
492
493/**
494 * @returns TRUE in case there were warnings recently
495 */
496bool warningVA(ObdCode code, bool reportToTs, const char *fmt, va_list args) {
498 return true;
499 }
500
502
503 if (known) {
504 // if known - just reset timer
506#if EFI_SIMULATOR || EFI_PROD_CODE
507 // we just had this same warning, let's not spam
508 return true;
509#endif
510 }
511
512 // print Pxxxx (for standard OBD) or Cxxxx (for custom) prefix
513 size_t size = snprintf(warningBuffer, sizeof(warningBuffer), "%s%04d: ",
514 code < ObdCode::CUSTOM_NAN_ENGINE_LOAD ? "P" : "C", (int) code);
515
516 chvsnprintf(warningBuffer + size, sizeof(warningBuffer) - size, fmt, args);
517
519#if EFI_SIMULATOR || EFI_PROD_CODE
520 efiPrintf("WARNING: %s", warningBuffer);
521#else
522 printf("unit_test_warning: %s\n", warningBuffer);
523#endif /* EFI_SIMULATOR || EFI_PROD_CODE */
524
525 return false;
526}
527
528bool warning(ObdCode code, const char *fmt, ...) {
529 va_list args;
530 va_start(args, fmt);
531 bool ret = warningVA(code, false, fmt, args);
532 va_end(args);
533 return ret;
534}
535
536bool warningTsReport(ObdCode code, const char *fmt, ...) {
537 va_list args;
538 va_start(args, fmt);
539 bool ret = warningVA(code, true, fmt, args);
540 va_end(args);
541 return ret;
542}
543
544#if EFI_CLOCK_LOCKS
546/**
547 * Maximum time before requesting lock and releasing lock at the end of critical section
548 */
549uint32_t maxLockedDuration = 0;
550
551/**
552 * this depends on chdebug.h patch
553 #if CH_DBG_SYSTEM_STATE_CHECK == TRUE
554-#define _dbg_enter_lock() (ch.dbg.lock_cnt = (cnt_t)1)
555-#define _dbg_leave_lock() (ch.dbg.lock_cnt = (cnt_t)0)
556+#define _dbg_enter_lock() {(ch.dbg.lock_cnt = (cnt_t)1); ON_LOCK_HOOK;}
557+#define _dbg_leave_lock() {ON_UNLOCK_HOOK;(ch.dbg.lock_cnt = (cnt_t)0);}
558 #endif
559 */
560#endif /* EFI_CLOCK_LOCKS */
561
562void onLockHook(void) {
563#if ENABLE_PERF_TRACE
565#endif /* ENABLE_PERF_TRACE */
566
567#if EFI_CLOCK_LOCKS
569#endif /* EFI_CLOCK_LOCKS */
570}
571
572void onUnlockHook(void) {
573#if EFI_CLOCK_LOCKS
574 uint32_t lockedDuration = getTimeNowLowerNt() - lastLockTime;
575 if (lockedDuration > maxLockedDuration) {
576 maxLockedDuration = lockedDuration;
577 }
578// if (lockedDuration > 2800) {
579// // un-comment this if you want a nice stop for a breakpoint
580// maxLockedDuration = lockedDuration + 1;
581// }
582#endif /* EFI_CLOCK_LOCKS */
583
584#if ENABLE_PERF_TRACE
586#endif /* ENABLE_PERF_TRACE */
587}
588
589#if EFI_SIMULATOR || EFI_UNIT_TEST
590#include <stdexcept>
591#endif
592
593void configError(const char *fmt, ...) {
594 va_list ap;
595 va_start(ap, fmt);
596 chvsnprintf(configErrorMessageBuffer, sizeof(configErrorMessageBuffer), fmt, ap);
597 va_end(ap);
598 hasConfigErrorFlag = true;
599}
600
603}
604
605static void firmwareErrorV(ObdCode code, const char *fmt, va_list ap) {
606#if EFI_PROD_CODE
607#if EFI_BACKUP_SRAM
608 // following is allocated on stack
609 // add some marker
610 uint32_t tmp = 0xfaaaaa11;
611#endif
613 return;
615
616 // construct error message
617 if (indexOf(fmt, '%') == -1) {
618 /**
619 * in case of simple error message let's reduce stack usage
620 * chvsnprintf could cause an overflow if we're already low
621 */
622 strlncpy((char*) criticalErrorMessageBuffer, fmt, sizeof(criticalErrorMessageBuffer));
623 criticalErrorMessageBuffer[sizeof(criticalErrorMessageBuffer) - 1] = 0; // just to be sure
624 } else {
625 chvsnprintf(criticalErrorMessageBuffer, sizeof(criticalErrorMessageBuffer), fmt, ap);
626 }
627
628 int errorMessageSize = strlen((char*)criticalErrorMessageBuffer);
629 static char versionBuffer[32];
630 chsnprintf(versionBuffer, sizeof(versionBuffer), " %d@%s", getRusEfiVersion(), FIRMWARE_ID);
631
632 if (errorMessageSize + strlen(versionBuffer) < sizeof(criticalErrorMessageBuffer)) {
633 strcpy((char*)(criticalErrorMessageBuffer) + errorMessageSize, versionBuffer);
634 }
635
636 // Evidence first!
637#if EFI_BACKUP_SRAM
638 auto bkpram = getBackupSram();
639 auto err = &bkpram->err;
640 if (err->Cookie == ErrorCookie::None) {
641 strlncpy(err->msg, criticalErrorMessageBuffer, sizeof(err->msg));
642 err->Cookie = ErrorCookie::FirmwareError;
643 // copy stack last as it can be corrupted and cause another exeption
644 uint32_t *sp = &tmp;
645 errorHandlerSaveStack(err, sp);
646 }
647#endif // EFI_BACKUP_SRAM
648
649#if EFI_ENGINE_CONTROL
651#endif // EFI_ENGINE_CONTROL
653 // criticalShutdown() shutdown can cause cascaded fault.
654 // So we first save some valuable evidence and only after try to gracefully shutdown HW
655 criticalShutdown();
656 enginePins.communicationLedPin.setValue(1, /*force*/true);
657#else // EFI_PROD_CODE
658
659 // large buffer on stack is risky we better use normal memory
660 static char errorBuffer[200];
661
662 vsnprintf(errorBuffer, sizeof(errorBuffer), fmt, ap);
663
664 printf("\x1B[31m>>>>>>>>>> firmwareError [%s]\r\n\x1B[0m\r\n", errorBuffer);
665
666 throw std::logic_error(errorBuffer);
667#endif // EFI_PROD_CODE
668}
669
670void firmwareError(ObdCode code, const char *fmt, ...) {
671 va_list ap;
672 va_start(ap, fmt);
673 firmwareErrorV(code, fmt, ap);
674 va_end(ap);
675}
676
677// This is critical error for plain C use.
678// From plain C file we cannot use somethings like this:
679// #define criticalError(...) firmwareError(ObdCode::OBD_PCM_Processor_Fault, __VA_ARGS__)
680// because of ObdCode::
681// Also we can not write some wrapper that will pass variable length argument list to another variable length argument list function
682void criticalErrorC(const char *fmt, ...) {
683 va_list ap;
684 va_start(ap, fmt);
686 va_end(ap);
687}
void causeHardFault()
Reset_Cause_t getMCUResetCause()
Non-volatile backup-RAM registers support.
BackupSramData * getBackupSram()
uint8_t code
Definition bluetooth.cpp:40
EngineState engineState
Definition engine.h:344
OutputPin communicationLedPin
Definition efi_gpio.h:106
OutputPin warningLedPin
Definition efi_gpio.h:107
WarningCodeState warnings
void setValue(const char *msg, int logicValue, bool isForce=false)
Definition efi_gpio.cpp:604
void addWarningCode(ObdCode code, const char *text=nullptr)
Definition engine2.cpp:38
bool isWarningNow() const
Definition engine2.cpp:114
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
EnginePins enginePins
Definition efi_gpio.cpp:24
LimpManager * getLimpManager()
Definition engine.cpp:596
static EngineAccessor engine
Definition engine.h:413
static constexpr engine_configuration_s * engineConfiguration
bool warning(ObdCode code, const char *fmt,...)
static int errorHandlerIsReportExist(ErrorCookie cookie)
static critical_msg_t warningBuffer
int dbg_panic_line
void firmwareError(ObdCode code, const char *fmt,...)
void onUnlockHook(void)
bool warningTsReport(ObdCode code, const char *fmt,...)
static void firmwareErrorV(ObdCode code, const char *fmt, va_list ap)
void logHardFault(uint32_t type, uintptr_t faultAddress, void *sp, port_extctx *ctx, uint32_t csfr)
bool needErrorReportFile
int errorHandlerCheckReportFiles()
uint32_t lastLockTime
bool warningVA(ObdCode code, bool reportToTs, const char *fmt, va_list args)
uint32_t maxLockedDuration
static bool hasConfigErrorFlag
const char * getCriticalErrorMessage()
bool errorHandlerIsStartFromError()
static uint32_t bootCount
void clearConfigErrorMessage()
void efiCriticalError(const char *message)
static void errorHandlerDeleteTypedReport(ErrorCookie cookie)
bool hasCriticalFirmwareErrorFlag
bool hasConfigError()
static critical_msg_t criticalErrorMessageBuffer
void onLockHook(void)
void errorHandlerDeleteReports()
void errorHandlerInit()
const char * errorCookieToName(ErrorCookie cookie)
static const char * errorHandlerGetErrorName(ErrorCookie cookie)
const char * dbg_panic_file
static backupErrorState lastBootError
void configError(const char *fmt,...)
static void errorHandlerSaveStack(backupErrorState *err, uint32_t *sp)
PUBLIC_API_WEAK void onBoardWriteErrorFile(FIL *)
void criticalErrorC(const char *fmt,...)
bool hasErrorReportFile()
bool isInHardFaultHandler
void errorHandlerShowBootReasonAndErrors()
static bool hasReportFile
void chDbgPanic3(const char *msg, const char *file, int line)
void errorHandlerWriteReportFile(FIL *fd)
static critical_msg_t configErrorMessageBuffer
const char * getConfigErrorMessage()
char[CRITICAL_BUFFER_SIZE] critical_msg_t
ErrorCookie
int getRusEfiVersion()
uint32_t getTimeNowLowerNt()
Reset_Cause_t
Definition mpu_util.h:104
@ Reset_Cause_WWatchdog
Definition mpu_util.h:107
@ Reset_Cause_NRST_Pin
Definition mpu_util.h:109
@ Reset_Cause_Unknown
Definition mpu_util.h:105
@ Reset_Cause_POR
Definition mpu_util.h:110
@ Reset_Cause_IWatchdog
Definition mpu_util.h:106
@ Reset_Cause_BOR
Definition mpu_util.h:112
ObdCode
@ RUNTIME_CRITICAL_TEST_ERROR
@ OBD_PCM_Processor_Fault
@ CUSTOM_NAN_ENGINE_LOAD
void perfEventInstantGlobal(PE event)
@ GlobalUnlock
@ GlobalLock
void onAssertionFailure()
Definition rusefi.cpp:165
static NO_CACHE FIL fd
uint32_t stack[ERROR_STACK_DEPTH]
composite packet size
printf("\n")