rusefi-1/firmware/controllers/error_handling.cpp

229 lines
5.4 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file error_handling.cpp
*
* @date Apr 1, 2014
2017-01-03 03:05:22 -08:00
* @author Andrey Belomutskiy, (c) 2012-2017
2015-07-10 06:01:56 -07:00
*/
#include "main.h"
#include "error_handling.h"
#include "io_pins.h"
#include "efilib2.h"
2016-07-13 16:03:06 -07:00
#include "engine.h"
2017-01-02 12:03:26 -08:00
#if EFI_SIMULATOR || EFI_PROD_CODE
2016-07-23 10:03:57 -07:00
//todo: move into simulator global
2017-01-02 12:03:26 -08:00
#include "memstreams.h"
2016-07-23 10:03:57 -07:00
#include <chprintf.h>
2017-01-02 12:03:26 -08:00
static MemoryStream warningStream;
static MemoryStream firmwareErrorMessageStream;
2017-01-26 20:03:04 -08:00
extern OutputPin communicationPin;
2017-01-02 12:03:26 -08:00
#endif
#define WARNING_BUFFER_SIZE 80
static char warningBuffer[WARNING_BUFFER_SIZE];
static bool isWarningStreamInitialized = false;
2015-07-10 06:01:56 -07:00
2016-07-23 10:03:57 -07:00
#if EFI_HD44780_LCD || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
#include "lcd_HD44780.h"
#endif /* EFI_HD44780_LCD */
static LoggingWithStorage logger("error handling");
2016-07-13 16:03:06 -07:00
EXTERN_ENGINE;
2015-07-10 06:01:56 -07:00
#define WARNING_PREFIX "WARNING: "
extern int warningEnabled;
2016-01-11 14:01:33 -08:00
extern bool main_loop_started;
2017-01-02 12:03:26 -08:00
fatal_msg_t errorMessageBuffer;
bool hasFirmwareErrorFlag = false;
2015-07-10 06:01:56 -07:00
const char *dbg_panic_file;
int dbg_panic_line;
2017-01-02 12:03:26 -08:00
char *getFirmwareError(void) {
return (char*) errorMessageBuffer;
}
#if EFI_SIMULATOR || EFI_PROD_CODE
2015-07-10 06:01:56 -07:00
void chDbgPanic3(const char *msg, const char * file, int line) {
if (hasFatalError())
return;
dbg_panic_file = file;
dbg_panic_line = line;
2016-07-23 10:03:57 -07:00
#if CH_DBG_SYSTEM_STATE_CHECK || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
dbg_panic_msg = msg;
#endif /* CH_DBG_SYSTEM_STATE_CHECK */
2016-07-23 10:03:57 -07:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
ON_FATAL_ERROR();
2016-07-23 10:03:57 -07:00
#else
printf("chDbgPanic3 %s %s%d", msg, file, line);
exit(-1);
#endif
#if EFI_HD44780_LCD || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
lcdShowFatalMessage((char *) msg);
#endif /* EFI_HD44780_LCD */
if (!main_loop_started) {
print("fatal %s %s:%d\r\n", msg, file, line);
chThdSleepSeconds(1);
chSysHalt();
}
}
2016-10-09 16:03:51 -07:00
/**
* @param forIndicator if we want to retrieving value for TS indicator, this case a minimal period is applued
*/
bool isWarningNow(efitimesec_t now, bool forIndicator) {
int period = forIndicator ? maxI(3, engineConfiguration->warningPeriod) : engineConfiguration->warningPeriod;
return absI(now - engine->engineState.timeOfPreviousWarning) < period;
2016-07-14 20:02:55 -07:00
}
2016-11-23 14:01:59 -08:00
void addWarningCode(obd_code_e code) {
2016-10-10 12:02:10 -07:00
engine->engineState.warningCounter++;
engine->engineState.lastErrorCode = code;
}
2017-03-28 15:30:53 -07:00
// todo: look into chsnprintf
2016-12-30 11:02:37 -08:00
// todo: move to some util file & reuse for 'firmwareError' method
void printToStream(MemoryStream *stream, const char *fmt, va_list ap) {
stream->eos = 0; // reset
chvprintf((BaseSequentialStream *) stream, fmt, ap);
stream->buffer[stream->eos] = 0;
}
2017-03-28 15:59:42 -07:00
#else
int unitTestWarningCounter = 0;
#endif /* EFI_SIMULATOR || EFI_PROD_CODE */
2017-01-02 12:03:26 -08:00
2016-12-30 11:02:37 -08:00
2015-07-10 06:01:56 -07:00
/**
* OBD_PCM_Processor_Fault is the general error code for now
*
* @returns TRUE in case there are too many warnings
*/
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
#if EFI_SIMULATOR || defined(__DOXYGEN__)
printf("sim_warning %s\r\n", fmt);
2016-09-26 17:02:24 -07:00
#endif
2017-01-02 12:03:26 -08:00
#if EFI_SIMULATOR || EFI_PROD_CODE
efiAssert(isWarningStreamInitialized, "warn stream not initialized", false);
2016-11-23 14:01:59 -08:00
addWarningCode(code);
2016-07-14 20:02:55 -07:00
efitimesec_t now = getTimeNowSeconds();
2016-10-09 16:03:51 -07:00
if (isWarningNow(now, false) || !warningEnabled)
2015-07-10 06:01:56 -07:00
return true; // we just had another warning, let's not spam
2016-11-23 14:01:59 -08:00
engine->engineState.timeOfPreviousWarning = now;
2016-01-30 19:03:36 -08:00
2015-07-10 06:01:56 -07:00
resetLogging(&logger); // todo: is 'reset' really needed here?
appendMsgPrefix(&logger);
2016-12-30 11:02:37 -08:00
append(&logger, WARNING_PREFIX);
2015-07-10 06:01:56 -07:00
va_list ap;
va_start(ap, fmt);
2016-12-30 11:02:37 -08:00
printToStream(&warningStream, fmt, ap);
2015-07-10 06:01:56 -07:00
va_end(ap);
append(&logger, warningBuffer);
append(&logger, DELIMETER);
scheduleLogging(&logger);
2017-01-02 12:03:26 -08:00
#else
2017-03-28 15:59:42 -07:00
unitTestWarningCounter++;
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-01-02 12:03:26 -08:00
#endif
return false;
2015-07-10 06:01:56 -07:00
}
2016-10-10 12:02:10 -07:00
char *getWarning(void) {
2015-07-10 06:01:56 -07:00
return warningBuffer;
}
uint32_t lastLockTime;
uint32_t maxLockTime = 0;
void onLockHook(void) {
lastLockTime = GET_TIMESTAMP();
}
void onUnlockHook(void) {
uint32_t t = GET_TIMESTAMP() - lastLockTime;
if (t > maxLockTime) {
maxLockTime = t;
}
// if (t > 2800) {
// // un-comment this if you want a nice stop for a breakpoint
// maxLockTime = t + 1;
// }
}
void initErrorHandling(void) {
2017-02-18 12:01:47 -08:00
#if EFI_SIMULATOR || EFI_PROD_CODE || defined(__DOXYGEN__)
2015-07-10 06:01:56 -07:00
msObjectInit(&warningStream, (uint8_t *) warningBuffer, WARNING_BUFFER_SIZE, 0);
2017-01-02 12:03:26 -08:00
msObjectInit(&firmwareErrorMessageStream, errorMessageBuffer, sizeof(errorMessageBuffer), 0);
#endif
2016-04-03 15:02:39 -07:00
isWarningStreamInitialized = true;
2015-07-10 06:01:56 -07:00
}
2017-01-02 12:03:26 -08:00
void firmwareError(obd_code_e code, const char *fmt, ...) {
2017-02-18 12:01:47 -08:00
#if EFI_PROD_CODE || defined(__DOXYGEN__)
2017-01-02 12:03:26 -08:00
if (hasFirmwareErrorFlag)
return;
addWarningCode(code);
ON_FATAL_ERROR()
;
hasFirmwareErrorFlag = true;
if (indexOf(fmt, '%') == -1) {
/**
* in case of simple error message let's reduce stack usage
* because chvprintf might be causing an error
*/
strncpy((char*) errorMessageBuffer, fmt, sizeof(errorMessageBuffer) - 1);
errorMessageBuffer[sizeof(errorMessageBuffer) - 1] = 0; // just to be sure
} else {
2017-03-28 15:30:53 -07:00
// todo: look into chsnprintf once on Chibios 3
2017-01-02 12:03:26 -08:00
firmwareErrorMessageStream.eos = 0; // reset
va_list ap;
va_start(ap, fmt);
chvprintf((BaseSequentialStream *) &firmwareErrorMessageStream, fmt, ap);
va_end(ap);
// todo: reuse warning buffer helper method
firmwareErrorMessageStream.buffer[firmwareErrorMessageStream.eos] = 0; // need to terminate explicitly
2015-07-10 06:01:56 -07:00
}
2017-01-02 12:03:26 -08:00
#else
printf("firmwareError [%s]\r\n", fmt);
2015-07-10 06:01:56 -07:00
2017-01-02 12:03:26 -08:00
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
2017-03-12 19:46:01 -07:00
printf("\r\n");
2015-07-10 06:01:56 -07:00
2017-02-18 12:01:47 -08:00
#if EFI_SIMULATOR || defined(__DOXYGEN__)
2017-01-02 12:03:26 -08:00
exit(-1);
#endif /* EFI_SIMULATOR */
#endif
2015-07-10 06:01:56 -07:00
}
2017-01-02 12:03:26 -08:00