fome-fw/firmware/controllers/core/error_handling.cpp

254 lines
6.6 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file error_handling.cpp
*
* @date Apr 1, 2014
2020-01-07 21:02:40 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2015-07-10 06:01:56 -07:00
*/
#include "pch.h"
2020-03-23 06:00:57 -07:00
#include "os_access.h"
2017-01-02 12:03:26 -08:00
static critical_msg_t warningBuffer;
static critical_msg_t criticalErrorMessageBuffer;
2019-04-12 19:07:03 -07:00
#if EFI_HD44780_LCD
#include "HD44780.h"
2015-07-10 06:01:56 -07:00
#endif /* EFI_HD44780_LCD */
extern int warningEnabled;
2017-01-02 12:03:26 -08:00
bool hasFirmwareErrorFlag = false;
2015-07-10 06:01:56 -07:00
const char *dbg_panic_file;
int dbg_panic_line;
2020-03-28 17:14:17 -07:00
#if EFI_TUNER_STUDIO && !defined(EFI_NO_CONFIG_WORKING_COPY)
extern persistent_config_s configWorkingCopy;
#endif
const char* getFirmwareError(void) {
return criticalErrorMessageBuffer;
2017-01-02 12:03:26 -08:00
}
#if EFI_PROD_CODE
extern ioportid_t criticalErrorLedPort;
extern ioportmask_t criticalErrorLedPin;
extern uint8_t criticalErrorLedState;
/**
* low-level function is used here to reduce stack usage
*/
2020-03-28 18:28:32 -07:00
#define ON_CRITICAL_ERROR() \
palWritePad(criticalErrorLedPort, criticalErrorLedPin, criticalErrorLedState); \
turnAllPinsOff(); \
enginePins.communicationLedPin.setValue(1);
#endif /* EFI_PROD_CODE */
2017-01-02 12:03:26 -08:00
#if EFI_SIMULATOR || EFI_PROD_CODE
2015-07-10 06:01:56 -07:00
void chDbgPanic3(const char *msg, const char * file, int line) {
2020-03-28 18:28:32 -07:00
if (hasOsPanicError())
2015-07-10 06:01:56 -07:00
return;
dbg_panic_file = file;
dbg_panic_line = line;
2019-04-12 19:07:03 -07:00
#if CH_DBG_SYSTEM_STATE_CHECK
2017-03-21 11:58:14 -07:00
ch.dbg.panic_msg = msg;
2015-07-10 06:01:56 -07:00
#endif /* CH_DBG_SYSTEM_STATE_CHECK */
2019-04-12 19:07:03 -07:00
#if EFI_PROD_CODE
2020-03-28 18:28:32 -07:00
ON_CRITICAL_ERROR();
2016-07-23 10:03:57 -07:00
#else
printf("chDbgPanic3 %s %s%d", msg, file, line);
exit(-1);
#endif
2019-04-12 19:07:03 -07:00
#if EFI_HD44780_LCD
2017-04-21 19:47:50 -07:00
lcdShowPanicMessage((char *) msg);
2015-07-10 06:01:56 -07:00
#endif /* EFI_HD44780_LCD */
firmwareError(OBD_PCM_Processor_Fault, "assert fail %s %s:%d", msg, file, line);
// Force unlock, since we may be throwing-under-lock
chSysUnconditionalUnlock();
// there was a port_disable in chSysHalt, reenable interrupts so USB works
port_enable();
// If on the main thread, longjmp back to the init process so we can keep USB alive
if (chThdGetSelfX()->threadId == 0) {
void onAssertionFailure();
onAssertionFailure();
} else {
// Not the main thread, simply try to terminate ourselves and let other threads continue living (so the user can diagnose, etc)
chThdTerminate(chThdGetSelfX());
}
2015-07-10 06:01:56 -07:00
}
2018-01-22 16:53:13 -08:00
#else
WarningCodeState unitTestWarningCodeState;
2018-01-22 16:53:13 -08:00
#endif /* EFI_SIMULATOR || EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
/**
* OBD_PCM_Processor_Fault is the general error code for now
*
* @returns TRUE in case there were warnings recently
2015-07-10 06:01:56 -07:00
*/
2016-10-10 12:02:10 -07:00
bool warning(obd_code_e code, const char *fmt, ...) {
if (hasFirmwareErrorFlag)
return true;
2016-09-26 17:02:24 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_SIMULATOR
printf("sim_warning %s\r\n", fmt);
2017-05-21 07:46:43 -07:00
#endif /* EFI_SIMULATOR */
2016-09-26 17:02:24 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_SIMULATOR || EFI_PROD_CODE
engine->engineState.warnings.addWarningCode(code);
2016-11-23 14:01:59 -08:00
// todo: move this logic into WarningCodeState?
2016-07-14 20:02:55 -07:00
efitimesec_t now = getTimeNowSeconds();
if (engine->engineState.warnings.isWarningNow(now, false) || !warningEnabled)
2015-07-10 06:01:56 -07:00
return true; // we just had another warning, let's not spam
engine->engineState.warnings.timeOfPreviousWarning = now;
2016-01-30 19:03:36 -08:00
2015-07-10 06:01:56 -07:00
va_list ap;
va_start(ap, fmt);
chvsnprintf(warningBuffer, sizeof(warningBuffer), fmt, ap);
2015-07-10 06:01:56 -07:00
va_end(ap);
if (CONFIG(showHumanReadableWarning)) {
#if EFI_TUNER_STUDIO
#if defined(EFI_NO_CONFIG_WORKING_COPY)
memcpy(persistentState.persistentConfiguration.warning_message, warningBuffer, sizeof(warningBuffer));
#else /* defined(EFI_NO_CONFIG_WORKING_COPY) */
memcpy(configWorkingCopy.warning_message, warningBuffer, sizeof(warningBuffer));
#endif /* defined(EFI_NO_CONFIG_WORKING_COPY) */
#endif /* EFI_TUNER_STUDIO */
}
efiPrintf("WARNING: %s", warningBuffer);
2017-01-02 12:03:26 -08:00
#else
2019-05-10 19:10:40 -07:00
// todo: we need access to 'engine' here so that we can migrate to real 'engine->engineState.warnings'
unitTestWarningCodeState.addWarningCode(code);
printf("unit_test_warning: ");
2017-01-02 12:03:26 -08:00
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\r\n");
2015-07-10 06:01:56 -07:00
2017-05-21 07:46:43 -07:00
#endif /* EFI_SIMULATOR || EFI_PROD_CODE */
2017-01-02 12:03:26 -08:00
return false;
2015-07-10 06:01:56 -07:00
}
const char* getWarningMessage(void) {
2015-07-10 06:01:56 -07:00
return warningBuffer;
}
2017-05-21 07:46:43 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_CLOCK_LOCKS
2015-07-10 06:01:56 -07:00
uint32_t lastLockTime;
2017-05-21 07:25:35 -07:00
/**
* Maximum time before requesting lock and releasing lock at the end of critical section
*/
uint32_t maxLockedDuration = 0;
2015-07-10 06:01:56 -07:00
2018-01-23 10:18:59 -08:00
/**
* this depends on chdebug.h patch
#if CH_DBG_SYSTEM_STATE_CHECK == TRUE
-#define _dbg_enter_lock() (ch.dbg.lock_cnt = (cnt_t)1)
-#define _dbg_leave_lock() (ch.dbg.lock_cnt = (cnt_t)0)
+#define _dbg_enter_lock() {(ch.dbg.lock_cnt = (cnt_t)1); ON_LOCK_HOOK;}
+#define _dbg_leave_lock() {ON_UNLOCK_HOOK;(ch.dbg.lock_cnt = (cnt_t)0);}
#endif
*/
#endif /* EFI_CLOCK_LOCKS */
2015-07-10 06:01:56 -07:00
void onLockHook(void) {
#if ENABLE_PERF_TRACE
perfEventInstantGlobal(PE::GlobalLock);
#endif /* ENABLE_PERF_TRACE */
#if EFI_CLOCK_LOCKS
2019-05-07 16:32:08 -07:00
lastLockTime = getTimeNowLowerNt();
#endif /* EFI_CLOCK_LOCKS */
2015-07-10 06:01:56 -07:00
}
void onUnlockHook(void) {
#if EFI_CLOCK_LOCKS
2019-05-07 16:32:08 -07:00
uint32_t lockedDuration = getTimeNowLowerNt() - lastLockTime;
2017-05-21 07:25:35 -07:00
if (lockedDuration > maxLockedDuration) {
maxLockedDuration = lockedDuration;
2015-07-10 06:01:56 -07:00
}
2017-06-03 19:43:05 -07:00
// if (lockedDuration > 2800) {
2015-07-10 06:01:56 -07:00
// // un-comment this if you want a nice stop for a breakpoint
2017-06-03 19:43:05 -07:00
// maxLockedDuration = lockedDuration + 1;
2015-07-10 06:01:56 -07:00
// }
2017-05-21 07:46:43 -07:00
#endif /* EFI_CLOCK_LOCKS */
#if ENABLE_PERF_TRACE
perfEventInstantGlobal(PE::GlobalUnlock);
#endif /* ENABLE_PERF_TRACE */
}
#if EFI_SIMULATOR || EFI_UNIT_TEST
#include <stdexcept>
#endif
2017-01-02 12:03:26 -08:00
void firmwareError(obd_code_e code, const char *fmt, ...) {
2019-04-12 19:07:03 -07:00
#if EFI_PROD_CODE
2017-01-02 12:03:26 -08:00
if (hasFirmwareErrorFlag)
return;
engine->limpManager.fatalError();
engine->engineState.warnings.addWarningCode(code);
#ifdef EFI_PRINT_ERRORS_AS_WARNINGS
va_list ap;
va_start(ap, fmt);
chvsnprintf(warningBuffer, sizeof(warningBuffer), fmt, ap);
va_end(ap);
#endif
2020-03-28 18:28:32 -07:00
ON_CRITICAL_ERROR()
2017-01-02 12:03:26 -08:00
;
hasFirmwareErrorFlag = true;
if (indexOf(fmt, '%') == -1) {
/**
* in case of simple error message let's reduce stack usage
* chvsnprintf could cause an overflow if we're already low
2017-01-02 12:03:26 -08:00
*/
2020-03-28 17:14:17 -07:00
strncpy((char*) criticalErrorMessageBuffer, fmt, sizeof(criticalErrorMessageBuffer) - 1);
criticalErrorMessageBuffer[sizeof(criticalErrorMessageBuffer) - 1] = 0; // just to be sure
2017-01-02 12:03:26 -08:00
} else {
va_list ap;
va_start(ap, fmt);
chvsnprintf(criticalErrorMessageBuffer, sizeof(criticalErrorMessageBuffer), fmt, ap);
2017-01-02 12:03:26 -08:00
va_end(ap);
2015-07-10 06:01:56 -07:00
}
int size = strlen((char*)criticalErrorMessageBuffer);
static char versionBuffer[32];
chsnprintf(versionBuffer, sizeof(versionBuffer), " %d@%s", getRusEfiVersion(), FIRMWARE_ID);
if (size + strlen(versionBuffer) < sizeof(criticalErrorMessageBuffer)) {
strcpy((char*)(criticalErrorMessageBuffer) + size, versionBuffer);
}
2020-03-28 17:14:17 -07:00
2017-01-02 12:03:26 -08:00
#else
2020-12-18 05:48:19 -08:00
char errorBuffer[200];
2015-07-10 06:01:56 -07:00
2017-01-02 12:03:26 -08:00
va_list ap;
va_start(ap, fmt);
2020-12-18 05:48:19 -08:00
vsnprintf(errorBuffer, sizeof(errorBuffer), fmt, ap);
2017-01-02 12:03:26 -08:00
va_end(ap);
2020-12-18 05:48:19 -08:00
printf("\x1B[31m>>>>>>>>>> firmwareError [%s]\r\n\x1B[0m\r\n", errorBuffer);
2015-07-10 06:01:56 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_SIMULATOR || EFI_UNIT_TEST
2020-12-18 05:48:19 -08:00
throw std::logic_error(errorBuffer);
2017-01-02 12:03:26 -08:00
#endif /* EFI_SIMULATOR */
#endif
2015-07-10 06:01:56 -07:00
}
2017-01-02 12:03:26 -08:00