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:
Matthew Kennedy 2020-12-16 05:28:53 -08:00 committed by GitHub
parent 38dc4e5761
commit 91d1acb50e
9 changed files with 140 additions and 1 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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"