diff --git a/.circleci/config.yml b/.circleci/config.yml index 2289ad8aa725e1..6b98610c507527 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -29,13 +29,17 @@ jobs: command: | docker run panda_build /bin/bash -c "cd /panda/board; make bin" - run: - name: Build Honda Pedal STM image + name: Build Panda STM bootstub image command: | - docker run panda_build /bin/bash -c "cd /panda/board/pedal_honda; make obj/comma.bin" + docker run panda_build /bin/bash -c "cd /panda/board; make obj/bootstub.panda.bin" - run: - name: Build Toyota Pedal STM image + name: Build Pedal STM image command: | - docker run panda_build /bin/bash -c "cd /panda/board/pedal_toyota; make obj/comma.bin" + docker run panda_build /bin/bash -c "cd /panda/board/pedal; make obj/comma.bin" + - run: + name: Build Pedal STM bootstub image + command: | + docker run panda_build /bin/bash -c "cd /panda/board/pedal; make obj/bootstub.bin" - run: name: Build NEO STM image command: | diff --git a/board/build.mk b/board/build.mk index 9f2c4250c2c772..a84ed3fd9d9193 100644 --- a/board/build.mk +++ b/board/build.mk @@ -2,6 +2,14 @@ CFLAGS += -I inc -I ../ -nostdlib -fno-builtin -std=gnu11 -Os CFLAGS += -Tstm32_flash.ld +# Compile fast charge (DCP) only not on EON +ifeq (,$(wildcard /EON)) + BUILDER = DEV +else + CFLAGS += "-DEON" + BUILDER = EON +endif + CC = arm-none-eabi-gcc OBJCOPY = arm-none-eabi-objcopy OBJDUMP = arm-none-eabi-objdump diff --git a/board/gpio.h b/board/gpio.h index 6112f6f887c703..7bd24ecbb7c32d 100644 --- a/board/gpio.h +++ b/board/gpio.h @@ -454,6 +454,7 @@ void early() { #ifdef PANDA // enable the ESP, disable ESP boot mode // unless we are on a giant panda, then there's no ESP + // dont disable on grey panda if (is_giant_panda) { set_esp_mode(ESP_DISABLED); } else { diff --git a/board/main.c b/board/main.c index 16d64916a2ef36..8ee1bb0c8c830c 100644 --- a/board/main.c +++ b/board/main.c @@ -539,6 +539,9 @@ int main() { } else { // enable ESP uart uart_init(USART1, 115200); + #ifdef EON + set_esp_mode(ESP_DISABLED); + #endif } // enable LIN uart_init(UART5, 10400); @@ -590,8 +593,6 @@ int main() { uint64_t marker = 0; #define CURRENT_THRESHOLD 0xF00 #define CLICKS 8 - // Enough clicks to ensure that enumeration happened. Should be longer than bootup time of the device connected to EON - #define CLICKS_BOOTUP 30 #endif for (cnt=0;;cnt++) { @@ -618,8 +619,9 @@ int main() { } break; case USB_POWER_CDP: - // been CLICKS_BOOTUP clicks since we switched to CDP - if ((cnt-marker) >= CLICKS_BOOTUP ) { +#ifndef EON + // been CLICKS clicks since we switched to CDP + if ((cnt-marker) >= CLICKS) { // measure current draw, if positive and no enumeration, switch to DCP if (!is_enumerated && current < CURRENT_THRESHOLD) { puts("USBP: no enumeration with current draw, switching to DCP mode\n"); @@ -631,6 +633,7 @@ int main() { if (current >= CURRENT_THRESHOLD) { marker = cnt; } +#endif break; case USB_POWER_DCP: // been at least CLICKS clicks since we switched to DCP diff --git a/board/pedal_honda/.gitignore b/board/pedal/.gitignore similarity index 100% rename from board/pedal_honda/.gitignore rename to board/pedal/.gitignore diff --git a/board/pedal_honda/Makefile b/board/pedal/Makefile similarity index 85% rename from board/pedal_honda/Makefile rename to board/pedal/Makefile index 9917e381503b03..37b95f90fb1880 100644 --- a/board/pedal_honda/Makefile +++ b/board/pedal/Makefile @@ -30,12 +30,20 @@ recover: obj/bootstub.bin obj/$(PROJ_NAME).bin $(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin $(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.bin +include ../../common/version.mk + +obj/cert.h: ../../crypto/getcertheader.py + ../../crypto/getcertheader.py ../../certs/debug.pub ../../certs/release.pub > $@ + obj/main.o: main.c ../*.h mkdir -p obj $(CC) $(CFLAGS) -o $@ -c $< -obj/bootstub.o: ../bootstub.c ../*.h +obj/bootstub.o: ../bootstub.c ../*.h obj/gitversion.h obj/cert.h mkdir -p obj + mkdir -p ../obj + cp obj/gitversion.h ../obj/gitversion.h + cp obj/cert.h ../obj/cert.h $(CC) $(CFLAGS) -o $@ -c $< obj/$(STARTUP_FILE).o: ../$(STARTUP_FILE).s diff --git a/board/pedal_honda/README b/board/pedal/README similarity index 100% rename from board/pedal_honda/README rename to board/pedal/README diff --git a/board/pedal_honda/main.c b/board/pedal/main.c similarity index 83% rename from board/pedal_honda/main.c rename to board/pedal/main.c index 5d5264791ccf54..13a221a871fafc 100644 --- a/board/pedal_honda/main.c +++ b/board/pedal/main.c @@ -70,21 +70,24 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { #endif -// ***************************** honda can checksum ***************************** - -int can_cksum(uint8_t *dat, int len, int addr, int idx) { - int i; - int s = 0; - for (i = 0; i < len; i++) { - s += (dat[i] >> 4); - s += dat[i] & 0xF; +// ***************************** pedal can checksum ***************************** + +uint8_t pedal_checksum(uint8_t *dat, int len) { + uint8_t crc = 0xFF; + uint8_t poly = 0xD5; // standard crc8 + int i, j; + for (i = len - 1; i >= 0; i--) { + crc ^= dat[i]; + for (j = 0; j < 8; j++) { + if ((crc & 0x80) != 0) { + crc = (uint8_t)((crc << 1) ^ poly); + } + else { + crc <<= 1; + } + } } - s += (addr>>0)&0xF; - s += (addr>>4)&0xF; - s += (addr>>8)&0xF; - s += idx; - s = 8-s; - return s&0xF; + return crc; } // ***************************** can port ***************************** @@ -92,6 +95,8 @@ int can_cksum(uint8_t *dat, int len, int addr, int idx) { // addresses to be used on CAN #define CAN_GAS_INPUT 0x200 #define CAN_GAS_OUTPUT 0x201 +#define CAN_GAS_SIZE 6 +#define COUNTER_CYCLE 0xF void CAN1_TX_IRQHandler() { // clear interrupt @@ -134,14 +139,19 @@ void CAN1_RX0_IRQHandler() { } // normal packet - uint8_t *dat = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR; - uint8_t *dat2 = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR; + uint8_t dat[8]; + uint8_t *rdlr = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR; + uint8_t *rdhr = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR; + for (int i=0; i<4; i++) { + dat[i] = rdlr[i]; + dat[i+4] = rdhr[i]; + } uint16_t value_0 = (dat[0] << 8) | dat[1]; uint16_t value_1 = (dat[2] << 8) | dat[3]; - uint8_t enable = (dat2[0] >> 7) & 1; - uint8_t index = (dat2[1] >> 4) & 3; - if (can_cksum(dat, 5, CAN_GAS_INPUT, index) == (dat2[1] & 0xF)) { - if (((current_index+1)&3) == index) { + uint8_t enable = (dat[4] >> 7) & 1; + uint8_t index = dat[4] & COUNTER_CYCLE; + if (pedal_checksum(dat, CAN_GAS_SIZE - 1) == dat[5]) { + if (((current_index + 1) & COUNTER_CYCLE) == index) { #ifdef DEBUG puts("setting gas "); puth(value); @@ -196,18 +206,18 @@ void TIM3_IRQHandler() { // check timer for sending the user pedal and clearing the CAN if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { uint8_t dat[8]; - dat[0] = (pdl0>>8)&0xFF; - dat[1] = (pdl0>>0)&0xFF; - dat[2] = (pdl1>>8)&0xFF; - dat[3] = (pdl1>>0)&0xFF; - dat[4] = state; - dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT, pkt_idx) | (pkt_idx<<4); + dat[0] = (pdl0>>8) & 0xFF; + dat[1] = (pdl0>>0) & 0xFF; + dat[2] = (pdl1>>8) & 0xFF; + dat[3] = (pdl1>>0) & 0xFF; + dat[4] = (state & 0xF) << 4 | pkt_idx; + dat[5] = pedal_checksum(dat, CAN_GAS_SIZE - 1); CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1]<<8) | (dat[2]<<16) | (dat[3]<<24); CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5]<<8); CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5 CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1; ++pkt_idx; - pkt_idx &= 3; + pkt_idx &= COUNTER_CYCLE; } else { // old can packet hasn't sent! state = FAULT_SEND; diff --git a/board/pedal_honda/obj/.gitkeep b/board/pedal/obj/.gitkeep similarity index 100% rename from board/pedal_honda/obj/.gitkeep rename to board/pedal/obj/.gitkeep diff --git a/board/pedal_toyota/.gitignore b/board/pedal_toyota/.gitignore deleted file mode 100644 index 94053f2925089b..00000000000000 --- a/board/pedal_toyota/.gitignore +++ /dev/null @@ -1 +0,0 @@ -obj/* diff --git a/board/pedal_toyota/Makefile b/board/pedal_toyota/Makefile deleted file mode 100644 index 1235cc7156ed9f..00000000000000 --- a/board/pedal_toyota/Makefile +++ /dev/null @@ -1,58 +0,0 @@ -# :set noet -PROJ_NAME = comma - -CFLAGS = -O2 -Wall -std=gnu11 -DPEDAL -CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3 -CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx -CFLAGS += -I ../inc -I ../ -I ../../ -nostdlib -CFLAGS += -T../stm32_flash.ld - -STARTUP_FILE = startup_stm32f205xx - -CC = arm-none-eabi-gcc -OBJCOPY = arm-none-eabi-objcopy -OBJDUMP = arm-none-eabi-objdump -DFU_UTIL = "dfu-util" - -# pedal only uses the debug cert -CERT = ../../certs/debug -CFLAGS += "-DALLOW_DEBUG" - -canflash: obj/$(PROJ_NAME).bin - ../../tests/pedal/enter_canloader.py $< - -usbflash: obj/$(PROJ_NAME).bin - ../../tests/pedal/enter_canloader.py; sleep 0.5 - PYTHONPATH=../../ python -c "from python import Panda; p = [x for x in [Panda(x) for x in Panda.list()] if x.bootstub]; assert(len(p)==1); p[0].flash('obj/$(PROJ_NAME).bin', reconnect=False)" - -recover: obj/bootstub.bin obj/$(PROJ_NAME).bin - ../../tests/pedal/enter_canloader.py --recover; sleep 0.5 - $(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08004000 -D obj/$(PROJ_NAME).bin - $(DFU_UTIL) -d 0483:df11 -a 0 -s 0x08000000:leave -D obj/bootstub.bin - -obj/main.o: main.c ../*.h - mkdir -p obj - $(CC) $(CFLAGS) -o $@ -c $< - -obj/bootstub.o: ../bootstub.c ../*.h - mkdir -p obj - $(CC) $(CFLAGS) -o $@ -c $< - -obj/$(STARTUP_FILE).o: ../$(STARTUP_FILE).s - $(CC) $(CFLAGS) -o $@ -c $< - -obj/%.o: ../../crypto/%.c - $(CC) $(CFLAGS) -o $@ -c $< - -obj/$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/main.o - # hack - $(CC) -Wl,--section-start,.isr_vector=0x8004000 $(CFLAGS) -o obj/$(PROJ_NAME).elf $^ - $(OBJCOPY) -v -O binary obj/$(PROJ_NAME).elf obj/code.bin - SETLEN=1 ../../crypto/sign.py obj/code.bin $@ $(CERT) - -obj/bootstub.bin: obj/$(STARTUP_FILE).o obj/bootstub.o obj/sha.o obj/rsa.o - $(CC) $(CFLAGS) -o obj/bootstub.$(PROJ_NAME).elf $^ - $(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@ - -clean: - rm -f obj/* diff --git a/board/pedal_toyota/README b/board/pedal_toyota/README deleted file mode 100644 index f7c56c3bf40279..00000000000000 --- a/board/pedal_toyota/README +++ /dev/null @@ -1,30 +0,0 @@ -MOVE ALL FILES TO board/pedal TO FLASH - - -This is the firmware for the comma pedal. It borrows a lot from panda. - -The comma pedal is a gas pedal interceptor for Honda/Acura. It allows you to "virtually" press the pedal. - -This is the open source software. Note that it is not ready to use yet. - -== Test Plan == - -* Startup -** Confirm STATE_FAULT_STARTUP -* Timeout -** Send value -** Confirm value is output -** Stop sending messages -** Confirm value is passthru after 100ms -** Confirm STATE_FAULT_TIMEOUT -* Random values -** Send random 6 byte messages -** Confirm random values cause passthru -** Confirm STATE_FAULT_BAD_CHECKSUM -* Same message lockout -** Send same message repeated -** Confirm timeout behavior -* Don't set enable -** Confirm no output -* Set enable and values -** Confirm output diff --git a/board/pedal_toyota/main.c b/board/pedal_toyota/main.c deleted file mode 100644 index a9b6cec46732f2..00000000000000 --- a/board/pedal_toyota/main.c +++ /dev/null @@ -1,291 +0,0 @@ -//#define DEBUG -//#define CAN_LOOPBACK_MODE -//#define USE_INTERNAL_OSC - -#include "../config.h" - -#include "drivers/drivers.h" -#include "drivers/llgpio.h" -#include "gpio.h" - -#define CUSTOM_CAN_INTERRUPTS - -#include "libc.h" -#include "safety.h" -#include "drivers/adc.h" -#include "drivers/uart.h" -#include "drivers/dac.h" -#include "drivers/can.h" -#include "drivers/timer.h" - -#define CAN CAN1 - -//#define PEDAL_USB - -#ifdef PEDAL_USB - #include "drivers/usb.h" -#endif - -#define ENTER_BOOTLOADER_MAGIC 0xdeadbeef -uint32_t enter_bootloader_mode; - -void __initialize_hardware_early() { - early(); -} - -// ********************* serial debugging ********************* - -void debug_ring_callback(uart_ring *ring) { - char rcv; - while (getc(ring, &rcv)) { - putc(ring, rcv); - } -} - -#ifdef PEDAL_USB - -int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { return 0; } -void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) {} -void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) {} -void usb_cb_enumeration_complete() {} - -int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { - int resp_len = 0; - uart_ring *ur = NULL; - switch (setup->b.bRequest) { - // **** 0xe0: uart read - case 0xe0: - ur = get_ring_by_number(setup->b.wValue.w); - if (!ur) break; - if (ur == &esp_ring) uart_dma_drain(); - // read - while ((resp_len < min(setup->b.wLength.w, MAX_RESP_LEN)) && - getc(ur, (char*)&resp[resp_len])) { - ++resp_len; - } - break; - } - return resp_len; -} - -#endif - -// ***************************** toyota can checksum **************************** - -int can_cksum(uint8_t *dat, uint8_t len, uint16_t addr) -{ - uint8_t checksum = 0; - checksum =((addr & 0xFF00) >> 8) + (addr & 0x00FF) + len + 1; - //uint16_t temp_msg = msg; - - for (int ii = 0; ii < len; ii++) - { - checksum += (dat[ii]); - //temp_msg = temp_msg >> 8; - } - //return ((msg & ~0xFF) & (checksum & 0xFF)); - return checksum; -} - -// ***************************** can port ***************************** - -// addresses to be used on CAN -#define CAN_GAS_INPUT 0x200 -#define CAN_GAS_OUTPUT 0x201 - -void CAN1_TX_IRQHandler() { - // clear interrupt - CAN->TSR |= CAN_TSR_RQCP0; -} - -// two independent values -uint16_t gas_set_0 = 0; -uint16_t gas_set_1 = 0; - -#define MAX_TIMEOUT 10 -uint32_t timeout = 0; - -#define NO_FAULT 0 -#define FAULT_BAD_CHECKSUM 1 -#define FAULT_SEND 2 -#define FAULT_SCE 3 -#define FAULT_STARTUP 4 -#define FAULT_TIMEOUT 5 -#define FAULT_INVALID 6 -uint8_t state = FAULT_STARTUP; - -void CAN1_RX0_IRQHandler() { - while (CAN->RF0R & CAN_RF0R_FMP0) { - #ifdef DEBUG - puts("CAN RX\n"); - #endif - uint32_t address = CAN->sFIFOMailBox[0].RIR>>21; - if (address == CAN_GAS_INPUT) { - // softloader entry - if (CAN->sFIFOMailBox[0].RDLR == 0xdeadface) { - if (CAN->sFIFOMailBox[0].RDHR == 0x0ab00b1e) { - enter_bootloader_mode = ENTER_SOFTLOADER_MAGIC; - NVIC_SystemReset(); - } else if (CAN->sFIFOMailBox[0].RDHR == 0x02b00b1e) { - enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC; - NVIC_SystemReset(); - } - } - - // normal packet - uint8_t *dat = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR; - uint8_t *dat2 = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR; - uint16_t value_0 = (dat[0] << 8) | dat[1]; - uint16_t value_1 = (dat[2] << 8) | dat[3]; - uint8_t enable = (dat2[0] >> 7) & 1; - uint8_t index = 0; - if (can_cksum(dat, 5, CAN_GAS_INPUT) == dat2[1]) { - if (index == 0) { - #ifdef DEBUG - puts("setting gas "); - puth(value); - puts("\n"); - #endif - if (enable) { - gas_set_0 = value_0; - gas_set_1 = value_1; - } else { - // clear the fault state if values are 0 - if (value_0 == 0 && value_1 == 0) { - state = NO_FAULT; - } else { - state = FAULT_INVALID; - } - gas_set_0 = gas_set_1 = 0; - } - // clear the timeout - timeout = 0; - } - - } else { - // wrong checksum = fault - state = FAULT_BAD_CHECKSUM; - } - } - // next - CAN->RF0R |= CAN_RF0R_RFOM0; - } -} - -void CAN1_SCE_IRQHandler() { - state = FAULT_SCE; - can_sce(CAN); -} - -int pdl0 = 0, pdl1 = 0; - - -int led_value = 0; - -void TIM3_IRQHandler() { - #ifdef DEBUG - puth(TIM3->CNT); - puts(" "); - puth(pdl0); - puts(" "); - puth(pdl1); - puts("\n"); - #endif - - // check timer for sending the user pedal and clearing the CAN - if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { - uint8_t dat[8]; - dat[0] = (pdl0>>8)&0xFF; - dat[1] = (pdl0>>0)&0xFF; - dat[2] = (pdl1>>8)&0xFF; - dat[3] = (pdl1>>0)&0xFF; - dat[4] = state; - dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT); - CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1]<<8) | (dat[2]<<16) | (dat[3]<<24); - CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5]<<8); - CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5 - CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1; - } else { - // old can packet hasn't sent! - state = FAULT_SEND; - #ifdef DEBUG - puts("CAN MISS\n"); - #endif - } - - // blink the LED - set_led(LED_GREEN, led_value); - led_value = !led_value; - - TIM3->SR = 0; - - // up timeout for gas set - if (timeout == MAX_TIMEOUT) { - state = FAULT_TIMEOUT; - } else { - timeout += 1; - } -} - -// ***************************** main code ***************************** - -void pedal() { - // read/write - pdl0 = adc_get(ADCCHAN_ACCEL0); - pdl1 = adc_get(ADCCHAN_ACCEL1); - - // write the pedal to the DAC - if (state == NO_FAULT) { - dac_set(0, max(gas_set_0, pdl0)); - dac_set(1, max(gas_set_1, pdl1)); - } else { - dac_set(0, pdl0); - dac_set(1, pdl1); - } - - // feed the watchdog - IWDG->KR = 0xAAAA; -} - -int main() { - __disable_irq(); - - // init devices - clock_init(); - periph_init(); - gpio_init(); - -#ifdef PEDAL_USB - // enable USB - usb_init(); -#endif - - // pedal stuff - dac_init(); - adc_init(); - - // init can - can_silent = ALL_CAN_LIVE; - can_init(0); - - // 48mhz / 65536 ~= 732 - timer_init(TIM3, 15); - NVIC_EnableIRQ(TIM3_IRQn); - - // setup watchdog - IWDG->KR = 0x5555; - IWDG->PR = 0; // divider /4 - // 0 = 0.125 ms, let's have a 50ms watchdog - IWDG->RLR = 400 - 1; - IWDG->KR = 0xCCCC; - - puts("**** INTERRUPTS ON ****\n"); - __enable_irq(); - - // main pedal loop - while (1) { - pedal(); - } - - return 0; -} \ No newline at end of file diff --git a/board/pedal_toyota/obj/.gitkeep b/board/pedal_toyota/obj/.gitkeep deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/board/safety/safety_subaru.h b/board/safety/safety_subaru.h index 3d21d2269a733e..00fe1abf91d2f7 100644 --- a/board/safety/safety_subaru.h +++ b/board/safety/safety_subaru.h @@ -1,28 +1,110 @@ -void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {} +const int SUBARU_MAX_STEER = 2047; // 1s +// real time torque limit to prevent controls spamming +// the real time limit is 1500/sec +const int SUBARU_MAX_RT_DELTA = 940; // max delta torque allowed for real time checks +const int32_t SUBARU_RT_INTERVAL = 250000; // 250ms between real time checks +const int SUBARU_MAX_RATE_UP = 50; +const int SUBARU_MAX_RATE_DOWN = 70; +const int SUBARU_DRIVER_TORQUE_ALLOWANCE = 60; +const int SUBARU_DRIVER_TORQUE_FACTOR = 10; -// FIXME -// *** all output safety mode *** +int subaru_cruise_engaged_last = 0; +int subaru_rt_torque_last = 0; +int subaru_desired_torque_last = 0; +uint32_t subaru_ts_last = 0; +struct sample_t subaru_torque_driver; // last few driver torques measured -static void subaru_init(int16_t param) { - controls_allowed = 1; + +static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { + int bus_number = (to_push->RDTR >> 4) & 0xFF; + uint32_t addr = to_push->RIR >> 21; + + if ((addr == 0x119) && (bus_number == 0)){ + int torque_driver_new = ((to_push->RDLR >> 16) & 0x7FF); + torque_driver_new = to_signed(torque_driver_new, 11); + // update array of samples + update_sample(&subaru_torque_driver, torque_driver_new); + } + + // enter controls on rising edge of ACC, exit controls on ACC off + if ((addr == 0x240) && (bus_number == 0)) { + int cruise_engaged = (to_push->RDHR >> 9) & 1; + if (cruise_engaged && !subaru_cruise_engaged_last) { + controls_allowed = 1; + } else if (!cruise_engaged) { + controls_allowed = 0; + } + subaru_cruise_engaged_last = cruise_engaged; + } } static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { + uint32_t addr = to_send->RIR >> 21; + + // steer cmd checks + if (addr == 0x122) { + int desired_torque = ((to_send->RDLR >> 16) & 0x1FFF); + int violation = 0; + uint32_t ts = TIM2->CNT; + desired_torque = to_signed(desired_torque, 13); + + if (controls_allowed) { + + // *** global torque limit check *** + violation |= max_limit_check(desired_torque, SUBARU_MAX_STEER, -SUBARU_MAX_STEER); + + // *** torque rate limit check *** + int desired_torque_last = subaru_desired_torque_last; + violation |= driver_limit_check(desired_torque, desired_torque_last, &subaru_torque_driver, + SUBARU_MAX_STEER, SUBARU_MAX_RATE_UP, SUBARU_MAX_RATE_DOWN, + SUBARU_DRIVER_TORQUE_ALLOWANCE, SUBARU_DRIVER_TORQUE_FACTOR); + + // used next time + subaru_desired_torque_last = desired_torque; + + // *** torque real time rate limit check *** + violation |= rt_rate_limit_check(desired_torque, subaru_rt_torque_last, SUBARU_MAX_RT_DELTA); + + // every RT_INTERVAL set the new limits + uint32_t ts_elapsed = get_ts_elapsed(ts, subaru_ts_last); + if (ts_elapsed > SUBARU_RT_INTERVAL) { + subaru_rt_torque_last = desired_torque; + subaru_ts_last = ts; + } + } + + // no torque if controls is not allowed + if (!controls_allowed && (desired_torque != 0)) { + violation = 1; + } + + // reset to 0 if either controls is not allowed or there's a violation + if (violation || !controls_allowed) { + subaru_desired_torque_last = 0; + subaru_rt_torque_last = 0; + subaru_ts_last = ts; + } + + if (violation) { + return false; + } + + } return true; } static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { - + // shifts bits 29 > 11 int32_t addr = to_fwd->RIR >> 21; // forward CAN 0 > 1 if (bus_num == 0) { - return 1; // ES CAN + return 2; // ES CAN } // forward CAN 1 > 0, except ES_LKAS - else if (bus_num == 1) { - + else if (bus_num == 2) { + // outback 2015 if (addr == 0x164) { return -1; @@ -40,10 +122,10 @@ static int subaru_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { } const safety_hooks subaru_hooks = { - .init = subaru_init, + .init = nooutput_init, .rx = subaru_rx_hook, .tx = subaru_tx_hook, .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = subaru_fwd_hook, -}; \ No newline at end of file +}; diff --git a/board/safety/safety_toyota.h b/board/safety/safety_toyota.h index 9cab1512f167cb..50d457ab69c6c7 100644 --- a/board/safety/safety_toyota.h +++ b/board/safety/safety_toyota.h @@ -79,6 +79,15 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // no IPAS in non IPAS mode if (((to_send->RIR>>21) == 0x266) || ((to_send->RIR>>21) == 0x167)) return false; + // GAS PEDAL: safety check + if ((to_send->RIR>>21) == 0x200) { + if (controls_allowed && toyota_actuation_limits) { + // all messages are fine here + } else { + if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; + } + } + // ACCEL: safety check on byte 1-2 if ((to_send->RIR>>21) == 0x343) { int desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF); diff --git a/common/version.mk b/common/version.mk index cc42223da3d03d..cc66efaa6dbc4b 100644 --- a/common/version.mk +++ b/common/version.mk @@ -1,18 +1,20 @@ ifeq ($(RELEASE),1) - BUILD_TYPE = "RELEASE" + BUILD_TYPE = "RELEASE" else - BUILD_TYPE = "DEBUG" + BUILD_TYPE = "DEBUG" endif -ifneq ($(wildcard ../.git/HEAD),) -obj/gitversion.h: ../VERSION ../.git/HEAD ../.git/index - echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@ +SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) + +ifneq ($(wildcard $(SELF_DIR)/../.git/HEAD),) +obj/gitversion.h: $(SELF_DIR)/../VERSION $(SELF_DIR)/../.git/HEAD $(SELF_DIR)/../.git/index + echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@ else -ifneq ($(wildcard ../../.git/modules/panda/HEAD),) -obj/gitversion.h: ../VERSION ../../.git/modules/panda/HEAD ../../.git/modules/panda/index - echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@ +ifneq ($(wildcard $(SELF_DIR)/../../.git/modules/panda/HEAD),) +obj/gitversion.h: $(SELF_DIR)/../VERSION $(SELF_DIR)/../../.git/modules/panda/HEAD $(SELF_DIR)/../../.git/modules/panda/index + echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-$(shell git rev-parse --short=8 HEAD)-$(BUILD_TYPE)\";" > $@ else -obj/gitversion.h: ../VERSION - echo "const uint8_t gitversion[] = \"$(shell cat ../VERSION)-unknown-$(BUILD_TYPE)\";" > $@ +obj/gitversion.h: $(SELF_DIR)/../VERSION + echo "const uint8_t gitversion[] = \"$(shell cat $(SELF_DIR)/../VERSION)-$(BUILDER)-unknown-$(BUILD_TYPE)\";" > $@ endif endif diff --git a/python/__init__.py b/python/__init__.py index c49ee83622f523..b3610e6c3f9970 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -8,6 +8,7 @@ import os import time import traceback +import subprocess from dfu import PandaDFU from esptool import ESPROM, CesantaFlasher from flash_release import flash_release @@ -25,7 +26,13 @@ def build_st(target, mkfile="Makefile"): from panda import BASEDIR - assert(os.system('cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "board"), mkfile, mkfile, target)) == 0) + cmd = 'cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "board"), mkfile, mkfile, target) + try: + output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as exception: + output = exception.output + returncode = exception.returncode + raise def parse_can_buffer(dat): ret = [] @@ -243,6 +250,7 @@ def flash_static(handle, code): pass def flash(self, fn=None, code=None, reconnect=True): + print("flash: main version is " + self.get_version()) if not self.bootstub: self.reset(enter_bootstub=True) assert(self.bootstub) @@ -263,7 +271,7 @@ def flash(self, fn=None, code=None, reconnect=True): code = f.read() # get version - print("flash: version is "+self.get_version()) + print("flash: bootstub version is " + self.get_version()) # do flash Panda.flash_static(self._handle, code) @@ -541,4 +549,3 @@ def kline_recv(self, bus=2): msg = self.kline_ll_recv(2, bus=bus) msg += self.kline_ll_recv(ord(msg[1])-2, bus=bus) return msg - diff --git a/python/update.py b/python/update.py index d393df9fb44152..ce730e4919119e 100755 --- a/python/update.py +++ b/python/update.py @@ -8,6 +8,8 @@ def ensure_st_up_to_date(): with open(os.path.join(BASEDIR, "VERSION")) as f: repo_version = f.read() + repo_version += "-EON" if os.path.isfile('/EON') else "-DEV" + panda = None panda_dfu = None should_flash_recover = False @@ -24,7 +26,7 @@ def ensure_st_up_to_date(): if len(panda_dfu) > 0: panda_dfu = PandaDFU(panda_dfu[0]) panda_dfu.recover() - + print "waiting for board..." time.sleep(1) diff --git a/tests/safety/libpandasafety_py.py b/tests/safety/libpandasafety_py.py index 53936761d52d3b..d8cb27cf8c8092 100644 --- a/tests/safety/libpandasafety_py.py +++ b/tests/safety/libpandasafety_py.py @@ -30,25 +30,20 @@ uint32_t CNT; } TIM_TypeDef; -void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); -int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); -void toyota_init(int16_t param); void set_controls_allowed(int c); -void reset_angle_control(void); int get_controls_allowed(void); -void init_tests_toyota(void); void set_timer(int t); -void set_toyota_torque_meas(int min, int max); -void set_cadillac_torque_driver(int min, int max); -void set_gm_torque_driver(int min, int max); -void set_hyundai_torque_driver(int min, int max); -void set_chrysler_torque_meas(int min, int max); -void set_toyota_rt_torque_last(int t); -void set_toyota_desired_torque_last(int t); +void reset_angle_control(void); + +void init_tests_toyota(void); +void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); +int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); +void toyota_init(int16_t param); int get_toyota_torque_meas_min(void); int get_toyota_torque_meas_max(void); -int get_chrysler_torque_meas_min(void); -int get_chrysler_torque_meas_max(void); +void set_toyota_torque_meas(int min, int max); +void set_toyota_desired_torque_last(int t); +void set_toyota_rt_torque_last(int t); void init_tests_honda(void); int get_ego_speed(void); @@ -66,6 +61,7 @@ int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); void set_cadillac_desired_torque_last(int t); void set_cadillac_rt_torque_last(int t); +void set_cadillac_torque_driver(int min, int max); void init_tests_gm(void); void gm_init(int16_t param); @@ -73,6 +69,7 @@ int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); void set_gm_desired_torque_last(int t); void set_gm_rt_torque_last(int t); +void set_gm_torque_driver(int min, int max); void init_tests_hyundai(void); void nooutput_init(int16_t param); @@ -80,6 +77,7 @@ int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); void set_hyundai_desired_torque_last(int t); void set_hyundai_rt_torque_last(int t); +void set_hyundai_torque_driver(int min, int max); void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); @@ -89,6 +87,16 @@ int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); void set_chrysler_desired_torque_last(int t); void set_chrysler_rt_torque_last(int t); +int get_chrysler_torque_meas_min(void); +int get_chrysler_torque_meas_max(void); +void set_chrysler_torque_meas(int min, int max); + +void init_tests_subaru(void); +void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); +int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); +void set_subaru_desired_torque_last(int t); +void set_subaru_rt_torque_last(int t); +void set_subaru_torque_driver(int min, int max); """) diff --git a/tests/safety/test.c b/tests/safety/test.c index b1390c41c25528..9b4c807d72d3f7 100644 --- a/tests/safety/test.c +++ b/tests/safety/test.c @@ -26,7 +26,8 @@ struct sample_t toyota_torque_meas; struct sample_t cadillac_torque_driver; struct sample_t gm_torque_driver; struct sample_t hyundai_torque_driver; -struct sample_t chrysler_torque_driver; +struct sample_t chrysler_torque_meas; +struct sample_t subaru_torque_driver; TIM_TypeDef timer; TIM_TypeDef *TIM2 = &timer; @@ -87,6 +88,11 @@ void set_chrysler_torque_meas(int min, int max){ chrysler_torque_meas.max = max; } +void set_subaru_torque_driver(int min, int max){ + subaru_torque_driver.min = min; + subaru_torque_driver.max = max; +} + int get_chrysler_torque_meas_min(void){ return chrysler_torque_meas.min; } @@ -123,6 +129,10 @@ void set_chrysler_rt_torque_last(int t){ chrysler_rt_torque_last = t; } +void set_subaru_rt_torque_last(int t){ + subaru_rt_torque_last = t; +} + void set_toyota_desired_torque_last(int t){ toyota_desired_torque_last = t; } @@ -143,6 +153,10 @@ void set_chrysler_desired_torque_last(int t){ chrysler_desired_torque_last = t; } +void set_subaru_desired_torque_last(int t){ + subaru_desired_torque_last = t; +} + int get_ego_speed(void){ return ego_speed; } @@ -200,14 +214,23 @@ void init_tests_hyundai(void){ } void init_tests_chrysler(void){ - chrysler_torque_driver.min = 0; - chrysler_torque_driver.max = 0; + chrysler_torque_meas.min = 0; + chrysler_torque_meas.max = 0; chrysler_desired_torque_last = 0; chrysler_rt_torque_last = 0; chrysler_ts_last = 0; set_timer(0); } +void init_tests_subaru(void){ + subaru_torque_driver.min = 0; + subaru_torque_driver.max = 0; + subaru_desired_torque_last = 0; + subaru_rt_torque_last = 0; + subaru_ts_last = 0; + set_timer(0); +} + void init_tests_honda(void){ ego_speed = 0; gas_interceptor_detected = 0; diff --git a/tests/safety/test_chrysler.py b/tests/safety/test_chrysler.py index 568c92aaaadbf7..0fcfc3bcfbf07d 100755 --- a/tests/safety/test_chrysler.py +++ b/tests/safety/test_chrysler.py @@ -1,4 +1,6 @@ #!/usr/bin/env python2 +import csv +import glob import unittest import numpy as np import libpandasafety_py @@ -24,6 +26,11 @@ def sign(a): else: return -1 +def swap_bytes(data_str): + """Accepts string with hex, returns integer with order swapped for CAN.""" + a = int(data_str, 16) + return ((a & 0xff) << 24) + ((a & 0xff00) << 8) + ((a & 0x00ff0000) >> 8) + ((a & 0xff000000) >> 24) + class TestChryslerSafety(unittest.TestCase): @classmethod def setUp(cls): @@ -166,6 +173,33 @@ def test_torque_measurements(self): self.assertEqual(0, self.safety.get_chrysler_torque_meas_max()) self.assertEqual(0, self.safety.get_chrysler_torque_meas_min()) + def _replay_drive(self, csv_reader): + for row in csv_reader: + if len(row) != 4: # sometimes truncated at end of the file + continue + if row[0] == 'time': # skip CSV header + continue + addr = int(row[1]) + bus = int(row[2]) + data_str = row[3] # Example '081407ff0806e06f' + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = addr << 21 + to_send[0].RDHR = swap_bytes(data_str[8:]) + to_send[0].RDLR = swap_bytes(data_str[:8]) + if (bus == 128): + self.assertTrue(self.safety.chrysler_tx_hook(to_send), msg=row) + else: + self.safety.chrysler_rx_hook(to_send) + + def test_replay_drive(self): + # In Cabana, click "Save Log" and then put the downloaded CSV in this directory. + test_files = glob.glob('chrysler_*.csv') + for filename in test_files: + print 'testing %s' % filename + with open(filename) as csvfile: + reader = csv.reader(csvfile) + self._replay_drive(reader) + if __name__ == "__main__": unittest.main() diff --git a/tests/safety/test_subaru.py b/tests/safety/test_subaru.py new file mode 100644 index 00000000000000..a1e03fea15cc85 --- /dev/null +++ b/tests/safety/test_subaru.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python2 +import unittest +import numpy as np +import libpandasafety_py + +MAX_RATE_UP = 50 +MAX_RATE_DOWN = 70 +MAX_STEER = 2047 + +MAX_RT_DELTA = 940 +RT_INTERVAL = 250000 + +DRIVER_TORQUE_ALLOWANCE = 60; +DRIVER_TORQUE_FACTOR = 10; + +def twos_comp(val, bits): + if val >= 0: + return val + else: + return (2**bits) + val + +def sign(a): + if a > 0: + return 1 + else: + return -1 + +class TestSubaruSafety(unittest.TestCase): + @classmethod + def setUp(cls): + cls.safety = libpandasafety_py.libpandasafety + cls.safety.nooutput_init(0) + cls.safety.init_tests_subaru() + + def _set_prev_torque(self, t): + self.safety.set_subaru_desired_torque_last(t) + self.safety.set_subaru_rt_torque_last(t) + + def _torque_driver_msg(self, torque): + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = 0x119 << 21 + + t = twos_comp(torque, 11) + to_send[0].RDLR = ((t & 0x7FF) << 16) + return to_send + + def _torque_msg(self, torque): + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = 0x122 << 21 + + t = twos_comp(torque, 13) + to_send[0].RDLR = (t << 16) + return to_send + + def test_default_controls_not_allowed(self): + self.assertFalse(self.safety.get_controls_allowed()) + + def test_enable_control_allowed_from_cruise(self): + to_push = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_push[0].RIR = 0x240 << 21 + to_push[0].RDHR = 1 << 9 + + self.safety.subaru_rx_hook(to_push) + self.assertTrue(self.safety.get_controls_allowed()) + + def test_disable_control_allowed_from_cruise(self): + to_push = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_push[0].RIR = 0x240 << 21 + to_push[0].RDHR = 0 + + self.safety.set_controls_allowed(1) + self.safety.subaru_rx_hook(to_push) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_steer_safety_check(self): + for enabled in [0, 1]: + for t in range(-3000, 3000): + self.safety.set_controls_allowed(enabled) + self._set_prev_torque(t) + if abs(t) > MAX_STEER or (not enabled and abs(t) > 0): + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(t))) + else: + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t))) + + def test_manually_enable_controls_allowed(self): + self.safety.set_controls_allowed(1) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.set_controls_allowed(0) + self.assertFalse(self.safety.get_controls_allowed()) + + def test_non_realtime_limit_up(self): + self.safety.set_subaru_torque_driver(0, 0) + self.safety.set_controls_allowed(True) + + self._set_prev_torque(0) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(MAX_RATE_UP))) + self._set_prev_torque(0) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(-MAX_RATE_UP))) + + self._set_prev_torque(0) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(MAX_RATE_UP + 1))) + self.safety.set_controls_allowed(True) + self._set_prev_torque(0) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(-MAX_RATE_UP - 1))) + + def test_non_realtime_limit_down(self): + self.safety.set_subaru_torque_driver(0, 0) + self.safety.set_controls_allowed(True) + + def test_against_torque_driver(self): + self.safety.set_controls_allowed(True) + + for sign in [-1, 1]: + for t in np.arange(0, DRIVER_TORQUE_ALLOWANCE + 1, 1): + t *= -sign + self.safety.set_subaru_torque_driver(t, t) + self._set_prev_torque(MAX_STEER * sign) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(MAX_STEER * sign))) + + self.safety.set_subaru_torque_driver(DRIVER_TORQUE_ALLOWANCE + 1, DRIVER_TORQUE_ALLOWANCE + 1) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(-MAX_STEER))) + + # spot check some individual cases + for sign in [-1, 1]: + driver_torque = (DRIVER_TORQUE_ALLOWANCE + 10) * sign + torque_desired = (MAX_STEER - 10 * DRIVER_TORQUE_FACTOR) * sign + delta = 1 * sign + self._set_prev_torque(torque_desired) + self.safety.set_subaru_torque_driver(-driver_torque, -driver_torque) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(torque_desired))) + self._set_prev_torque(torque_desired + delta) + self.safety.set_subaru_torque_driver(-driver_torque, -driver_torque) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(torque_desired + delta))) + + self._set_prev_torque(MAX_STEER * sign) + self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN) * sign))) + self._set_prev_torque(MAX_STEER * sign) + self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(0))) + self._set_prev_torque(MAX_STEER * sign) + self.safety.set_subaru_torque_driver(-MAX_STEER * sign, -MAX_STEER * sign) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg((MAX_STEER - MAX_RATE_DOWN + 1) * sign))) + + + def test_realtime_limits(self): + self.safety.set_controls_allowed(True) + + for sign in [-1, 1]: + self.safety.init_tests_subaru() + self._set_prev_torque(0) + self.safety.set_subaru_torque_driver(0, 0) + for t in np.arange(0, MAX_RT_DELTA, 1): + t *= sign + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t))) + self.assertFalse(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1)))) + + self._set_prev_torque(0) + for t in np.arange(0, MAX_RT_DELTA, 1): + t *= sign + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(t))) + + # Increase timer to update rt_torque_last + self.safety.set_timer(RT_INTERVAL + 1) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA - 1)))) + self.assertTrue(self.safety.subaru_tx_hook(self._torque_msg(sign * (MAX_RT_DELTA + 1)))) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/safety/test_toyota.py b/tests/safety/test_toyota.py index 40bc4bcf5d8f97..52c7015af3e5bc 100644 --- a/tests/safety/test_toyota.py +++ b/tests/safety/test_toyota.py @@ -119,6 +119,13 @@ def _accel_msg(self, accel): to_send[0].RDLR = (a & 0xFF) << 8 | (a >> 8) return to_send + def _gas_msg(self, gas): + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = 0x200 << 21 + to_send[0].RDLR = gas + + return to_send + def test_default_controls_not_allowed(self): self.assertFalse(self.safety.get_controls_allowed()) @@ -409,6 +416,13 @@ def test_angle_measured_rate(self): # reset no angle control at the end of the test self.safety.reset_angle_control() + def test_gas_safety_check(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self.safety.honda_tx_hook(self._gas_msg(0x0000))) + self.assertFalse(self.safety.honda_tx_hook(self._gas_msg(0x1000))) + self.safety.set_controls_allowed(1) + self.assertTrue(self.safety.honda_tx_hook(self._gas_msg(0x1000))) + if __name__ == "__main__": unittest.main() diff --git a/tests/safety/trim_csv.py b/tests/safety/trim_csv.py new file mode 100755 index 00000000000000..511bd385f4e49a --- /dev/null +++ b/tests/safety/trim_csv.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python2 + +# This trims CAN message CSV files to just the messages relevant for Panda testing. +# Usage: +# cat input.csv | ./trim_csv.py > output.csv +import fileinput + +addr_to_keep = [544, 0x1f4, 0x292] # For Chrysler, update to the addresses that matter for you. + +for line in fileinput.input(): + line = line.strip() + cols = line.split(',') + if len(cols) != 4: + continue # malformed, such as at the end or every 60s. + (_, addr, bus, _) = cols + if (addr == 'addr'): + continue + if (int(bus) == 128): # Keep all messages sent by OpenPilot. + print line + elif (int(addr) in addr_to_keep): + print line