lua hooks for CAN tx (#2967)

* CanTxMessage usable from unit test

* testLuaReturnsNil

* CAN hook and tests

* it helps if parameter names exist

* nameless params

* s

* redefinition of default argument

Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
Matthew Kennedy 2021-07-16 11:06:26 -07:00 committed by GitHub
parent d70754d3a8
commit 45d185b09d
7 changed files with 136 additions and 3 deletions

View File

@ -370,6 +370,18 @@ int testLuaReturnsInteger(const char* script) {
return lua_tointeger(ls, -1);
}
void testLuaExecString(const char* script) {
auto ls = setupLuaState();
if (!ls) {
throw new std::logic_error("Call to setupLuaState failed, returned null");
}
if (!loadScript(ls, script)) {
throw new std::logic_error("Call to loadScript failed");
}
}
#endif // EFI_UNIT_TEST
#endif // EFI_LUA

View File

@ -11,6 +11,7 @@
#include "airmass.h"
#include "lua_airmass.h"
#include "pwm_generator_logic.h"
#include "can_msg_tx.h"
// Some functions lean on existing FSIO implementation
#include "fsio_impl.h"
@ -67,6 +68,62 @@ static int lua_table3d(lua_State* l) {
return 1;
}
static int lua_txCan(lua_State* l) {
auto channel = luaL_checkinteger(l, 1);
// TODO: support multiple channels
luaL_argcheck(l, channel == 1, 1, "only channel 1 currently supported");
auto id = luaL_checkinteger(l, 2);
auto ext = luaL_checkinteger(l, 3);
// Check that ID is valid based on std vs. ext
if (ext == 0) {
luaL_argcheck(l, id <= 0x7FF, 2, "ID specified is greater than max std ID");
} else {
luaL_argcheck(l, id <= 0x1FFF'FFFF, 2, "ID specified is greater than max ext ID");
}
luaL_checktype(l, 4, LUA_TTABLE);
// conform ext parameter to true/false
CanTxMessage msg(id, 8, ext == 0 ? false : true);
// Unfortunately there is no way to inspect the length of a table,
// so we have to just iterate until we run out of numbers
uint8_t dlc = 0;
while (true) {
lua_pushnumber(l, dlc + 1);
auto elementType = lua_gettable(l, 4);
auto val = lua_tointeger(l, -1);
lua_pop(l, 1);
if (elementType == LUA_TNIL) {
// we're done, this is the end of the array.
break;
}
if (elementType != LUA_TNUMBER) {
// We're not at the end, but this isn't a number!
luaL_error(l, "Unexpected CAN data at position %d: %s", dlc, lua_tostring(l, -1));
}
// This element is valid, increment DLC
dlc++;
if (dlc > 8) {
luaL_error(l, "CAN frame length cannot be longer than 8");
}
msg[dlc - 1] = val;
}
msg.setDlc(dlc);
// no return value
return 0;
}
static LuaAirmass luaAirmass;
AirmassModelBase& getLuaAirmassModel() {
@ -235,6 +292,7 @@ void configureRusefiLuaHooks(lua_State* l) {
lua_register(l, "getSensorRaw", lua_getSensorRaw);
lua_register(l, "hasSensor", lua_hasSensor);
lua_register(l, "table3d", lua_table3d);
lua_register(l, "txCan", lua_txCan);
#if !EFI_UNIT_TEST
lua_register(l, "startPwm", lua_startPwm);

View File

@ -10,4 +10,5 @@ void startLua();
expected<float> testLuaReturnsNumberOrNil(const char* script);
float testLuaReturnsNumber(const char* script);
int testLuaReturnsInteger(const char* script);
void testLuaExecString(const char* script);
#endif

View File

@ -9,10 +9,10 @@
#include "efifeatures.h"
#include "global.h"
#include "can_msg_tx.h"
#if EFI_CAN_SUPPORT
#include "can.h"
#include "can_msg_tx.h"
#include "engine_configuration.h"
EXTERN_CONFIG
@ -43,7 +43,7 @@ CanTxMessage::CanTxMessage(uint32_t eid, uint8_t dlc, bool isExtended) {
CAN_SID(m_frame) = eid;
}
m_frame.DLC = dlc;
setDlc(dlc);
memset(m_frame.data8, 0, sizeof(m_frame.data8));
}
@ -73,6 +73,10 @@ CanTxMessage::~CanTxMessage() {
}
}
void CanTxMessage::setDlc(uint8_t dlc) {
m_frame.DLC = dlc;
}
uint8_t& CanTxMessage::operator[](size_t index) {
return m_frame.data8[index];
}
@ -86,4 +90,20 @@ void CanTxMessage::setBit(size_t byteIdx, size_t bitIdx) {
m_frame.data8[byteIdx] |= 1 << bitIdx;
}
#else
CanTxMessage::CanTxMessage(uint32_t /*eid*/, uint8_t /*dlc*/, bool /*isExtended*/) {
}
CanTxMessage::~CanTxMessage() {
}
uint8_t& CanTxMessage::operator[](size_t index) {
return m_data8[index];
}
void CanTxMessage::setDlc(uint8_t) { }
#endif // EFI_CAN_SUPPORT

View File

@ -56,9 +56,13 @@ public:
*/
void setBit(size_t byteIdx, size_t bitIdx);
void setDlc(uint8_t dlc);
protected:
#if EFI_CAN_SUPPORT
CANTxFrame m_frame;
#else // not EFI_CAN_SUPPORT
uint8_t m_data8[8];
#endif // EFI_CAN_SUPPORT
private:

View File

@ -13,12 +13,12 @@ HW_LAYER_DRIVERS_CORE = \
HW_LAYER_DRIVERS_CORE_CPP = \
$(DRIVERS_DIR)/gpio/core.cpp \
$(DRIVERS_DIR)/i2c/i2c_bb.cpp \
$(DRIVERS_DIR)/can/can_msg_tx.cpp \
HW_LAYER_DRIVERS =
HW_LAYER_DRIVERS_CPP = \
$(DRIVERS_DIR)/can/can_hw.cpp \
$(DRIVERS_DIR)/can/can_msg_tx.cpp \
$(DRIVERS_DIR)/serial/serial_hw.cpp \
$(DRIVERS_DIR)/gpio/tle6240.cpp \
$(DRIVERS_DIR)/gpio/tle8888.cpp \

View File

@ -36,3 +36,41 @@ TEST(LuaHooks, Table3d) {
setTable(config->fsioTable2, (uint8_t)14);
EXPECT_EQ(testLuaReturnsNumber(tableTest), 14);
}
TEST(LuaHooks, CanTxChannel) {
// channel 1 valid
EXPECT_NO_THROW(testLuaExecString("txCan(1, 0, 0, {0})"));
// channel 0 invalid
EXPECT_ANY_THROW(testLuaExecString("txCan(0, 0, 0, {0})"));
}
TEST(LuaHooks, CanTxId) {
// std ID ok
EXPECT_NO_THROW(testLuaExecString("txCan(1, 2047, 0, {0})"));
// std ID too high
EXPECT_ANY_THROW(testLuaExecString("txCan(1, 2048, 0, {0})"));
// ext ID ok
EXPECT_NO_THROW(testLuaExecString("txCan(1, 536870911, 1, {0})"));
// ext ID too high
EXPECT_ANY_THROW(testLuaExecString("txCan(1, 536870912, 1, {0})"));
}
TEST(LuaHooks, CanTxDataLength) {
// valid: DLC = 0
EXPECT_NO_THROW(testLuaExecString("txCan(1, 0, 0, {})"));
// valid: DLC = 1
EXPECT_NO_THROW(testLuaExecString("txCan(1, 0, 0, {0})"));
// valid: DLC = 8
EXPECT_NO_THROW(testLuaExecString("txCan(1, 0, 0, {1, 2, 3, 4, 5, 6, 7, 8})"));
// invalid: DLC = 9
EXPECT_ANY_THROW(testLuaExecString("txCan(1, 0, 0, {1, 2, 3, 4, 5, 6, 7, 8, 9})"));
// invalid: is a table, but contains a not-number
EXPECT_ANY_THROW(testLuaExecString("txCan(1, 0, 0, {1, 2, 3, 'hello', 5, 6})"));
// invalid: not a table
EXPECT_ANY_THROW(testLuaExecString("txCan(1, 0, 0, 26)"));
}