mirror of https://github.com/FOME-Tech/fome-fw.git
execute critical tasks on one big thread (#462)
* wire up main loop * remove PeriodicTimerController * patch up defines, comments * happy simulator * format * simulator * ETB runs via main loop * happy tests * protection against invalid LoopPeriod * stack size * ccm * fix |= operator * move perf trace * ordering * ordering
This commit is contained in:
parent
7cb539d65f
commit
01a397094d
|
@ -33,7 +33,7 @@
|
||||||
#define ENABLE_PERF_TRACE TRUE
|
#define ENABLE_PERF_TRACE TRUE
|
||||||
|
|
||||||
// H7 runs faster "slow" ADC to make up for reduced oversampling
|
// H7 runs faster "slow" ADC to make up for reduced oversampling
|
||||||
#define SLOW_ADC_RATE 1000
|
#define ADC_UPDATE_RATE LoopPeriod::Period1000hz
|
||||||
|
|
||||||
#undef LUA_USER_HEAP
|
#undef LUA_USER_HEAP
|
||||||
#define LUA_USER_HEAP 100000
|
#define LUA_USER_HEAP 100000
|
||||||
|
|
|
@ -659,14 +659,7 @@ void EtbController::autoCalibrateTps() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
/**
|
|
||||||
* Things running on a timer (instead of a thread) don't participate it the RTOS's thread priority system,
|
|
||||||
* and operate essentially "first come first serve", which risks starvation.
|
|
||||||
* Since ETB is a safety critical device, we need the hard RTOS guarantee that it will be scheduled over other less important tasks.
|
|
||||||
*/
|
|
||||||
#include "periodic_thread_controller.h"
|
|
||||||
#else
|
|
||||||
#define chThdSleepMilliseconds(x) {}
|
#define chThdSleepMilliseconds(x) {}
|
||||||
#endif // EFI_UNIT_TEST
|
#endif // EFI_UNIT_TEST
|
||||||
|
|
||||||
|
@ -754,23 +747,6 @@ static EtbImpl<EtbController2> etb2;
|
||||||
static_assert(ETB_COUNT == 2);
|
static_assert(ETB_COUNT == 2);
|
||||||
static EtbController* etbControllers[] = { &etb1, &etb2 };
|
static EtbController* etbControllers[] = { &etb1, &etb2 };
|
||||||
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
|
|
||||||
struct DcThread final : public PeriodicController<512> {
|
|
||||||
DcThread() : PeriodicController("DC", PRIO_ETB, ETB_LOOP_FREQUENCY) {}
|
|
||||||
|
|
||||||
void PeriodicTask(efitick_t) override {
|
|
||||||
// Simply update all controllers
|
|
||||||
for (int i = 0 ; i < ETB_COUNT; i++) {
|
|
||||||
etbControllers[i]->update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static DcThread dcThread CCM_OPTIONAL;
|
|
||||||
|
|
||||||
#endif // EFI_UNIT_TEST
|
|
||||||
|
|
||||||
void etbPidReset() {
|
void etbPidReset() {
|
||||||
for (int i = 0 ; i < ETB_COUNT; i++) {
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
||||||
if (auto controller = engine->etbControllers[i]) {
|
if (auto controller = engine->etbControllers[i]) {
|
||||||
|
@ -957,14 +933,6 @@ void doInitElectronicThrottle() {
|
||||||
startupPositionError = true;
|
startupPositionError = true;
|
||||||
}
|
}
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
static bool started = false;
|
|
||||||
if (started == false) {
|
|
||||||
dcThread.start();
|
|
||||||
started = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initElectronicThrottle() {
|
void initElectronicThrottle() {
|
||||||
|
|
|
@ -121,8 +121,6 @@ void Engine::updateTriggerWaveform() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::periodicSlowCallback() {
|
void Engine::periodicSlowCallback() {
|
||||||
ScopePerf perf(PE::EnginePeriodicSlowCallback);
|
|
||||||
|
|
||||||
#if EFI_SHAFT_POSITION_INPUT
|
#if EFI_SHAFT_POSITION_INPUT
|
||||||
// Re-read config in case it's changed
|
// Re-read config in case it's changed
|
||||||
triggerCentral.primaryTriggerConfiguration.update();
|
triggerCentral.primaryTriggerConfiguration.update();
|
||||||
|
|
|
@ -76,9 +76,6 @@
|
||||||
#include "global_execution_queue.h"
|
#include "global_execution_queue.h"
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
|
||||||
#define FAST_CALLBACK_PERIOD_MS 5
|
|
||||||
#define SLOW_CALLBACK_PERIOD_MS 50
|
|
||||||
|
|
||||||
struct AirmassModelBase;
|
struct AirmassModelBase;
|
||||||
|
|
||||||
#define MAF_DECODING_CACHE_SIZE 256
|
#define MAF_DECODING_CACHE_SIZE 256
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
|
|
||||||
CONTROLLERS_CORE_SRC_CPP = \
|
CONTROLLERS_CORE_SRC_CPP = \
|
||||||
|
$(PROJECT_DIR)/controllers/core/main_loop.cpp \
|
||||||
$(PROJECT_DIR)/controllers/core/state_sequence.cpp \
|
$(PROJECT_DIR)/controllers/core/state_sequence.cpp \
|
||||||
$(PROJECT_DIR)/controllers/core/big_buffer.cpp \
|
$(PROJECT_DIR)/controllers/core/big_buffer.cpp \
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "pch.h"
|
||||||
|
|
||||||
|
#include "periodic_thread_controller.h"
|
||||||
|
#include "electronic_throttle.h"
|
||||||
|
|
||||||
|
#define MAIN_LOOP_RATE 1000
|
||||||
|
|
||||||
|
class MainLoop : public PeriodicController<1024> {
|
||||||
|
public:
|
||||||
|
MainLoop();
|
||||||
|
void PeriodicTask(efitick_t nowNt) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
template <LoopPeriod TFlag>
|
||||||
|
LoopPeriod makePeriodFlag() const;
|
||||||
|
|
||||||
|
LoopPeriod makePeriodFlags();
|
||||||
|
|
||||||
|
int m_cycleCounter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static MainLoop mainLoop CCM_OPTIONAL;
|
||||||
|
|
||||||
|
void initMainLoop() {
|
||||||
|
mainLoop.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLoop::MainLoop()
|
||||||
|
: PeriodicController("MainLoop", PRIO_MAIN_LOOP, MAIN_LOOP_RATE)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainLoop::PeriodicTask(efitick_t nowNt) {
|
||||||
|
ScopePerf perf(PE::MainLoop);
|
||||||
|
|
||||||
|
LoopPeriod p = makePeriodFlags();
|
||||||
|
|
||||||
|
#if HAL_USE_ADC
|
||||||
|
if (p & ADC_UPDATE_RATE) {
|
||||||
|
updateSlowAdc(nowNt);
|
||||||
|
}
|
||||||
|
#endif // HAL_USE_ADC
|
||||||
|
|
||||||
|
#if EFI_ELECTRONIC_THROTTLE_BODY
|
||||||
|
if (p & ETB_UPDATE_RATE) {
|
||||||
|
for (int i = 0 ; i < ETB_COUNT; i++) {
|
||||||
|
engine->etbControllers[i]->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // EFI_ELECTRONIC_THROTTLE_BODY
|
||||||
|
|
||||||
|
if (p & SLOW_CALLBACK_RATE) {
|
||||||
|
doPeriodicSlowCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p & FAST_CALLBACK_RATE) {
|
||||||
|
engine->periodicFastCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <LoopPeriod flag>
|
||||||
|
static constexpr int loopCounts() {
|
||||||
|
constexpr auto hz = hzForPeriod(flag);
|
||||||
|
|
||||||
|
// check that this cleanly divides
|
||||||
|
static_assert(MAIN_LOOP_RATE % hz == 0);
|
||||||
|
|
||||||
|
return MAIN_LOOP_RATE / hz;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <LoopPeriod TFlag>
|
||||||
|
LoopPeriod MainLoop::makePeriodFlag() const {
|
||||||
|
if (m_cycleCounter % loopCounts<TFlag>() == 0) {
|
||||||
|
return TFlag;
|
||||||
|
} else {
|
||||||
|
return LoopPeriod::None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LoopPeriod MainLoop::makePeriodFlags() {
|
||||||
|
if (m_cycleCounter >= MAIN_LOOP_RATE) {
|
||||||
|
m_cycleCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoopPeriod lp = LoopPeriod::None;
|
||||||
|
lp |= makePeriodFlag<LoopPeriod::Period1000hz>();
|
||||||
|
lp |= makePeriodFlag<LoopPeriod::Period500hz>();
|
||||||
|
lp |= makePeriodFlag<LoopPeriod::Period250hz>();
|
||||||
|
lp |= makePeriodFlag<LoopPeriod::Period20hz>();
|
||||||
|
|
||||||
|
m_cycleCounter++;
|
||||||
|
|
||||||
|
return lp;
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
void initMainLoop();
|
||||||
|
|
||||||
|
enum class LoopPeriod : uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Period1000hz = 1 << 0,
|
||||||
|
Period500hz = 1 << 1,
|
||||||
|
Period250hz = 1 << 2,
|
||||||
|
Period20hz = 1 << 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
inline constexpr LoopPeriod& operator|=(LoopPeriod& a, const LoopPeriod& b) {
|
||||||
|
a = static_cast<LoopPeriod>(static_cast<uint8_t>(a) | static_cast<uint8_t>(b));
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline constexpr bool operator&(LoopPeriod a, LoopPeriod b) {
|
||||||
|
return 0 != (static_cast<uint8_t>(a) & static_cast<uint8_t>(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int hzForPeriod(LoopPeriod p) {
|
||||||
|
switch (p) {
|
||||||
|
case LoopPeriod::None: return 0;
|
||||||
|
case LoopPeriod::Period1000hz: return 1000;
|
||||||
|
case LoopPeriod::Period500hz: return 500;
|
||||||
|
case LoopPeriod::Period250hz: return 200;
|
||||||
|
case LoopPeriod::Period20hz: return 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float loopPeriodMs(LoopPeriod p) {
|
||||||
|
return 1000.0f / hzForPeriod(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef ADC_UPDATE_RATE
|
||||||
|
#define ADC_UPDATE_RATE LoopPeriod::Period500hz
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ETB_UPDATE_RATE LoopPeriod::Period500hz
|
||||||
|
#define FAST_CALLBACK_RATE LoopPeriod::Period250hz
|
||||||
|
#define SLOW_CALLBACK_RATE LoopPeriod::Period20hz
|
||||||
|
|
||||||
|
#define FAST_CALLBACK_PERIOD_MS loopPeriodMs(FAST_CALLBACK_RATE)
|
||||||
|
#define SLOW_CALLBACK_PERIOD_MS loopPeriodMs(SLOW_CALLBACK_RATE)
|
|
@ -65,9 +65,6 @@
|
||||||
#include "logic_analyzer.h"
|
#include "logic_analyzer.h"
|
||||||
#endif /* EFI_LOGIC_ANALYZER */
|
#endif /* EFI_LOGIC_ANALYZER */
|
||||||
|
|
||||||
#include "periodic_task.h"
|
|
||||||
|
|
||||||
|
|
||||||
#if ! EFI_UNIT_TEST
|
#if ! EFI_UNIT_TEST
|
||||||
#include "init.h"
|
#include "init.h"
|
||||||
#endif /* EFI_UNIT_TEST */
|
#endif /* EFI_UNIT_TEST */
|
||||||
|
@ -93,37 +90,6 @@ void initDataStructures() {
|
||||||
#endif // EFI_ENGINE_CONTROL
|
#endif // EFI_ENGINE_CONTROL
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
|
|
||||||
static void doPeriodicSlowCallback();
|
|
||||||
|
|
||||||
class PeriodicFastController : public PeriodicTimerController {
|
|
||||||
protected:
|
|
||||||
void PeriodicTask() override {
|
|
||||||
engine->periodicFastCallback();
|
|
||||||
|
|
||||||
if (m_slowCallbackCounter == 0) {
|
|
||||||
doPeriodicSlowCallback();
|
|
||||||
|
|
||||||
// Check that an integer number of fast callbacks fit in a slow callback
|
|
||||||
static_assert((SLOW_CALLBACK_PERIOD_MS % FAST_CALLBACK_PERIOD_MS) == 0);
|
|
||||||
|
|
||||||
m_slowCallbackCounter = SLOW_CALLBACK_PERIOD_MS / FAST_CALLBACK_PERIOD_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_slowCallbackCounter--;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPeriodMs() override {
|
|
||||||
return FAST_CALLBACK_PERIOD_MS;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
size_t m_slowCallbackCounter = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
static PeriodicFastController fastController;
|
|
||||||
|
|
||||||
static void resetAccel() {
|
static void resetAccel() {
|
||||||
engine->module<TpsAccelEnrichment>()->resetAE();
|
engine->module<TpsAccelEnrichment>()->resetAE();
|
||||||
|
|
||||||
|
@ -133,7 +99,9 @@ static void resetAccel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doPeriodicSlowCallback() {
|
void doPeriodicSlowCallback() {
|
||||||
|
ScopePerf perf(PE::EnginePeriodicSlowCallback);
|
||||||
|
|
||||||
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
#if EFI_ENGINE_CONTROL && EFI_SHAFT_POSITION_INPUT
|
||||||
efiAssertVoid(ObdCode::CUSTOM_ERR_6661, getCurrentRemainingStack() > 64, "lowStckOnEv");
|
efiAssertVoid(ObdCode::CUSTOM_ERR_6661, getCurrentRemainingStack() > 64, "lowStckOnEv");
|
||||||
|
|
||||||
|
@ -177,10 +145,6 @@ static void doPeriodicSlowCallback() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void initPeriodicEvents() {
|
|
||||||
fastController.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer) {
|
char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer) {
|
||||||
#if HAL_USE_ADC
|
#if HAL_USE_ADC
|
||||||
if (!isAdcChannelValid(hwChannel)) {
|
if (!isAdcChannelValid(hwChannel)) {
|
||||||
|
@ -349,7 +313,6 @@ static void initConfigActions() {
|
||||||
addConsoleActionI("get_byte", getByte);
|
addConsoleActionI("get_byte", getByte);
|
||||||
addConsoleActionII("get_bit", getBit);
|
addConsoleActionII("get_bit", getBit);
|
||||||
}
|
}
|
||||||
#endif /* EFI_UNIT_TEST */
|
|
||||||
|
|
||||||
void LedBlinkingTask::onSlowCallback() {
|
void LedBlinkingTask::onSlowCallback() {
|
||||||
updateRunningLed();
|
updateRunningLed();
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
// todo: huh we also have validateConfiguration()?!
|
// todo: huh we also have validateConfiguration()?!
|
||||||
bool validateConfig();
|
bool validateConfig();
|
||||||
char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer);
|
char * getPinNameByAdcChannel(const char *msg, adc_channel_e hwChannel, char *buffer);
|
||||||
void initPeriodicEvents();
|
|
||||||
void initEngineController();
|
void initEngineController();
|
||||||
void commonInitEngineController();
|
void commonInitEngineController();
|
||||||
void initStartStopButton();
|
void initStartStopButton();
|
||||||
|
@ -19,3 +18,5 @@ void initStartStopButton();
|
||||||
void initDataStructures();
|
void initDataStructures();
|
||||||
|
|
||||||
void slowStartStopButtonCallback();
|
void slowStartStopButtonCallback();
|
||||||
|
|
||||||
|
void doPeriodicSlowCallback();
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
/*
|
|
||||||
* @file periodic_task.cpp
|
|
||||||
*
|
|
||||||
* @date: Jul 8, 2019
|
|
||||||
* @author Andrey Belomutskiy, (c) 2012-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "periodic_task.h"
|
|
||||||
#include "os_util.h"
|
|
||||||
#include "perf_trace.h"
|
|
||||||
|
|
||||||
void runAndScheduleNext(PeriodicTimerController *controller) {
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
{
|
|
||||||
ScopePerf perf(PE::PeriodicTimerControllerPeriodicTask);
|
|
||||||
controller->PeriodicTask();
|
|
||||||
}
|
|
||||||
|
|
||||||
chVTSetAny(&controller->timer, TIME_MS2I(controller->getPeriodMs()), (vtfunc_t) &runAndScheduleNext, controller);
|
|
||||||
#endif /* EFI_UNIT_TEST */
|
|
||||||
}
|
|
|
@ -1,46 +0,0 @@
|
||||||
/*
|
|
||||||
* @file periodic_task.h
|
|
||||||
*
|
|
||||||
* @date Jul 8, 2019
|
|
||||||
* @author Andrey Belomutskiy, (c) 2012-2020
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
class PeriodicTimerController;
|
|
||||||
|
|
||||||
void runAndScheduleNext(PeriodicTimerController *controller);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* this is an intermediate implementation - we should probably move from using virtual_timer_t which works on interrupts
|
|
||||||
* into sharing one thread with potentially lower priority instead
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PeriodicTimerController {
|
|
||||||
|
|
||||||
public:
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
virtual_timer_t timer;
|
|
||||||
#endif /* EFI_UNIT_TEST */
|
|
||||||
|
|
||||||
virtual void PeriodicTask() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is invoked after corresponding PeriodicTask() invocation
|
|
||||||
*/
|
|
||||||
virtual int getPeriodMs() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This invokes PeriodicTask() immediately and starts the cycle of invocations and sleeps
|
|
||||||
*/
|
|
||||||
virtual void start() {
|
|
||||||
#if !EFI_UNIT_TEST
|
|
||||||
chVTObjectInit(&timer);
|
|
||||||
#endif // EFI_UNIT_TEST
|
|
||||||
|
|
||||||
runAndScheduleNext(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ SYSTEMSRC_CPP = \
|
||||||
$(PROJECT_DIR)/controllers/system/efi_output.cpp \
|
$(PROJECT_DIR)/controllers/system/efi_output.cpp \
|
||||||
$(PROJECT_DIR)/controllers/system/injection_gpio.cpp \
|
$(PROJECT_DIR)/controllers/system/injection_gpio.cpp \
|
||||||
$(PROJECT_DIR)/controllers/system/efi_gpio.cpp \
|
$(PROJECT_DIR)/controllers/system/efi_gpio.cpp \
|
||||||
$(PROJECT_DIR)/controllers/system/periodic_task.cpp \
|
|
||||||
$(PROJECT_DIR)/controllers/system/dc_motor.cpp \
|
$(PROJECT_DIR)/controllers/system/dc_motor.cpp \
|
||||||
$(PROJECT_DIR)/controllers/system/timer/scheduler.cpp \
|
$(PROJECT_DIR)/controllers/system/timer/scheduler.cpp \
|
||||||
$(PROJECT_DIR)/controllers/system/timer/trigger_scheduler.cpp \
|
$(PROJECT_DIR)/controllers/system/timer/trigger_scheduler.cpp \
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// ADC and ETB get highest priority - not much else actually runs the engine
|
// Main loop gets highest priority - it does all the critical
|
||||||
#define PRIO_ADC (NORMALPRIO + 10)
|
// non-interrupt work to actually run the engine
|
||||||
#define PRIO_ETB (NORMALPRIO + 9)
|
#define PRIO_MAIN_LOOP (NORMALPRIO + 10)
|
||||||
|
|
||||||
// GPIO chips should be fast and go right back to sleep, plus can be timing sensitive
|
// GPIO chips should be fast and go right back to sleep, plus can be timing sensitive
|
||||||
#define PRIO_GPIOCHIP (NORMALPRIO + 8)
|
#define PRIO_GPIOCHIP (NORMALPRIO + 8)
|
||||||
|
|
|
@ -32,7 +32,7 @@ enum class PE : uint8_t {
|
||||||
SingleTimerExecutorDoExecute,
|
SingleTimerExecutorDoExecute,
|
||||||
SingleTimerExecutorScheduleTimerCallback,
|
SingleTimerExecutorScheduleTimerCallback,
|
||||||
PeriodicControllerPeriodicTask,
|
PeriodicControllerPeriodicTask,
|
||||||
PeriodicTimerControllerPeriodicTask,
|
MainLoop,
|
||||||
AdcCallbackFast,
|
AdcCallbackFast,
|
||||||
AdcProcessSlow,
|
AdcProcessSlow,
|
||||||
AdcConversionSlow,
|
AdcConversionSlow,
|
||||||
|
|
|
@ -264,36 +264,28 @@ void waitForSlowAdc(uint32_t lastAdcCounter) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SlowAdcController : public PeriodicController<256> {
|
void updateSlowAdc(efitick_t nowNt) {
|
||||||
public:
|
|
||||||
SlowAdcController()
|
|
||||||
: PeriodicController("ADC", PRIO_ADC, SLOW_ADC_RATE)
|
|
||||||
{
|
{
|
||||||
}
|
ScopePerf perf(PE::AdcConversionSlow);
|
||||||
|
|
||||||
void PeriodicTask(efitick_t nowNt) override {
|
if (!readSlowAnalogInputs(slowAdcSamples)) {
|
||||||
{
|
return;
|
||||||
ScopePerf perf(PE::AdcConversionSlow);
|
|
||||||
|
|
||||||
if (!readSlowAnalogInputs(slowAdcSamples)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ask the port to sample the MCU temperature
|
|
||||||
mcuTemperature = getMcuTemperature();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
// Ask the port to sample the MCU temperature
|
||||||
ScopePerf perf(PE::AdcProcessSlow);
|
mcuTemperature = getMcuTemperature();
|
||||||
|
|
||||||
slowAdcCounter++;
|
|
||||||
|
|
||||||
AdcSubscription::UpdateSubscribers(nowNt);
|
|
||||||
|
|
||||||
protectedGpio_check(nowNt);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
{
|
||||||
|
ScopePerf perf(PE::AdcProcessSlow);
|
||||||
|
|
||||||
|
slowAdcCounter++;
|
||||||
|
|
||||||
|
AdcSubscription::UpdateSubscribers(nowNt);
|
||||||
|
|
||||||
|
protectedGpio_check(nowNt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void addFastAdcChannel(const char* /*name*/, adc_channel_e setting) {
|
void addFastAdcChannel(const char* /*name*/, adc_channel_e setting) {
|
||||||
if (!isAdcChannelValid(setting)) {
|
if (!isAdcChannelValid(setting)) {
|
||||||
|
@ -319,8 +311,6 @@ void removeFastAdcChannel(const char *name, adc_channel_e setting) {
|
||||||
// Weak link a stub so that every board doesn't have to implement this function
|
// Weak link a stub so that every board doesn't have to implement this function
|
||||||
__attribute__((weak)) void setAdcChannelOverrides() { }
|
__attribute__((weak)) void setAdcChannelOverrides() { }
|
||||||
|
|
||||||
static CCM_OPTIONAL SlowAdcController slowAdcController;
|
|
||||||
|
|
||||||
void initAdcInputs() {
|
void initAdcInputs() {
|
||||||
efiPrintf("initAdcInputs()");
|
efiPrintf("initAdcInputs()");
|
||||||
|
|
||||||
|
@ -334,9 +324,6 @@ void initAdcInputs() {
|
||||||
#if EFI_INTERNAL_ADC
|
#if EFI_INTERNAL_ADC
|
||||||
portInitAdc();
|
portInitAdc();
|
||||||
|
|
||||||
// Start the slow ADC thread
|
|
||||||
slowAdcController.start();
|
|
||||||
|
|
||||||
#if EFI_USE_FAST_ADC
|
#if EFI_USE_FAST_ADC
|
||||||
fastAdc.init();
|
fastAdc.init();
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,6 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "adc_math.h"
|
#include "adc_math.h"
|
||||||
|
|
||||||
#ifndef SLOW_ADC_RATE
|
|
||||||
#define SLOW_ADC_RATE 500
|
|
||||||
#endif
|
|
||||||
|
|
||||||
float getAnalogInputDividerCoefficient(adc_channel_e);
|
float getAnalogInputDividerCoefficient(adc_channel_e);
|
||||||
|
|
||||||
inline bool isAdcChannelValid(adc_channel_e hwChannel) {
|
inline bool isAdcChannelValid(adc_channel_e hwChannel) {
|
||||||
|
@ -41,6 +37,7 @@ enum class AdcChannelMode : char {
|
||||||
};
|
};
|
||||||
|
|
||||||
void initAdcInputs();
|
void initAdcInputs();
|
||||||
|
void updateSlowAdc(efitick_t nowNt);
|
||||||
|
|
||||||
// deprecated - migrate to 'getAdcChannelBrainPin'
|
// deprecated - migrate to 'getAdcChannelBrainPin'
|
||||||
int getAdcChannelPin(adc_channel_e hwChannel);
|
int getAdcChannelPin(adc_channel_e hwChannel);
|
||||||
|
|
|
@ -94,7 +94,7 @@ TODO: this code is similar to initIfValid, what is the plan? shall we extract he
|
||||||
// Populate the entry
|
// Populate the entry
|
||||||
entry->VoltsPerAdcVolt = voltsPerAdcVolt;
|
entry->VoltsPerAdcVolt = voltsPerAdcVolt;
|
||||||
entry->Channel = channel;
|
entry->Channel = channel;
|
||||||
entry->Filter.configureLowpass(SLOW_ADC_RATE, lowpassCutoff);
|
entry->Filter.configureLowpass(hzForPeriod(ADC_UPDATE_RATE), lowpassCutoff);
|
||||||
entry->HasUpdated = false;
|
entry->HasUpdated = false;
|
||||||
|
|
||||||
// Set the sensor last - it's the field we use to determine whether this entry is in use
|
// Set the sensor last - it's the field we use to determine whether this entry is in use
|
||||||
|
|
|
@ -416,9 +416,6 @@ void initHardware() {
|
||||||
|
|
||||||
#if HAL_USE_ADC
|
#if HAL_USE_ADC
|
||||||
initAdcInputs();
|
initAdcInputs();
|
||||||
|
|
||||||
// wait for first set of ADC values so that we do not produce invalid sensor data
|
|
||||||
waitForSlowAdc(1);
|
|
||||||
#endif /* HAL_USE_ADC */
|
#endif /* HAL_USE_ADC */
|
||||||
|
|
||||||
#if EFI_SOFTWARE_KNOCK
|
#if EFI_SOFTWARE_KNOCK
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "thread_priority.h"
|
#include "thread_priority.h"
|
||||||
#include "tooth_logger.h"
|
#include "tooth_logger.h"
|
||||||
|
#include "main_loop.h"
|
||||||
|
|
||||||
#if EFI_UNIT_TEST
|
#if EFI_UNIT_TEST
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
|
@ -235,7 +235,7 @@ void runRusEfi() {
|
||||||
runRusEfiWithConfig();
|
runRusEfiWithConfig();
|
||||||
|
|
||||||
// periodic events need to be initialized after fuel&spark pins to avoid a warning
|
// periodic events need to be initialized after fuel&spark pins to avoid a warning
|
||||||
initPeriodicEvents();
|
initMainLoop();
|
||||||
|
|
||||||
runMainLoop();
|
runMainLoop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class EnumNames {
|
||||||
"SingleTimerExecutorDoExecute",
|
"SingleTimerExecutorDoExecute",
|
||||||
"SingleTimerExecutorScheduleTimerCallback",
|
"SingleTimerExecutorScheduleTimerCallback",
|
||||||
"PeriodicControllerPeriodicTask",
|
"PeriodicControllerPeriodicTask",
|
||||||
"PeriodicTimerControllerPeriodicTask",
|
"INVALID2",
|
||||||
"AdcCallbackFast",
|
"AdcCallbackFast",
|
||||||
"AdcProcessSlow",
|
"AdcProcessSlow",
|
||||||
"AdcConversionSlow",
|
"AdcConversionSlow",
|
||||||
|
|
|
@ -116,7 +116,7 @@ void rusEfiFunctionalTest(void) {
|
||||||
|
|
||||||
runChprintfTest();
|
runChprintfTest();
|
||||||
|
|
||||||
initPeriodicEvents();
|
initMainLoop();
|
||||||
|
|
||||||
setTriggerEmulatorRPM(DEFAULT_SIM_RPM);
|
setTriggerEmulatorRPM(DEFAULT_SIM_RPM);
|
||||||
engineConfiguration->engineSnifferRpmThreshold = DEFAULT_SNIFFER_THR;
|
engineConfiguration->engineSnifferRpmThreshold = DEFAULT_SNIFFER_THR;
|
||||||
|
|
Loading…
Reference in New Issue