rusefi-1/firmware/development/engine_sniffer.cpp

259 lines
6.6 KiB
C++
Raw Normal View History

2015-07-10 06:01:56 -07:00
/**
2015-07-15 18:01:45 -07:00
* @file engine_sniffer.cpp
2019-05-02 14:52:48 -07:00
* @brief rusEfi console wave sniffer logic
2015-07-10 06:01:56 -07:00
*
* Here we have our own build-in logic analyzer. The data we aggregate here is sent to the
2019-05-02 14:52:48 -07:00
* java UI rusEfi Console so that it can be displayed nicely in the Sniffer tab.
2015-07-10 06:01:56 -07:00
*
* Both external events (see logic_analyzer.cpp) and internal (see signal executors) are supported
2015-07-10 06:01:56 -07:00
*
* @date Jun 23, 2013
2020-01-07 21:02:40 -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/>.
*/
2018-09-16 19:26:57 -07:00
#include "global.h"
#include "os_access.h"
2015-07-15 18:01:45 -07:00
#include "engine_sniffer.h"
2017-11-24 14:40:20 -08:00
#include "adc_inputs.h"
2016-01-22 23:01:34 -08:00
2019-04-12 19:10:57 -07:00
#if EFI_ENGINE_SNIFFER
2015-07-10 06:01:56 -07:00
#include "engine_configuration.h"
#include "eficonsole.h"
#include "status_loop.h"
#include "perf_trace.h"
2015-07-10 06:01:56 -07:00
#define CHART_DELIMETER '!'
EXTERN_ENGINE;
2017-05-21 07:26:51 -07:00
extern uint32_t maxLockedDuration;
2015-07-10 06:01:56 -07:00
/**
* This is the number of events in the digital chart which would be displayed
* on the 'digital sniffer' pane
*/
#if EFI_PROD_CODE
#define WAVE_LOGGING_SIZE 5000
#else
#define WAVE_LOGGING_SIZE 35000
#endif
static char WAVE_LOGGING_BUFFER[WAVE_LOGGING_SIZE] CCM_OPTIONAL;
2015-07-10 06:01:56 -07:00
int waveChartUsedSize;
//#define DEBUG_WAVE 1
#if DEBUG_WAVE
static Logging debugLogging;
#endif /* DEBUG_WAVE */
static LoggingWithStorage logger("wave info");
/**
* We want to skip some engine cycles to skip what was scheduled before parameters were changed
*/
2015-07-14 06:01:29 -07:00
static uint32_t skipUntilEngineCycle = 0;
2015-07-10 06:01:56 -07:00
2019-04-12 19:10:57 -07:00
#if ! EFI_UNIT_TEST
2015-07-10 06:01:56 -07:00
extern WaveChart waveChart;
2016-01-30 19:03:36 -08:00
static void resetNow(void) {
skipUntilEngineCycle = getRevolutionCounter() + 3;
2016-01-30 19:03:36 -08:00
waveChart.reset();
2015-07-10 06:01:56 -07:00
}
#endif
WaveChart::WaveChart() {
}
void WaveChart::init() {
logging.initLoggingExt("wave chart", WAVE_LOGGING_BUFFER, sizeof(WAVE_LOGGING_BUFFER));
isInitialized = true;
reset();
}
2016-01-30 19:03:36 -08:00
void WaveChart::reset() {
2015-07-10 06:01:56 -07:00
#if DEBUG_WAVE
scheduleSimpleMsg(&debugLogging, "reset while at ", counter);
#endif /* DEBUG_WAVE */
resetLogging(&logging);
counter = 0;
startTimeNt = 0;
collectingData = false;
2019-07-05 16:40:12 -07:00
appendPrintf(&logging, "%s%s", PROTOCOL_ENGINE_SNIFFER, DELIMETER);
2015-07-10 06:01:56 -07:00
}
void WaveChart::startDataCollection() {
collectingData = true;
}
2015-07-10 06:01:56 -07:00
bool WaveChart::isStartedTooLongAgo() const {
2015-07-10 06:01:56 -07:00
/**
* Say at 300rpm we should get at least four events per revolution.
* That's 300/60*4=20 events per second
* engineChartSize/20 is the longest meaningful chart.
*
*/
efitick_t chartDurationNt = getTimeNowNt() - startTimeNt;
2015-07-10 06:01:56 -07:00
return startTimeNt != 0 && NT2US(chartDurationNt) > engineConfiguration->engineChartSize * 1000000 / 20;
}
bool WaveChart::isFull() const {
2017-05-25 19:44:57 -07:00
return counter >= CONFIG(engineChartSize);
2015-07-10 06:01:56 -07:00
}
static void printStatus(void) {
scheduleMsg(&logger, "engine chart: %s", boolToString(engineConfiguration->isEngineChartEnabled));
scheduleMsg(&logger, "engine chart size=%d", engineConfiguration->engineChartSize);
}
static void setChartActive(int value) {
engineConfiguration->isEngineChartEnabled = value;
printStatus();
2019-04-12 19:10:57 -07:00
#if EFI_CLOCK_LOCKS
2017-05-21 07:46:43 -07:00
maxLockedDuration = 0; // todo: why do we reset this here? why only this and not all metrics?
#endif /* EFI_CLOCK_LOCKS */
2015-07-10 06:01:56 -07:00
}
void setChartSize(int newSize) {
if (newSize < 5) {
return;
}
engineConfiguration->engineChartSize = newSize;
printStatus();
}
2016-01-30 19:03:36 -08:00
void WaveChart::publishIfFull() {
if (isFull() || isStartedTooLongAgo()) {
publish();
reset();
2015-07-10 06:01:56 -07:00
}
}
2016-01-30 19:03:36 -08:00
void WaveChart::publish() {
2015-07-10 06:01:56 -07:00
appendPrintf(&logging, DELIMETER);
waveChartUsedSize = loggingSize(&logging);
#if DEBUG_WAVE
Logging *l = &chart->logging;
scheduleSimpleMsg(&debugLogging, "IT'S TIME", strlen(l->buffer));
#endif
2019-07-09 04:52:20 -07:00
if (ENGINE(isEngineChartEnabled)) {
2015-07-10 06:01:56 -07:00
scheduleLogging(&logging);
}
}
/**
* @brief Register an event for digital sniffer
*/
2016-01-30 19:03:36 -08:00
void WaveChart::addEvent3(const char *name, const char * msg) {
ScopePerf perf(PE::EngineSniffer);
2020-05-25 20:38:15 -07:00
efitick_t nowNt = getTimeNowNt();
2020-05-25 20:38:15 -07:00
if (nowNt < pauseEngineSnifferUntilNt) {
return;
}
2019-04-12 19:10:57 -07:00
#if EFI_TEXT_LOGGING
2016-01-30 19:03:36 -08:00
if (!ENGINE(isEngineChartEnabled)) {
2015-07-10 06:01:56 -07:00
return;
}
if (skipUntilEngineCycle != 0 && getRevolutionCounter() < skipUntilEngineCycle)
2017-05-25 20:22:35 -07:00
return;
#if EFI_SIMULATOR
// todo: add UI control to enable this for firmware if desired
// CONFIG(alignEngineSnifferAtTDC) &&
if (!collectingData) {
return;
}
#endif
2018-07-25 20:03:04 -07:00
efiAssertVoid(CUSTOM_ERR_6651, name!=NULL, "WC: NULL name");
2015-07-10 06:01:56 -07:00
#if EFI_PROD_CODE
2019-02-23 09:33:49 -08:00
efiAssertVoid(CUSTOM_ERR_6652, getCurrentRemainingStack() > 32, "lowstck#2c");
#endif /* EFI_PROD_CODE */
2015-07-10 06:01:56 -07:00
2018-07-25 20:03:04 -07:00
efiAssertVoid(CUSTOM_ERR_6653, isInitialized, "chart not initialized");
2015-07-10 06:01:56 -07:00
#if DEBUG_WAVE
scheduleSimpleMsg(&debugLogging, "current", chart->counter);
#endif /* DEBUG_WAVE */
2016-01-30 19:03:36 -08:00
if (isFull()) {
2015-07-10 06:01:56 -07:00
return;
}
bool alreadyLocked = lockOutputBuffer(); // we have multiple threads writing to the same output buffer
if (counter == 0) {
startTimeNt = nowNt;
}
counter++;
/**
* We want smaller times within a chart in order to reduce packet size.
*/
/**
* todo: migrate to binary fractions in order to eliminate
* this division? I do not like division
*
* at least that's 32 bit division now
*/
uint32_t diffNt = nowNt - startTimeNt;
2020-05-25 22:08:21 -07:00
uint32_t time100 = NT2US(diffNt / ENGINE_SNIFFER_UNIT_US);
2015-07-10 06:01:56 -07:00
if (remainingSize(&logging) > 35) {
/**
* printf is a heavy method, append is used here as a performance optimization
*/
appendFast(&logging, name);
appendChar(&logging, CHART_DELIMETER);
appendFast(&logging, msg);
appendChar(&logging, CHART_DELIMETER);
// time100 -= startTime100;
itoa10(timeBuffer, time100);
appendFast(&logging, timeBuffer);
appendChar(&logging, CHART_DELIMETER);
logging.linePointer[0] = 0;
}
if (!alreadyLocked) {
unlockOutputBuffer();
}
2018-09-16 21:00:19 -07:00
#endif /* EFI_TEXT_LOGGING */
2015-07-10 06:01:56 -07:00
}
void initWaveChart(WaveChart *chart) {
/**
* constructor does not work because we need specific initialization order
*/
chart->init();
printStatus();
2019-04-12 19:10:57 -07:00
#if DEBUG_WAVE
2015-07-10 06:01:56 -07:00
initLoggingExt(&debugLogging, "wave chart debug", &debugLogging.DEFAULT_BUFFER, sizeof(debugLogging.DEFAULT_BUFFER));
#endif
2019-04-12 19:10:57 -07:00
#if EFI_HISTOGRAMS
2016-01-30 19:03:36 -08:00
initHistogram(&engineSnifferHisto, "wave chart");
2015-07-10 06:01:56 -07:00
#endif /* EFI_HISTOGRAMS */
addConsoleActionI("chartsize", setChartSize);
addConsoleActionI("chart", setChartActive);
2019-04-12 19:10:57 -07:00
#if ! EFI_UNIT_TEST
2019-12-21 16:59:33 -08:00
addConsoleAction(CMD_RESET_ENGINE_SNIFFER, resetNow);
2015-07-10 06:01:56 -07:00
#endif
}
2015-07-15 18:01:45 -07:00
#endif /* EFI_ENGINE_SNIFFER */