diff --git a/firmware/controllers/algo/wave_chart.cpp b/firmware/controllers/algo/wave_chart.cpp index aa41ec093c..b36f0585fa 100644 --- a/firmware/controllers/algo/wave_chart.cpp +++ b/firmware/controllers/algo/wave_chart.cpp @@ -72,7 +72,7 @@ void WaveChart::resetWaveChart() { #endif /* DEBUG_WAVE */ resetLogging(&logging); counter = 0; - startTimeUs = 0; + startTimeNt = 0; appendPrintf(&logging, "wave_chart%s", DELIMETER); } @@ -86,8 +86,8 @@ int WaveChart::isWaveChartFull() { * digitalChartSize/20 is the longest meaningful chart. * */ - uint64_t chartDurationInSeconds = (getTimeNowUs() - startTimeUs) / 1000000; - bool startedTooLongAgo = startTimeUs!= 0 && chartDurationInSeconds > engineConfiguration->digitalChartSize / 20; + uint64_t chartDurationNt = getTimeNowNt() - startTimeNt; + bool startedTooLongAgo = startTimeNt!= 0 && NT2US(chartDurationNt) > engineConfiguration->digitalChartSize * 1000000 / 20; return startedTooLongAgo || counter >= engineConfiguration->digitalChartSize; } @@ -158,19 +158,24 @@ void WaveChart::addWaveChartEvent3(const char *name, const char * msg, const cha #endif uint64_t nowUs = getTimeNowUs(); - /** - * todo: migrate to binary fractions in order to eliminate - * this division? I do not like division - */ - uint64_t time100 = nowUs / 10; bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer if (counter == 0) { - startTime100 = time100; - startTimeUs = nowUs; + startTimeNt = US2NT(nowUs); } counter++; + + /** + * We want smaller times within a chart in order to reduce packet size. + */ + /** + * todo: migrate to binary fractions in order to eliminate + * this division? I do not like division + */ + uint64_t time100 = (nowUs - NT2US(startTimeNt)) / 10; + + if (remainingSize(&logging) > 30) { /** * printf is a heavy method, append is used here as a performance optimization @@ -179,10 +184,7 @@ void WaveChart::addWaveChartEvent3(const char *name, const char * msg, const cha appendFast(&logging, CHART_DELIMETER); appendFast(&logging, msg); appendFast(&logging, CHART_DELIMETER); - /** - * We want smaller times within a chart in order to reduce packet size. - */ - time100 -= startTime100; +// time100 -= startTime100; itoa10(timeBuffer, time100); appendFast(&logging, timeBuffer); diff --git a/firmware/controllers/algo/wave_chart.h b/firmware/controllers/algo/wave_chart.h index 43250839a5..2a01e56320 100644 --- a/firmware/controllers/algo/wave_chart.h +++ b/firmware/controllers/algo/wave_chart.h @@ -31,8 +31,7 @@ private: Logging logging; #endif /* EFI_WAVE_CHART */ uint32_t counter; - uint64_t startTime100; - uint64_t startTimeUs; + uint64_t startTimeNt; volatile int isInitialized; }; diff --git a/firmware/controllers/math/efitime.h b/firmware/controllers/math/efitime.h index 11aabafe94..76c4f9cd9f 100644 --- a/firmware/controllers/math/efitime.h +++ b/firmware/controllers/math/efitime.h @@ -26,6 +26,7 @@ extern "C" #endif /* __cplusplus */ #define US_PER_SECOND 1000000 +#define US_PER_SECOND_LL 1000000LL #define MS2US(MS_TIME) ((MS_TIME) * 1000) diff --git a/firmware/controllers/trigger/rpm_calculator.cpp b/firmware/controllers/trigger/rpm_calculator.cpp index e8ba2274c0..7d661693bc 100644 --- a/firmware/controllers/trigger/rpm_calculator.cpp +++ b/firmware/controllers/trigger/rpm_calculator.cpp @@ -63,7 +63,7 @@ RpmCalculator::RpmCalculator() { rpmValue = 0; // we need this initial to have not_running at first invocation - lastRpmEventTimeNt = (uint64_t) -10 * US2NT(US_PER_SECOND); + lastRpmEventTimeNt = (uint64_t) -10 * US2NT(US_PER_SECOND_LL); revolutionCounterSinceStart = 0; revolutionCounterSinceBoot = 0; } @@ -155,7 +155,7 @@ void rpmShaftPositionCallback(trigger_event_e ckpSignalType, uint32_t index, Rpm rpmState->rpmValue = NOISY_RPM; } else { // todo: interesting what is this *2 about? four stroke magic constant? - int rpm = (int) (60 * US2NT(US_PER_SECOND) * 2 / diffNt); + int rpm = (int) (60 * US2NT(US_PER_SECOND_LL) * 2 / diffNt); rpmState->rpmValue = rpm > UNREALISTIC_RPM ? NOISY_RPM : rpm; } } diff --git a/firmware/controllers/trigger/trigger_central.cpp b/firmware/controllers/trigger/trigger_central.cpp index 9c3151fbd3..4e7d4ba4a3 100644 --- a/firmware/controllers/trigger/trigger_central.cpp +++ b/firmware/controllers/trigger/trigger_central.cpp @@ -61,7 +61,7 @@ void addTriggerEventListener(ShaftPositionListener listener, const char *name, v extern Engine engine; void hwHandleShaftSignal(trigger_event_e signal) { - triggerCentral.handleShaftSignal(&engine, signal, getTimeNowUs()); + triggerCentral.handleShaftSignal(&engine, signal); } #endif /* EFI_PROD_CODE */ @@ -96,9 +96,11 @@ static void reportEventToWaveChart(trigger_event_e ckpSignalType, int index) { // todo: improve this extern Engine engine; -void TriggerCentral::handleShaftSignal(Engine *engine, trigger_event_e signal, uint64_t nowUs) { +void TriggerCentral::handleShaftSignal(Engine *engine, trigger_event_e signal) { efiAssertVoid(engine!=NULL, "configuration"); + uint64_t nowUs = getTimeNowUs(); + efiAssertVoid(engine->engineConfiguration!=NULL, "engineConfiguration"); efiAssertVoid(engine->engineConfiguration2!=NULL, "engineConfiguration2"); diff --git a/firmware/controllers/trigger/trigger_central.h b/firmware/controllers/trigger/trigger_central.h index c4620dff2a..420ccc7594 100644 --- a/firmware/controllers/trigger/trigger_central.h +++ b/firmware/controllers/trigger/trigger_central.h @@ -24,7 +24,7 @@ class TriggerCentral { public: TriggerCentral(); void addEventListener(ShaftPositionListener handler, const char *name, void *arg); - void handleShaftSignal(Engine *engine, trigger_event_e signal, uint64_t nowUs); + void handleShaftSignal(Engine *engine, trigger_event_e signal); int getHwEventCounter(int index); TriggerState triggerState; private: diff --git a/firmware/hw_layer/stm32f4/mpu_util.cpp b/firmware/hw_layer/stm32f4/mpu_util.cpp index 61356ad5ff..a6ef7bd8d4 100644 --- a/firmware/hw_layer/stm32f4/mpu_util.cpp +++ b/firmware/hw_layer/stm32f4/mpu_util.cpp @@ -11,6 +11,7 @@ extern "C" { int getRemainingStack(Thread *otp); +void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress); } extern stkalign_t __main_stack_base__; @@ -19,7 +20,7 @@ extern stkalign_t __main_stack_base__; // GCC version int getRemainingStack(Thread *otp) { - + #if CH_DBG_ENABLE_STACK_CHECK register struct intctx *r13 asm ("r13"); otp->activeStack = r13; @@ -41,19 +42,18 @@ int getRemainingStack(Thread *otp) { #else /* __GNUC__ */ - int getRemainingStack(Thread *otp) { #if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__) - int remainingStack; - if (dbg_isr_cnt > 0) { - remainingStack = 999; // todo - } else { - remainingStack = (stkalign_t *)(__get_SP() - sizeof(struct intctx)) - otp->p_stklimit; - } - otp->remainingStack = remainingStack; - return remainingStack; + int remainingStack; + if (dbg_isr_cnt > 0) { + remainingStack = 999; // todo + } else { + remainingStack = (stkalign_t *)(__get_SP() - sizeof(struct intctx)) - otp->p_stklimit; + } + otp->remainingStack = remainingStack; + return remainingStack; #else - return 999999; + return 999999; #endif } @@ -61,10 +61,6 @@ int getRemainingStack(Thread *otp) { #endif - - - - void baseHardwareInit(void) { // looks like this holds a random value on start? Let's set a nice clean zero DWT_CYCCNT = 0; @@ -91,16 +87,100 @@ void BusFaultVector(void) { chDbgPanic3("BusFaultVector", __FILE__, __LINE__); while (TRUE) { - } + } +} + +/** + + * @brief Register values for postmortem debugging. + + */ +volatile uint32_t postmortem_r0; +volatile uint32_t postmortem_r1; +volatile uint32_t postmortem_r2; +volatile uint32_t postmortem_r3; +volatile uint32_t postmortem_r12; +volatile uint32_t postmortem_lr; /* Link register. */ +volatile uint32_t postmortem_pc; /* Program counter. */ +volatile uint32_t postmortem_psr;/* Program status register. */ +volatile uint32_t postmortem_CFSR; +volatile uint32_t postmortem_HFSR; +volatile uint32_t postmortem_DFSR; +volatile uint32_t postmortem_AFSR; +volatile uint32_t postmortem_BFAR; +volatile uint32_t postmortem_MMAR; +volatile uint32_t postmortem_SCB_SHCSR; + +/** + * @brief Evaluates to TRUE if system runs under debugger control. + * @note This bit resets only by power reset. + */ +#define is_under_debugger() (((CoreDebug)->DHCSR) & \ + CoreDebug_DHCSR_C_DEBUGEN_Msk) + +/** + * + */ +void prvGetRegistersFromStack(uint32_t *pulFaultStackAddress) { + + postmortem_r0 = pulFaultStackAddress[0]; + postmortem_r1 = pulFaultStackAddress[1]; + postmortem_r2 = pulFaultStackAddress[2]; + postmortem_r3 = pulFaultStackAddress[3]; + postmortem_r12 = pulFaultStackAddress[4]; + postmortem_lr = pulFaultStackAddress[5]; + postmortem_pc = pulFaultStackAddress[6]; + postmortem_psr = pulFaultStackAddress[7]; + + /* Configurable Fault Status Register. Consists of MMSR, BFSR and UFSR */ + postmortem_CFSR = (*((volatile uint32_t *) (0xE000ED28))); + + /* Hard Fault Status Register */ + postmortem_HFSR = (*((volatile uint32_t *) (0xE000ED2C))); + + /* Debug Fault Status Register */ + postmortem_DFSR = (*((volatile uint32_t *) (0xE000ED30))); + + /* Auxiliary Fault Status Register */ + postmortem_AFSR = (*((volatile uint32_t *) (0xE000ED3C))); + + /* Read the Fault Address Registers. These may not contain valid values. + Check BFARVALID/MMARVALID to see if they are valid values + MemManage Fault Address Register */ + postmortem_MMAR = (*((volatile uint32_t *) (0xE000ED34))); + /* Bus Fault Address Register */ + postmortem_BFAR = (*((volatile uint32_t *) (0xE000ED38))); + + postmortem_SCB_SHCSR = SCB->SHCSR; + + if (is_under_debugger()) { + __asm("BKPT #0\n"); + // Break into the debugger + } + + /* harmless infinite loop */ + while (1) { + ; + } } void HardFaultVector(void) { - +#if 0 && defined __GNUC__ + __asm volatile ( + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, handler2_address_const \n" + " bx r2 \n" + " handler2_address_const: .word prvGetRegistersFromStack \n" + ); + +#else +#endif + chDbgPanic3("HardFaultVector", __FILE__, __LINE__); while (TRUE) { } } - - diff --git a/unit_tests/engine_test_helper.cpp b/unit_tests/engine_test_helper.cpp index 4818925834..f7a623a141 100644 --- a/unit_tests/engine_test_helper.cpp +++ b/unit_tests/engine_test_helper.cpp @@ -33,9 +33,9 @@ EngineTestHelper::EngineTestHelper(engine_type_e engineType) { void EngineTestHelper::fireTriggerEvents() { for (int i = 0; i < 24; i++) { timeNow += 5000; // 5ms - triggerCentral.handleShaftSignal(&engine, SHAFT_PRIMARY_UP, timeNow); + triggerCentral.handleShaftSignal(&engine, SHAFT_PRIMARY_UP); timeNow += 5000; - triggerCentral.handleShaftSignal(&engine, SHAFT_PRIMARY_DOWN, timeNow); + triggerCentral.handleShaftSignal(&engine, SHAFT_PRIMARY_DOWN); } } diff --git a/unit_tests/test_trigger_decoder.cpp b/unit_tests/test_trigger_decoder.cpp index 7d03a7b21b..fd12d661b3 100644 --- a/unit_tests/test_trigger_decoder.cpp +++ b/unit_tests/test_trigger_decoder.cpp @@ -422,7 +422,7 @@ static void testRpmCalculator(void) { prepareTimingMap(); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); assertEqualsM("index #2", 0, eth.triggerCentral.triggerState.getCurrentIndex()); assertEqualsM("queue size", 4, schedulingQueue.size()); assertEqualsM("ev 1", 248000, schedulingQueue.getForUnitText(0)->momentUs); @@ -430,11 +430,11 @@ static void testRpmCalculator(void) { schedulingQueue.clear(); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); assertEqualsM("index #3", 3, eth.triggerCentral.triggerState.getCurrentIndex()); assertEqualsM("queue size 3", 6, schedulingQueue.size()); assertEquals(258333, schedulingQueue.getForUnitText(0)->momentUs); @@ -444,24 +444,24 @@ static void testRpmCalculator(void) { schedulingQueue.clear(); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); assertEqualsM("index #4", 6, eth.triggerCentral.triggerState.getCurrentIndex()); assertEqualsM("queue size 4", 6, schedulingQueue.size()); assertEqualsM("4/0", 271666, schedulingQueue.getForUnitText(0)->momentUs); schedulingQueue.clear(); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); assertEqualsM("queue size 5", 1, schedulingQueue.size()); assertEqualsM("5/1", 284500, schedulingQueue.getForUnitText(0)->momentUs); schedulingQueue.clear(); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); assertEqualsM("queue size 6", 5, schedulingQueue.size()); assertEqualsM("6/0", 285000, schedulingQueue.getForUnitText(0)->momentUs); assertEqualsM("6/1", 288000, schedulingQueue.getForUnitText(1)->momentUs); @@ -469,12 +469,12 @@ static void testRpmCalculator(void) { schedulingQueue.clear(); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); assertEqualsM("queue size 7", 0, schedulingQueue.size()); schedulingQueue.clear(); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); assertEqualsM("queue size 8", 6, schedulingQueue.size()); assertEqualsM("8/0", 298333, schedulingQueue.getForUnitText(0)->momentUs); assertEqualsM("8/1", 297833, schedulingQueue.getForUnitText(1)->momentUs); @@ -483,12 +483,12 @@ static void testRpmCalculator(void) { schedulingQueue.clear(); timeNow += 5000; - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_DOWN); assertEqualsM("queue size 9", 0, schedulingQueue.size()); schedulingQueue.clear(); timeNow += 5000; // 5ms - eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP, timeNow); + eth.triggerCentral.handleShaftSignal(ð.engine, SHAFT_PRIMARY_UP); assertEqualsM("queue size 10", 0, schedulingQueue.size()); schedulingQueue.clear(); }