FSIO testability and test-driven development

This commit is contained in:
rusefi 2019-01-19 22:09:37 -05:00
parent 1b0c46aaa7
commit 5b18f9f360
9 changed files with 76 additions and 30 deletions

View File

@ -111,10 +111,7 @@ void Engine::periodicSlowCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
checkShutdown();
#if EFI_FSIO || defined(__DOXYGEN__)
// todo: enable this for unit tests
#if ! EFI_UNIT_TEST
runFsio(PASS_ENGINE_PARAMETER_SIGNATURE);
#endif
#endif /* EFI_PROD_CODE && EFI_FSIO */
cylinderCleanupControl(PASS_ENGINE_PARAMETER_SIGNATURE);
@ -375,3 +372,9 @@ void Engine::periodicFastCallback(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
engine->m.fuelCalcTime = GET_TIMESTAMP() - engine->m.beforeFuelCalc;
}
void doScheduleStopEngine(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
engine->stopEngineRequestTimeNt = getTimeNowNt();
// let's close injectors or else if these happen to be open right now
enginePins.stopPins();
}

View File

@ -94,6 +94,9 @@ public:
* values are in Celsius
*/
float iat;
#if EFI_UNIT_TEST
float mockClt = NAN;
#endif
float clt;
/**
@ -310,6 +313,7 @@ public:
float fsioTimingAdjustment;
float fsioIdleTargetRPMAdjustment;
float servoValues[SERVO_COUNT];
float fsioLastValue[FSIO_COMMAND_COUNT];
#if EFI_ENABLE_ENGINE_WARNING
/**
@ -364,8 +368,6 @@ public:
FuelSchedule injectionEvents;
#endif /* EFI_ENGINE_CONTROL */
float fsioLastValue[FSIO_COMMAND_COUNT];
WallFuel wallFuel;
bool needToStopEngine(efitick_t nowNt);
bool etbAutoTune;
@ -592,5 +594,6 @@ void applyNonPersistentConfiguration(Logging * logger DECLARE_ENGINE_PARAMETER_S
void prepareOutputSignals(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void validateConfiguration(DECLARE_ENGINE_PARAMETER_SIGNATURE);
void doScheduleStopEngine(DECLARE_ENGINE_PARAMETER_SIGNATURE);
#endif /* H_ENGINE_H_ */

View File

@ -113,6 +113,11 @@ EngineState::EngineState() {
void EngineState::updateSlowSensors(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
engine->sensors.iat = getIntakeAirTemperature(PASS_ENGINE_PARAMETER_SIGNATURE);
engine->sensors.clt = getCoolantTemperature(PASS_ENGINE_PARAMETER_SIGNATURE);
#if EFI_UNIT_TEST
if (!cisnan(engine->sensors.mockClt)) {
engine->sensors.clt = engine->sensors.mockClt;
}
#endif
engine->sensors.oilPressure = getOilPressure(PASS_ENGINE_PARAMETER_SIGNATURE);
warmupTargetAfr = interpolate2d("warm", engine->sensors.clt, engineConfiguration->warmupTargetAfrBins,

View File

@ -26,9 +26,6 @@
*/
#define NO_PWM 0
#define MAGIC_OFFSET_FOR_ENGINE_WARNING 4
#define MAGIC_OFFSET_FOR_CRITICAL_ENGINE 5
// see useFSIO15ForIdleRpmAdjustment
#define MAGIC_OFFSET_FOR_IDLE_TARGET_RPM 14
// see useFSIO16ForTimingAdjustment
@ -322,7 +319,7 @@ float getFsioOutputValue(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
warning(CUSTOM_NO_FSIO, "no FSIO for #%d %s", index + 1, hwPortname(CONFIGB(fsioOutputPins)[index]));
return NAN;
} else {
return calc.getValue2(engine->fsioLastValue[index], state.fsioLogics[index] PASS_ENGINE_PARAMETER_SUFFIX);
return calc.getValue2(engine->fsioState.fsioLastValue[index], state.fsioLogics[index] PASS_ENGINE_PARAMETER_SUFFIX);
}
}
@ -331,14 +328,14 @@ float getFsioOutputValue(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
*/
static void handleFsio(int index DECLARE_ENGINE_PARAMETER_SUFFIX) {
if (CONFIGB(fsioOutputPins)[index] == GPIO_UNASSIGNED) {
engine->fsioLastValue[index] = NAN;
engine->fsioState.fsioLastValue[index] = NAN;
return;
}
bool isPwmMode = CONFIGB(fsioFrequency)[index] != NO_PWM;
float fvalue = getFsioOutputValue(index PASS_ENGINE_PARAMETER_SUFFIX);
engine->fsioLastValue[index] = fvalue;
engine->fsioState.fsioLastValue[index] = fvalue;
if (isPwmMode) {
fsioPwm[index].setSimplePwmDutyCycle(fvalue);
@ -495,9 +492,7 @@ void runFsio(DECLARE_ENGINE_PARAMETER_SIGNATURE) {
if (engineConfiguration->useFSIO5ForCriticalIssueEngineStop) {
bool changed = updateValueOrWarning(MAGIC_OFFSET_FOR_CRITICAL_ENGINE, "eng critical", &ENGINE(fsioState.isCriticalEngineCondition) PASS_ENGINE_PARAMETER_SUFFIX);
if (changed && float2bool(ENGINE(fsioState.isCriticalEngineCondition))) {
#if EFI_PROD_CODE || EFI_SIMULATOR
scheduleStopEngine();
#endif
doScheduleStopEngine(PASS_ENGINE_PARAMETER_SIGNATURE);
}
}
#endif /* EFI_ENABLE_CRITICAL_ENGINE_STOP */
@ -569,7 +564,7 @@ static void showFsioInfo(void) {
*/
scheduleMsg(logger, "FSIO #%d [%s] at %s@%dHz value=%.2f", (i + 1), exp,
hwPortname(CONFIGB(fsioOutputPins)[i]), CONFIGB(fsioFrequency)[i],
engine->fsioLastValue[i]);
engine->fsioState.fsioLastValue[i]);
// scheduleMsg(logger, "user-defined #%d value=%.2f", i, engine->engineConfigurationPtr2->fsioLastValue[i]);
showFsio(NULL, state.fsioLogics[i]);
}

View File

@ -17,6 +17,8 @@
typedef Map3D<FSIO_TABLE_8, FSIO_TABLE_8, float> fsio8_Map3D_f32t;
typedef Map3D<FSIO_TABLE_8, FSIO_TABLE_8, uint8_t> fsio8_Map3D_u8t;
#define MAGIC_OFFSET_FOR_ENGINE_WARNING 4
#define MAGIC_OFFSET_FOR_CRITICAL_ENGINE 5
float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX);
void setFsio(int index, brain_pin_e pin, const char * exp DECLARE_ENGINE_PARAMETER_SUFFIX);

View File

@ -975,9 +975,7 @@ static void disableSpi(int index) {
* weird: we stop pins from here? we probably should stop engine from the code which is actually stopping engine?
*/
void scheduleStopEngine(void) {
engine->stopEngineRequestTimeNt = getTimeNowNt();
// let's close injectors or else if these happen to be open right now
enginePins.stopPins();
doScheduleStopEngine(PASS_ENGINE_PARAMETER_SIGNATURE);
}
static void printAllInfo(void) {

View File

@ -22,6 +22,9 @@
// Human-readable: vbatt < 14.5
#define ALTERNATOR_LOGIC "vbatt 14.5 <"
// Human-readable: coolant > 120 (Celsius)
#define TOO_HOT_LOGIC "coolant 120 >"
// Human-readable: ac_on_switch
#define AC_RELAY_LOGIC "ac_on_switch"
// Combined RPM, CLT and VBATT warning light

View File

@ -8,12 +8,12 @@
#include "engine_test_helper.h"
#include "event_queue.h"
#include "tps.h"
#include "fsio_impl.h"
TEST(fuelCut, coasting) {
printf("*************************************************** testCoastingFuelCut\r\n");
EngineTestHelper eth(TEST_ENGINE);
EXPAND_EngineTestHelper
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
// configure coastingFuelCut
engineConfiguration->bc.coastingFuelCutEnabled = true;
@ -95,3 +95,30 @@ TEST(fuelCut, coasting) {
// Fuel cut-off is active again!
assertEqualsM("inj dur#7 cut", 0.0f, ENGINE(injectionDuration));
}
TEST(fuelCut, criticalEngineTemperature) {
WITH_ENGINE_TEST_HELPER(TEST_ENGINE);
setupSimpleTestEngineWithMafAndTT_ONE_trigger(&eth);
engineConfiguration->useFSIO5ForCriticalIssueEngineStop = true;
setFsio(MAGIC_OFFSET_FOR_CRITICAL_ENGINE, GPIOD_7, TOO_HOT_LOGIC PASS_ENGINE_PARAMETER_SUFFIX);
applyFsioConfiguration(PASS_ENGINE_PARAMETER_SIGNATURE);
// we need some non-zero time as getTimeNow() which would become stopEngineRequestTimeNt
eth.moveTimeForwardUs(1000);
engine->rpmCalculator.mockRpm = 2000;
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
eth.engine.periodicSlowCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
ASSERT_EQ(engine->stopEngineRequestTimeNt, 0);
ASSERT_FALSE(engine->stopEngineRequestTimeNt > 0);
engine->sensors.mockClt = 200; // 200C is really hot!
eth.engine.periodicFastCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
eth.engine.periodicSlowCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
ASSERT_TRUE(engine->stopEngineRequestTimeNt > 0);
}

View File

@ -14,7 +14,6 @@
#define TEST_POOL_SIZE 256
static float mockCoolant;
static float mockFan;
static float mockRpm;
static float mockCrankingRpm;
@ -25,7 +24,7 @@ float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX) {
case LE_METHOD_FAN:
return mockFan;
case LE_METHOD_COOLANT:
return mockCoolant;
return engine->sensors.clt;
case LE_METHOD_RPM:
return mockRpm;
case LE_METHOD_CRANKING_RPM:
@ -36,6 +35,8 @@ float getEngineValue(le_action_e action DECLARE_ENGINE_PARAMETER_SUFFIX) {
return 0;
case LE_METHOD_FAN_OFF_SETTING:
return 0;
case LE_METHOD_VBATT:
return 12;
default:
firmwareError(OBD_PCM_Processor_Fault, "No mock value for %d", action);
return NAN;
@ -87,7 +88,7 @@ static void testParsing(void) {
ASSERT_TRUE(element == NULL);
}
static void testExpression2(float selfValue, const char *line, float expected) {
static void testExpression2(float selfValue, const char *line, float expected, Engine *engine) {
LEElement thepool[TEST_POOL_SIZE];
LEElementPool pool(thepool, TEST_POOL_SIZE);
LEElement * element = pool.parseExpression(line);
@ -95,9 +96,14 @@ static void testExpression2(float selfValue, const char *line, float expected) {
ASSERT_TRUE(element != NULL) << "Not NULL expected";
LECalculator c;
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
EXPAND_Engine;
assertEqualsM(line, expected, c.getValue2(selfValue, element PASS_ENGINE_PARAMETER_SUFFIX));
ASSERT_EQ(expected, c.getValue2(selfValue, element PASS_ENGINE_PARAMETER_SUFFIX)) << line;
}
static void testExpression2(float selfValue, const char *line, float expected) {
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
testExpression2(selfValue, line, expected, engine);
}
static void testExpression(const char *line, float expected) {
@ -108,6 +114,7 @@ TEST(misc, testLogicExpressions) {
printf("*************************************************** testLogicExpressions\r\n");
testParsing();
{
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
@ -163,17 +170,20 @@ TEST(misc, testLogicExpressions) {
element = pool.parseExpression("fan no_such_method");
ASSERT_TRUE(element == NULL) << "NULL expected";
}
/**
* fan = (not fan && coolant > 90) OR (fan && coolant > 85)
* fan = fan NOT coolant 90 AND more fan coolant 85 more AND OR
*/
mockFan = 0;
mockCoolant = 100;
testExpression("coolant", 100);
{
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
engine->sensors.mockClt = 100;
engine->periodicSlowCallback(PASS_ENGINE_PARAMETER_SIGNATURE);
testExpression2(0, "coolant 1 +", 101, engine);
}
testExpression("fan", 0);
testExpression("fan not", 1);
testExpression("coolant 90 >", 1);
@ -186,6 +196,7 @@ TEST(misc, testLogicExpressions) {
testExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR", 1);
{
WITH_ENGINE_TEST_HELPER(FORD_INLINE_6_1995);
LEElement thepool[TEST_POOL_SIZE];
LEElementPool pool(thepool, TEST_POOL_SIZE);
LEElement * element = pool.parseExpression("fan NOT coolant 90 > AND fan coolant 85 > AND OR");
@ -198,7 +209,6 @@ TEST(misc, testLogicExpressions) {
ASSERT_EQ(0, c.calcLogValue[0]);
}
testExpression("coolant", 100);
testExpression("fan_off_setting", 0);
testExpression("coolant fan_off_setting >", 1);