prototype wideband firmware update (#2074)
* add submodule for firmware * ts * add updater * add bench_test * don't collide idx * feature flag * send acks * fix timeout logic * ui * do it on the bench thread * guard * guard * only do twice * guard * bump version * update * file name Co-authored-by: Matthew Kennedy <makenne@microsoft.com>
This commit is contained in:
parent
38dc4e5761
commit
91d1acb50e
|
@ -18,3 +18,6 @@
|
|||
[submodule "firmware/ext/cmsis-svd"]
|
||||
path = firmware/ext/cmsis-svd
|
||||
url = https://github.com/posborne/cmsis-svd
|
||||
[submodule "firmware/controllers/can/wideband_firmware"]
|
||||
path = firmware/controllers/can/wideband_firmware
|
||||
url = https://github.com/mck1117/wideband
|
||||
|
|
|
@ -202,6 +202,8 @@
|
|||
#define EFI_CAN_SUPPORT TRUE
|
||||
#endif
|
||||
|
||||
#define EFI_WIDEBAND_FIRMWARE_UPDATE TRUE
|
||||
|
||||
#ifndef EFI_AUX_SERIAL
|
||||
#define EFI_AUX_SERIAL TRUE
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
#include "malfunction_central.h"
|
||||
#include "tunerstudio_outputs.h"
|
||||
|
||||
#if EFI_WIDEBAND_FIRMWARE_UPDATE
|
||||
#include "can.h"
|
||||
#endif
|
||||
|
||||
#if EFI_PROD_CODE
|
||||
#include "rusefi.h"
|
||||
#include "mpu_util.h"
|
||||
|
@ -86,6 +90,7 @@ static void runBench(brain_pin_e brainPin, OutputPin *output, float delayMs, flo
|
|||
}
|
||||
|
||||
static volatile bool isBenchTestPending = false;
|
||||
static bool widebandUpdatePending = false;
|
||||
static float onTime;
|
||||
static float offTime;
|
||||
static float delayMs;
|
||||
|
@ -231,6 +236,13 @@ private:
|
|||
isBenchTestPending = false;
|
||||
runBench(brainPin, pinX, delayMs, onTime, offTime, count);
|
||||
}
|
||||
|
||||
if (widebandUpdatePending) {
|
||||
#if EFI_WIDEBAND_FIRMWARE_UPDATE
|
||||
updateWidebandFirmware(logger);
|
||||
#endif
|
||||
widebandUpdatePending = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -312,6 +324,9 @@ static void handleCommandX14(uint16_t index) {
|
|||
case 0xF:
|
||||
engine->directSelfStimulation = false;
|
||||
return;
|
||||
case 0x12:
|
||||
widebandUpdatePending = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -385,6 +400,7 @@ void initBenchTest(Logging *sharedLogger) {
|
|||
addConsoleActionS("fuelpumpbench2", fuelPumpBenchExt);
|
||||
addConsoleAction("fanbench", fanBench);
|
||||
addConsoleActionS("fanbench2", fanBenchExt);
|
||||
addConsoleAction("update_wideband", []() { widebandUpdatePending = true; });
|
||||
|
||||
addConsoleAction(CMD_STARTER_BENCH, starterRelayBench);
|
||||
addConsoleAction(CMD_MIL_BENCH, milBench);
|
||||
|
|
|
@ -22,6 +22,11 @@ class CanSensorBase;
|
|||
void processCanRxMessage(const CANRxFrame& msg, Logging* logger, efitick_t nowNt);
|
||||
void registerCanSensor(CanSensorBase& sensor);
|
||||
|
||||
// Indicate that an ack response was received from the wideband bootloader
|
||||
void handleWidebandBootloaderAck();
|
||||
// Update the firmware on any connected wideband controller
|
||||
void updateWidebandFirmware(Logging*);
|
||||
|
||||
class CanWrite final : public PeriodicController<512> {
|
||||
public:
|
||||
CanWrite();
|
||||
|
|
|
@ -64,6 +64,13 @@ void processCanRxMessage(const CANRxFrame& frame, Logging* logger, efitick_t now
|
|||
{
|
||||
obdOnCanPacketRx(frame);
|
||||
}
|
||||
|
||||
#if EFI_WIDEBAND_FIRMWARE_UPDATE
|
||||
// Bootloader acks with address 0x727573 aka ascii "rus"
|
||||
if (frame.EID == 0x727573) {
|
||||
handleWidebandBootloaderAck();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // EFI_CAN_SUPPORT
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
#include "global.h"
|
||||
|
||||
#if EFI_WIDEBAND_FIRMWARE_UPDATE
|
||||
|
||||
#include "ch.h"
|
||||
#include "can_msg_tx.h"
|
||||
|
||||
// This file contains an array called build_wideband_noboot_bin
|
||||
// This array contains the firmware image for the wideband contoller
|
||||
#include "wideband_firmware/for_rusefi/wideband_image.h"
|
||||
|
||||
#define EVT_BOOTLOADER_ACK EVENT_MASK(0)
|
||||
|
||||
static thread_t* waitingBootloaderThread = nullptr;
|
||||
|
||||
void handleWidebandBootloaderAck() {
|
||||
auto t = waitingBootloaderThread;
|
||||
if (t) {
|
||||
chEvtSignal(t, EVT_BOOTLOADER_ACK);
|
||||
}
|
||||
}
|
||||
|
||||
bool waitAck() {
|
||||
return chEvtWaitAnyTimeout(EVT_BOOTLOADER_ACK, TIME_MS2I(1000)) != 0;
|
||||
}
|
||||
|
||||
void updateWidebandFirmware(Logging* logging) {
|
||||
// Clear any pending acks for this thread
|
||||
chEvtGetAndClearEvents(EVT_BOOTLOADER_ACK);
|
||||
|
||||
// Send messages to the current thread when acks come in
|
||||
waitingBootloaderThread = chThdGetSelfX();
|
||||
|
||||
scheduleMsg(logging, "***************************************");
|
||||
scheduleMsg(logging, " WIDEBAND FIRMWARE UPDATE");
|
||||
scheduleMsg(logging, "***************************************");
|
||||
scheduleMsg(logging, "Wideband Update: Rebooting to bootloader...");
|
||||
|
||||
// The first request will reboot the chip (if necessary), and the second one will enable bootloader mode
|
||||
// If the chip was already in bootloader (aka manual mode), then that's ok - the second request will
|
||||
// just be safely ignored (but acked)
|
||||
for (int i = 0; i < 2; i++) {
|
||||
{
|
||||
// Send bootloader entry command
|
||||
CanTxMessage m(0xEF0'0000, 0, true);
|
||||
}
|
||||
|
||||
if (!waitAck()) {
|
||||
scheduleMsg(logging, "Wideband Update ERROR: Expected ACK from entry to bootloader, didn't get one.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Let the controller reboot (and show blinky lights for a second before the update begins)
|
||||
chThdSleepMilliseconds(200);
|
||||
}
|
||||
|
||||
scheduleMsg(logging, "Wideband Update: in update mode, erasing flash...");
|
||||
|
||||
{
|
||||
// Erase flash - opcode 1, magic value 0x5A5A
|
||||
CanTxMessage m(0xEF1'5A5A, 0, true);
|
||||
}
|
||||
|
||||
if (!waitAck()) {
|
||||
scheduleMsg(logging, "Wideband Update ERROR: Expected ACK from flash erase command, didn't get one.");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t totalSize = sizeof(build_wideband_image_bin);
|
||||
|
||||
scheduleMsg(logging, "Wideband Update: Flash erased! Sending %d bytes...", totalSize);
|
||||
|
||||
// Send flash data 8 bytes at a time
|
||||
for (size_t i = 0; i < totalSize; i += 8) {
|
||||
{
|
||||
CanTxMessage m(0xEF2'0000 + i, 8, true);
|
||||
memcpy(&m[0], build_wideband_image_bin + i, 8);
|
||||
}
|
||||
|
||||
if (!waitAck()) {
|
||||
scheduleMsg(logging, "Wideband Update ERROR: Expected ACK from data write, didn't get one.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
scheduleMsg(logging, "Wideband Update: Update complete! Rebooting controller.");
|
||||
|
||||
{
|
||||
// Reboot to firmware!
|
||||
CanTxMessage m(0xEF3'0000, 0, true);
|
||||
}
|
||||
|
||||
waitAck();
|
||||
|
||||
waitingBootloaderThread = nullptr;
|
||||
}
|
||||
|
||||
#endif // EFI_WIDEBAND_FIRMWARE_UPDATE
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 3fe5b76975d5b6a2e093709e50ca938ecd16347f
|
|
@ -42,6 +42,7 @@ CONTROLLERS_SRC_CPP = \
|
|||
$(CONTROLLERS_DIR)/can/obd2.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_verbose.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_rx.cpp \
|
||||
$(CONTORLLERS_DIR)/can/wideband_bootloader.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_tx.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_dash.cpp \
|
||||
$(CONTROLLERS_DIR)/can/can_vss.cpp \
|
||||
|
|
|
@ -1521,6 +1521,7 @@ menuDialog = main
|
|||
subMenu = parkingLot, "Experimental/Broken"
|
||||
subMenu = multisparkSettings, "Multispark", 0, {isIgnitionEnabled == 1}
|
||||
subMenu = mc33Dialog, "GDI Dreams"
|
||||
subMenu = widebandConfig, "rusEFI Wideband Controller", 0, { canReadEnabled && canWriteEnabled }
|
||||
subMenu = std_separator
|
||||
|
||||
subMenu = hipFunction, "HIP9011 settings (knock sensor) (alpha version)" @@if_ts_show_hip9011
|
||||
|
@ -1623,9 +1624,10 @@ cmd_write_config = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x0A"
|
|||
cmd_etb_autotune = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x0C"
|
||||
cmd_enable_self_stim = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x0D"
|
||||
cmb_etb_auto_calibrate = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x0E"
|
||||
cmb_etb_auto_calibrate_2 = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x11"
|
||||
cmd_disable_self_stim = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x0F"
|
||||
cmd_etb_autotune_stop = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x10"
|
||||
cmb_etb_auto_calibrate_2 = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x11"
|
||||
cmd_wideband_firmare_update = "@@TS_IO_TEST_COMMAND_char@@\x00\x14\x00\x12"
|
||||
|
||||
cmd_cj125_calibrate = "@@TS_IO_TEST_COMMAND_char@@\x00\x18\x00\x00"
|
||||
cmd_call_from_pit = "@@TS_IO_TEST_COMMAND_char@@\x00\x20\x34\x56"
|
||||
|
@ -3248,6 +3250,10 @@ cmd_set_engine_type_default = "@@TS_IO_TEST_COMMAND_char@@\x00\x31\x00\x00"
|
|||
panel = testInjectors
|
||||
panel = testFsio
|
||||
panel = testMisc
|
||||
|
||||
dialog = widebandConfig, "rusEFI Wideband Config"
|
||||
field = "!Please connect exactly one wideband controller before pressing this button!"
|
||||
commandButton = "Update Firmware", cmd_wideband_firmare_update
|
||||
|
||||
dialog = engineTypeDialog, "Popular vehicles"
|
||||
field = "!These buttons send a command to rusEFI controller to apply preset values"
|
||||
|
|
Loading…
Reference in New Issue