diff --git a/firmware/controllers/algo/io_pins.h b/firmware/controllers/algo/io_pins.h index e4e31fddfb..ed2dbb4aea 100644 --- a/firmware/controllers/algo/io_pins.h +++ b/firmware/controllers/algo/io_pins.h @@ -148,10 +148,9 @@ extern "C" const char *getPinName(io_pin_e io_pin); io_pin_e getPinByName(const char *name); -void turnOutputPinOn(io_pin_e pin); -void turnOutputPinOff(io_pin_e pin); -void setDefaultPinState(io_pin_e pin, pin_output_mode_e *defaultState); +void setDefaultPinState(io_pin_e pin, pin_output_mode_e *defaultState); +void turnAllPinsOff(void); void outputPinRegisterExt2(const char *msg, io_pin_e ioPin, brain_pin_e brainPin, pin_output_mode_e *outputMode); #ifdef __cplusplus } diff --git a/firmware/controllers/error_handling.c b/firmware/controllers/error_handling.c index ef526a9e82..7832237a01 100644 --- a/firmware/controllers/error_handling.c +++ b/firmware/controllers/error_handling.c @@ -25,9 +25,6 @@ extern int main_loop_started; const char *dbg_panic_file; int dbg_panic_line; -static void turnAllPinsOff(void) { -} - void chDbgPanic3(const char *msg, const char * file, int line) { if (hasFatalError()) return; @@ -41,10 +38,10 @@ void chDbgPanic3(const char *msg, const char * file, int line) { * low-level function is used here to reduce stack usage */ palWritePad(LED_ERROR_PORT, LED_ERROR_PIN, 1); + turnAllPinsOff(); #if EFI_HD44780_LCD lcdShowFatalMessage((char *) msg); #endif /* EFI_HD44780_LCD */ - turnAllPinsOff(); if (!main_loop_started) { print("fatal %s %s:%d\r\n", msg, file, line); diff --git a/firmware/controllers/injector_central.cpp b/firmware/controllers/injector_central.cpp index 98ba7bde71..baf77afeab 100644 --- a/firmware/controllers/injector_central.cpp +++ b/firmware/controllers/injector_central.cpp @@ -93,9 +93,9 @@ static void runBench(brain_pin_e brainPin, io_pin_e pin, float delayMs, float on isRunningBench = true; for (int i = 0; i < count; i++) { - setOutputPinValue(pin, TRUE); + setOutputPinValue(pin, true); chThdSleep((int) (onTimeMs * CH_FREQUENCY / 1000)); - setOutputPinValue(pin, FALSE); + setOutputPinValue(pin, false); int offTimeSt = (int) (offTimeMs * CH_FREQUENCY / 1000); if (offTimeSt > 0) { chThdSleep(offTimeSt); diff --git a/firmware/controllers/malfunction_indicator.c b/firmware/controllers/malfunction_indicator.c index 0359e737a4..1eb5dbe7ec 100644 --- a/firmware/controllers/malfunction_indicator.c +++ b/firmware/controllers/malfunction_indicator.c @@ -29,6 +29,7 @@ #include "io_pins.h" #include "malfunction_central.h" #include "malfunction_indicator.h" +#include "efiGpio.h" #if EFI_MALFUNCTION_INDICATOR diff --git a/firmware/controllers/system/efiGpio.cpp b/firmware/controllers/system/efiGpio.cpp index 9b39336717..a73be1a4f2 100644 --- a/firmware/controllers/system/efiGpio.cpp +++ b/firmware/controllers/system/efiGpio.cpp @@ -17,44 +17,15 @@ int getOutputPinValue(io_pin_e pin) { return getLogicPinValue(&outputs[pin]); } -int getLogicPinValue(OutputPin * outputPin) { - return outputPin->currentLogicValue; -} - /** - * @return 0 for OM_DEFAULT and OM_OPENDRAIN + * This is used from fatal error handler so it's a macro to be sure that stack is not used */ - -inline static int getElectricalValue0(pin_output_mode_e mode) { - return mode == OM_INVERTED || mode == OM_OPENDRAIN_INVERTED; -} - -/** - * @return 1 for OM_DEFAULT and OM_OPENDRAIN - */ -inline static int getElectricalValue1(pin_output_mode_e mode) { - return mode == OM_DEFAULT || mode == OM_OPENDRAIN; -} - int getElectricalValue(int logicalValue, pin_output_mode_e mode) { efiAssert(mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e", -1); return logicalValue ? getElectricalValue1(mode) : getElectricalValue0(mode); } -/** - * Set's the value of the pin. On this layer the value is assigned as is, without any conversion. - */ -void setPinValue(OutputPin * outputPin, int electricalValue, int logicValue) { - if (getLogicPinValue(outputPin) == logicValue) - return; - -#if EFI_PROD_CODE - palWritePad(outputPin->port, outputPin->pin, electricalValue); -#endif - outputPin->currentLogicValue = logicValue; -} - /** * @brief Sets the value according to current electrical settings */ diff --git a/firmware/controllers/system/efiGpio.h b/firmware/controllers/system/efiGpio.h index 4016d3a3ca..dd5574525f 100644 --- a/firmware/controllers/system/efiGpio.h +++ b/firmware/controllers/system/efiGpio.h @@ -25,17 +25,56 @@ typedef struct { int currentLogicValue; } OutputPin; +/** + * it's a macro to be sure that stack is not used + * @return 0 for OM_DEFAULT and OM_OPENDRAIN + */ + +#define getElectricalValue0(mode) ((mode) == OM_INVERTED || (mode) == OM_OPENDRAIN_INVERTED) + + +/** + * it's a macro to be sure that stack is not used + * @return 1 for OM_DEFAULT and OM_OPENDRAIN + */ +#define getElectricalValue1(mode) ((mode) == OM_DEFAULT || (mode) == OM_OPENDRAIN) + +#define getLogicPinValue(outputPin) ((outputPin)->currentLogicValue) + +/** + * Sets the value of the pin. On this layer the value is assigned as is, without any conversion. + */ + +#if EFI_PROD_CODE \ + +#define setPinValue(outputPin, electricalValue, logicValue) \ + { \ + if (getLogicPinValue(outputPin) != (logicValue)) { \ + palWritePad((outputPin)->port, (outputPin)->pin, (electricalValue)); \ + (outputPin)->currentLogicValue = (logicValue); \ + } \ + } +#else /* EFI_PROD_CODE */ +#define setPinValue(outputPin, electricalValue, logicValue) \ + { \ + if (getLogicPinValue(outputPin) != (logicValue)) { \ + (outputPin)->currentLogicValue = (logicValue); \ + } \ + } +#endif /* EFI_PROD_CODE */ + +#define turnOutputPinOn(pin) setOutputPinValue((pin), true) +#define turnOutputPinOff(pin) setOutputPinValue((pin), false) + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -int getLogicPinValue(OutputPin * outputPin); int getOutputPinValue(io_pin_e pin); int getElectricalValue(int logicalValue, pin_output_mode_e mode); void setOutputPinValue(io_pin_e pin, int logicValue); bool isPinAssigned(io_pin_e pin); -void setPinValue(OutputPin * outputPin, int electricalValue, int logicValue); #ifdef __cplusplus } diff --git a/firmware/hw_layer/io_pins.c b/firmware/hw_layer/io_pins.c index 06b6edb344..076da15cc3 100644 --- a/firmware/hw_layer/io_pins.c +++ b/firmware/hw_layer/io_pins.c @@ -9,6 +9,7 @@ #include #include "main.h" #include "io_pins.h" +#include "efiGpio.h" #include "pin_repository.h" #include "gpio_helper.h" @@ -33,14 +34,6 @@ static GPIO_TypeDef *PORTS[] = { GPIOA, GPIOB, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG static pin_output_mode_e DEFAULT_OUTPUT = OM_DEFAULT; -void turnOutputPinOn(io_pin_e pin) { - setOutputPinValue(pin, TRUE); -} - -void turnOutputPinOff(io_pin_e pin) { - setOutputPinValue(pin, FALSE); -} - inline static void assertOMode(pin_output_mode_e mode) { // mode >= 0 is always true since that's an unsigned efiAssertVoid(mode <= OM_OPENDRAIN_INVERTED, "invalid pin_output_mode_e"); @@ -201,3 +194,24 @@ void initOutputPins(void) { addConsoleActionS("get_pin_value", getPinValue); } + +static io_pin_e TO_BE_TURNED_OFF_ON_ERROR[] = { SPARKOUT_1_OUTPUT, SPARKOUT_2_OUTPUT, SPARKOUT_3_OUTPUT, + SPARKOUT_4_OUTPUT, SPARKOUT_5_OUTPUT, SPARKOUT_6_OUTPUT, SPARKOUT_7_OUTPUT, SPARKOUT_8_OUTPUT, + SPARKOUT_9_OUTPUT, SPARKOUT_10_OUTPUT, SPARKOUT_11_OUTPUT, SPARKOUT_12_OUTPUT, + + INJECTOR_1_OUTPUT, INJECTOR_2_OUTPUT, INJECTOR_3_OUTPUT, INJECTOR_4_OUTPUT, INJECTOR_5_OUTPUT, + INJECTOR_6_OUTPUT, INJECTOR_7_OUTPUT, INJECTOR_8_OUTPUT, INJECTOR_9_OUTPUT, INJECTOR_10_OUTPUT, + INJECTOR_11_OUTPUT, INJECTOR_12_OUTPUT, FUEL_PUMP_RELAY }; + +/** + * This method is part of fatal error handling. + * Please note that worst case scenario the pins might get re-enabled by some other code :( + * The whole method is pretty naive, but that's at least something. + */ +void turnAllPinsOff(void) { + int l = sizeof(TO_BE_TURNED_OFF_ON_ERROR) / sizeof(io_pin_e); + for (int i = 0; i < l; i++) { + turnOutputPinOff(l); + } +} + diff --git a/firmware/hw_layer/stm32f4/mpu_util.cpp b/firmware/hw_layer/stm32f4/mpu_util.cpp index f180ee4f2d..d9525eac97 100644 --- a/firmware/hw_layer/stm32f4/mpu_util.cpp +++ b/firmware/hw_layer/stm32f4/mpu_util.cpp @@ -16,6 +16,8 @@ void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress); extern stkalign_t __main_stack_base__; +#define GET_CFSR() (*((volatile uint32_t *) (0xE000ED28))) + #if defined __GNUC__ // GCC version @@ -42,8 +44,8 @@ int getRemainingStack(Thread *otp) { #else /* __GNUC__ */ -extern uint32_t CSTACK$$Base; /* symbol created by the IAR linker */ -extern uint32_t IRQSTACK$$Base; /* symbol created by the IAR linker */ +extern uint32_t CSTACK$$Base; /* symbol created by the IAR linker */ +extern uint32_t IRQSTACK$$Base; /* symbol created by the IAR linker */ int getRemainingStack(Thread *otp) { #if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) @@ -134,7 +136,7 @@ void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress) { postmortem_psr = pulFaultStackAddress[7]; /* Configurable Fault Status Register. Consists of MMSR, BFSR and UFSR */ - postmortem_CFSR = (*((volatile uint32_t *) (0xE000ED28))); + postmortem_CFSR = GET_CFSR(); /* Hard Fault Status Register */ postmortem_HFSR = (*((volatile uint32_t *) (0xE000ED2C))); @@ -177,13 +179,20 @@ void HardFaultVector(void) { " bx r2 \n" " handler2_address_const: .word prvGetRegistersFromStack \n" ); - + #else #endif - - chDbgPanic3("HardFaultVector", __FILE__, __LINE__); + + int cfsr = GET_CFSR(); + if (cfsr & 0x100) { + chDbgPanic3("H IBUSERR", __FILE__, __LINE__); + } else if (cfsr & 0x20000) { + chDbgPanic3("H INVSTATE", __FILE__, __LINE__); + } else { + chDbgPanic3("HardFaultVector", __FILE__, __LINE__); + } while (TRUE) { - } + } } diff --git a/firmware/rusefi.cpp b/firmware/rusefi.cpp index 6be78b14bd..40169a3271 100644 --- a/firmware/rusefi.cpp +++ b/firmware/rusefi.cpp @@ -235,10 +235,12 @@ bool hasFirmwareError(void) { return hasFirmwareErrorFlag; } +// todo: why is this method here and not in error_handling.c ? void firmwareError(const char *fmt, ...) { if (hasFirmwareErrorFlag) return; setOutputPinValue(LED_ERROR, 1); + turnAllPinsOff(); hasFirmwareErrorFlag = TRUE; firmwareErrorMessageStream.eos = 0; // reset va_list ap; diff --git a/firmware/svnversion.h b/firmware/svnversion.h index d1ec72ba19..527a545510 100644 --- a/firmware/svnversion.h +++ b/firmware/svnversion.h @@ -1,5 +1,5 @@ // This file was generated by Version2Header -// Tue Nov 04 16:07:39 EST 2014 +// Sat Nov 08 10:29:01 EST 2014 #ifndef VCS_VERSION -#define VCS_VERSION "5101" +#define VCS_VERSION "5226" #endif diff --git a/firmware/util/efilib.cpp b/firmware/util/efilib.cpp index add964586e..30dff36ba4 100644 --- a/firmware/util/efilib.cpp +++ b/firmware/util/efilib.cpp @@ -29,7 +29,7 @@ int minI(int i1, int i2) { } float efiRound(float value, float precision) { - int a = (int)(value / precision); + int a = (int) (value / precision); return a * precision; } @@ -55,11 +55,11 @@ uint32_t efiStrlen(const char *param) { bool startsWith(const char *line, const char *prefix) { uint32_t len = efiStrlen(prefix); - if(efiStrlen(line) < len) { + if (efiStrlen(line) < len) { return false; } - for(int i =0;i