rusefi-1/firmware/controllers/bench_test.cpp

417 lines
11 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
* @file bench_test.cpp
* @brief Utility methods related to bench testing.
2015-07-10 06:01:56 -07:00
*
*
* @date Sep 8, 2013
2020-01-13 18:57:43 -08:00
* @author Andrey Belomutskiy, (c) 2012-2020
2015-07-10 06:01:56 -07:00
*
* This file is part of rusEfi - see http://rusefi.com
*
* rusEfi is free software; you can redistribute it and/or modify it under the terms of
* the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* rusEfi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
// todo: rename this file
2018-09-16 19:26:57 -07:00
#include "global.h"
2015-07-10 06:01:56 -07:00
2019-04-12 19:07:03 -07:00
#if EFI_ENGINE_CONTROL
#if !EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
#include "os_access.h"
#include "flash_main.h"
#include "bench_test.h"
2015-07-10 06:01:56 -07:00
#include "io_pins.h"
#include "main_trigger_callback.h"
#include "engine_configuration.h"
#include "pin_repository.h"
2019-03-29 06:11:13 -07:00
#include "efi_gpio.h"
2017-07-25 19:00:39 -07:00
#include "settings.h"
2019-01-13 16:41:39 -08:00
#include "idle_thread.h"
#include "periodic_thread_controller.h"
2019-04-29 22:21:09 -07:00
#include "tps.h"
#include "electronic_throttle.h"
2020-03-24 16:50:04 -07:00
#include "cj125.h"
#include "malfunction_central.h"
2020-07-26 15:34:47 -07:00
#include "tunerstudio_outputs.h"
2019-09-05 07:30:27 -07:00
#if EFI_PROD_CODE
#include "rusefi.h"
2019-08-03 16:58:38 -07:00
#include "mpu_util.h"
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
2019-09-05 07:30:27 -07:00
#if (BOARD_TLE8888_COUNT > 0)
#include "gpio/tle8888.h"
#endif
EXTERN_ENGINE;
2015-07-10 06:01:56 -07:00
2016-03-14 20:01:43 -07:00
static Logging * logger;
2016-01-11 14:01:33 -08:00
static bool isRunningBench = false;
2015-07-10 06:01:56 -07:00
2016-01-11 14:01:33 -08:00
bool isRunningBenchTest(void) {
2015-07-10 06:01:56 -07:00
return isRunningBench;
}
static void runBench(brain_pin_e brainPin, OutputPin *output, float delayMs, float onTimeMs, float offTimeMs,
int count) {
2019-01-28 17:00:17 -08:00
int delaySt = delayMs < 1 ? 1 : TIME_MS2I(delayMs);
int onTimeSt = onTimeMs < 1 ? 1 : TIME_MS2I(onTimeMs);
int offTimeSt = offTimeMs < 1 ? 1 : TIME_MS2I(offTimeMs);
2015-07-10 06:01:56 -07:00
if (delaySt < 0) {
2018-01-23 09:05:14 -08:00
scheduleMsg(logger, "Invalid delay %.2f", delayMs);
2015-07-10 06:01:56 -07:00
return;
}
if (onTimeSt <= 0) {
2018-01-23 09:05:14 -08:00
scheduleMsg(logger, "Invalid onTime %.2f", onTimeMs);
2015-07-10 06:01:56 -07:00
return;
}
if (offTimeSt <= 0) {
2018-01-23 09:05:14 -08:00
scheduleMsg(logger, "Invalid offTime %.2f", offTimeMs);
2015-07-10 06:01:56 -07:00
return;
}
2018-01-23 09:05:14 -08:00
scheduleMsg(logger, "Running bench: ON_TIME=%.2f ms OFF_TIME=%.2fms Counter=%d", onTimeMs, offTimeMs, count);
2016-03-14 20:01:43 -07:00
scheduleMsg(logger, "output on %s", hwPortname(brainPin));
2015-07-10 06:01:56 -07:00
if (delaySt != 0) {
chThdSleep(delaySt);
}
isRunningBench = true;
for (int i = 0; i < count; i++) {
output->setValue(true);
chThdSleep(onTimeSt);
output->setValue(false);
chThdSleep(offTimeSt);
}
2016-03-14 20:01:43 -07:00
scheduleMsg(logger, "Done!");
2015-07-10 06:01:56 -07:00
isRunningBench = false;
}
2017-07-24 16:38:00 -07:00
static volatile bool isBenchTestPending = false;
2015-07-10 06:01:56 -07:00
static float onTime;
static float offTime;
static float delayMs;
static int count;
static brain_pin_e brainPin;
static OutputPin* pinX;
static void pinbench(const char *delayStr, const char *onTimeStr, const char *offTimeStr, const char *countStr,
OutputPin* pinParam, brain_pin_e brainPinParam) {
delayMs = atoff(delayStr);
onTime = atoff(onTimeStr);
offTime = atoff(offTimeStr);
count = atoi(countStr);
brainPin = brainPinParam;
pinX = pinParam;
2017-07-24 17:40:01 -07:00
isBenchTestPending = true; // let's signal bench thread to wake up
2015-07-10 06:01:56 -07:00
}
2016-03-14 21:01:37 -07:00
static void doRunFuel(int humanIndex, const char *delayStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
if (humanIndex < 1 || humanIndex > engineConfiguration->specs.cylindersCount) {
scheduleMsg(logger, "Invalid index: %d", humanIndex);
return;
}
brain_pin_e b = CONFIG(injectionPins)[humanIndex - 1];
2016-03-14 21:01:37 -07:00
pinbench(delayStr, onTimeStr, offTimeStr, countStr, &enginePins.injectors[humanIndex - 1], b);
}
static void doBenchTestFsio(int humanIndex, const char *delayStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
if (humanIndex < 1 || humanIndex > FSIO_COMMAND_COUNT) {
scheduleMsg(logger, "Invalid index: %d", humanIndex);
return;
}
brain_pin_e b = CONFIG(fsioOutputPins)[humanIndex - 1];
pinbench(delayStr, onTimeStr, offTimeStr, countStr, &enginePins.fsioOutputs[humanIndex - 1], b);
}
2015-07-10 06:01:56 -07:00
/**
* delay 100, cylinder #2, 5ms ON, 1000ms OFF, repeat 3 times
* fuelbench2 100 2 5 1000 3
2015-07-10 06:01:56 -07:00
*/
static void fuelbench2(const char *delayStr, const char *indexStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
int index = atoi(indexStr);
2016-03-14 21:01:37 -07:00
doRunFuel(index, delayStr, onTimeStr, offTimeStr, countStr);
2015-07-10 06:01:56 -07:00
}
/**
* delay 100, channel #1, 5ms ON, 1000ms OFF, repeat 3 times
* fsiobench2 100 1 5 1000 3
*/
static void fsioBench2(const char *delayStr, const char *indexStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
int index = atoi(indexStr);
doBenchTestFsio(index, delayStr, onTimeStr, offTimeStr, countStr);
}
2017-07-24 17:40:01 -07:00
static void fanBenchExt(const char *durationMs) {
pinbench("0", durationMs, "100", "1", &enginePins.fanRelay, CONFIG(fanPin));
2017-07-24 17:40:01 -07:00
}
2015-07-10 06:01:56 -07:00
void fanBench(void) {
2017-07-24 17:40:01 -07:00
fanBenchExt("3000");
2015-07-10 06:01:56 -07:00
}
2019-01-13 16:41:39 -08:00
/**
* we are blinking for 16 seconds so that one can click the button and walk around to see the light blinking
*/
2015-07-10 06:01:56 -07:00
void milBench(void) {
pinbench("0", "500", "500", "16", &enginePins.checkEnginePin, CONFIG(malfunctionIndicatorPin));
2015-07-10 06:01:56 -07:00
}
2020-03-29 14:21:17 -07:00
void starterRelayBench(void) {
pinbench("0", "6000", "100", "1", &enginePins.starterControl, CONFIG(starterControlPin));
}
2016-01-07 18:02:35 -08:00
void fuelPumpBenchExt(const char *durationMs) {
pinbench("0", durationMs, "100", "1", &enginePins.fuelPumpRelay, CONFIG(fuelPumpPin));
2016-01-07 18:02:35 -08:00
}
2019-09-14 14:56:17 -07:00
void acRelayBench(void) {
pinbench("0", "1000", "100", "1", &enginePins.acRelay, CONFIG(acRelayPin));
2019-09-14 14:56:17 -07:00
}
void mainRelayBench(void) {
pinbench("0", "1000", "100", "1", &enginePins.mainRelay, CONFIG(mainRelayPin));
}
2020-11-21 21:09:36 -08:00
void hpfpValveBench(void) {
2020-11-22 09:43:28 -08:00
pinbench(/*delay*/"1000", /* onTime */"20", /*oftime*/"500", "3", &enginePins.hpfpValve, CONFIG(hpfpValvePin));
2020-11-21 21:09:36 -08:00
}
2015-07-10 06:01:56 -07:00
void fuelPumpBench(void) {
2016-01-07 18:02:35 -08:00
fuelPumpBenchExt("3000");
2015-07-10 06:01:56 -07:00
}
// fuelbench 5 1000 2
static void fuelbench(const char * onTimeStr, const char *offTimeStr, const char *countStr) {
fuelbench2("0", "1", onTimeStr, offTimeStr, countStr);
}
2016-03-14 21:01:37 -07:00
static void doRunSpark(int humanIndex, const char *delayStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
if (humanIndex < 1 || humanIndex > engineConfiguration->specs.cylindersCount) {
scheduleMsg(logger, "Invalid index: %d", humanIndex);
return;
}
brain_pin_e b = CONFIG(ignitionPins)[humanIndex - 1];
2016-03-14 21:01:37 -07:00
pinbench(delayStr, onTimeStr, offTimeStr, countStr, &enginePins.coils[humanIndex - 1], b);
}
2015-07-10 06:01:56 -07:00
/**
* sparkbench2 0 1 5 1000 2
*/
static void sparkbench2(const char *delayStr, const char *indexStr, const char * onTimeStr, const char *offTimeStr,
const char *countStr) {
int index = atoi(indexStr);
2016-03-14 21:01:37 -07:00
doRunSpark(index, delayStr, onTimeStr, offTimeStr, countStr);
2015-07-10 06:01:56 -07:00
}
/**
* sparkbench 5 400 2
* 5 ms ON, 400 ms OFF, two times
*/
static void sparkbench(const char * onTimeStr, const char *offTimeStr, const char *countStr) {
sparkbench2("0", "1", onTimeStr, offTimeStr, countStr);
}
2019-02-10 20:54:41 -08:00
class BenchController : public PeriodicController<UTILITY_THREAD_STACK_SIZE> {
public:
2019-02-11 12:09:24 -08:00
BenchController() : PeriodicController("BenchThread") { }
2019-02-10 20:54:41 -08:00
private:
void PeriodicTask(efitick_t nowNt) override {
UNUSED(nowNt);
2019-04-25 15:49:16 -07:00
setPeriod(50 /* ms */);
2017-04-24 19:35:16 -07:00
validateStack("Bench", STACK_USAGE_BENCH, 128);
2017-07-24 16:38:00 -07:00
// naive inter-thread communication - waiting for a flag
2019-02-10 20:54:41 -08:00
if (isBenchTestPending) {
isBenchTestPending = false;
runBench(brainPin, pinX, delayMs, onTime, offTime, count);
2015-07-10 06:01:56 -07:00
}
}
2019-02-10 20:54:41 -08:00
};
static BenchController instance;
2015-07-10 06:01:56 -07:00
static void handleBenchCategory(uint16_t index) {
switch(index) {
case CMD_TS_BENCH_MAIN_RELAY:
mainRelayBench();
return;
2020-11-21 21:13:55 -08:00
case CMD_TS_BENCH_HPFP_VALVE:
hpfpValveBench();
return;
case CMD_TS_BENCH_FUEL_PUMP:
// cmd_test_fuel_pump
fuelPumpBench();
return;
case CMD_TS_BENCH_STARTER_ENABLE_RELAY:
starterRelayBench();
return;
case CMD_TS_BENCH_CHECK_ENGINE_LIGHT:
// cmd_test_check_engine_light
milBench();
return;
case CMD_TS_BENCH_AC_COMPRESSOR_RELAY:
acRelayBench();
return;
}
}
2019-04-23 20:20:14 -07:00
static void handleCommandX14(uint16_t index) {
switch (index) {
2019-04-29 22:21:09 -07:00
case 2:
grabTPSIsClosed();
return;
case 3:
grabTPSIsWideOpen();
return;
2019-09-05 07:30:27 -07:00
// case 4: tps2_closed
// case 5: tps2_wot
case 6:
2019-04-30 15:46:39 -07:00
grabPedalIsUp();
return;
2019-09-05 07:30:27 -07:00
case 7:
2019-04-30 15:46:39 -07:00
grabPedalIsWideOpen();
return;
2019-09-05 07:30:27 -07:00
case 8:
#if (BOARD_TLE8888_COUNT > 0)
Tle8888 big update 1 (#1892) * smart gpio: fix tle8888 direct pin mapping for MRE * MRE: use TLE8888 pins instead of MCU gpios that drives TLE8888 * TLE8888: cleanup * TLE8888: do not reset driver private data on WD/undervoltage reset * TLE8888: diagnostic updates * TLE8888 driver: BIG driver rework * TLE8888: check SPI answers for abnormal states Reply with other than requested register can be a sign of: -Power-On-Reset, then OpStat0 will be replyed -WatchDog reset, then FWDStat1 will be replyed -Invalid communication frame, then Diag0 will be replyed Keep tracking last accessed register and check with the next reply. * TLE8888: debug clean-up * TLE8888: implement spi array write This reduce CS inactive state time between two consequent accesses from 8.8 uS to 1.4 uS * TLE8888: fix PP outputs in OD mode * TLE8888: cleanup register definitions * TLE8888: run separate driver thread for each chip instance Calculating poll interval for few chips become more complex, avoid this running thread for each device. * TLE8888: fix cypress and kinetic compilation Both platforms define its own MAX and cause redifination error if common.h is included in driver. * MRE: update mapping.yaml and fix direct pin mapping for TLE8888 * TLE8888: diagnnostic: disable switch off in case of overcurrent For all output, use current limiting instead * TLE8888: check for overvoltage on OUT8..OUT13 * TLE8888: add TODO note about how to recover from failure condition Currently TLE8888 automaticly recovers only from overcurrent and (may be) overtemperature conditions. Short to bat cause output disable (bit in OECONFIG is reset) and needs driver/host intervention. * TLE8888: save few bytes of RAM * TLE8888: Lada Kalina is test mule for IDLE stepper on TLE8888 Don't forget to enable PP mode for TLE8888 outputs 21..24: uncomment line 1087 in tle8888.c * TLE8888: reorder code, cleanup * TLE8888: mode all debug/statisctic to per-chip struct * TLE8888: rework poll interval calculation * MRE: use TLE8888 pins instead of MCU gpios that drives TLE8888 #2
2020-10-23 09:25:30 -07:00
tle8888_req_init();
2019-09-05 07:30:27 -07:00
#endif
return;
2020-03-29 14:21:17 -07:00
case 0xA:
// cmd_write_config
#if EFI_INTERNAL_FLASH
writeToFlashNow();
#endif /* EFI_INTERNAL_FLASH */
return;
case 0xD:
engine->directSelfStimulation = true;
return;
#if EFI_ELECTRONIC_THROTTLE_BODY
case 0xE:
etbAutocal(0);
return;
case 0x11:
etbAutocal(1);
return;
case 0xC:
engine->etbAutoTune = true;
return;
case 0x10:
engine->etbAutoTune = false;
2020-07-26 15:24:02 -07:00
#if EFI_TUNER_STUDIO
2020-07-26 15:39:26 -07:00
tsOutputChannels.calibrationMode = TsCalMode::None;
2020-07-26 15:24:02 -07:00
#endif // EFI_TUNER_STUDIO
return;
#endif
2020-05-01 16:42:09 -07:00
case 0xF:
engine->directSelfStimulation = false;
return;
2019-04-23 20:20:14 -07:00
}
}
extern bool rebootForPresetPending;
static void fatalErrorForPresetApply() {
rebootForPresetPending = true;
firmwareError(OBD_PCM_Processor_Fault,
"\n\nTo complete preset apply:\n"
" 1. Close TunerStudio\n"
" 2. Power cycle ECU\n"
" 3. Open TunerStudio and reconnect\n\n");
}
2019-04-23 20:20:14 -07:00
// todo: this is probably a wrong place for this method now
2019-03-12 17:33:13 -07:00
void executeTSCommand(uint16_t subsystem, uint16_t index) {
2016-03-14 20:01:43 -07:00
scheduleMsg(logger, "IO test subsystem=%d index=%d", subsystem, index);
bool running = !ENGINE(rpmCalculator).isStopped();
2020-03-24 16:21:20 -07:00
if (subsystem == 0x11) {
clearWarnings();
} else if (subsystem == CMD_TS_IGNITION_CATEGORY && !running) {
2016-03-14 21:01:37 -07:00
doRunSpark(index, "300", "4", "400", "3");
} else if (subsystem == CMD_TS_INJECTOR_CATEGORY && !running) {
2016-03-15 10:01:47 -07:00
doRunFuel(index, "300", "4", "400", "3");
} else if (subsystem == CMD_TS_FSIO_CATEGORY && !running) {
doBenchTestFsio(index, "300", "4", "400", "3");
2016-03-15 10:01:47 -07:00
} else if (subsystem == 0x14) {
2019-04-23 20:20:14 -07:00
handleCommandX14(index);
2016-03-15 10:01:47 -07:00
} else if (subsystem == 0x15) {
fanBench();
} else if (subsystem == CMD_TS_BENCH_CATEGORY) {
handleBenchCategory(index);
2016-03-15 10:01:47 -07:00
} else if (subsystem == 0x17) {
2019-01-13 16:41:39 -08:00
// cmd_test_idle_valve
2019-04-12 19:07:03 -07:00
#if EFI_IDLE_CONTROL
2019-01-13 16:41:39 -08:00
startIdleBench();
2020-03-24 16:50:04 -07:00
#endif /* EFI_IDLE_CONTROL */
2020-03-24 16:21:20 -07:00
} else if (subsystem == 0x18) {
2020-04-08 20:14:21 -07:00
#if EFI_CJ125 && HAL_USE_SPI
2020-05-01 17:22:49 -07:00
cjStartCalibration();
2020-03-24 16:50:04 -07:00
#endif /* EFI_CJ125 */
2017-05-01 19:33:20 -07:00
} else if (subsystem == 0x20 && index == 0x3456) {
2017-07-25 19:00:39 -07:00
// call to pit
setCallFromPitStop(30000);
2019-01-20 19:17:06 -08:00
} else if (subsystem == 0x30) {
fatalErrorForPresetApply();
2019-01-20 19:17:06 -08:00
setEngineType(index);
2019-03-12 17:33:13 -07:00
} else if (subsystem == 0x31) {
fatalErrorForPresetApply();
2019-03-12 17:33:13 -07:00
setEngineType(DEFAULT_ENGINE_TYPE);
2019-03-12 11:35:49 -07:00
} else if (subsystem == 0x79) {
2019-01-05 20:33:04 -08:00
scheduleStopEngine();
} else if (subsystem == 0xba) {
#if EFI_PROD_CODE
jump_to_bootloader();
#endif /* EFI_PROD_CODE */
} else if (subsystem == 0xbb) {
2019-06-23 06:46:14 -07:00
#if EFI_PROD_CODE
rebootNow();
#endif /* EFI_PROD_CODE */
2016-03-14 21:01:37 -07:00
}
2016-03-14 20:01:43 -07:00
}
void initBenchTest(Logging *sharedLogger) {
2016-03-14 20:01:43 -07:00
logger = sharedLogger;
2015-07-10 06:01:56 -07:00
addConsoleAction("fuelpumpbench", fuelPumpBench);
2019-09-14 14:56:17 -07:00
addConsoleAction("acrelaybench", acRelayBench);
2016-01-07 18:02:35 -08:00
addConsoleActionS("fuelpumpbench2", fuelPumpBenchExt);
2015-07-10 06:01:56 -07:00
addConsoleAction("fanbench", fanBench);
2017-07-24 17:40:01 -07:00
addConsoleActionS("fanbench2", fanBenchExt);
2015-07-10 06:01:56 -07:00
2020-08-19 18:05:08 -07:00
addConsoleAction(CMD_STARTER_BENCH, starterRelayBench);
addConsoleAction(CMD_MIL_BENCH, milBench);
addConsoleActionSSS(CMD_FUEL_BENCH, fuelbench);
2015-07-10 06:01:56 -07:00
addConsoleActionSSS("sparkbench", sparkbench);
2020-11-21 21:47:43 -08:00
addConsoleAction(CMD_HPFP_BENCH, hpfpValveBench);
2015-07-10 06:01:56 -07:00
addConsoleActionSSSSS("fuelbench2", fuelbench2);
addConsoleActionSSSSS("fsiobench2", fsioBench2);
2015-07-10 06:01:56 -07:00
addConsoleActionSSSSS("sparkbench2", sparkbench2);
2019-02-10 20:54:41 -08:00
instance.setPeriod(200 /*ms*/);
instance.Start();
2015-07-10 06:01:56 -07:00
}
#endif /* EFI_UNIT_TEST */
2015-07-10 06:01:56 -07:00
#endif