more graceful chibios assertion failure (#2859)

* no custom assert hook

* dead

* setjmp/longjmp

* always call tid hook

* tests get threadid

* simulator threadid

* kick

* stubs for kinetis

* make it happier

* noreturn

* oops

* comments

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-07-05 15:18:58 -07:00 committed by GitHub
parent 3e62beec6d
commit a3d3638232
8 changed files with 56 additions and 24 deletions

View File

@ -19,7 +19,6 @@ static critical_msg_t criticalErrorMessageBuffer;
EXTERN_ENGINE; EXTERN_ENGINE;
extern int warningEnabled; extern int warningEnabled;
extern bool main_loop_started;
bool hasFirmwareErrorFlag = false; bool hasFirmwareErrorFlag = false;
@ -71,6 +70,23 @@ void chDbgPanic3(const char *msg, const char * file, int line) {
#if EFI_HD44780_LCD #if EFI_HD44780_LCD
lcdShowPanicMessage((char *) msg); lcdShowPanicMessage((char *) msg);
#endif /* EFI_HD44780_LCD */ #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());
}
} }
#else #else

View File

@ -651,10 +651,6 @@ void initEngineContoller(DECLARE_ENGINE_PARAMETER_SUFFIX) {
initCJ125(PASS_ENGINE_PARAMETER_SIGNATURE); initCJ125(PASS_ENGINE_PARAMETER_SIGNATURE);
#endif /* EFI_CJ125 */ #endif /* EFI_CJ125 */
// periodic events need to be initialized after fuel&spark pins to avoid a warning
initPeriodicEvents(PASS_ENGINE_PARAMETER_SIGNATURE);
if (hasFirmwareError()) { if (hasFirmwareError()) {
return; return;
} }

View File

@ -14,7 +14,6 @@ EXTERN_ENGINE;
extern ButtonDebounce startStopButtonDebounce; extern ButtonDebounce startStopButtonDebounce;
#if ENABLE_PERF_TRACE
static uint8_t nextThreadId = 0; static uint8_t nextThreadId = 0;
void threadInitHook(void* vtp) { void threadInitHook(void* vtp) {
// No lock required, this is already under lock // No lock required, this is already under lock
@ -22,6 +21,7 @@ void threadInitHook(void* vtp) {
tp->threadId = ++nextThreadId; tp->threadId = ++nextThreadId;
} }
#if ENABLE_PERF_TRACE
void irqEnterHook() { void irqEnterHook() {
perfEventBegin(PE::ISR); perfEventBegin(PE::ISR);
} }
@ -35,7 +35,6 @@ void contextSwitchHook() {
} }
#else #else
void threadInitHook(void*) {}
void irqEnterHook() {} void irqEnterHook() {}
void irqExitHook() {} void irqExitHook() {}
void contextSwitchHook() {} void contextSwitchHook() {}

View File

@ -6,8 +6,6 @@
egt_cs_array_t max31855_cs; egt_cs_array_t max31855_cs;
int main_loop_started;
void firmwareError(const char *fmt, ...) { void firmwareError(const char *fmt, ...) {
} }

View File

@ -116,16 +116,6 @@ extern "C" {
#define hasOsPanicError() (FALSE) #define hasOsPanicError() (FALSE)
#endif #endif
#define chDbgAssert(c, remark) do { \
if (CH_DBG_ENABLE_ASSERTS != FALSE) { \
if (!(c)) { \
/*lint -restore*/ \
firmwareError(OBD_PCM_Processor_Fault, "chDbg %s", remark); \
chSysHalt(remark); \
} \
} \
} while (false)
#ifndef __ASSEMBLER__ #ifndef __ASSEMBLER__
#ifdef __cplusplus #ifdef __cplusplus
extern "C" extern "C"

View File

@ -129,6 +129,8 @@
#include "trigger_emulator_algo.h" #include "trigger_emulator_algo.h"
#include "rusefi_lua.h" #include "rusefi_lua.h"
#include <setjmp.h>
#if EFI_ENGINE_EMULATOR #if EFI_ENGINE_EMULATOR
#include "engine_emulator.h" #include "engine_emulator.h"
#endif /* EFI_ENGINE_EMULATOR */ #endif /* EFI_ENGINE_EMULATOR */
@ -227,6 +229,16 @@ static bool validateConfig() {
return true; return true;
} }
static jmp_buf jmpEnv;
void onAssertionFailure() {
// There's been an assertion failure: instead of hanging, jump back to where we check
// if (setjmp(jmpEnv)) (see below for more complete explanation)
longjmp(jmpEnv, 1);
}
void runRusEfiWithConfig();
void runMainLoop();
void runRusEfi(void) { void runRusEfi(void) {
efiAssertVoid(CUSTOM_RM_STACK_1, getCurrentRemainingStack() > 512, "init s"); efiAssertVoid(CUSTOM_RM_STACK_1, getCurrentRemainingStack() > 512, "init s");
assertEngineReference(); assertEngineReference();
@ -248,9 +260,6 @@ void runRusEfi(void) {
// Perform hardware initialization that doesn't need configuration // Perform hardware initialization that doesn't need configuration
initHardwareNoConfig(); initHardwareNoConfig();
// Read configuration from flash memory
loadConfiguration(PASS_ENGINE_PARAMETER_SIGNATURE);
#if EFI_USB_SERIAL #if EFI_USB_SERIAL
startUsbConsole(); startUsbConsole();
#endif #endif
@ -264,6 +273,9 @@ void runRusEfi(void) {
*/ */
initializeConsole(); initializeConsole();
// Read configuration from flash memory
loadConfiguration(PASS_ENGINE_PARAMETER_SIGNATURE);
#if EFI_TUNER_STUDIO #if EFI_TUNER_STUDIO
startTunerStudioConnectivity(); startTunerStudioConnectivity();
#endif /* EFI_TUNER_STUDIO */ #endif /* EFI_TUNER_STUDIO */
@ -271,11 +283,28 @@ void runRusEfi(void) {
// Start hardware serial ports (including bluetooth, if present) // Start hardware serial ports (including bluetooth, if present)
startSerialChannels(); startSerialChannels();
runRusEfiWithConfig();
runMainLoop();
}
void runRusEfiWithConfig() {
// If some config operation caused an OS assertion failure, return immediately
// This sets the "unwind point" that we can jump back to later with longjmp if we have
// an assertion failure. If that happens, setjmp() will return non-zero, so we will
// return immediately from this function instead of trying to init hardware again (which failed last time)
if (setjmp(jmpEnv)) {
return;
}
/** /**
* Initialize hardware drivers * Initialize hardware drivers
*/ */
initHardware(); initHardware();
// periodic events need to be initialized after fuel&spark pins to avoid a warning
initPeriodicEvents(PASS_ENGINE_PARAMETER_SIGNATURE);
#if EFI_FILE_LOGGING #if EFI_FILE_LOGGING
initMmcCard(); initMmcCard();
#endif /* EFI_FILE_LOGGING */ #endif /* EFI_FILE_LOGGING */
@ -314,7 +343,9 @@ void runRusEfi(void) {
runSchedulingPrecisionTestIfNeeded(); runSchedulingPrecisionTestIfNeeded();
} }
}
void runMainLoop() {
efiPrintf("Running main loop"); efiPrintf("Running main loop");
main_loop_started = true; main_loop_started = true;
/** /**

View File

@ -636,6 +636,7 @@
* @details User fields added to the end of the @p thread_t structure. * @details User fields added to the end of the @p thread_t structure.
*/ */
#define CH_CFG_THREAD_EXTRA_FIELDS \ #define CH_CFG_THREAD_EXTRA_FIELDS \
unsigned char threadId; \
/* Add threads custom fields here.*/ /* Add threads custom fields here.*/
/** /**

View File

@ -9,9 +9,10 @@ typedef uint32_t systime_t;
class thread_t { class thread_t {
public: public:
const char *name; const char *name;
tfunc_t funcp; tfunc_t funcp;
void *arg; void *arg;
unsigned char threadId;
}; };
bool chThdShouldTerminateX(void); bool chThdShouldTerminateX(void);