From 410391598ece7d0eea195129d13197a5587df488 Mon Sep 17 00:00:00 2001 From: rusefi Date: Sun, 10 Nov 2019 23:54:08 -0500 Subject: [PATCH] Strange INJ1 signal behavior (when the frequency of scheduler's timer is less than 1MHz) fix #996 --- firmware/controllers/algo/obd_error_codes.h | 4 +- firmware/controllers/engine_controller.cpp | 2 +- firmware/hw_layer/microsecond_timer.cpp | 44 +++++++++++++++++++++ 3 files changed, 47 insertions(+), 3 deletions(-) diff --git a/firmware/controllers/algo/obd_error_codes.h b/firmware/controllers/algo/obd_error_codes.h index f38b27e818..92dd57942d 100644 --- a/firmware/controllers/algo/obd_error_codes.h +++ b/firmware/controllers/algo/obd_error_codes.h @@ -2070,8 +2070,8 @@ typedef enum { CUSTOM_ERR_BOTH_FRONTS_REQUIRED = 6704, CUSTOM_TLE8888 = 6705, CUSTOM_ERR_6706 = 6706, - CUSTOM_ERR_6707 = 6707, - CUSTOM_ERR_6708 = 6708, + CUSTOM_ERR_TIMER_TEST_CALLBACK_NOT_HAPPENED = 6707, + CUSTOM_ERR_TIMER_TEST_CALLBACK_WRONG_TIME = 6708, CUSTOM_ERR_PIN_COUNT_TOO_LARGE = 6709, CUSTOM_DUTY_INVALID = 6710, CUSTOM_DUTY_TOO_HIGH = 6711, diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index f6a64ffe8b..b92ccbc981 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -839,6 +839,6 @@ int getRusEfiVersion(void) { if (initBootloader() != 0) return 123; #endif /* EFI_BOOTLOADER_INCLUDE_CODE */ - return 20191109; + return 20191110; } #endif /* EFI_UNIT_TEST */ diff --git a/firmware/hw_layer/microsecond_timer.cpp b/firmware/hw_layer/microsecond_timer.cpp index 526f4a90be..9309c5f6e5 100644 --- a/firmware/hw_layer/microsecond_timer.cpp +++ b/firmware/hw_layer/microsecond_timer.cpp @@ -25,6 +25,14 @@ #include "engine.h" EXTERN_ENGINE; +// Just in case we have a mechanism to validate that hardware timer is clocked right and all the +// conversions between wall clock and hardware frequencies are done right +// delay in milliseconds +#define TEST_CALLBACK_DELAY 30 +// if hardware timer is 20% off we throw a fatal error and call it a day +// maybe this threshold should be 5%? 10%? +#define TIMER_PRECISION_THRESHOLD 0.2 + /** * Maximum duration of complete timer callback, all pending events together * See also 'maxEventCallbackDuration' for maximum duration of one event @@ -142,6 +150,10 @@ class MicrosecondTimerWatchdogController : public PeriodicTimerController { static MicrosecondTimerWatchdogController watchdogControllerInstance; +/* + * The specific 1MHz frequency is important here since 'setHardwareUsTimer' method takes microsecond parameter + * For any arbitrary frequency to work we would need an additional layer of conversion. + */ static constexpr GPTConfig gpt5cfg = { 1000000, /* 1 MHz timer clock.*/ hwTimerCallback, /* Timer callback.*/ 0, 0 }; @@ -158,6 +170,36 @@ static void watchDogBuddyCallback(void *arg) { engine->executor.scheduleForLater(&watchDogBuddy, MS2US(1000), watchDogBuddyCallback, NULL); } +static volatile bool testSchedulingHappened = false; +static efitimems_t testSchedulingStart; + +static void timerValidationCallback(void *arg) { + (void)arg; + + testSchedulingHappened = true; + efitimems_t actualTimeSinceScheduling = (currentTimeMillis() - testSchedulingStart); + + if (absI(actualTimeSinceScheduling - TEST_CALLBACK_DELAY) > TEST_CALLBACK_DELAY * TIMER_PRECISION_THRESHOLD) { + firmwareError(CUSTOM_ERR_TIMER_TEST_CALLBACK_WRONG_TIME, "hwTimer broken precision"); + } +} + +/** + * This method would validate that hardware timer callbacks happen with some reasonable precision + * helps to make sure our GPT hardware settings are somewhat right + */ +static void validateHardwareTimer() { + testSchedulingStart = currentTimeMillis(); + + // to save RAM let's use 'watchDogBuddy' here once before we enable watchdog + engine->executor.scheduleForLater(&watchDogBuddy, MS2US(TEST_CALLBACK_DELAY), timerValidationCallback, NULL); + + chThdSleepMilliseconds(2 * TEST_CALLBACK_DELAY); + if (!testSchedulingHappened) { + firmwareError(CUSTOM_ERR_TIMER_TEST_CALLBACK_NOT_HAPPENED, "hwTimer not alive"); + } +} + void initMicrosecondTimer(void) { gptStart(&GPTDEVICE, &gpt5cfg); @@ -166,6 +208,8 @@ void initMicrosecondTimer(void) { lastSetTimerTimeNt = getTimeNowNt(); + validateHardwareTimer(); + watchDogBuddyCallback(NULL); #if EFI_EMULATE_POSITION_SENSORS watchdogControllerInstance.Start();