diff --git a/SConscript b/SConscript index f6501e88cc..1f5be8fcba 100644 --- a/SConscript +++ b/SConscript @@ -62,7 +62,9 @@ def to_c_uint32(x): return "{" + 'U,'.join(map(str, nums)) + "U}" -def build_project(project_name, project, extra_flags): +def build_project(project_name, project, extra_flags, cppdefines=None): + cppdefines = cppdefines or [] + print(f"{project_name} -> CPPDEFINES [{', '.join(cppdefines)}]") linkerscript_fn = File(project["LINKER_SCRIPT"]).srcnode().relpath flags = project["PROJECT_FLAGS"] + extra_flags + common_flags + [ @@ -101,6 +103,7 @@ def build_project(project_name, project, extra_flags): 'Objcopy': Builder(generator=objcopy, suffix='.bin', src_suffix='.elf') }, tools=["default", "compilation_db"], + CPPDEFINES=cppdefines, ) startup = env.Object(f"obj/startup_{project_name}", project["STARTUP_FILE"]) @@ -179,12 +182,15 @@ with open("board/obj/cert.h", "w") as f: for cert in certs: f.write("\n".join(cert) + "\n") -# panda fw -SConscript('board/SConscript') - -# panda jungle fw -SConscript('board/jungle/SConscript') - -# test files -if GetOption('extras'): - SConscript('tests/libpanda/SConscript') +if not GetOption('escc'): # if we are building ESCC, we don't build anything else + # panda fw + SConscript('board/SConscript') + + # panda jungle fw + SConscript('board/jungle/SConscript') + + # test files + if GetOption('extras'): + SConscript('tests/libpanda/SConscript') +else: + SConscript('board/escc/SConscript') diff --git a/SConstruct b/SConstruct index 11ff21738e..5e5a100830 100644 --- a/SConstruct +++ b/SConstruct @@ -20,6 +20,10 @@ AddOption('--mutation', action='store_true', help='generate mutation-ready code') +AddOption('--escc', + action='store_true', + help='build escc firmware') + env = Environment( COMPILATIONDB_USE_ABSPATH=True, tools=["default", "compilation_db"], diff --git a/board/escc/.gitignore b/board/escc/.gitignore new file mode 100644 index 0000000000..94053f2925 --- /dev/null +++ b/board/escc/.gitignore @@ -0,0 +1 @@ +obj/* diff --git a/board/escc/README.MD b/board/escc/README.MD new file mode 100644 index 0000000000..6eea4ba81a --- /dev/null +++ b/board/escc/README.MD @@ -0,0 +1,81 @@ +## Documentation +[see more](https://github.com/sunnypilot/sunnypilot/blob/5d754169a6285e88e755ff9a592a851cb92b0abc/docs/escc/ESCC%20IONIQ%20PHEV%20Guide.md) + +### Detailed Connection List + +#### Molex 5018762640 Pinout: + +- Pin 1: GND +- Pin 2: IGN +- Pin 3: internal 120 Ohm Resistor, simply bridge to Pin 5 +- Pin 4: C-CAN HIGH +- Pin 5: internal 120 Ohm Resistor, simply bridge to Pin 3 +- Pin 6: C-CAN LOW +- Pin 8: L-CAN HIGH +- Pin 10: L-CAN LOW +- Pin 12: 12v +- Pin 14: 12v +- Pin 16: IGN +- Pin 18: L-CAN HIGH +- Pin 20: L-CAN LOW +- Pin 22: C-CAN HIGH +- Pin 24: C-CAN LOW +- Pin 26: GND + +#### **IONIQ 2203663 (Car Harness, Female):** + +- Pin 1: 12v -> Molex Pin 12 +- Pin 4: GND -> Molex Pin 1 +- Pin 7: C-CAN LOW -> Molex Pin 6 +- Pin 8: C-CAN HIGH -> Molex Pin 4 +- Pin 9: L-CAN LOW -> Molex Pin 10 +- Pin 10: IGPM (IGN) -> Molex Pin 2 +- Pin 18: L-CAN HIGH -> Molex Pin 8 + +#### **IONIQ 2203663 (Car Radar, Male):** + +- Molex Pin: 14 -> Pin 1: 12v +- Molex Pin: 26 -> Pin 4: GND +- Molex Pin: 24 -> Pin 7: C-CAN LOW +- Molex Pin: 22 -> Pin 8: C-CAN HIGH +- Molex Pin: 20 -> Pin 9: L-CAN LOW +- Molex Pin: 16 -> Pin 10: IGN +- Molex Pin: 18 -> Pin 18: L-CAN HIGH + + +``` +IONIQ 2203663 Molex 5018762640 IONIQ 2203663 +Car Harness (Female) Car Radar (Male) ++-----+-----+ +-----+-----+ +-----+-----+ +| 18 | 9 | | 2 | 1 | | 10 | 1 | +| 17 | 8 | | 4 | 3 | | 11 | 2 | +| 16 | 7 | | 6 | 5 | | 12 | 3 | +| 15 | 6 | | 8 | 7 | | 13 | 4 | +| 14 | 5 | NOTCH | 10 | 9 | | 14 | 5 | NOTCH +| 13 | 4 | | 12 | 11 | | 15 | 6 | +| 12 | 3 | | 14 | 13 | NOTCH | 16 | 7 | +| 11 | 2 | | 16 | 15 | | 17 | 8 | +| 10 | 1 | | 18 | 17 | | 18 | 9 | ++-----+-----+ | 20 | 19 | +-----+-----+ + | 22 | 21 | + | 24 | 23 | + | 26 | 25 | + +-----+-----+ + +Connections: +Molex Pin 3 (120 Ohm) <--> Molex Pin 5 (120 Ohm) +Harness Pin 1 (12V) <--> Molex Pin 12 (12V) +Harness Pin 4 (GND) <--> Molex Pin 1 (GND) +Harness Pin 10 (IGN) <--> Molex Pin 2 (IGN) +Harness Pin 8 (C-CAN H) <--> Molex Pin 4 (C-CAN H) +Harness Pin 7 (C-CAN L) <--> Molex Pin 6 (C-CAN L) +Harness Pin 18 (L-CAN H) <--> Molex Pin 8 (L-CAN H) +Harness Pin 9 (L-CAN L) <--> Molex Pin 10 (L-CAN L) + Molex Pin 20 (L-CAN L) <--> Radar Pin 9 (L-CAN L) + Molex Pin 18 (L-CAN H) <--> Radar Pin 18 (L-CAN H) + Molex Pin 24 (C-CAN L) <--> Radar Pin 7 (C-CAN L) + Molex Pin 22 (C-CAN H) <--> Radar Pin 8 (C-CAN H) + Molex Pin 16 (IGN) <--> Radar Pin 10 (IGN) + Molex Pin 14 (12V) <--> Radar Pin 1 (12V) + Molex Pin 26 (GND) <--> Radar Pin 4 (GND) +``` \ No newline at end of file diff --git a/board/escc/SConscript b/board/escc/SConscript new file mode 100644 index 0000000000..79a7c98e22 --- /dev/null +++ b/board/escc/SConscript @@ -0,0 +1,34 @@ +import os +import copy + +Import('build_project') + +build_projects = {} + +build_projects["escc"] = { + "MAIN": "../main.c", + "BOOTSTUB": "../bootstub.c", + "STARTUP_FILE": File("../stm32f4/startup_stm32f413xx.s"), + "LINKER_SCRIPT": File("../stm32f4/stm32f4_flash.ld"), + "APP_START_ADDRESS": "0x8004000", + "PROJECT_FLAGS": [ + "-mcpu=cortex-m4", + "-mhard-float", + "-DSTM32F4", + "-DSTM32F413xx", + "-mfpu=fpv4-sp-d16", + "-fsingle-precision-constant", + "-Os", + "-g", + ], +} + +for project_name, project in build_projects.items(): + flags = [ + "-DPANDA", + "-DESCC", + ] + if ("ENABLE_SPI" in os.environ or "h7" in project_name) and not project_name.startswith('pedal'): + flags.append('-DENABLE_SPI') + + build_project(project_name, project, flags, ["ESCC"]) diff --git a/board/escc/flash.py b/board/escc/flash.py new file mode 100755 index 0000000000..cc7e7212f6 --- /dev/null +++ b/board/escc/flash.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +import os +import subprocess + +from panda import Panda + +board_path = os.path.dirname(os.path.realpath(__file__)) + +if __name__ == "__main__": + print(board_path) + subprocess.check_call(f"scons -C {board_path}/../.. -j$(nproc) {board_path} --escc", shell=True) + + serials = Panda.list() + print(f"found {len(serials)} panda(s) - {serials}") + for s in serials: + print("flashing", s) + with Panda(serial=s) as p: + p.flash("obj/escc.bin.signed") diff --git a/board/escc/flash_can.sh b/board/escc/flash_can.sh new file mode 100755 index 0000000000..634f1acdd1 --- /dev/null +++ b/board/escc/flash_can.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh +set -e + +cd .. +scons -u -j$(nproc) --escc +cd escc + +../../tests/escc/enter_canloader.py obj/escc.bin.signed diff --git a/board/escc/recover.sh b/board/escc/recover.sh new file mode 100755 index 0000000000..6276742dac --- /dev/null +++ b/board/escc/recover.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env sh +set -e + +DFU_UTIL="dfu-util" + +cd .. +scons -u -j$(nproc) --escc +cd escc + +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08004000 -D obj/escc.bin.signed +$DFU_UTIL -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.escc.bin diff --git a/board/main.c b/board/main.c index 7c068113a0..2a5dde30c0 100644 --- a/board/main.c +++ b/board/main.c @@ -117,6 +117,7 @@ void set_safety_mode(uint16_t mode, uint16_t param) { can_init_all(); } +// cppcheck-suppress misra-c2012-5.5 bool is_car_safety_mode(uint16_t mode) { return (mode != SAFETY_SILENT) && (mode != SAFETY_NOOUTPUT) && @@ -124,6 +125,61 @@ bool is_car_safety_mode(uint16_t mode) { (mode != SAFETY_ELM327); } +#ifdef ESCC +// ***************************** ESCC code ***************************** +bool is_car_safety_mode_escc(uint16_t mode) { + return is_car_safety_mode(mode) && (mode != SAFETY_HYUNDAI_ESCC); +} +#define is_car_safety_mode is_car_safety_mode_escc + +#define CAN_ESCC_INPUT 0x2AC +#define CAN_ESCC_OUTPUT 0x2ABU + +void send_escc_msg(const ESCC_Msg *msg, const int bus_number) { +#ifdef DEBUG + + print("send_escc_msg\n"); + print("fca_cmd_act: "); putui(msg->fca_cmd_act); print("\n"); + print("aeb_cmd_act: "); putui(msg->aeb_cmd_act); print("\n"); + print("cf_vsm_warn_fca11: "); putui(msg->cf_vsm_warn_fca11); print("\n"); + print("cf_vsm_warn_scc12: "); putui(msg->cf_vsm_warn_scc12); print("\n"); + print("cf_vsm_deccmdact_scc12: "); putui(msg->cf_vsm_deccmdact_scc12); print("\n"); + print("cf_vsm_deccmdact_fca11: "); putui(msg->cf_vsm_deccmdact_fca11); print("\n"); + print("cr_vsm_deccmd_scc12: "); putui(msg->cr_vsm_deccmd_scc12); print("\n"); + print("cr_vsm_deccmd_fca11: "); putui(msg->cr_vsm_deccmd_fca11); print("\n"); + print("obj_valid: "); putui(msg->obj_valid); print("\n"); + print("acc_objstatus: "); putui(msg->acc_objstatus); print("\n"); + print("acc_obj_lat_pos_1: "); putui(msg->acc_obj_lat_pos_1); print("\n"); + print("acc_obj_lat_pos_2: "); putui(msg->acc_obj_lat_pos_2); print("\n"); + print("acc_obj_dist_1: "); putui(msg->acc_obj_dist_1); print("\n"); + print("acc_obj_dist_2: "); putui(msg->acc_obj_dist_2); print("\n"); + print("acc_obj_rel_spd_1: "); putui(msg->acc_obj_rel_spd_1); print("\n"); + print("acc_obj_rel_spd_2: "); putui(msg->acc_obj_rel_spd_2); print("\n"); +#endif + + uint8_t dat[8]; + dat[0] = (msg->fca_cmd_act) | (msg->cf_vsm_warn_fca11 << 1) | (msg->aeb_cmd_act << 3) | + (msg->cf_vsm_warn_scc12 << 4) | (msg->cf_vsm_deccmdact_scc12 << 6) | (msg->cf_vsm_deccmdact_fca11 << 7); + dat[1] = (msg->cr_vsm_deccmd_scc12); + dat[2] = (msg->obj_valid) | (msg->acc_objstatus << 1); + dat[3] = (msg->acc_obj_lat_pos_1); + dat[4] = (msg->acc_obj_lat_pos_2) | (msg->acc_obj_dist_1 << 1); + dat[5] = (msg->acc_obj_dist_2) | (msg->acc_obj_rel_spd_1 << 4); + dat[6] = (msg->acc_obj_rel_spd_2); + dat[7] = (msg->cr_vsm_deccmd_fca11); + + CANPacket_t to_send; + to_send.extended = CAN_ESCC_OUTPUT >= 0x800 ? 1 : 0; + to_send.addr = CAN_ESCC_OUTPUT; + to_send.bus = bus_number; + to_send.data_len_code = sizeof(dat); + memcpy(to_send.data, dat, sizeof(dat)); + + can_set_checksum(&to_send); + can_send(&to_send, bus_number, true); +} +#endif + // ***************************** main code ***************************** // cppcheck-suppress unusedFunction ; used in headers not included in cppcheck @@ -186,7 +242,9 @@ static void tick_handler(void) { print("rx:"); puth4(can_rx_q.r_ptr); print("-"); puth4(can_rx_q.w_ptr); print(" "); print("tx1:"); puth4(can_tx1_q.r_ptr); print("-"); puth4(can_tx1_q.w_ptr); print(" "); print("tx2:"); puth4(can_tx2_q.r_ptr); print("-"); puth4(can_tx2_q.w_ptr); print(" "); - print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print("\n"); + print("tx3:"); puth4(can_tx3_q.r_ptr); print("-"); puth4(can_tx3_q.w_ptr); print(" "); + print("SAFETY MODE:"); putui(current_safety_mode); + print("\n"); #endif // set green LED to be controls allowed @@ -235,6 +293,7 @@ static void tick_handler(void) { mads_heartbeat_engaged_check(); +#ifndef ESCC // Hearbet disabled when ESCC if (!heartbeat_disabled) { // if the heartbeat has been gone for a while, go to SILENT safety mode and enter power save if (heartbeat_counter >= (check_started() ? HEARTBEAT_IGNITION_CNT_ON : HEARTBEAT_IGNITION_CNT_OFF)) { @@ -273,6 +332,7 @@ static void tick_handler(void) { fan_set_power(enabled ? 50U : 0U); } } +#endif // check registers check_registers(); @@ -335,8 +395,13 @@ int main(void) { fan_init(); } +#ifdef ESCC + // init to SAFETY_HYUNDAI_ESCC and can all output + set_safety_mode(SAFETY_HYUNDAI_ESCC, 1U); +#else // init to SILENT and can silent set_safety_mode(SAFETY_SILENT, 0U); +#endif // enable CAN TXs current_board->enable_can_transceivers(true); diff --git a/board/safety.h b/board/safety.h index 5470e7b364..821bdd45ee 100644 --- a/board/safety.h +++ b/board/safety.h @@ -23,6 +23,10 @@ #include "safety/safety_elm327.h" #include "safety/safety_body.h" +#ifdef ESCC +#include "safety/safety_hyundai_escc.h" +#endif + // CAN-FD only safety modes #ifdef CANFD #include "safety/safety_hyundai_canfd.h" @@ -56,6 +60,10 @@ #define SAFETY_BODY 27U #define SAFETY_HYUNDAI_CANFD 28U +#ifdef ESCC +#define SAFETY_HYUNDAI_ESCC 29U +#endif + uint32_t GET_BYTES(const CANPacket_t *msg, int start, int len) { uint32_t ret = 0U; for (int i = 0; i < len; i++) { @@ -375,6 +383,9 @@ int set_safety_hooks(uint16_t mode, uint16_t param) { {SAFETY_GM, &gm_hooks}, {SAFETY_HONDA_BOSCH, &honda_bosch_hooks}, {SAFETY_HYUNDAI, &hyundai_hooks}, +#ifdef ESCC + {SAFETY_HYUNDAI_ESCC, &hyundai_escc_hooks}, +#endif {SAFETY_CHRYSLER, &chrysler_hooks}, {SAFETY_SUBARU, &subaru_hooks}, {SAFETY_VOLKSWAGEN_MQB, &volkswagen_mqb_hooks}, diff --git a/board/safety/safety_hyundai_escc.h b/board/safety/safety_hyundai_escc.h new file mode 100644 index 0000000000..e35497608e --- /dev/null +++ b/board/safety/safety_hyundai_escc.h @@ -0,0 +1,107 @@ +#pragma once + +#define DEVNULL_BUS (-1) +#define CAR_BUS 0 +#define RADAR_BUS 2 + +bool scc_block_allowed = false; +uint32_t sunnypilot_detected_last = 0; + +// Initialize bytes to send to 2AB +ESCC_Msg escc = {0}; + +static void escc_rx_hook(const CANPacket_t* to_push) { + const int bus = GET_BUS(to_push); + const int addr = GET_ADDR(to_push); + + + const int is_scc_msg = addr == 0x420 || addr == 0x421 || addr == 0x50A || addr == 0x389; + const int is_fca_msg = addr == 0x38D || addr == 0x483; +#ifdef DEBUG + print("escc_rx_hook: "); putui(bus); print(" - "); puth4(addr); print(" is_scc_msg: "); print(is_scc_msg?"yes":"no"); print(" is_fca_msg: "); print(is_fca_msg?"yes":"no"); print("\n"); +#endif + + if (bus == RADAR_BUS && (is_scc_msg || is_fca_msg)) { + switch (addr) { + // This messsage is blocked if scc_block_allowed is true, and ESCC is updated with the data and sent to sunnypilot + case 0x420: // SCC11: Forward radar points to sunnypilot + escc.obj_valid = (GET_BYTE(to_push, 2) & 0x1U); + escc.acc_objstatus = ((GET_BYTE(to_push, 2) >> 6) & 0x3U); + escc.acc_obj_lat_pos_1 = GET_BYTE(to_push, 3); + escc.acc_obj_lat_pos_2 = (GET_BYTE(to_push, 4) & 0x1U); + escc.acc_obj_dist_1 = ((GET_BYTE(to_push, 4) >> 1) & 0x7FU); + escc.acc_obj_dist_2 = (GET_BYTE(to_push, 5) & 0xFU); + escc.acc_obj_rel_spd_1 = ((GET_BYTE(to_push, 5) >> 4) & 0xFU); + escc.acc_obj_rel_spd_2 = GET_BYTE(to_push, 6); + send_escc_msg(&escc, CAR_BUS); + break; + + // This messsage is blocked if scc_block_allowed is true, and ESCC is updated with the data and sent to sunnypilot + case 0x421: // SCC12: Detect AEB, get the data and write it on the next ESCC msg to sunnypilot. + escc.aeb_cmd_act = GET_BYTE(to_push, 6) >> 6 & 1U; + escc.cf_vsm_warn_scc12 = GET_BYTE(to_push, 0) >> 4 & 0x3U; + escc.cf_vsm_deccmdact_scc12 = GET_BYTE(to_push, 0) >> 1 & 1U; + escc.cr_vsm_deccmd_scc12 = GET_BYTE(to_push, 2); + break; + + // This message is not blocked, and is sent straight to the car. + case 0x38D: // FCA11: Detect AEB, get the data and write it on the next ESCC msg to sunnypilot + escc.fca_cmd_act = GET_BYTE(to_push, 2) >> 4 & 1U; + escc.cf_vsm_warn_fca11 = GET_BYTE(to_push, 0) >> 3 & 0x3U; + escc.cf_vsm_deccmdact_fca11 = GET_BYTE(to_push, 3) >> 7 & 1U; + escc.cr_vsm_deccmd_fca11 = GET_BYTE(to_push, 1); + break; + + default: ; + } + } +} + +static bool escc_tx_hook(const CANPacket_t* to_send) { +#ifdef DEBUG + const int target_bus = GET_BUS(to_send); + const int addr = GET_ADDR(to_send); + print("escc_tx_hook: "); putui(target_bus); print(" - "); puth4(addr); print("\n"); + #else + UNUSED(to_send); + #endif + return true; +} + +static int escc_fwd_hook(const int bus_src, const int addr) { +#ifdef DEBUG + print("escc_fwd_hook: "); putui(bus_src); print(" - "); puth4(addr); print(" scc_block_allowed: "); print(scc_block_allowed?"yes":"no" ); print("\n"); +#endif + // SCC messages are SCC11 (0x420), SCC12 (0x421), SCC13 (0x50A), SCC14 (0x389) + const int is_scc_msg = addr == 0x420 || addr == 0x421 || addr == 0x50A || addr == 0x389; + + const uint32_t ts = MICROSECOND_TIMER->CNT; + + // Update the last detected timestamp if an SCC message is from CAR_BUS + if (bus_src == CAR_BUS && is_scc_msg) { + sunnypilot_detected_last = ts; + } + + // Default forwarding logic + int bus_dst = (bus_src == CAR_BUS) ? RADAR_BUS : CAR_BUS; + + // Update the scc_block_allowed status based on elapsed time + const uint32_t ts_elapsed = get_ts_elapsed(ts, sunnypilot_detected_last); + scc_block_allowed = (ts_elapsed <= 150000); + + // If we are allowed to block, and this is an scc msg coming from radar (or somehow we are sending it TO the radar) we block + if (scc_block_allowed && is_scc_msg && (bus_src == RADAR_BUS || bus_dst == RADAR_BUS)) + bus_dst = DEVNULL_BUS; + + return bus_dst; +} + +const safety_hooks hyundai_escc_hooks = { + .init = alloutput_init, + .rx = escc_rx_hook, + .tx = escc_tx_hook, + .fwd = escc_fwd_hook, + .get_counter = hyundai_get_counter, + .get_checksum = hyundai_get_checksum, + .compute_checksum = hyundai_compute_checksum, +}; diff --git a/board/safety_sunnypilot_common.h b/board/safety_sunnypilot_common.h new file mode 100644 index 0000000000..e2dc1db2ef --- /dev/null +++ b/board/safety_sunnypilot_common.h @@ -0,0 +1,64 @@ +#ifndef SAFETY_SUNNYPILOT_COMMON_H +#define SAFETY_SUNNYPILOT_COMMON_H + +void mads_acc_main_check(const bool main_on) { + if (main_on && mads_enabled) { + controls_allowed = true; + } + if (!main_on && acc_main_on_prev) { + disengageFromBrakes = false; + controls_allowed = false; + controls_allowed_long = false; + } + acc_main_on_prev = main_on; +} + +void mads_lkas_button_check(const bool lkas_pressed) { + if (lkas_pressed && !lkas_pressed_prev) { + controls_allowed = true; + } + lkas_pressed_prev = lkas_pressed; +} + +void mads_exit_controls_check(void) { + if (alternative_experience & ALT_EXP_MADS_DISABLE_DISENGAGE_LATERAL_ON_BRAKE) { + disengageFromBrakes = true; + controls_allowed_long = false; + } else { + if ((alternative_experience & ALT_EXP_ENABLE_MADS) && controls_allowed) { + disengageFromBrakes = true; + } + controls_allowed = false; + controls_allowed_long = false; + } +} + +void mads_resume_controls_check(void) { + disengageFromBrakes = false; + if (alternative_experience & ALT_EXP_ENABLE_MADS) { + controls_allowed = true; + } +} + +typedef struct { + uint8_t fca_cmd_act; + uint8_t aeb_cmd_act; + uint8_t cf_vsm_warn_fca11; + uint8_t cf_vsm_warn_scc12; + uint8_t cf_vsm_deccmdact_scc12; + uint8_t cf_vsm_deccmdact_fca11; + uint8_t cr_vsm_deccmd_scc12; + uint8_t cr_vsm_deccmd_fca11; + uint8_t obj_valid; + uint8_t acc_objstatus; + uint8_t acc_obj_lat_pos_1; + uint8_t acc_obj_lat_pos_2; + uint8_t acc_obj_dist_1; + uint8_t acc_obj_dist_2; + uint8_t acc_obj_rel_spd_1; + uint8_t acc_obj_rel_spd_2; +} ESCC_Msg; + +void send_escc_msg(const ESCC_Msg *msg, int bus_number); + +#endif diff --git a/tests/escc/enter_canloader.py b/tests/escc/enter_canloader.py new file mode 100755 index 0000000000..787799f245 --- /dev/null +++ b/tests/escc/enter_canloader.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import time +import argparse +from panda import Panda, CanHandle, McuType + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='Flash ESCC over can') + parser.add_argument('--recover', action='store_true') + parser.add_argument("fn", type=str, nargs='?', help="flash file") + args = parser.parse_args() + + p = Panda() + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + + while 1: + if len(p.can_recv()) == 0: + break + + if args.recover: + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x02", 0) + exit(0) + else: + p.can_send(0x200, b"\xce\xfa\xad\xde\x1e\x0b\xb0\x0a", 0) + + if args.fn: + time.sleep(0.1) + print("flashing", args.fn) + code = open(args.fn, "rb").read() + Panda.flash_static(CanHandle(p, 0), code, mcu_type=McuType.F4) + + print("can flash done")