diff --git a/firmware/bootloader/src/Makefile b/firmware/bootloader/src/Makefile index 110a5e05fa..1e18d2b357 100644 --- a/firmware/bootloader/src/Makefile +++ b/firmware/bootloader/src/Makefile @@ -139,6 +139,7 @@ include $(CHIBIOS)/os/hal/osal/rt/osal.mk # RTOS files (optional). include $(CHIBIOS)/os/rt/rt.mk include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk +include $(CHIBIOS)/os/various/cpp_wrappers/chcpp.mk include $(CONFIG)/boards/$(PROJECT_BOARD)/board.mk include $(PROJECT_DIR)/init/init.mk diff --git a/firmware/controllers/engine_controller.cpp b/firmware/controllers/engine_controller.cpp index a2e6537b6e..88d4b2ae86 100644 --- a/firmware/controllers/engine_controller.cpp +++ b/firmware/controllers/engine_controller.cpp @@ -50,7 +50,6 @@ #include "spark_logic.h" #include "aux_valves.h" #include "accelerometer.h" -#include "counter64.h" #include "perf_trace.h" #include "boost_control.h" #include "launch_control.h" @@ -220,8 +219,6 @@ static void doPeriodicSlowCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) { #if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT efiAssertVoid(CUSTOM_ERR_6661, getCurrentRemainingStack() > 64, "lowStckOnEv"); #if EFI_PROD_CODE - touchTimeCounter(); - slowStartStopButtonCallback(PASS_ENGINE_PARAMETER_SIGNATURE); #endif /* EFI_PROD_CODE */ diff --git a/firmware/controllers/engine_controller.h b/firmware/controllers/engine_controller.h index 28741d0ca5..549f439067 100644 --- a/firmware/controllers/engine_controller.h +++ b/firmware/controllers/engine_controller.h @@ -17,7 +17,6 @@ void commonInitEngineController(Logging *sharedLogger DECLARE_ENGINE_PARAMETER_S void initStartStopButton(DECLARE_ENGINE_PARAMETER_SIGNATURE); void initDataStructures(DECLARE_ENGINE_PARAMETER_SIGNATURE); -void touchTimeCounter(); void slowStartStopButtonCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE); diff --git a/firmware/controllers/engine_controller_misc.cpp b/firmware/controllers/engine_controller_misc.cpp index 61d80dd722..35bc00bb68 100644 --- a/firmware/controllers/engine_controller_misc.cpp +++ b/firmware/controllers/engine_controller_misc.cpp @@ -7,7 +7,7 @@ #include "engine_controller.h" #include "perf_trace.h" -#include "counter64.h" +#include "os_access.h" #include "settings.h" EXTERN_ENGINE; @@ -84,8 +84,6 @@ void setMockState(brain_pin_e pin, bool state DECLARE_ENGINE_PARAMETER_SUFFIX) { #endif /* EFI_ENABLE_MOCK_ADC */ #if EFI_PROD_CODE -static Overflow64Counter halTime; - /** * 64-bit result would not overflow, but that's complex stuff for our 32-bit MCU */ @@ -95,34 +93,31 @@ efitimeus_t getTimeNowUs(void) { return getTimeNowNt() / (CORE_CLOCK / 1000000); } -//todo: macro to save method invocation -efitick_t getTimeNowNt(void) { -#if EFI_PROD_CODE - /* Entering a reentrant critical zone.*/ - syssts_t sts = chSysGetStatusAndLockX(); - efitime_t localH = halTime.state.highBits; - uint32_t localLow = halTime.state.lowBits; +volatile uint32_t lastLowerNt = 0; +volatile uint32_t upperTimeNt = 0; - uint32_t value = getTimeNowLowerNt(); +efitick_t getTimeNowNt() { + chibios_rt::CriticalSectionLocker csl; - if (value < localLow) { - // new value less than previous value means there was an overflow in that 32 bit counter - localH += 0x100000000LL; + uint32_t stamp = getTimeNowLowerNt(); + + // Lower 32 bits of the timer has wrapped - time to step upper bits + if (stamp < lastLowerNt) { + upperTimeNt++; } - efitime_t result = localH + value; + lastLowerNt = stamp; - /* Leaving the critical zone.*/ - chSysRestoreStatusX(sts); - return result; -#else /* EFI_PROD_CODE */ -// todo: why is this implementation not used? - /** - * this method is lock-free and thread-safe, that's because the 'update' method - * is atomic with a critical zone requirement. - * - * http://stackoverflow.com/questions/5162673/how-to-read-two-32bit-counters-as-a-64bit-integer-without-race-condition - */ + return ((int64_t)upperTimeNt << 32) | stamp; +} + +/* //Alternative lock free implementation (probably actually slower!) + // this method is lock-free and thread-safe, that's because the 'update' method + // is atomic with a critical zone requirement. + // + // http://stackoverflow.com/questions/5162673/how-to-read-two-32bit-counters-as-a-64bit-integer-without-race-condition + +etitick_t getTimeNowNt() { efitime_t localH; efitime_t localH2; uint32_t localLow; @@ -131,14 +126,11 @@ efitick_t getTimeNowNt(void) { localH = halTime.state.highBits; localLow = halTime.state.lowBits; localH2 = halTime.state.highBits; -#if EFI_PROD_CODE if (counter++ == 10000) chDbgPanic("lock-free frozen"); -#endif /* EFI_PROD_CODE */ } while (localH != localH2); - /** - * We need to take current counter after making a local 64 bit snapshot - */ + + // We need to take current counter after making a local 64 bit snapshot uint32_t value = getTimeNowLowerNt(); if (value < localLow) { @@ -147,20 +139,8 @@ efitick_t getTimeNowNt(void) { } return localH + value; -#endif /* EFI_PROD_CODE */ - -} - -void touchTimeCounter() { - /** - * We need to push current value into the 64 bit counter often enough so that we do not miss an overflow - */ - /* Entering a reentrant critical zone.*/ - syssts_t sts = chSysGetStatusAndLockX(); - updateAndSet(&halTime.state, getTimeNowLowerNt()); - /* Leaving the critical zone.*/ - chSysRestoreStatusX(sts); } +*/ static void onStartStopButtonToggle(DECLARE_ENGINE_PARAMETER_SIGNATURE) { engine->startStopStateToggleCounter++; diff --git a/firmware/os_access.h b/firmware/os_access.h index 339f580f7e..64a057ce51 100644 --- a/firmware/os_access.h +++ b/firmware/os_access.h @@ -9,19 +9,14 @@ #pragma once -#ifdef __cplusplus -extern "C" -{ -#endif /* __cplusplus */ - #include #include #include "chprintf.h" - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - #include "io_pins.h" +#ifdef __cplusplus +// ChibiOS c++ wrappers +#include "ch.hpp" +#endif /* __cplusplus */ + #define HAS_OS_ACCESS diff --git a/firmware/util/containers/counter64.cpp b/firmware/util/containers/counter64.cpp deleted file mode 100644 index b541c1ca72..0000000000 --- a/firmware/util/containers/counter64.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * counter64.cpp - * - * Created on: Mar 31, 2019 - * @author Andrey Belomutskiy, (c) 2012-2020 - */ - -#include "counter64.h" - -/** - * The main use-case of this class is to keep track of a 64-bit global number of CPU ticks from reset. - * - * stm32f4 hardware has a 32-bit Cycle Count Register (CYCCNT), which is incremented with every CPU cycle. - * With 32 bits and 168MHz speed this counter overflows every 4B/168M = 23 seconds. The job of this class is to - * keep track of the current CYCCNT value, detect these overflows, and provide a nice, - * clean 64 bit global cycle counter. - * - * In order for this to function, it's your responsibility to invoke offer() method at least once a second. - */ -Overflow64Counter::Overflow64Counter() { - state.highBits = 0; - state.lowBits = 0; -} - -/** - * in order to have atomic writes this should be invoked within a critical section - */ -void updateAndSet(State64 *state, uint32_t value) { - if (value < state->lowBits) { - // new value less than previous value means there was an overflow in that 32 bit counter - state->highBits += 0x100000000LL; - } - state->lowBits = value; -} - -#if EFI_UNIT_TEST -efitime_t Overflow64Counter::update(uint32_t value) { - updateAndSet(&state, value); - return state.highBits + state.lowBits; -} -#endif - diff --git a/firmware/util/containers/counter64.h b/firmware/util/containers/counter64.h deleted file mode 100644 index 8696f654ff..0000000000 --- a/firmware/util/containers/counter64.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * @file counter64.h - * - * Created on: Mar 31, 2019 - * @author Andrey Belomutskiy, (c) 2012-2020 - */ - -#pragma once - -#include "global.h" - -typedef struct { - // todo: would probably be better to keep the high bits as 32 bit field to be sure - volatile efitime_t highBits; - volatile uint32_t lowBits; -} State64; - -void updateAndSet(State64 *state, uint32_t value); - -class Overflow64Counter -{ - public: - Overflow64Counter(); - - efitime_t get(); -#if EFI_UNIT_TEST - efitime_t update(uint32_t value); -#endif - - State64 state; -}; diff --git a/firmware/util/util.mk b/firmware/util/util.mk index 534439946b..3012b3cd71 100644 --- a/firmware/util/util.mk +++ b/firmware/util/util.mk @@ -8,7 +8,6 @@ UTILSRC = \ UTILSRC_CPP = \ $(UTIL_DIR)/containers/cyclic_buffer.cpp \ $(UTIL_DIR)/containers/listener_array.cpp \ - $(UTIL_DIR)/containers/counter64.cpp \ $(UTIL_DIR)/containers/local_version_holder.cpp \ $(UTIL_DIR)/containers/table_helper.cpp \ $(UTIL_DIR)/math/biquad.cpp \ diff --git a/unit_tests/tests/test_util.cpp b/unit_tests/tests/test_util.cpp index e13f8f7b9b..968406bb81 100644 --- a/unit_tests/tests/test_util.cpp +++ b/unit_tests/tests/test_util.cpp @@ -22,7 +22,6 @@ #include "crc.h" #include "fl_stack.h" #include "io_pins.h" -#include "counter64.h" #include "efi_gpio.h" #include "efilib.h" @@ -66,20 +65,6 @@ TEST(util, crc) { assertEqualsM("crc32 line inc", 0x4775a7b1, c); } - -TEST(util, Overflow64Counter) { - print("*************************************** testOverflow64Counter\r\n"); - - Overflow64Counter o; - ASSERT_EQ(0, o.update(0)); - ASSERT_EQ(10, o.update(10)); - - ASSERT_EQ(20, o.update(20)); - - // overflow - ASSERT_EQ(4294967296, o.update(0)); -} - TEST(util, cyclicBufferContains) { cyclic_buffer sb; sb.add(10);