use libfirmware for a few things (#4351)

* use libfirmware

* unit tests

* crc

* missed one

* bootloader
This commit is contained in:
Matthew Kennedy 2022-07-15 23:22:51 -07:00 committed by GitHub
parent 2a5e8d6d64
commit a0d8ae3f4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 38 additions and 363 deletions

3
.gitmodules vendored
View File

@ -45,3 +45,6 @@
path = java_console/luaformatter
url = https://github.com/rusefi/luaformatter
branch = prod
[submodule "firmware/libfirmware"]
path = firmware/libfirmware
url = https://github.com/rusefi/libfirmware.git

View File

@ -23,6 +23,10 @@ PCHSUB = firmware
# Imported source files and paths
CHIBIOS_CONTRIB = ChibiOS-Contrib
# Configure libfirmware Paths/Includes
RUSEFI_LIB = $(PROJECT_DIR)/libfirmware
include $(RUSEFI_LIB)/util/util.mk
include rusefi.mk
# by default EXTRA_PARAMS is empty and we create 'debug' version of the firmware with additional assertions and statistics
@ -241,7 +245,8 @@ CPPSRC = \
$(HW_LAYER_DRIVERS_CORE_CPP) \
$(HW_LAYER_DRIVERS_CPP) \
$(CONSOLE_SRC_CPP) \
rusefi.cpp \
$(RUSEFI_LIB_CPP) \
rusefi.cpp \
main.cpp
# C sources to be compiled in ARM mode regardless of the global setting.
@ -280,6 +285,7 @@ INCDIR = \
$(BOOTLOADERINC) \
$(CHIBIOS)/os/various \
$(CHIBIOS)/os/hal/lib/peripherals/sensors \
$(RUSEFI_LIB_INC) \
$(CONFDIR) \
ext \
$(PROJECT_DIR)/hw_layer/mass_storage \

View File

@ -130,6 +130,10 @@ CHIBIOS = $(PROJECT_DIR)/ChibiOS
# todo: looks like 'CHIBIOS_CONTRIB' path is universal shall we defined it only once?
CHIBIOS_CONTRIB = $(CHIBIOS)/../ChibiOS-Contrib
# Configure libfirmware Paths/Includes
RUSEFI_LIB = $(PROJECT_DIR)/libfirmware
include $(RUSEFI_LIB)/util/util.mk
RULESPATH = $(CHIBIOS)/os/common/startup/ARMCMx/compilers/GCC/mk
RULESFILE = $(RULESPATH)/rules.mk
@ -187,6 +191,7 @@ CPPSRC = $(ALLCPPSRC) \
$(PROJECT_DIR)/hw_layer/io_pins.cpp \
$(PROJECT_DIR)/util/efilib.cpp \
$(PROJECT_DIR)/hw_layer/pin_repository.cpp \
$(RUSEFI_LIB_CPP) \
src/rusefi_stubs.cpp \
src/dfu.cpp \
src/main.cpp
@ -251,6 +256,7 @@ INCDIR = $(ALLINC) \
$(CONTROLLERS_INC) \
$(PROJECT_DIR)/controllers/sensors \
$(PROJECT_DIR)/init \
$(RUSEFI_LIB_INC) \
config
BUILDDIR=blbuild

View File

@ -12,7 +12,6 @@
#include "pch.h"
#include "os_access.h"
#include "crc.h"
#if EFI_UNIT_TEST
#define PRINT printf

View File

@ -71,7 +71,6 @@
#include "tunerstudio_io.h"
#include "malfunction_central.h"
#include "console_io.h"
#include "crc.h"
#include "bluetooth.h"
#include "tunerstudio_io.h"
#include "tooth_logger.h"

View File

@ -7,7 +7,6 @@
#include "binary_logging.h"
#include "log_field.h"
#include "crc.h"
#include "buffered_writer.h"
#define TIME_PRECISION 1000

View File

@ -8,7 +8,6 @@
#pragma once
#include "globalaccess.h"
#include "crc.h"
#include "engine_configuration_generated_structures.h"
typedef struct {

View File

@ -10,7 +10,6 @@
#if EFI_CAN_SUPPORT || EFI_UNIT_TEST
#include "can_msg_tx.h"
#endif // EFI_CAN_SUPPORT
#include "crc.h"
#include "settings.h"
#include <new>

View File

@ -7,9 +7,10 @@
#pragma once
#include "sensor_converter_func.h"
#include "interpolation.h"
#include "efi_ratio.h"
#include <rusefi/interpolation.h>
template <class TBin, class TValue, int TSize, typename TOutputScale = efi::ratio<1>>
class TableFunc final : public SensorConverter {
public:

1
firmware/libfirmware Submodule

@ -0,0 +1 @@
Subproject commit a8d6982d409a83fa7beb5c37d907d742b620ee2e

View File

@ -17,6 +17,11 @@
#define TRUE (!(FALSE))
#endif /* TRUE */
#include <rusefi/arrays.h>
#include <rusefi/crc.h>
#include <rusefi/interpolation.h>
#include <rusefi/isnan.h>
#include "efifeatures.h"
#include "rusefi_generated.h"
#include "loggingcentral.h"

View File

@ -137,41 +137,6 @@ constexpr void clear(T& obj) {
#define assertIsInBoundsWithResult(length, array, msg, failedResult) efiAssert(OBD_PCM_Processor_Fault, std::is_unsigned_v<decltype(length)> && (length) < efi::size(array), msg, failedResult)
/**
* Copies an array from src to dest. The lengths of the arrays must match.
*/
template <typename DElement, typename SElement, size_t N>
constexpr void copyArray(DElement (&dest)[N], const SElement (&src)[N]) {
for (size_t i = 0; i < N; i++) {
dest[i] = src[i];
}
}
// specialization that can use memcpy when src and dest types match
template <typename DElement, size_t N>
constexpr void copyArray(scaled_channel<DElement, 1, 1> (&dest)[N], const DElement (&src)[N]) {
memcpy(dest, src, sizeof(DElement) * N);
}
template <typename DElement, size_t N>
constexpr void copyArray(DElement (&dest)[N], const DElement (&src)[N]) {
memcpy(dest, src, sizeof(DElement) * N);
}
/**
* Copies an array from src to the beginning of dst. If dst is larger
* than src, then only the elements copied from src will be touched.
* Any remaining elements at the end will be untouched.
*/
template <typename TElement, size_t NSrc, size_t NDest>
constexpr void copyArrayPartial(TElement (&dest)[NDest], const TElement (&src)[NSrc]) {
static_assert(NDest >= NSrc, "Source array must be larger than destination.");
for (size_t i = 0; i < NSrc; i++) {
dest[i] = src[i];
}
}
template <typename T>
bool isInRange(T min, T val, T max) {
return val >= min && val <= max;
@ -195,16 +160,3 @@ static constexpr Gpio operator+(size_t a, Gpio b) {
}
#endif /* __cplusplus */
#if defined(__cplusplus) && defined(__OPTIMIZE__)
#include <type_traits>
// "g++ -O2" version, adds more strict type check and yet no "strict-aliasing" warnings!
#define cisnan(f) ({ \
static_assert(sizeof(f) == sizeof(int32_t)); \
union cisnanu_t { std::remove_reference_t<decltype(f)> __f; int32_t __i; } __cisnan_u = { f }; \
__cisnan_u.__i == 0x7FC00000; \
})
#else
// "g++ -O0" or other C++/C compilers
#define cisnan(f) (*(((int*) (&f))) == 0x7FC00000)
#endif /* __cplusplus && __OPTIMIZE__ */

View File

@ -1,94 +0,0 @@
/**
* @file crc.c
* @date Sep 20, 2013
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "crc.h"
static const uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb,
0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e,
0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75,
0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808,
0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162,
0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49,
0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc,
0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3,
0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d,
0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0,
0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767,
0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a,
0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14,
0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b,
0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee,
0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5,
0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
/**
* Online CRC calculator:
* http://www.zorc.breitbandkatze.de/crc.html
*/
uint32_t crc32(const void *buf, uint32_t size) {
return crc32inc(buf, 0, size);
}
uint32_t crc32inc(const void *buf, uint32_t crc, uint32_t size) {
const uint8_t *p;
p = buf;
crc = crc ^ 0xFFFFFFFF;
while (size--) {
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
}
return crc ^ 0xFFFFFFFF;
}
/**
* http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
* https://stackoverflow.com/questions/38639423/understanding-results-of-crc8-sae-j1850-normal-vs-zero
* j1850 SAE crc8
*/
uint8_t crc8(const uint8_t *data, uint8_t len) {
uint8_t crc = 0;
if (data == 0)
return 0;
crc ^= 0xff;
while (len--) {
crc ^= *data++;
for (unsigned k = 0; k < 8; k++)
crc = crc & 0x80 ? (crc << 1) ^ 0x1d : crc << 1;
}
crc &= 0xff;
crc ^= 0xff;
return crc;
}

View File

@ -1,22 +0,0 @@
/**
* @file crc.h
*
* @date Sep 20, 2013
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#pragma once
#include "stdint.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
uint8_t crc8(const uint8_t * buf, uint8_t len);
uint32_t crc32(const void *buf, uint32_t size);
uint32_t crc32inc(const void *buf, uint32_t crc, uint32_t size);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -45,113 +45,6 @@ void ensureArrayIsAscendingOrDefault(const char* msg, const TValue (&values)[TSi
ensureArrayIsAscending(msg, values);
}
namespace priv {
struct BinResult
{
size_t Idx;
float Frac;
};
/**
* @brief Finds the location of a value in the bin array.
*
* @param value The value to find in the bins.
* @return A result containing the index to the left of the value,
* and how far from (idx) to (idx + 1) the value is located.
*/
template<class TBin, int TSize>
BinResult getBin(float value, const TBin (&bins)[TSize]) {
// Enforce numeric only (int, float, uintx_t, etc)
static_assert(std::is_arithmetic_v<TBin>, "Table bins must be an arithmetic type");
// Enforce that there are enough bins to make sense (what does one bin even mean?)
static_assert(TSize >= 2);
// Handle NaN
if (cisnan(value)) {
return { 0, 0.0f };
}
// Handle off-scale low
if (value <= bins[0]) {
return { 0, 0.0f };
}
// Handle off-scale high
if (value >= bins[TSize - 1]) {
return { TSize - 2, 1.0f };
}
size_t idx = 0;
// Find the last index less than the searched value
// Linear search for now, maybe binary search in future
// after collecting real perf data
for (idx = 0; idx < TSize - 1; idx++) {
if (bins[idx + 1] > value) {
break;
}
}
float low = bins[idx];
float high = bins[idx + 1];
// Compute how far along the bin we are
// (0.0f = left side, 1.0f = right side)
float fraction = (value - low) / (high - low);
return { idx, fraction };
}
template<class TBin, int TSize, int TMult, int TDiv>
BinResult getBin(float value, const scaled_channel<TBin, TMult, TDiv> (&bins)[TSize]) {
return getBin(value * (float(TMult) / TDiv), *reinterpret_cast<const TBin (*)[TSize]>(&bins));
}
static float linterp(float low, float high, float frac)
{
return high * frac + low * (1 - frac);
}
} // namespace priv
template <class TBin, class TValue, int TSize>
float interpolate2d(const float value, const TBin (&bin)[TSize], const TValue (&values)[TSize]) {
// Enforce numeric only (int, float, uintx_t, etc)
static_assert(std::is_arithmetic_v<TBin> || is_scaled_channel<TBin>, "Table values must be an arithmetic type or scaled channel");
auto b = priv::getBin(value, bin);
// Convert to float as we read it out
float low = static_cast<float>(values[b.Idx]);
float high = static_cast<float>(values[b.Idx + 1]);
float frac = b.Frac;
return priv::linterp(low, high, frac);
}
template<typename VType, unsigned RNum, typename RType, unsigned CNum, typename CType>
float interpolate3d(const VType (&table)[RNum][CNum],
const RType (&rowBins)[RNum], float rowValue,
const CType (&colBins)[CNum], float colValue)
{
auto row = priv::getBin(rowValue, rowBins);
auto col = priv::getBin(colValue, colBins);
// Orient the table such that (0, 0) is the bottom left corner,
// then the following variable names will make sense
float lowerLeft = table[row.Idx ][col.Idx ];
float upperLeft = table[row.Idx + 1][col.Idx ];
float lowerRight = table[row.Idx ][col.Idx + 1];
float upperRight = table[row.Idx + 1][col.Idx + 1];
// Interpolate each side by itself
float left = priv::linterp(lowerLeft, upperLeft, row.Frac);
float right = priv::linterp(lowerRight, upperRight, row.Frac);
// Then interpolate between those
return priv::linterp(left, right, col.Frac);
}
/** @brief Binary search
* @returns the highest index within sorted array such that array[i] is greater than or equal to the parameter
* @note If the parameter is smaller than the first element of the array, -1 is returned.

View File

@ -11,85 +11,9 @@
#pragma once
#include <cmath>
#include <cstdint>
#include <type_traits>
#include <rusefi/scaled_channel.h>
#include "rusefi_generated.h"
struct scaled_channel_base { };
template <typename TTest>
static constexpr bool is_scaled_channel = std::is_base_of_v<scaled_channel_base, TTest>;
// This class lets us transparently store something at a ratio inside an integer type
// Just use it like a float - you can read and write to it, like this:
// scaled_channel<uint8_t, 10> myVar;
// myVar = 2.4f; // converts to an int, stores 24
// float x = myVar; // converts back to float, returns 2.4f
template <typename T, int mul = 1, int div = 1>
class scaled_channel : scaled_channel_base {
using TSelf = scaled_channel<T, mul, div>;
public:
struct IncompleteType;
constexpr scaled_channel() : m_value(static_cast<T>(0)) { }
// Only allow conversion directly to T when mul/div are both 1, otherwise this constructor doesn't exist and the float conversion is used.
constexpr scaled_channel(std::conditional_t<mul == 1 && div == 1, T, IncompleteType> val) {
m_value = val;
}
// Scale the float in to our scaled channel
constexpr scaled_channel(std::conditional_t<mul != 1 || div != 1, float, IncompleteType> val) {
// If there are scale factors, it must NOT be a float. Why would you scale a float?
static_assert(std::is_integral_v<T>);
m_value = std::roundf(val * float(mul) / div);
}
// Only allow conversion directly to T when mul/div are both 1, otherwise this operator doesn't exist and the float conversion is used.
constexpr operator typename std::conditional_t<mul == 1 && div == 1, T, IncompleteType>() const {
return m_value;
}
// Allow reading back out as a float (note: this may be lossy!)
constexpr operator typename std::conditional_t<mul != 1 || div != 1, float, IncompleteType>() const {
return m_value * (float(div) / mul);
}
// Postfix increment operator
// only enable if:
// - base type T is an integral type (integer)
// - multiplier is equal to 1
void operator++(int) {
static_assert(mul == 1 && div == 1,
"Increment operator only supported for non-scaled integer types");
static_assert(std::is_integral_v<T>, "Increment operator only supported for non-scaled integer types");
m_value++;
}
constexpr const char* getFirstByteAddr() const {
return &m_firstByte;
}
private:
union {
T m_value;
char m_firstByte;
};
};
// We need to guarantee that scaled values containing some type are the same size
// as that underlying type. We rely on the class only having a single member for
// this trick to work.
static_assert(sizeof(scaled_channel<uint8_t>) == 1);
static_assert(sizeof(scaled_channel<uint16_t>) == 2);
static_assert(sizeof(scaled_channel<uint32_t>) == 4);
static_assert(sizeof(scaled_channel<float>) == 4);
// Common scaling options - use these if you can!
using scaled_temperature = scaled_channel<int16_t, PACK_MULT_TEMPERATURE>; // +-327 deg C at 0.01 deg resolution
using scaled_ms = scaled_channel<int16_t, PACK_MULT_MS>; // +- 100ms at 0.003ms precision
@ -101,7 +25,3 @@ using scaled_voltage = scaled_channel<uint16_t, PACK_MULT_VOLTAGE>; // 0-65v at
using scaled_afr = scaled_channel<uint16_t, PACK_MULT_AFR>; // 0-65afr at 0.001 resolution
using scaled_lambda = scaled_channel<uint16_t, PACK_MULT_LAMBDA>; // 0-6.5 lambda at 0.0001 resolution
using scaled_fuel_mass_mg = scaled_channel<uint16_t, PACK_MULT_FUEL_MASS>; // 0 - 655.35 milligrams, 0.01mg resolution
// make sure the scaled channel detector works
static_assert(!is_scaled_channel<int>);
static_assert(is_scaled_channel<scaled_channel<int, 5>>);

View File

@ -1,7 +1,6 @@
UTIL_DIR=$(PROJECT_DIR)/util
UTILSRC = \
$(UTIL_DIR)/math/crc.c \
$(UTIL_DIR)/tinymt32.c \
UTILSRC_CPP = \

View File

@ -129,6 +129,10 @@ PROJECT_DIR = ../firmware
# Imported source files and paths
# Configure libfirmware Paths/Includes
RUSEFI_LIB = $(PROJECT_DIR)/libfirmware
include $(RUSEFI_LIB)/util/util.mk
# Licensing files.
include $(CHIBIOS)/os/license/license.mk
# Startup files.
@ -173,6 +177,7 @@ CPPSRC = $(ALLCPPSRC) \
simulator/framework.cpp \
simulator/boards.cpp \
$(TEST_SRC_CPP) \
$(RUSEFI_LIB_CPP) \
main.cpp
@ -186,6 +191,7 @@ INCDIR = . \
$(PROJECT_DIR)/hw_layer/drivers/can \
${CHIBIOS}/os/various \
$(CHIBIOS)/os/hal/lib/streams \
$(RUSEFI_LIB_INC) \
simulator/can \
simulator

View File

@ -14,6 +14,9 @@ include $(UNIT_TESTS_DIR)/tests/tests.mk
include $(PROJECT_DIR)/../unit_tests/tests/util/test_util.mk
include $(PROJECT_DIR)/common.mk
RUSEFI_LIB = $(PROJECT_DIR)/libfirmware
include $(RUSEFI_LIB)/util/util.mk
# C sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
CSRC += $(ALLCSRC) \
@ -34,6 +37,7 @@ CPPSRC += $(ALLCPPSRC) \
$(PROJECT_DIR)/../unit_tests/main.cpp \
$(PROJECT_DIR)/../unit_tests/global_mocks.cpp \
$(PROJECT_DIR)/../unit_tests/mocks.cpp \
$(RUSEFI_LIB_CPP) \
INCDIR += \
$(PCH_DIR) \
@ -45,7 +49,8 @@ INCDIR += \
$(UNIT_TESTS_DIR)/native \
$(UNIT_TESTS_DIR)/tests \
$(UNIT_TESTS_DIR)/tests/sensor \
$(UNIT_TESTS_DIR)/test_basic_math
$(UNIT_TESTS_DIR)/test_basic_math \
$(RUSEFI_LIB_INC) \
include $(UNIT_TESTS_DIR)/unit_test_rules.mk

View File

@ -18,7 +18,6 @@
#include "nmea.h"
#include "mmc_card.h"
#include "lcd_menu_tree.h"
#include "crc.h"
#include "fl_stack.h"
TEST(util, testitoa) {