diff --git a/panda/.circleci/config.yml b/panda/.circleci/config.yml index 6b98610c507527..06dae5735bae71 100644 --- a/panda/.circleci/config.yml +++ b/panda/.circleci/config.yml @@ -12,6 +12,37 @@ jobs: name: Run safety test command: | docker run panda_safety /bin/bash -c "cd /panda/tests/safety; ./test.sh" + + misra-c2012: + machine: + docker_layer_caching: true + steps: + - checkout + - run: + name: Build image + command: "docker build -t panda_misra -f tests/misra/Dockerfile ." + - run: + name: Run Misra C 2012 test + command: | + mkdir /tmp/misra + docker run -v /tmp/misra:/tmp/misra panda_misra /bin/bash -c "cd /panda/tests/misra; ./test_misra.sh" + - store_artifacts: + name: Store misra test output + path: /tmp/misra/output.txt + + strict-compiler: + machine: + docker_layer_caching: true + steps: + - checkout + - run: + name: Build image + command: "docker build -t panda_strict_compiler -f tests/build_strict/Dockerfile ." + - run: + name: Build Panda with strict compiler rules + command: | + docker run panda_strict_compiler /bin/bash -c "cd /panda/board; make -f Makefile.strict clean; make -f Makefile.strict bin" + build: machine: docker_layer_caching: true @@ -40,10 +71,6 @@ jobs: 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: | - docker run panda_build /bin/bash -c "cd /panda/board; make clean; make -f Makefile.legacy obj/comma.bin" - run: name: Build ESP image command: | @@ -54,4 +81,6 @@ workflows: main: jobs: - safety + - misra-c2012 + - strict-compiler - build diff --git a/panda/.gitignore b/panda/.gitignore index 7b7762ef490663..70d010fabf3d7f 100644 --- a/panda/.gitignore +++ b/panda/.gitignore @@ -10,5 +10,6 @@ a.out dist/ pandacan.egg-info/ board/obj/ -examples/output.csv -.DS_Store +examples/output.csv +.DS_Store +nosetests.xml diff --git a/panda/Dockerfile b/panda/Dockerfile index 100509f514e000..1a0d924661d6ce 100644 --- a/panda/Dockerfile +++ b/panda/Dockerfile @@ -59,6 +59,4 @@ USER pandauser RUN cd /tmp/panda/boardesp && ./get_sdk_ci.sh USER root -COPY ./xx/pandaextra /tmp/pandaextra - ADD ./panda.tar.gz /tmp/panda diff --git a/panda/Jenkinsfile b/panda/Jenkinsfile index c67a1005151e49..0a861a5fa1ae2c 100644 --- a/panda/Jenkinsfile +++ b/panda/Jenkinsfile @@ -14,8 +14,6 @@ pipeline { steps { timeout(time: 60, unit: 'MINUTES') { script { - sh 'git clone --no-checkout --depth 1 git@github.com:commaai/xx.git || true' - sh 'cd xx && git fetch origin && git checkout origin/master -- pandaextra && cd ..' // Needed for certs for panda flashing sh 'git archive -v -o panda.tar.gz --format=tar.gz HEAD' dockerImage = docker.build("${env.DOCKER_IMAGE_TAG}") } diff --git a/panda/VERSION b/panda/VERSION index 24e56e03c0da59..23c38c24118c76 100644 --- a/panda/VERSION +++ b/panda/VERSION @@ -1 +1 @@ -v1.2.1 \ No newline at end of file +v1.3.1 \ No newline at end of file diff --git a/panda/board/Makefile.legacy b/panda/board/Makefile.legacy deleted file mode 100644 index f6f9f9f32822fc..00000000000000 --- a/panda/board/Makefile.legacy +++ /dev/null @@ -1,9 +0,0 @@ -# :set noet -PROJ_NAME = comma -CFLAGS = -g -Wall - -CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m3 -CFLAGS += -msoft-float -DSTM32F2 -DSTM32F205xx -STARTUP_FILE = startup_stm32f205xx - -include build.mk diff --git a/panda/board/Makefile.strict b/panda/board/Makefile.strict new file mode 100644 index 00000000000000..b2ff83d3091cd0 --- /dev/null +++ b/panda/board/Makefile.strict @@ -0,0 +1,8 @@ +PROJ_NAME = panda +CFLAGS = -g -Wall -Wextra -pedantic -Wstrict-prototypes + +CFLAGS += -mlittle-endian -mthumb -mcpu=cortex-m4 +CFLAGS += -mhard-float -DSTM32F4 -DSTM32F413xx -mfpu=fpv4-sp-d16 -fsingle-precision-constant +STARTUP_FILE = startup_stm32f413xx + +include build.mk diff --git a/panda/board/README.md b/panda/board/README.md index b3be654be31ebe..5fe2e4b238c2dd 100644 --- a/panda/board/README.md +++ b/panda/board/README.md @@ -23,12 +23,6 @@ Programming make ``` -**NEO** - -``` -make -f Makefile.legacy -``` - Troubleshooting ---- diff --git a/panda/board/bootstub.c b/panda/board/bootstub.c index e44986c29ec47c..6fcb386dea13f1 100644 --- a/panda/board/bootstub.c +++ b/panda/board/bootstub.c @@ -12,11 +12,14 @@ #include "stm32f2xx_hal_gpio_ex.h" #endif +// default since there's no serial +int puts(const char *a) { return 0; } +void puth(unsigned int i) {} + #include "libc.h" #include "provision.h" -#include "drivers/drivers.h" - +#include "drivers/clock.h" #include "drivers/llgpio.h" #include "gpio.h" @@ -24,15 +27,6 @@ #include "drivers/usb.h" //#include "drivers/uart.h" -#ifdef PEDAL -#define CUSTOM_CAN_INTERRUPTS -#include "safety.h" -#include "drivers/can.h" -#endif - -int puts(const char *a) { return 0; } -void puth(unsigned int i) {} - #include "crypto/rsa.h" #include "crypto/sha.h" diff --git a/panda/board/drivers/can.h b/panda/board/drivers/can.h index 9f02c2eba74d2d..43e4d41de8cbf4 100644 --- a/panda/board/drivers/can.h +++ b/panda/board/drivers/can.h @@ -1,10 +1,38 @@ -// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE, CAN2_TX, CAN2_RX0, CAN2_SCE, CAN3_TX, CAN3_RX0, CAN3_SCE +// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE +// CAN2_TX, CAN2_RX0, CAN2_SCE +// CAN3_TX, CAN3_RX0, CAN3_SCE + +typedef struct { + uint32_t w_ptr; + uint32_t r_ptr; + uint32_t fifo_size; + CAN_FIFOMailBox_TypeDef *elems; +} can_ring; + +#define CAN_BUS_RET_FLAG 0x80 +#define CAN_BUS_NUM_MASK 0x7F + +#define BUS_MAX 4 + +extern int can_live, pending_can_live; + +// must reinit after changing these +extern int can_loopback, can_silent; +extern uint32_t can_speed[]; + +void can_set_forwarding(int from, int to); + +void can_init(uint8_t can_number); +void can_init_all(); +void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); +int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem); + +// end API + #define ALL_CAN_SILENT 0xFF #define ALL_CAN_BUT_MAIN_SILENT 0xFE #define ALL_CAN_LIVE 0 -#include "lline_relay.h" - int can_live = 0, pending_can_live = 0, can_loopback = 0, can_silent = ALL_CAN_SILENT; // ********************* instantiate queues ********************* @@ -16,19 +44,9 @@ int can_live = 0, pending_can_live = 0, can_loopback = 0, can_silent = ALL_CAN_S can_buffer(rx_q, 0x1000) can_buffer(tx1_q, 0x100) can_buffer(tx2_q, 0x100) - -#ifdef PANDA - can_buffer(tx3_q, 0x100) - can_buffer(txgmlan_q, 0x100) - can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q}; -#else - can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q}; -#endif - -#ifdef PANDA -// Forward declare -void power_save_reset_timer(); -#endif +can_buffer(tx3_q, 0x100) +can_buffer(txgmlan_q, 0x100) +can_ring *can_queues[] = {&can_tx1_q, &can_tx2_q, &can_tx3_q, &can_txgmlan_q}; // ********************* interrupt safe queue ********************* @@ -85,76 +103,20 @@ int can_tx_cnt = 0; int can_txd_cnt = 0; int can_err_cnt = 0; -// NEO: Bus 1=CAN1 Bus 2=CAN2 // Panda: Bus 0=CAN1 Bus 1=CAN2 Bus 2=CAN3 -#ifdef PANDA - CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3}; - uint8_t bus_lookup[] = {0,1,2}; - uint8_t can_num_lookup[] = {0,1,2,-1}; - int8_t can_forwarding[] = {-1,-1,-1,-1}; - uint32_t can_speed[] = {5000, 5000, 5000, 333}; - bool can_autobaud_enabled[] = {false, false, false, false}; - #define CAN_MAX 3 -#else - CAN_TypeDef *cans[] = {CAN1, CAN2}; - uint8_t bus_lookup[] = {1,0}; - uint8_t can_num_lookup[] = {1,0}; - int8_t can_forwarding[] = {-1,-1}; - uint32_t can_speed[] = {5000, 5000}; - bool can_autobaud_enabled[] = {false, false}; - #define CAN_MAX 2 -#endif - -uint32_t can_autobaud_speeds[] = {5000, 2500, 1250, 1000, 10000}; -#define AUTOBAUD_SPEEDS_LEN (sizeof(can_autobaud_speeds) / sizeof(can_autobaud_speeds[0])) +CAN_TypeDef *cans[] = {CAN1, CAN2, CAN3}; +uint8_t bus_lookup[] = {0,1,2}; +uint8_t can_num_lookup[] = {0,1,2,-1}; +int8_t can_forwarding[] = {-1,-1,-1,-1}; +uint32_t can_speed[] = {5000, 5000, 5000, 333}; +#define CAN_MAX 3 #define CANIF_FROM_CAN_NUM(num) (cans[num]) -#ifdef PANDA #define CAN_NUM_FROM_CANIF(CAN) (CAN==CAN1 ? 0 : (CAN==CAN2 ? 1 : 2)) #define CAN_NAME_FROM_CANIF(CAN) (CAN==CAN1 ? "CAN1" : (CAN==CAN2 ? "CAN2" : "CAN3")) -#else -#define CAN_NUM_FROM_CANIF(CAN) (CAN==CAN1 ? 0 : 1) -#define CAN_NAME_FROM_CANIF(CAN) (CAN==CAN1 ? "CAN1" : "CAN2") -#endif #define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num]) #define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num]) -// other option -/*#define CAN_QUANTA 16 -#define CAN_SEQ1 13 -#define CAN_SEQ2 2*/ - -// this is needed for 1 mbps support -#define CAN_QUANTA 8 -#define CAN_SEQ1 6 // roundf(quanta * 0.875f) - 1; -#define CAN_SEQ2 1 // roundf(quanta * 0.125f); - -#define CAN_PCLK 24000 -// 333 = 33.3 kbps -// 5000 = 500 kbps -#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10 / (x)) - -void can_autobaud_speed_increment(uint8_t can_number) { - uint32_t autobaud_speed = can_autobaud_speeds[0]; - uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); - for (int i = 0; i < AUTOBAUD_SPEEDS_LEN; i++) { - if (can_speed[bus_number] == can_autobaud_speeds[i]) { - if (i+1 < AUTOBAUD_SPEEDS_LEN) { - autobaud_speed = can_autobaud_speeds[i+1]; - } - break; - } - } - can_speed[bus_number] = autobaud_speed; -#ifdef DEBUG - CAN_TypeDef* CAN = CANIF_FROM_CAN_NUM(can_number); - puts(CAN_NAME_FROM_CANIF(CAN)); - puts(" auto-baud test "); - putui(can_speed[bus_number]); - puts(" cbps\n"); -#endif -} - void process_can(uint8_t can_number); void can_set_speed(uint8_t can_number) { @@ -162,41 +124,14 @@ void can_set_speed(uint8_t can_number) { uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); while (true) { - // initialization mode - CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ; - while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK); - - // set time quanta from defines - CAN->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) | - (CAN_BTR_TS2_0 * (CAN_SEQ2-1)) | - (can_speed_to_prescaler(can_speed[bus_number]) - 1); - - // silent loopback mode for debugging - if (can_loopback) { - CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM; - } - if (can_silent & (1 << can_number)) { - CAN->BTR |= CAN_BTR_SILM; - } - - // reset - CAN->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM; - - #define CAN_TIMEOUT 1000000 - int tmp = 0; - while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++; - if (tmp < CAN_TIMEOUT) { + if (llcan_set_speed(CAN, can_speed[bus_number], can_loopback, can_silent & (1 << can_number))) { return; } - if (can_autobaud_enabled[bus_number]) { - can_autobaud_speed_increment(can_number); - } else { - puts("CAN init FAILED!!!!!\n"); - puth(can_number); puts(" "); - puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n"); - return; - } + puts("CAN init FAILED!!!!!\n"); + puth(can_number); puts(" "); + puth(BUS_NUM_FROM_CAN_NUM(can_number)); puts("\n"); + return; } } @@ -207,40 +142,7 @@ void can_init(uint8_t can_number) { set_can_enable(CAN, 1); can_set_speed(can_number); - // accept all filter - CAN->FMR |= CAN_FMR_FINIT; - - // no mask - CAN->sFilterRegister[0].FR1 = 0; - CAN->sFilterRegister[0].FR2 = 0; - CAN->sFilterRegister[14].FR1 = 0; - CAN->sFilterRegister[14].FR2 = 0; - CAN->FA1R |= 1 | (1 << 14); - - CAN->FMR &= ~(CAN_FMR_FINIT); - - // enable certain CAN interrupts - CAN->IER |= CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_WKUIE; - - switch (can_number) { - case 0: - NVIC_EnableIRQ(CAN1_TX_IRQn); - NVIC_EnableIRQ(CAN1_RX0_IRQn); - NVIC_EnableIRQ(CAN1_SCE_IRQn); - break; - case 1: - NVIC_EnableIRQ(CAN2_TX_IRQn); - NVIC_EnableIRQ(CAN2_RX0_IRQn); - NVIC_EnableIRQ(CAN2_SCE_IRQn); - break; -#ifdef CAN3 - case 2: - NVIC_EnableIRQ(CAN3_TX_IRQn); - NVIC_EnableIRQ(CAN3_RX0_IRQn); - NVIC_EnableIRQ(CAN3_SCE_IRQn); - break; -#endif - } + llcan_init(CAN); // in case there are queued up messages process_can(can_number); @@ -253,7 +155,6 @@ void can_init_all() { } void can_set_gmlan(int bus) { - #ifdef PANDA if (bus == -1 || bus != can_num_lookup[3]) { // GMLAN OFF switch (can_num_lookup[3]) { @@ -284,7 +185,7 @@ void can_set_gmlan(int bus) { can_num_lookup[1] = -1; can_num_lookup[3] = 1; can_init(1); - } else if (bus == 2 && revision == PANDA_REV_C) { + } else if (bus == 2) { puts("GMLAN on CAN3\n"); // GMLAN on CAN3 set_can_mode(2, 1); @@ -293,7 +194,6 @@ void can_set_gmlan(int bus) { can_num_lookup[3] = 2; can_init(2); } - #endif } // CAN error @@ -319,34 +219,8 @@ void can_sce(CAN_TypeDef *CAN) { puts("\n"); #endif - uint8_t can_number = CAN_NUM_FROM_CANIF(CAN); - uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); - - if (CAN->MSR & CAN_MSR_WKUI) { - //Waking from sleep - #ifdef DEBUG - puts("WAKE\n"); - #endif - set_can_enable(CAN, 1); - CAN->MSR &= ~(CAN_MSR_WKUI); - CAN->MSR = CAN->MSR; -#ifdef PANDA - power_save_reset_timer(); -#endif - } else { - can_err_cnt += 1; - - - if (can_autobaud_enabled[bus_number] && (CAN->ESR & CAN_ESR_LEC)) { - can_autobaud_speed_increment(can_number); - can_set_speed(can_number); - } - - // clear current send - CAN->TSR |= CAN_TSR_ABRQ0; - CAN->MSR &= ~(CAN_MSR_ERRI); - CAN->MSR = CAN->MSR; - } + can_err_cnt += 1; + llcan_clear_send(CAN); exit_critical_section(); } @@ -354,9 +228,6 @@ void can_sce(CAN_TypeDef *CAN) { void process_can(uint8_t can_number) { if (can_number == 0xff) return; -#ifdef PANDA - power_save_reset_timer(); -#endif enter_critical_section(); @@ -422,22 +293,9 @@ void process_can(uint8_t can_number) { // CAN receive handlers // blink blue when we are receiving CAN messages void can_rx(uint8_t can_number) { - #ifdef PANDA - power_save_reset_timer(); - #endif CAN_TypeDef *CAN = CANIF_FROM_CAN_NUM(can_number); uint8_t bus_number = BUS_NUM_FROM_CAN_NUM(can_number); while (CAN->RF0R & CAN_RF0R_FMP0) { - if (can_autobaud_enabled[bus_number]) { - can_autobaud_enabled[bus_number] = false; - puts(CAN_NAME_FROM_CANIF(CAN)); - #ifdef DEBUG - puts(" auto-baud "); - putui(can_speed[bus_number]); - puts(" cbps\n"); - #endif - } - can_rx_cnt += 1; // can is live @@ -454,25 +312,19 @@ void can_rx(uint8_t can_number) { to_push.RDTR = (to_push.RDTR & 0xFFFF000F) | (bus_number << 4); // forwarding (panda only) - #ifdef PANDA - if ((get_lline_status() != 0) || !relay_control) { //Relay engaged or relay isn't controlled, allow fwd - int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push); - if (bus_fwd_num != -1) { - CAN_FIFOMailBox_TypeDef to_send; - to_send.RIR = to_push.RIR | 1; // TXRQ - to_send.RDTR = to_push.RDTR; - to_send.RDLR = to_push.RDLR; - to_send.RDHR = to_push.RDHR; - can_send(&to_send, bus_fwd_num); - } - } - #endif + int bus_fwd_num = can_forwarding[bus_number] != -1 ? can_forwarding[bus_number] : safety_fwd_hook(bus_number, &to_push); + if (bus_fwd_num != -1) { + CAN_FIFOMailBox_TypeDef to_send; + to_send.RIR = to_push.RIR | 1; // TXRQ + to_send.RDTR = to_push.RDTR; + to_send.RDLR = to_push.RDLR; + to_send.RDHR = to_push.RDHR; + can_send(&to_send, bus_fwd_num); + } safety_rx_hook(&to_push); - #ifdef PANDA - set_led(LED_BLUE, 1); - #endif + set_led(LED_BLUE, 1); can_push(&can_rx_q, &to_push); // next @@ -480,8 +332,6 @@ void can_rx(uint8_t can_number) { } } -#ifndef CUSTOM_CAN_INTERRUPTS - void CAN1_TX_IRQHandler() { process_can(0); } void CAN1_RX0_IRQHandler() { can_rx(0); } void CAN1_SCE_IRQHandler() { can_sce(CAN1); } @@ -490,25 +340,19 @@ void CAN2_TX_IRQHandler() { process_can(1); } void CAN2_RX0_IRQHandler() { can_rx(1); } void CAN2_SCE_IRQHandler() { can_sce(CAN2); } -#ifdef CAN3 void CAN3_TX_IRQHandler() { process_can(2); } void CAN3_RX0_IRQHandler() { can_rx(2); } void CAN3_SCE_IRQHandler() { can_sce(CAN3); } -#endif - -#endif void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { - if (safety_tx_hook(to_push) && !can_autobaud_enabled[bus_number]) { + if (safety_tx_hook(to_push)) { if (bus_number < BUS_MAX) { // add CAN packet to send queue // bus number isn't passed through to_push->RDTR &= 0xF; if (bus_number == 3 && can_num_lookup[3] == 0xFF) { - #ifdef PANDA // TODO: why uint8 bro? only int8? bitbang_gmlan(to_push); - #endif } else { can_push(can_queues[bus_number], to_push); process_can(CAN_NUM_FROM_BUS_NUM(bus_number)); @@ -520,3 +364,4 @@ void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number) { void can_set_forwarding(int from, int to) { can_forwarding[from] = to; } + diff --git a/panda/board/drivers/clock.h b/panda/board/drivers/clock.h new file mode 100644 index 00000000000000..c999c3f597a9d0 --- /dev/null +++ b/panda/board/drivers/clock.h @@ -0,0 +1,40 @@ +void clock_init() { + // enable external oscillator + RCC->CR |= RCC_CR_HSEON; + while ((RCC->CR & RCC_CR_HSERDY) == 0); + + // divide shit + RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4; + + // 16mhz crystal + RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | + RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE; + + // start PLL + RCC->CR |= RCC_CR_PLLON; + while ((RCC->CR & RCC_CR_PLLRDY) == 0); + + // Configure Flash prefetch, Instruction cache, Data cache and wait state + // *** without this, it breaks *** + FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS; + + // switch to PLL + RCC->CFGR |= RCC_CFGR_SW_PLL; + while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); + + // *** running on PLL *** +} + +void watchdog_init() { + // 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; +} + +void watchdog_feed() { + IWDG->KR = 0xAAAA; +} + diff --git a/panda/board/drivers/drivers.h b/panda/board/drivers/drivers.h deleted file mode 100644 index d3409d60994eed..00000000000000 --- a/panda/board/drivers/drivers.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef PANDA_DRIVERS_H -#define PANDA_DRIVERS_H - -// ********************* LLGPIO ********************* - -#define MODE_INPUT 0 -#define MODE_OUTPUT 1 -#define MODE_ALTERNATE 2 -#define MODE_ANALOG 3 - -#define PULL_NONE 0 -#define PULL_UP 1 -#define PULL_DOWN 2 - -void set_gpio_mode(GPIO_TypeDef *GPIO, int pin, int mode); -void set_gpio_output(GPIO_TypeDef *GPIO, int pin, int val); -void set_gpio_alternate(GPIO_TypeDef *GPIO, int pin, int mode); -void set_gpio_pullup(GPIO_TypeDef *GPIO, int pin, int mode); - -int get_gpio_input(GPIO_TypeDef *GPIO, int pin); - - -// ********************* USB ********************* -// IRQs: OTG_FS - -typedef union { - uint16_t w; - struct BW { - uint8_t msb; - uint8_t lsb; - } - bw; -} -uint16_t_uint8_t; - -typedef union _USB_Setup { - uint32_t d8[2]; - struct _SetupPkt_Struc - { - uint8_t bmRequestType; - uint8_t bRequest; - uint16_t_uint8_t wValue; - uint16_t_uint8_t wIndex; - uint16_t_uint8_t wLength; - } b; -} -USB_Setup_TypeDef; - -void usb_init(); -int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired); -int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired); -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(); - - -// ********************* UART ********************* -// IRQs: USART1, USART2, USART3, UART5 - -#define FIFO_SIZE 0x400 -typedef struct uart_ring { - uint16_t w_ptr_tx; - uint16_t r_ptr_tx; - uint8_t elems_tx[FIFO_SIZE]; - uint16_t w_ptr_rx; - uint16_t r_ptr_rx; - uint8_t elems_rx[FIFO_SIZE]; - USART_TypeDef *uart; - void (*callback)(struct uart_ring*); -} uart_ring; - -void uart_init(USART_TypeDef *u, int baud); - -int getc(uart_ring *q, char *elem); -int putc(uart_ring *q, char elem); - -int puts(const char *a); -void puth(unsigned int i); -void hexdump(const void *a, int l); - - -// ********************* ADC ********************* - -void adc_init(); -uint32_t adc_get(int channel); - - -// ********************* DAC ********************* - -void dac_init(); -void dac_set(int channel, uint32_t value); - - -// ********************* TIMER ********************* - -void timer_init(TIM_TypeDef *TIM, int psc); - - -// ********************* SPI ********************* -// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4 - -void spi_init(); -int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out); - - -// ********************* CAN ********************* -// IRQs: CAN1_TX, CAN1_RX0, CAN1_SCE -// CAN2_TX, CAN2_RX0, CAN2_SCE -// CAN3_TX, CAN3_RX0, CAN3_SCE - -typedef struct { - uint32_t w_ptr; - uint32_t r_ptr; - uint32_t fifo_size; - CAN_FIFOMailBox_TypeDef *elems; -} can_ring; - -#define CAN_BUS_RET_FLAG 0x80 -#define CAN_BUS_NUM_MASK 0x7F - -#ifdef PANDA - #define BUS_MAX 4 -#else - #define BUS_MAX 2 -#endif - -extern int can_live, pending_can_live; - -// must reinit after changing these -extern int can_loopback, can_silent; -extern uint32_t can_speed[]; - -void can_set_forwarding(int from, int to); - -void can_init(uint8_t can_number); -void can_init_all(); -void can_send(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); -int can_pop(can_ring *q, CAN_FIFOMailBox_TypeDef *elem); - -#endif - diff --git a/panda/board/drivers/gmlan_alt.h b/panda/board/drivers/gmlan_alt.h index 8521100a88083a..d24833a8fb1ff8 100644 --- a/panda/board/drivers/gmlan_alt.h +++ b/panda/board/drivers/gmlan_alt.h @@ -114,8 +114,6 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) { return len; } -#ifdef PANDA - void setup_timer4() { // setup TIM4->PSC = 48-1; // tick on 1 us @@ -273,4 +271,3 @@ void bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) { setup_timer4(); } -#endif diff --git a/panda/board/drivers/llcan.h b/panda/board/drivers/llcan.h new file mode 100644 index 00000000000000..5c771f76f03602 --- /dev/null +++ b/panda/board/drivers/llcan.h @@ -0,0 +1,80 @@ +// this is needed for 1 mbps support +#define CAN_QUANTA 8 +#define CAN_SEQ1 6 // roundf(quanta * 0.875f) - 1; +#define CAN_SEQ2 1 // roundf(quanta * 0.125f); + +#define CAN_PCLK 24000 +// 333 = 33.3 kbps +// 5000 = 500 kbps +#define can_speed_to_prescaler(x) (CAN_PCLK / CAN_QUANTA * 10 / (x)) + +bool llcan_set_speed(CAN_TypeDef *CAN, uint32_t speed, bool loopback, bool silent) { + // initialization mode + CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ; + while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK); + + // set time quanta from defines + CAN->BTR = (CAN_BTR_TS1_0 * (CAN_SEQ1-1)) | + (CAN_BTR_TS2_0 * (CAN_SEQ2-1)) | + (can_speed_to_prescaler(speed) - 1); + + // silent loopback mode for debugging + if (loopback) { + CAN->BTR |= CAN_BTR_SILM | CAN_BTR_LBKM; + } + if (silent) { + CAN->BTR |= CAN_BTR_SILM; + } + + // reset + CAN->MCR = CAN_MCR_TTCM | CAN_MCR_ABOM; + + #define CAN_TIMEOUT 1000000 + int tmp = 0; + while((CAN->MSR & CAN_MSR_INAK) == CAN_MSR_INAK && tmp < CAN_TIMEOUT) tmp++; + if (tmp < CAN_TIMEOUT) { + return true; + } + + return false; +} + +void llcan_init(CAN_TypeDef *CAN) { + // accept all filter + CAN->FMR |= CAN_FMR_FINIT; + + // no mask + CAN->sFilterRegister[0].FR1 = 0; + CAN->sFilterRegister[0].FR2 = 0; + CAN->sFilterRegister[14].FR1 = 0; + CAN->sFilterRegister[14].FR2 = 0; + CAN->FA1R |= 1 | (1 << 14); + + CAN->FMR &= ~(CAN_FMR_FINIT); + + // enable certain CAN interrupts + CAN->IER |= CAN_IER_TMEIE | CAN_IER_FMPIE0 | CAN_IER_WKUIE; + + if (CAN == CAN1) { + NVIC_EnableIRQ(CAN1_TX_IRQn); + NVIC_EnableIRQ(CAN1_RX0_IRQn); + NVIC_EnableIRQ(CAN1_SCE_IRQn); + } else if (CAN == CAN2) { + NVIC_EnableIRQ(CAN2_TX_IRQn); + NVIC_EnableIRQ(CAN2_RX0_IRQn); + NVIC_EnableIRQ(CAN2_SCE_IRQn); +#ifdef CAN3 + } else if (CAN == CAN3) { + NVIC_EnableIRQ(CAN3_TX_IRQn); + NVIC_EnableIRQ(CAN3_RX0_IRQn); + NVIC_EnableIRQ(CAN3_SCE_IRQn); +#endif + } +} + +void llcan_clear_send(CAN_TypeDef *CAN) { + CAN->TSR |= CAN_TSR_ABRQ0; + CAN->MSR &= ~(CAN_MSR_ERRI); + CAN->MSR = CAN->MSR; +} + diff --git a/panda/board/drivers/llgpio.h b/panda/board/drivers/llgpio.h index e1835ec0f40c91..984127631221f7 100644 --- a/panda/board/drivers/llgpio.h +++ b/panda/board/drivers/llgpio.h @@ -1,3 +1,12 @@ +#define MODE_INPUT 0 +#define MODE_OUTPUT 1 +#define MODE_ALTERNATE 2 +#define MODE_ANALOG 3 + +#define PULL_NONE 0 +#define PULL_UP 1 +#define PULL_DOWN 2 + void set_gpio_mode(GPIO_TypeDef *GPIO, int pin, int mode) { uint32_t tmp = GPIO->MODER; tmp &= ~(3 << (pin*2)); diff --git a/panda/board/drivers/lline_relay.h b/panda/board/drivers/lline_relay.h deleted file mode 100644 index 217e7dfe3006bf..00000000000000 --- a/panda/board/drivers/lline_relay.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifdef PANDA - -int relay_control = 0; // True if relay is controlled through l-line - -/* Conrol a relay connected to l-line pin */ - -// 160us cycles, 1 high, 25 low - -volatile int turn_on_relay = 0; -volatile int on_cycles = 25; - -//5s timeout -#define LLINE_TIMEOUT_CYCLES 31250 -volatile int timeout_cycles = LLINE_TIMEOUT_CYCLES; - -void TIM5_IRQHandler(void) { - if (TIM5->SR & TIM_SR_UIF) { - on_cycles--; - timeout_cycles--; - if (timeout_cycles == 0) { - turn_on_relay = 0; - } - if (on_cycles > 0) { - if (turn_on_relay) { - set_gpio_output(GPIOC, 10, 0); - } - } - else { - set_gpio_output(GPIOC, 10, 1); - on_cycles = 25; - } - } - TIM5->ARR = 160-1; - TIM5->SR = 0; -} - -void lline_relay_init (void) { - set_lline_output(0); - relay_control = 1; - set_gpio_output(GPIOC, 10, 1); - - // setup - TIM5->PSC = 48-1; // tick on 1 us - TIM5->CR1 = TIM_CR1_CEN; // enable - TIM5->ARR = 50-1; // 50 us - TIM5->DIER = TIM_DIER_UIE; // update interrupt - TIM5->CNT = 0; - - NVIC_EnableIRQ(TIM5_IRQn); - -#ifdef DEBUG - puts("INIT LLINE\n"); - puts(" SR "); - putui(TIM5->SR); - puts(" PSC "); - putui(TIM5->PSC); - puts(" CR1 "); - putui(TIM5->CR1); - puts(" ARR "); - putui(TIM5->ARR); - puts(" DIER "); - putui(TIM5->DIER); - puts(" SR "); - putui(TIM5->SR); - puts(" CNT "); - putui(TIM5->CNT); - puts("\n"); -#endif -} - -void lline_relay_release (void) { - set_lline_output(0); - relay_control = 0; - puts("RELEASE LLINE\n"); - set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); - NVIC_DisableIRQ(TIM5_IRQn); -} - -void set_lline_output(int to_set) { - timeout_cycles = LLINE_TIMEOUT_CYCLES; - turn_on_relay = to_set; -} - -int get_lline_status() { - return turn_on_relay; -} - -#endif diff --git a/panda/board/drivers/spi.h b/panda/board/drivers/spi.h index 7a5945d37257cb..f31f20590d9add 100644 --- a/panda/board/drivers/spi.h +++ b/panda/board/drivers/spi.h @@ -1,5 +1,10 @@ // IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4 +void spi_init(); +int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out); + +// end API + #define SPI_BUF_SIZE 256 uint8_t spi_buf[SPI_BUF_SIZE]; int spi_buf_count = 0; @@ -23,8 +28,8 @@ void spi_init() { // setup interrupt on falling edge of SPI enable (on PA4) SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA; - EXTI->IMR = (1 << 4); - EXTI->FTSR = (1 << 4); + EXTI->IMR |= (1 << 4); + EXTI->FTSR |= (1 << 4); NVIC_EnableIRQ(EXTI4_IRQn); } @@ -108,7 +113,7 @@ void DMA2_Stream3_IRQHandler(void) { } void EXTI4_IRQHandler(void) { - volatile int pr = EXTI->PR; + volatile int pr = EXTI->PR & (1 << 4); #ifdef DEBUG_SPI puts("exti4\n"); #endif diff --git a/panda/board/drivers/uart.h b/panda/board/drivers/uart.h index 5ca82888d4fe7a..baba42e3432d67 100644 --- a/panda/board/drivers/uart.h +++ b/panda/board/drivers/uart.h @@ -1,5 +1,27 @@ // IRQs: USART1, USART2, USART3, UART5 +#define FIFO_SIZE 0x400 +typedef struct uart_ring { + uint16_t w_ptr_tx; + uint16_t r_ptr_tx; + uint8_t elems_tx[FIFO_SIZE]; + uint16_t w_ptr_rx; + uint16_t r_ptr_rx; + uint8_t elems_rx[FIFO_SIZE]; + USART_TypeDef *uart; + void (*callback)(struct uart_ring*); +} uart_ring; + +void uart_init(USART_TypeDef *u, int baud); + +int getc(uart_ring *q, char *elem); +int putc(uart_ring *q, char elem); + +int puts(const char *a); +void puth(unsigned int i); +void hexdump(const void *a, int l); + + // ***************************** serial port queues ***************************** // esp = USART1 diff --git a/panda/board/drivers/usb.h b/panda/board/drivers/usb.h index f2cffa1416e645..606c8c6b86eb99 100644 --- a/panda/board/drivers/usb.h +++ b/panda/board/drivers/usb.h @@ -1,5 +1,35 @@ // IRQs: OTG_FS +typedef union { + uint16_t w; + struct BW { + uint8_t msb; + uint8_t lsb; + } + bw; +} +uint16_t_uint8_t; + +typedef union _USB_Setup { + uint32_t d8[2]; + struct _SetupPkt_Struc + { + uint8_t bmRequestType; + uint8_t bRequest; + uint16_t_uint8_t wValue; + uint16_t_uint8_t wIndex; + uint16_t_uint8_t wLength; + } b; +} +USB_Setup_TypeDef; + +void usb_init(); +int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired); +int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired); +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(); + // **** supporting defines **** typedef struct @@ -186,17 +216,10 @@ uint16_t string_manufacturer_desc[] = { 'c', 'o', 'm', 'm', 'a', '.', 'a', 'i' }; -#ifdef PANDA uint16_t string_product_desc[] = { STRING_DESCRIPTOR_HEADER(5), 'p', 'a', 'n', 'd', 'a' }; -#else -uint16_t string_product_desc[] = { - STRING_DESCRIPTOR_HEADER(5), - 'N', 'E', 'O', 'v', '1' -}; -#endif // default serial number when we're not a panda uint16_t string_serial_desc[] = { @@ -210,7 +233,6 @@ uint16_t string_configuration_desc[] = { '0', '1' // "01" }; -#ifdef PANDA // WCID (auto install WinUSB driver) // https://github.com/pbatard/libwdi/wiki/WCID-Devices // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/winusb-installation#automatic-installation-of--winusb-without-an-inf-file @@ -360,8 +382,6 @@ uint8_t winusb_20_desc[WINUSB_PLATFORM_DESCRIPTOR_LENGTH] = { '1', 0x00, 'a', 0x00, 'd', 0x00, 'e', 0x00, '9', 0x00, '}', 0x00, 0x00, 0x00 // 78 bytes }; -#endif - // current packet USB_Setup_TypeDef setup; uint8_t usbdata[0x100]; @@ -550,7 +570,7 @@ void usb_setup() { USB_WritePacket((uint8_t*)string_product_desc, min(sizeof(string_product_desc), setup.b.wLength.w), 0); break; case STRING_OFFSET_ISERIAL: - #ifdef PANDA + #ifdef UID_BASE resp[0] = 0x02 + 12*4; resp[1] = 0x03; @@ -568,14 +588,12 @@ void usb_setup() { USB_WritePacket((const uint8_t *)string_serial_desc, min(sizeof(string_serial_desc), setup.b.wLength.w), 0); #endif break; - #ifdef PANDA case STRING_OFFSET_ICONFIGURATION: USB_WritePacket((uint8_t*)string_configuration_desc, min(sizeof(string_configuration_desc), setup.b.wLength.w), 0); break; case 238: USB_WritePacket((uint8_t*)string_238_desc, min(sizeof(string_238_desc), setup.b.wLength.w), 0); break; - #endif default: // nothing USB_WritePacket(0, 0, 0); @@ -583,12 +601,10 @@ void usb_setup() { } USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; break; - #ifdef PANDA case USB_DESC_TYPE_BINARY_OBJECT_STORE: USB_WritePacket(binary_object_store_desc, min(sizeof(binary_object_store_desc), setup.b.wLength.w), 0); USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; break; - #endif default: // nothing here? USB_WritePacket(0, 0, 0); @@ -609,7 +625,6 @@ void usb_setup() { USB_WritePacket(0, 0, 0); USBx_OUTEP(0)->DOEPCTL |= USB_OTG_DOEPCTL_CNAK; break; - #ifdef PANDA case WEBUSB_VENDOR_CODE: switch (setup.b.wIndex.w) { case WEBUSB_REQ_GET_URL: @@ -641,7 +656,6 @@ void usb_setup() { USB_WritePacket_EP0(0, 0); } break; - #endif default: resp_len = usb_cb_control_msg(&setup, resp, 1); USB_WritePacket(resp, min(resp_len, setup.b.wLength.w), 0); diff --git a/panda/board/gpio.h b/panda/board/gpio.h index ede6c9b3e929c0..7ba0dff58f86af 100644 --- a/panda/board/gpio.h +++ b/panda/board/gpio.h @@ -1,3 +1,5 @@ +// this is last place with ifdef PANDA + #ifdef STM32F4 #include "stm32f4xx_hal_gpio_ex.h" #else @@ -61,43 +63,6 @@ void detect() { // ********************* bringup ********************* -void clock_init() { - // enable external oscillator - RCC->CR |= RCC_CR_HSEON; - while ((RCC->CR & RCC_CR_HSERDY) == 0); - - // divide shit - RCC->CFGR = RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV2 | RCC_CFGR_PPRE1_DIV4; - #ifdef PANDA - RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | - RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE; - #else - #ifdef PEDAL - // comma pedal has a 16mhz crystal - RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | - RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLSRC_HSE; - #else - // NEO board has a 8mhz crystal - RCC->PLLCFGR = RCC_PLLCFGR_PLLQ_2 | RCC_PLLCFGR_PLLM_3 | - RCC_PLLCFGR_PLLN_7 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLSRC_HSE; - #endif - #endif - - // start PLL - RCC->CR |= RCC_CR_PLLON; - while ((RCC->CR & RCC_CR_PLLRDY) == 0); - - // Configure Flash prefetch, Instruction cache, Data cache and wait state - // *** without this, it breaks *** - FLASH->ACR = FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_LATENCY_5WS; - - // switch to PLL - RCC->CFGR |= RCC_CFGR_SW_PLL; - while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); - - // *** running on PLL *** -} - void periph_init() { // enable GPIOB, UART2, CAN, USB clock RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; @@ -117,18 +82,16 @@ void periph_init() { RCC->APB1ENR |= RCC_APB1ENR_CAN3EN; #endif RCC->APB1ENR |= RCC_APB1ENR_DACEN; - RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; - RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; + RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; // main counter + RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // slow loop and pedal + RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // gmlan_alt + //RCC->APB1ENR |= RCC_APB1ENR_TIM5EN; + //RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; RCC->AHB2ENR |= RCC_AHB2ENR_OTGFSEN; - RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; + //RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; - - // needed? RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; } @@ -197,7 +160,7 @@ void set_can_mode(int can, int use_gmlan) { set_gpio_alternate(GPIOB, 12, GPIO_AF9_CAN2); set_gpio_alternate(GPIOB, 13, GPIO_AF9_CAN2); #ifdef CAN3 - } else if (revision == PANDA_REV_C && can == 2) { + } else if (can == 2) { // A8,A15: disable normal mode set_gpio_mode(GPIOA, 8, MODE_INPUT); set_gpio_mode(GPIOA, 15, MODE_INPUT); @@ -218,11 +181,9 @@ void set_can_mode(int can, int use_gmlan) { set_gpio_alternate(GPIOB, 6, GPIO_AF9_CAN2); #ifdef CAN3 } else if (can == 2) { - if(revision == PANDA_REV_C){ - // B3,B4: disable gmlan mode - set_gpio_mode(GPIOB, 3, MODE_INPUT); - set_gpio_mode(GPIOB, 4, MODE_INPUT); - } + // B3,B4: disable gmlan mode + set_gpio_mode(GPIOB, 3, MODE_INPUT); + set_gpio_mode(GPIOB, 4, MODE_INPUT); // A8,A15: normal mode set_gpio_alternate(GPIOA, 8, GPIO_AF11_CAN3); set_gpio_alternate(GPIOA, 15, GPIO_AF11_CAN3); @@ -377,11 +338,7 @@ void gpio_init() { #ifdef PANDA // K-line enable moved from B4->B7 to make room for GMLAN on CAN3 - if (revision == PANDA_REV_C) { - set_gpio_output(GPIOB, 7, 1); // REV C - } else { - set_gpio_output(GPIOB, 4, 1); // REV AB - } + set_gpio_output(GPIOB, 7, 1); // REV C // C12,D2: K-Line setup on UART 5 set_gpio_alternate(GPIOC, 12, GPIO_AF8_UART5); @@ -392,16 +349,12 @@ void gpio_init() { set_gpio_output(GPIOA, 14, 1); // C10,C11: L-Line setup on USART 3 - // LLine now used for relay output - set_gpio_output(GPIOC, 10, 1); - //set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); + set_gpio_alternate(GPIOC, 10, GPIO_AF7_USART3); set_gpio_alternate(GPIOC, 11, GPIO_AF7_USART3); set_gpio_pullup(GPIOC, 11, PULL_UP); #endif - if (revision == PANDA_REV_C) { - set_usb_power_mode(USB_POWER_CLIENT); - } + set_usb_power_mode(USB_POWER_CLIENT); } // ********************* early bringup ********************* diff --git a/panda/board/main.c b/panda/board/main.c index 4fb5e9ff0468c9..c80a3b9badb195 100644 --- a/panda/board/main.c +++ b/panda/board/main.c @@ -1,14 +1,15 @@ +//#define EON + #include "config.h" #include "obj/gitversion.h" // ********************* includes ********************* + #include "libc.h" -#include "safety.h" #include "provision.h" -#include "drivers/drivers.h" - +#include "drivers/llcan.h" #include "drivers/llgpio.h" #include "gpio.h" @@ -16,25 +17,13 @@ #include "drivers/adc.h" #include "drivers/usb.h" #include "drivers/gmlan_alt.h" -#include "drivers/can.h" #include "drivers/spi.h" #include "drivers/timer.h" +#include "drivers/clock.h" #include "power_saving.h" - - -// ***************************** fan ***************************** - -void fan_init() { - // timer for fan PWM - TIM3->CCMR2 = TIM_CCMR2_OC3M_2 | TIM_CCMR2_OC3M_1; - TIM3->CCER = TIM_CCER_CC3E; - timer_init(TIM3, 10); -} - -void fan_set_speed(int fan_speed) { - TIM3->CCR3 = fan_speed; -} +#include "safety.h" +#include "drivers/can.h" // ********************* serial debugging ********************* @@ -70,6 +59,41 @@ void debug_ring_callback(uart_ring *ring) { } } +// ***************************** started logic ***************************** + +int is_gpio_started() { + // ignition is on PA1 + return (GPIOA->IDR & (1 << 1)) == 0; +} + +void EXTI1_IRQHandler() { + volatile int pr = EXTI->PR & (1 << 1); + if (pr & (1 << 1)) { + #ifdef DEBUG + puts("got started interrupt\n"); + #endif + + // jenky debounce + delay(100000); + + // set power savings mode here + if (is_gpio_started() == 1) { + power_save_disable(); + } else { + power_save_enable(); + } + EXTI->PR = (1 << 1); + } +} + +void started_interrupt_init() { + SYSCFG->EXTICR[1] = SYSCFG_EXTICR1_EXTI1_PA; + EXTI->IMR |= (1 << 1); + EXTI->RTSR |= (1 << 1); + EXTI->FTSR |= (1 << 1); + NVIC_EnableIRQ(EXTI1_IRQn); +} + // ***************************** USB port ***************************** int get_health_pkt(void *dat) { @@ -85,40 +109,25 @@ int get_health_pkt(void *dat) { //Voltage will be measured in mv. 5000 = 5V uint32_t voltage = adc_get(ADCCHAN_VOLTAGE); - if (revision == PANDA_REV_AB) { - //REVB has a 100, 27 (27/127) voltage divider - //Here is the calculation for the scale - //ADCV = VIN_S * (27/127) * (4095/3.3) - //RETVAL = ADCV * s = VIN_S*1000 - //s = 1000/((4095/3.3)*(27/127)) = 3.79053046 - - //Avoid needing floating point math - health->voltage = (voltage * 3791) / 1000; - } else { - //REVC has a 10, 1 (1/11) voltage divider - //Here is the calculation for the scale (s) - //ADCV = VIN_S * (1/11) * (4095/3.3) - //RETVAL = ADCV * s = VIN_S*1000 - //s = 1000/((4095/3.3)*(1/11)) = 8.8623046875 - - //Avoid needing floating point math - health->voltage = (voltage * 8862) / 1000; - } -#ifdef PANDA + // REVC has a 10, 1 (1/11) voltage divider + // Here is the calculation for the scale (s) + // ADCV = VIN_S * (1/11) * (4095/3.3) + // RETVAL = ADCV * s = VIN_S*1000 + // s = 1000/((4095/3.3)*(1/11)) = 8.8623046875 + + // Avoid needing floating point math + health->voltage = (voltage * 8862) / 1000; + health->current = adc_get(ADCCHAN_CURRENT); int safety_ignition = safety_ignition_hook(); if (safety_ignition < 0) { //Use the GPIO pin to determine ignition - health->started = (GPIOA->IDR & (1 << 1)) == 0; + health->started = is_gpio_started(); } else { //Current safety hooks want to determine ignition (ex: GM) health->started = safety_ignition; } -#else - health->current = 0; - health->started = (GPIOC->IDR & (1 << 13)) != 0; -#endif health->controls_allowed = controls_allowed; health->gas_interceptor_detected = gas_interceptor_detected; @@ -143,7 +152,6 @@ void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) { uart_ring *ur = get_ring_by_number(usbdata[0]); if (!ur) return; if ((usbdata[0] < 2) || safety_tx_lin_hook(usbdata[0]-2, usbdata+1, len-1)) { - if (ur == &esp_ring) power_save_reset_timer(); for (int i = 1; i < len; i++) while (!putc(ur, usbdata[i])); } } @@ -163,14 +171,6 @@ void usb_cb_ep3_out(uint8_t *usbdata, int len, int hardwired) { uint8_t bus_number = (to_push.RDTR >> 4) & CAN_BUS_NUM_MASK; can_send(&to_push, bus_number); - - #ifdef PANDA - // Enable relay on can message if allowed. - // Temporary until OP has support for relay - if (safety_relay_hook()) { - set_lline_output(1); - } - #endif } } @@ -201,16 +201,14 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { break; // **** 0xd0: fetch serial number case 0xd0: - #ifdef PANDA - // addresses are OTP - if (setup->b.wValue.w == 1) { - memcpy(resp, (void *)0x1fff79c0, 0x10); - resp_len = 0x10; - } else { - get_provision_chunk(resp); - resp_len = PROVISION_CHUNK_LEN; - } - #endif + // addresses are OTP + if (setup->b.wValue.w == 1) { + memcpy(resp, (void *)0x1fff79c0, 0x10); + resp_len = 0x10; + } else { + get_provision_chunk(resp); + resp_len = PROVISION_CHUNK_LEN; + } break; // **** 0xd1: enter bootloader mode case 0xd1: @@ -235,10 +233,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { case 0xd2: resp_len = get_health_pkt(resp); break; - // **** 0xd3: set fan speed - case 0xd3: - fan_set_speed(setup->b.wValue.w); - break; // **** 0xd6: get version case 0xd6: COMPILE_TIME_ASSERT(sizeof(gitversion) <= MAX_RESP_LEN) @@ -273,44 +267,43 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { break; // **** 0xdb: set GMLAN multiplexing mode case 0xdb: - #ifdef PANDA - if (setup->b.wValue.w == 1) { - // GMLAN ON - if (setup->b.wIndex.w == 1) { - can_set_gmlan(1); - } else if (setup->b.wIndex.w == 2) { - // might be ignored on rev b panda - can_set_gmlan(2); - } - } else { - can_set_gmlan(-1); + if (setup->b.wValue.w == 1) { + // GMLAN ON + if (setup->b.wIndex.w == 1) { + can_set_gmlan(1); + } else if (setup->b.wIndex.w == 2) { + can_set_gmlan(2); } - #endif + } else { + can_set_gmlan(-1); + } break; // **** 0xdc: set safety mode case 0xdc: // this is the only way to leave silent mode // and it's blocked over WiFi // Allow ELM security mode to be set over wifi. - if (hardwired || setup->b.wValue.w == SAFETY_NOOUTPUT || setup->b.wValue.w == SAFETY_ELM327) { + if (hardwired || (setup->b.wValue.w == SAFETY_NOOUTPUT) || (setup->b.wValue.w == SAFETY_ELM327)) { safety_set_mode(setup->b.wValue.w, (int16_t)setup->b.wIndex.w); - switch (setup->b.wValue.w) { - case SAFETY_NOOUTPUT: - can_silent = ALL_CAN_SILENT; - break; - case SAFETY_ELM327: - can_silent = ALL_CAN_BUT_MAIN_SILENT; - can_autobaud_enabled[0] = false; - break; - default: - can_silent = ALL_CAN_LIVE; - can_autobaud_enabled[0] = false; - can_autobaud_enabled[1] = false; - #ifdef PANDA - can_autobaud_enabled[2] = false; - #endif - break; + if (safety_ignition_hook() != -1) { + // if the ignition hook depends on something other than the started GPIO + // we have to disable power savings (fix for GM and Tesla) + power_save_disable(); } + #ifndef EON + // always LIVE on EON + switch (setup->b.wValue.w) { + case SAFETY_NOOUTPUT: + can_silent = ALL_CAN_SILENT; + break; + case SAFETY_ELM327: + can_silent = ALL_CAN_BUT_MAIN_SILENT; + break; + default: + can_silent = ALL_CAN_LIVE; + break; + } + #endif can_init_all(); } break; @@ -318,21 +311,26 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { case 0xdd: // wValue = Can Bus Num to forward from // wIndex = Can Bus Num to forward to - if (setup->b.wValue.w < BUS_MAX && setup->b.wIndex.w < BUS_MAX && - setup->b.wValue.w != setup->b.wIndex.w) { // set forwarding + if ((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w < BUS_MAX) && + (setup->b.wValue.w != setup->b.wIndex.w)) { // set forwarding can_set_forwarding(setup->b.wValue.w, setup->b.wIndex.w & CAN_BUS_NUM_MASK); - } else if(setup->b.wValue.w < BUS_MAX && setup->b.wIndex.w == 0xFF){ //Clear Forwarding + } else if((setup->b.wValue.w < BUS_MAX) && (setup->b.wIndex.w == 0xFF)){ //Clear Forwarding can_set_forwarding(setup->b.wValue.w, -1); } break; // **** 0xde: set can bitrate case 0xde: if (setup->b.wValue.w < BUS_MAX) { - can_autobaud_enabled[setup->b.wValue.w] = false; can_speed[setup->b.wValue.w] = setup->b.wIndex.w; can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w)); } break; + // **** 0xdf: set long controls allowed + case 0xdf: + if (hardwired) { + long_controls_allowed = setup->b.wValue.w & 1; + } + break; // **** 0xe0: uart read case 0xe0: ur = get_ring_by_number(setup->b.wValue.w); @@ -386,17 +384,15 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { break; // **** 0xe6: set USB power case 0xe6: - if (revision == PANDA_REV_C) { - if (setup->b.wValue.w == 1) { - puts("user setting CDP mode\n"); - set_usb_power_mode(USB_POWER_CDP); - } else if (setup->b.wValue.w == 2) { - puts("user setting DCP mode\n"); - set_usb_power_mode(USB_POWER_DCP); - } else { - puts("user setting CLIENT mode\n"); - set_usb_power_mode(USB_POWER_CLIENT); - } + if (setup->b.wValue.w == 1) { + puts("user setting CDP mode\n"); + set_usb_power_mode(USB_POWER_CDP); + } else if (setup->b.wValue.w == 2) { + puts("user setting DCP mode\n"); + set_usb_power_mode(USB_POWER_DCP); + } else { + puts("user setting CLIENT mode\n"); + set_usb_power_mode(USB_POWER_CLIENT); } break; // **** 0xf0: do k-line wValue pulse on uart2 for Acura @@ -452,16 +448,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { } break; } - // **** 0xf3: set l-line relay - case 0xf3: - { - #ifdef PANDA - if (safety_relay_hook()) { - set_lline_output(setup->b.wValue.w == 1); - } - #endif - break; - } default: puts("NO HANDLER "); puth(setup->b.bRequest); @@ -471,7 +457,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { return resp_len; } -#ifdef PANDA int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { // data[0] = endpoint // data[2] = length @@ -499,12 +484,6 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { return resp_len; } -#else - -int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { return 0; }; - -#endif - // ***************************** main code ***************************** @@ -514,7 +493,99 @@ void __initialize_hardware_early() { void __attribute__ ((noinline)) enable_fpu() { // enable the FPU - SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); + SCB->CPACR |= ((3UL << (10 * 2)) | (3UL << (11 * 2))); +} + +uint64_t tcnt = 0; +uint64_t marker = 0; + +// called once per second +void TIM3_IRQHandler() { + #define CURRENT_THRESHOLD 0xF00 + #define CLICKS 5 // 5 seconds to switch modes + + if (TIM3->SR != 0) { + can_live = pending_can_live; + + //puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n"); + + uint32_t current = adc_get(ADCCHAN_CURRENT); + + switch (usb_power_mode) { + case USB_POWER_CLIENT: + if ((tcnt-marker) >= CLICKS) { + if (!is_enumerated) { + puts("USBP: didn't enumerate, switching to CDP mode\n"); + // switch to CDP + set_usb_power_mode(USB_POWER_CDP); + marker = tcnt; + } + } + // keep resetting the timer if it's enumerated + if (is_enumerated) { + marker = tcnt; + } + break; + case USB_POWER_CDP: + // On the EON, if we get into CDP mode we stay here. No need to go to DCP. + #ifndef EON + // been CLICKS clicks since we switched to CDP + if ((tcnt-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"); + set_usb_power_mode(USB_POWER_DCP); + marker = tcnt; + } + } + // keep resetting the timer if there's no current draw in CDP + if (current >= CURRENT_THRESHOLD) { + marker = tcnt; + } + #endif + break; + case USB_POWER_DCP: + // been at least CLICKS clicks since we switched to DCP + if ((tcnt-marker) >= CLICKS) { + // if no current draw, switch back to CDP + if (current >= CURRENT_THRESHOLD) { + puts("USBP: no current draw, switching back to CDP mode\n"); + set_usb_power_mode(USB_POWER_CDP); + marker = tcnt; + } + } + // keep resetting the timer if there's current draw in DCP + if (current < CURRENT_THRESHOLD) { + marker = tcnt; + } + break; + } + + // ~0x9a = 500 ma + /*puth(current); + puts("\n");*/ + + // reset this every 16th pass + if ((tcnt&0xF) == 0) pending_can_live = 0; + + #ifdef DEBUG + puts("** blink "); + puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" "); + puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" "); + puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n"); + #endif + + // set green LED to be controls allowed + set_led(LED_GREEN, controls_allowed); + + // turn off the blue LED, turned on by CAN + // unless we are in power saving mode + set_led(LED_BLUE, (tcnt&1) && power_save_status == POWER_SAVE_STATUS_ENABLED); + + // on to the next one + tcnt += 1; + } + TIM3->SR = 0; } int main() { @@ -531,21 +602,19 @@ int main() { // detect the revision and init the GPIOs puts("config:\n"); - #ifdef PANDA - puts(revision == PANDA_REV_C ? " panda rev c\n" : " panda rev a or b\n"); - #else - puts(" legacy\n"); - #endif + puts((revision == PANDA_REV_C) ? " panda rev c\n" : " panda rev a or b\n"); puts(has_external_debug_serial ? " real serial\n" : " USB serial\n"); puts(is_giant_panda ? " GIANTpanda detected\n" : " not GIANTpanda\n"); puts(is_grey_panda ? " gray panda detected!\n" : " white panda\n"); puts(is_entering_bootmode ? " ESP wants bootmode\n" : " no bootmode\n"); + + // non rev c panda are no longer supported + while (revision != PANDA_REV_C); + gpio_init(); -#ifdef PANDA // panda has an FPU, let's use it! enable_fpu(); -#endif // enable main uart if it's connected if (has_external_debug_serial) { @@ -554,22 +623,18 @@ int main() { uart_init(USART2, 115200); } -#ifdef PANDA if (is_grey_panda) { uart_init(USART1, 9600); } else { // enable ESP uart uart_init(USART1, 115200); - #ifdef EON - set_esp_mode(ESP_DISABLED); - #endif } + // enable LIN uart_init(UART5, 10400); UART5->CR2 |= USART_CR2_LINEN; uart_init(USART3, 10400); USART3->CR2 |= USART_CR2_LINEN; -#endif // init microsecond system timer // increments 1000000 times per second @@ -585,136 +650,65 @@ int main() { // default to silent mode to prevent issues with Ford // hardcode a specific safety mode if you want to force the panda to be in a specific mode safety_set_mode(SAFETY_NOOUTPUT, 0); +#ifdef EON + // if we're on an EON, it's fine for CAN to be live for fingerprinting + can_silent = ALL_CAN_LIVE; +#else can_silent = ALL_CAN_SILENT; +#endif can_init_all(); adc_init(); - -#ifdef PANDA spi_init(); + +#ifdef EON + // have to save power + if (!is_grey_panda) { + set_esp_mode(ESP_DISABLED); + } + // only enter power save after the first cycle + /*if (is_gpio_started() == 0) { + power_save_enable(); + }*/ + // interrupt on started line + started_interrupt_init(); #endif + + // 48mhz / 65536 ~= 732 / 732 = 1 + timer_init(TIM3, 732); + NVIC_EnableIRQ(TIM3_IRQn); + #ifdef DEBUG puts("DEBUG ENABLED\n"); #endif - // set PWM - fan_init(); - fan_set_speed(0); - puts("**** INTERRUPTS ON ****\n"); __enable_irq(); - power_save_init(); - - // if the error interrupt is enabled to quickly when the CAN bus is active - // something bad happens and you can't connect to the device over USB - delay(10000000); - CAN1->IER |= CAN_IER_ERRIE | CAN_IER_LECIE; - // LED should keep on blinking all the time uint64_t cnt = 0; - #ifdef PANDA - uint64_t marker = 0; - #define CURRENT_THRESHOLD 0xF00 - #define CLICKS 8 - #endif - for (cnt=0;;cnt++) { - can_live = pending_can_live; - - //puth(usart1_dma); puts(" "); puth(DMA2_Stream5->M0AR); puts(" "); puth(DMA2_Stream5->NDTR); puts("\n"); - - #ifdef PANDA - uint32_t current = adc_get(ADCCHAN_CURRENT); - - switch (usb_power_mode) { - case USB_POWER_CLIENT: - if ((cnt-marker) >= CLICKS) { - if (!is_enumerated) { - puts("USBP: didn't enumerate, switching to CDP mode\n"); - // switch to CDP - set_usb_power_mode(USB_POWER_CDP); - marker = cnt; - } - } - // keep resetting the timer if it's enumerated - if (is_enumerated) { - marker = cnt; - } - break; - case USB_POWER_CDP: -#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"); - set_usb_power_mode(USB_POWER_DCP); - marker = cnt; - } - } - // keep resetting the timer if there's no current draw in CDP - if (current >= CURRENT_THRESHOLD) { - marker = cnt; - } -#endif - break; - case USB_POWER_DCP: - // been at least CLICKS clicks since we switched to DCP - if ((cnt-marker) >= CLICKS) { - // if no current draw, switch back to CDP - if (current >= CURRENT_THRESHOLD) { - puts("USBP: no current draw, switching back to CDP mode\n"); - set_usb_power_mode(USB_POWER_CDP); - marker = cnt; - } - } - // keep resetting the timer if there's current draw in DCP - if (current < CURRENT_THRESHOLD) { - marker = cnt; + if (power_save_status == POWER_SAVE_STATUS_DISABLED) { + int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1); + + // useful for debugging, fade breaks = panda is overloaded + for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) { + for (int fade = 0; fade < 1024; fade += 8) { + for (int i = 0; i < (128/div_mode); i++) { + set_led(LED_RED, 1); + if (fade < 512) { delay(fade); } else { delay(1024-fade); } + set_led(LED_RED, 0); + if (fade < 512) { delay(512-fade); } else { delay(fade-512); } } - break; - } - - // ~0x9a = 500 ma - /*puth(current); - puts("\n");*/ - #endif - - // reset this every 16th pass - if ((cnt&0xF) == 0) pending_can_live = 0; - - #ifdef DEBUG - puts("** blink "); - puth(can_rx_q.r_ptr); puts(" "); puth(can_rx_q.w_ptr); puts(" "); - puth(can_tx1_q.r_ptr); puts(" "); puth(can_tx1_q.w_ptr); puts(" "); - puth(can_tx2_q.r_ptr); puts(" "); puth(can_tx2_q.w_ptr); puts("\n"); - #endif - - // set green LED to be controls allowed - set_led(LED_GREEN, controls_allowed); - - // blink the red LED - int div_mode = ((usb_power_mode == USB_POWER_DCP) ? 4 : 1); - - for (int div_mode_loop = 0; div_mode_loop < div_mode; div_mode_loop++) { - for (int fade = 0; fade < 1024; fade += 8) { - for (int i = 0; i < 128/div_mode; i++) { - set_led(LED_RED, 0); - if (fade < 512) { delay(512-fade); } else { delay(fade-512); } - set_led(LED_RED, 1); - if (fade < 512) { delay(fade); } else { delay(1024-fade); } } } + } else { + __WFI(); } - - // turn off the blue LED, turned on by CAN - #ifdef PANDA - set_led(LED_BLUE, 0); - #endif } return 0; } + diff --git a/panda/board/pedal/main.c b/panda/board/pedal/main.c index 6b55ca780c283f..df3219e32ce2a2 100644 --- a/panda/board/pedal/main.c +++ b/panda/board/pedal/main.c @@ -1,29 +1,26 @@ -//#define DEBUG -//#define CAN_LOOPBACK_MODE -//#define USE_INTERNAL_OSC - #include "../config.h" -#include "drivers/drivers.h" +#include "drivers/llcan.h" #include "drivers/llgpio.h" -#include "gpio.h" - -#define CUSTOM_CAN_INTERRUPTS - -#include "libc.h" -#include "safety.h" +#include "drivers/clock.h" #include "drivers/adc.h" -#include "drivers/uart.h" #include "drivers/dac.h" -#include "drivers/can.h" #include "drivers/timer.h" +#include "gpio.h" +#include "libc.h" + #define CAN CAN1 //#define PEDAL_USB #ifdef PEDAL_USB + #include "drivers/uart.h" #include "drivers/usb.h" +#else + // no serial either + int puts(const char *a) { return 0; } + void puth(unsigned int i) {} #endif #define ENTER_BOOTLOADER_MAGIC 0xdeadbeef @@ -35,6 +32,8 @@ void __initialize_hardware_early() { // ********************* serial debugging ********************* +#ifdef PEDAL_USB + void debug_ring_callback(uart_ring *ring) { char rcv; while (getc(ring, &rcv)) { @@ -42,8 +41,6 @@ void debug_ring_callback(uart_ring *ring) { } } -#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) {} @@ -185,7 +182,7 @@ void CAN1_RX0_IRQHandler() { void CAN1_SCE_IRQHandler() { state = FAULT_SCE; - can_sce(CAN); + llcan_clear_send(CAN); } int pdl0 = 0, pdl1 = 0; @@ -256,8 +253,7 @@ void pedal() { dac_set(1, pdl1); } - // feed the watchdog - IWDG->KR = 0xAAAA; + watchdog_feed(); } int main() { @@ -278,24 +274,18 @@ int main() { adc_init(); // init can - can_silent = ALL_CAN_LIVE; - can_init(0); + llcan_set_speed(CAN1, 5000, false, false); + llcan_init(CAN1); // 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; + watchdog_init(); puts("**** INTERRUPTS ON ****\n"); __enable_irq(); - // main pedal loop while (1) { pedal(); diff --git a/panda/board/power_saving.h b/panda/board/power_saving.h index c6f83457ff449c..3f40bce28f1209 100644 --- a/panda/board/power_saving.h +++ b/panda/board/power_saving.h @@ -1,157 +1,57 @@ #define POWER_SAVE_STATUS_DISABLED 0 -//Moving to enabled, but can wakeup not yet enabled -#define POWER_SAVE_STATUS_SWITCHING 1 -#define POWER_SAVE_STATUS_ENABLED 2 +#define POWER_SAVE_STATUS_ENABLED 1 -volatile int power_save_status = POWER_SAVE_STATUS_DISABLED; +int power_save_status = POWER_SAVE_STATUS_DISABLED; void power_save_enable(void) { - power_save_status = POWER_SAVE_STATUS_SWITCHING; - puts("Saving power\n"); - //Turn off can transciever + if (power_save_status == POWER_SAVE_STATUS_ENABLED) return; + puts("enable power savings\n"); + + // turn off can set_can_enable(CAN1, 0); set_can_enable(CAN2, 0); -#ifdef PANDA set_can_enable(CAN3, 0); -#endif - //Turn off GMLAN + // turn off GMLAN set_gpio_output(GPIOB, 14, 0); set_gpio_output(GPIOB, 15, 0); -#ifdef PANDA - //Turn off LIN K - if (revision == PANDA_REV_C) { - set_gpio_output(GPIOB, 7, 0); // REV C - } else { - set_gpio_output(GPIOB, 4, 0); // REV AB - } - // LIN L + // turn off LIN + set_gpio_output(GPIOB, 7, 0); set_gpio_output(GPIOA, 14, 0); -#endif if (is_grey_panda) { - char* UBLOX_SLEEP_MSG = "\xb5\x62\x06\x04\x04\x00\x01\x00\x08\x00\x17\x78"; - int len = 12; + char UBLOX_SLEEP_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x08\x00\x17\x78"; uart_ring *ur = get_ring_by_number(1); - for (int i = 0; i < len; i++) while (!putc(ur, UBLOX_SLEEP_MSG[i])); + for (int i = 0; i < sizeof(UBLOX_SLEEP_MSG)-1; i++) while (!putc(ur, UBLOX_SLEEP_MSG[i])); } - //Setup timer for can enable - TIM6->PSC = 48-1; // tick on 1 us - - TIM6->ARR = 12; // 12us - // Enable, One-Pulse Mode, Only overflow interrupt - TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; - TIM6->EGR = TIM_EGR_UG; - TIM6->CR1 |= TIM_CR1_CEN; -} - -void power_save_enable_can_wake(void) { - // CAN Automatic Wake must be done a little while after the sleep - // On some cars turning off the can transciver can trigger the wakeup power_save_status = POWER_SAVE_STATUS_ENABLED; - puts("Turning can off\n"); - CAN1->MCR |= CAN_MCR_SLEEP; - CAN1->MCR |= CAN_MCR_AWUM; - - CAN2->MCR |= CAN_MCR_SLEEP; - CAN2->MCR |= CAN_MCR_AWUM; -#ifdef PANDA - CAN3->MCR |= CAN_MCR_SLEEP; - CAN3->MCR |= CAN_MCR_AWUM; -#endif - - //set timer back - TIM6->PSC = 48000-1; // tick on 1 ms - TIM6->ARR = 10000; // 10s - // Enable, One-Pulse Mode, Only overflow interrupt - TIM6->CR1 = TIM_CR1_OPM | TIM_CR1_URS; - TIM6->EGR = TIM_EGR_UG; } void power_save_disable(void) { - power_save_status = POWER_SAVE_STATUS_DISABLED; - puts("not Saving power\n"); - TIM6->CR1 |= TIM_CR1_CEN; //Restart timer - TIM6->CNT = 0; + if (power_save_status == POWER_SAVE_STATUS_DISABLED) return; + puts("disable power savings\n"); - //Turn on can + // turn on can set_can_enable(CAN1, 1); set_can_enable(CAN2, 1); - -#ifdef PANDA set_can_enable(CAN3, 1); -#endif - //Turn on GMLAN + // turn on GMLAN set_gpio_output(GPIOB, 14, 1); set_gpio_output(GPIOB, 15, 1); -#ifdef PANDA - //Turn on LIN K - if (revision == PANDA_REV_C) { - set_gpio_output(GPIOB, 7, 1); // REV C - } else { - set_gpio_output(GPIOB, 4, 1); // REV AB - } - // LIN L + // turn on LIN + set_gpio_output(GPIOB, 7, 1); set_gpio_output(GPIOA, 14, 1); -#endif if (is_grey_panda) { - char* UBLOX_WAKE_MSG = "\xb5\x62\x06\x04\x04\x00\x01\x00\x09\x00\x18\x7a"; - int len = 12; + char UBLOX_WAKE_MSG[] = "\xb5\x62\x06\x04\x04\x00\x01\x00\x09\x00\x18\x7a"; uart_ring *ur = get_ring_by_number(1); - for (int i = 0; i < len; i++) while (!putc(ur, UBLOX_WAKE_MSG[i])); - } - - //set timer back - TIM6->PSC = 48000-1; // tick on 1 ms - TIM6->ARR = 10000; // 10s - // Enable, One-Pulse Mode, Only overflow interrupt - TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; - TIM6->EGR = TIM_EGR_UG; - TIM6->CR1 |= TIM_CR1_CEN; -} - - - -// Reset timer when activity -void power_save_reset_timer() { - TIM6->CNT = 0; - if (power_save_status != POWER_SAVE_STATUS_DISABLED){ - power_save_disable(); + for (int i = 0; i < sizeof(UBLOX_WAKE_MSG)-1; i++) while (!putc(ur, UBLOX_WAKE_MSG[i])); } -} -void power_save_init(void) { - puts("Saving power init\n"); - TIM6->PSC = 48000-1; // tick on 1 ms - - - TIM6->ARR = 10000; // 10s - // Enable, One-Pulse Mode, Only overflow interrupt - TIM6->CR1 = TIM_CR1_CEN | TIM_CR1_OPM | TIM_CR1_URS; - TIM6->EGR = TIM_EGR_UG; - NVIC_EnableIRQ(TIM6_DAC_IRQn); - puts("Saving power init done\n"); - TIM6->DIER = TIM_DIER_UIE; - TIM6->CR1 |= TIM_CR1_CEN; + power_save_status = POWER_SAVE_STATUS_DISABLED; } -void TIM6_DAC_IRQHandler(void) { - //Timeout switch to power saving mode. - if (TIM6->SR & TIM_SR_UIF) { - TIM6->SR = 0; -#ifdef EON - if (power_save_status == POWER_SAVE_STATUS_DISABLED) { - power_save_enable(); - } else if (power_save_status == POWER_SAVE_STATUS_SWITCHING) { - power_save_enable_can_wake(); - } -#endif - } else { - TIM6->CR1 |= TIM_CR1_CEN; - } -} diff --git a/panda/board/safety.h b/panda/board/safety.h index 5543333e3a6cb0..3addc65365c56e 100644 --- a/panda/board/safety.h +++ b/panda/board/safety.h @@ -5,13 +5,11 @@ struct sample_t { int max; } sample_t_default = {{0}, 0, 0}; -// no float support in STM32F2 micros (cortex-m3) -#ifdef PANDA +// safety code requires floats struct lookup_t { float x[3]; float y[3]; }; -#endif void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); @@ -27,21 +25,14 @@ int driver_limit_check(int val, int val_last, struct sample_t *val_driver, const int MAX, const int MAX_RATE_UP, const int MAX_RATE_DOWN, const int MAX_ALLOWANCE, const int DRIVER_FACTOR); int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA); -#ifdef PANDA float interpolate(struct lookup_t xy, float x); -void lline_relay_init (void); -void lline_relay_release (void); -void set_lline_output(int to_set); -#endif - typedef void (*safety_hook_init)(int16_t param); typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push); typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send); typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len); typedef int (*ign_hook)(); typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd); -typedef int (*relay_hook)(); typedef struct { safety_hook_init init; @@ -50,21 +41,23 @@ typedef struct { tx_hook tx; tx_lin_hook tx_lin; fwd_hook fwd; - relay_hook relay; } safety_hooks; // This can be set by the safety hooks. int controls_allowed = 0; +int gas_interceptor_detected = 0; +int gas_interceptor_prev = 0; + +// This is set by USB command 0xdf +int long_controls_allowed = 1; // Include the actual safety policies. #include "safety/safety_defaults.h" #include "safety/safety_honda.h" #include "safety/safety_toyota.h" -#ifdef PANDA #include "safety/safety_toyota_ipas.h" #include "safety/safety_tesla.h" #include "safety/safety_gm_ascm.h" -#endif #include "safety/safety_gm.h" #include "safety/safety_ford.h" #include "safety/safety_cadillac.h" @@ -97,10 +90,6 @@ int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return current_hooks->fwd(bus_num, to_fwd); } -int safety_relay_hook(void) { - return current_hooks->relay(); -} - typedef struct { uint16_t id; const safety_hooks *hooks; @@ -119,7 +108,6 @@ typedef struct { #define SAFETY_SUBARU 10 #define SAFETY_GM_ASCM 0x1334 #define SAFETY_TOYOTA_IPAS 0x1335 -#define SAFETY_TOYOTA_NOLIMITS 0x1336 #define SAFETY_ALLOUTPUT 0x1337 #define SAFETY_ELM327 0xE327 @@ -134,12 +122,9 @@ const safety_hook_config safety_hook_registry[] = { {SAFETY_HYUNDAI, &hyundai_hooks}, {SAFETY_CHRYSLER, &chrysler_hooks}, {SAFETY_SUBARU, &subaru_hooks}, - {SAFETY_TOYOTA_NOLIMITS, &toyota_nolimits_hooks}, -#ifdef PANDA {SAFETY_TOYOTA_IPAS, &toyota_ipas_hooks}, {SAFETY_GM_ASCM, &gm_ascm_hooks}, {SAFETY_TESLA, &tesla_hooks}, -#endif {SAFETY_ALLOUTPUT, &alloutput_hooks}, {SAFETY_ELM327, &elm327_hooks}, }; @@ -239,7 +224,6 @@ int rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA) { } -#ifdef PANDA // interp function that holds extreme values float interpolate(struct lookup_t xy, float x) { int size = sizeof(xy.x) / sizeof(xy.x[0]); @@ -264,4 +248,3 @@ float interpolate(struct lookup_t xy, float x) { return xy.y[size - 1]; } } -#endif diff --git a/panda/board/safety/safety_cadillac.h b/panda/board/safety/safety_cadillac.h index 0e6636a1a0764d..2a2d8b9857ff91 100644 --- a/panda/board/safety/safety_cadillac.h +++ b/panda/board/safety/safety_cadillac.h @@ -115,9 +115,6 @@ static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void cadillac_init(int16_t param) { controls_allowed = 0; cadillac_ign = 0; - #ifdef PANDA - lline_relay_release(); - #endif } static int cadillac_ign_hook() { @@ -131,5 +128,4 @@ const safety_hooks cadillac_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = cadillac_ign_hook, .fwd = alloutput_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_chrysler.h b/panda/board/safety/safety_chrysler.h index a8826b9154e80d..4af588401e0ec0 100644 --- a/panda/board/safety/safety_chrysler.h +++ b/panda/board/safety/safety_chrysler.h @@ -127,9 +127,6 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void chrysler_init(int16_t param) { chrysler_camera_detected = 0; - #ifdef PANDA - lline_relay_release(); - #endif } static int chrysler_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { @@ -153,5 +150,4 @@ const safety_hooks chrysler_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = chrysler_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_defaults.h b/panda/board/safety/safety_defaults.h index 88d31a7de57b48..196df65d2f8eb6 100644 --- a/panda/board/safety/safety_defaults.h +++ b/panda/board/safety/safety_defaults.h @@ -8,9 +8,6 @@ int default_ign_hook() { static void nooutput_init(int16_t param) { controls_allowed = 0; - #ifdef PANDA - lline_relay_release(); - #endif } static int nooutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { @@ -25,10 +22,6 @@ static int nooutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return -1; } -static int nooutput_relay_hook(int to_set) { - return false; -} - const safety_hooks nooutput_hooks = { .init = nooutput_init, .rx = default_rx_hook, @@ -36,16 +29,12 @@ const safety_hooks nooutput_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = nooutput_fwd_hook, - .relay = nooutput_relay_hook, }; // *** all output safety mode *** static void alloutput_init(int16_t param) { controls_allowed = 1; - #ifdef PANDA - lline_relay_release(); - #endif } static int alloutput_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { @@ -60,10 +49,6 @@ static int alloutput_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { return -1; } -static int alloutput_relay_hook(int to_set) { - return true; -} - const safety_hooks alloutput_hooks = { .init = alloutput_init, .rx = default_rx_hook, @@ -71,5 +56,4 @@ const safety_hooks alloutput_hooks = { .tx_lin = alloutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = alloutput_fwd_hook, - .relay = alloutput_relay_hook, }; diff --git a/panda/board/safety/safety_elm327.h b/panda/board/safety/safety_elm327.h index e89783bcca6d44..823d553dd738f1 100644 --- a/panda/board/safety/safety_elm327.h +++ b/panda/board/safety/safety_elm327.h @@ -1,5 +1,3 @@ -static void elm327_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {} - static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { //All ELM traffic must appear on CAN0 if(((to_send->RDTR >> 4) & 0xf) != 0) return 0; @@ -27,20 +25,11 @@ static int elm327_tx_lin_hook(int lin_num, uint8_t *data, int len) { return true; } -static void elm327_init(int16_t param) { - controls_allowed = 1; -} - -static int elm327_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { - return -1; -} - const safety_hooks elm327_hooks = { - .init = elm327_init, - .rx = elm327_rx_hook, + .init = nooutput_init, + .rx = default_rx_hook, .tx = elm327_tx_hook, .tx_lin = elm327_tx_lin_hook, .ignition = default_ign_hook, - .fwd = elm327_fwd_hook, - .relay = nooutput_relay_hook, + .fwd = nooutput_fwd_hook, }; diff --git a/panda/board/safety/safety_ford.h b/panda/board/safety/safety_ford.h index 1d3f16d0694676..075029fb623e0f 100644 --- a/panda/board/safety/safety_ford.h +++ b/panda/board/safety/safety_ford.h @@ -90,5 +90,4 @@ const safety_hooks ford_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = nooutput_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h index 396fb8770c36f4..996161127baa8f 100644 --- a/panda/board/safety/safety_gm.h +++ b/panda/board/safety/safety_gm.h @@ -101,7 +101,7 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // exit controls on rising edge of gas press if (addr == 417) { int gas = to_push->RDHR & 0xFF0000; - if (gas && !gm_gas_prev) { + if (gas && !gm_gas_prev && long_controls_allowed) { controls_allowed = 0; } gm_gas_prev = gas; @@ -148,7 +148,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int rdlr = to_send->RDLR; int brake = ((rdlr & 0xF) << 8) + ((rdlr & 0xFF00) >> 8); brake = (0x1000 - brake) & 0xFFF; - if (current_controls_allowed) { + if (current_controls_allowed && long_controls_allowed) { if (brake > GM_MAX_BRAKE) return 0; } else { if (brake != 0) return 0; @@ -212,7 +212,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { int rdlr = to_send->RDLR; int gas_regen = ((rdlr & 0x7F0000) >> 11) + ((rdlr & 0xF8000000) >> 27); int apply = rdlr & 1; - if (current_controls_allowed) { + if (current_controls_allowed && long_controls_allowed) { if (gas_regen > GM_MAX_GAS) return 0; } else { // Disabled message is !engaed with gas @@ -228,9 +228,6 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void gm_init(int16_t param) { controls_allowed = 0; gm_ignition_started = 0; - #ifdef PANDA - lline_relay_release(); - #endif } static int gm_ign_hook() { @@ -244,5 +241,4 @@ const safety_hooks gm_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = gm_ign_hook, .fwd = nooutput_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_gm_ascm.h b/panda/board/safety/safety_gm_ascm.h index b145466d9de225..70a042ec514a69 100644 --- a/panda/board/safety/safety_gm_ascm.h +++ b/panda/board/safety/safety_gm_ascm.h @@ -48,6 +48,5 @@ const safety_hooks gm_ascm_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = gm_ascm_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_honda.h b/panda/board/safety/safety_honda.h index 40c6917b0b4c43..3aeeefe835f449 100644 --- a/panda/board/safety/safety_honda.h +++ b/panda/board/safety/safety_honda.h @@ -7,15 +7,11 @@ // brake rising edge // brake > 0mph -// these are set in the Honda safety hooks...this is the wrong place -const int gas_interceptor_threshold = 328; -int gas_interceptor_detected = 0; -int brake_prev = 0; -int gas_prev = 0; -int gas_interceptor_prev = 0; -int ego_speed = 0; -// TODO: auto-detect bosch hardware based on CAN messages? -bool bosch_hardware = false; +const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 328; // ratio between offset and gain from dbc file +int honda_brake_prev = 0; +int honda_gas_prev = 0; +int honda_ego_speed = 0; +bool honda_bosch_hardware = false; bool honda_alt_brake_msg = false; static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { @@ -23,7 +19,7 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // sample speed if ((to_push->RIR>>21) == 0x158) { // first 2 bytes - ego_speed = to_push->RDLR & 0xFFFF; + honda_ego_speed = to_push->RDLR & 0xFFFF; } // state machine to enter and exit controls @@ -49,10 +45,10 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // speed > 0 if (IS_USER_BRAKE_MSG(to_push)) { int brake = USER_BRAKE_VALUE(to_push); - if (brake && (!(brake_prev) || ego_speed)) { + if (brake && (!(honda_brake_prev) || honda_ego_speed)) { controls_allowed = 0; } - brake_prev = brake; + honda_brake_prev = brake; } // exit controls on rising edge of gas press if interceptor (0x201 w/ len = 6) @@ -60,8 +56,9 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { if ((to_push->RIR>>21) == 0x201 && (to_push->RDTR & 0xf) == 6) { gas_interceptor_detected = 1; int gas_interceptor = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8); - if ((gas_interceptor > gas_interceptor_threshold) && - (gas_interceptor_prev <= gas_interceptor_threshold)) { + if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) && + (gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD) && + long_controls_allowed) { controls_allowed = 0; } gas_interceptor_prev = gas_interceptor; @@ -71,10 +68,10 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { if (!gas_interceptor_detected) { if ((to_push->RIR>>21) == 0x17C) { int gas = to_push->RDLR & 0xFF; - if (gas && !(gas_prev)) { + if (gas && !(honda_gas_prev) && long_controls_allowed) { controls_allowed = 0; } - gas_prev = gas; + honda_gas_prev = gas; } } } @@ -89,13 +86,13 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // disallow actuator commands if gas or brake (with vehicle moving) are pressed // and the the latching controls_allowed flag is True - int pedal_pressed = gas_prev || (gas_interceptor_prev > gas_interceptor_threshold) || - (brake_prev && ego_speed); + int pedal_pressed = honda_gas_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) || + (honda_brake_prev && honda_ego_speed); int current_controls_allowed = controls_allowed && !(pedal_pressed); // BRAKE: safety check if ((to_send->RIR>>21) == 0x1FA) { - if (current_controls_allowed) { + if (current_controls_allowed && long_controls_allowed) { if ((to_send->RDLR & 0xFFFFFF3F) != to_send->RDLR) return 0; } else { if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; @@ -113,7 +110,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // GAS: safety check if ((to_send->RIR>>21) == 0x200) { - if (current_controls_allowed) { + if (current_controls_allowed && long_controls_allowed) { // all messages are fine here } else { if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; @@ -123,7 +120,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW // ensuring that only the cancel button press is sent (VAL 2) when controls are off. // This avoids unintended engagements while still allowing resume spam - if (((to_send->RIR>>21) == 0x296) && bosch_hardware && + if (((to_send->RIR>>21) == 0x296) && honda_bosch_hardware && !current_controls_allowed && ((to_send->RDTR >> 4) & 0xFF) == 0) { if (((to_send->RDLR >> 5) & 0x7) != 2) return 0; } @@ -134,21 +131,15 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void honda_init(int16_t param) { controls_allowed = 0; - bosch_hardware = false; + honda_bosch_hardware = false; honda_alt_brake_msg = false; - #ifdef PANDA - lline_relay_release(); - #endif } static void honda_bosch_init(int16_t param) { controls_allowed = 0; - bosch_hardware = true; + honda_bosch_hardware = true; // Checking for alternate brake override from safety parameter honda_alt_brake_msg = param == 1 ? true : false; - #ifdef PANDA - lline_relay_release(); - #endif } static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { @@ -159,11 +150,15 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { int addr = to_fwd->RIR>>21; if (bus_num == 0) { return 2; - } else if (bus_num == 2 && addr != 0xE4 && addr != 0x194 && addr != 0x1FA && - addr != 0x30C && addr != 0x33D && addr != 0x39F) { + } else if (bus_num == 2) { + // block stock lkas messages and stock acc messages (if OP is doing ACC) + int is_lkas_msg = (addr == 0xE4 || addr == 0x194 || addr == 0x33D); + int is_acc_msg = (addr == 0x1FA || addr == 0x30C || addr == 0x39F); + if (is_lkas_msg || (is_acc_msg && long_controls_allowed)) { + return -1; + } return 0; } - return -1; } @@ -182,7 +177,6 @@ const safety_hooks honda_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = honda_fwd_hook, - .relay = nooutput_relay_hook, }; const safety_hooks honda_bosch_hooks = { @@ -192,5 +186,4 @@ const safety_hooks honda_bosch_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = honda_bosch_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_hyundai.h b/panda/board/safety/safety_hyundai.h index 9470e34d1556bd..b67632141d8365 100644 --- a/panda/board/safety/safety_hyundai.h +++ b/panda/board/safety/safety_hyundai.h @@ -152,9 +152,6 @@ static int hyundai_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { static void hyundai_init(int16_t param) { controls_allowed = 0; hyundai_giraffe_switch_2 = 0; - #ifdef PANDA - lline_relay_release(); - #endif } const safety_hooks hyundai_hooks = { @@ -164,5 +161,4 @@ const safety_hooks hyundai_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = hyundai_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_subaru.h b/panda/board/safety/safety_subaru.h index 5d2bd23d24b6a9..e64c777195da4d 100644 --- a/panda/board/safety/safety_subaru.h +++ b/panda/board/safety/safety_subaru.h @@ -15,9 +15,6 @@ uint32_t subaru_ts_last = 0; struct sample_t subaru_torque_driver; // last few driver torques measured static void subaru_init(int16_t param) { - #ifdef PANDA - lline_relay_init(); - #endif } static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { @@ -142,5 +139,4 @@ const safety_hooks subaru_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = subaru_fwd_hook, - .relay = alloutput_relay_hook, }; diff --git a/panda/board/safety/safety_tesla.h b/panda/board/safety/safety_tesla.h index 882a509f56105e..430a42ce94a827 100644 --- a/panda/board/safety/safety_tesla.h +++ b/panda/board/safety/safety_tesla.h @@ -219,20 +219,11 @@ static int tesla_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) return true; } -static int tesla_tx_lin_hook(int lin_num, uint8_t *data, int len) -{ - // LIN is not used on the Tesla - return false; -} - static void tesla_init(int16_t param) { controls_allowed = 0; tesla_ignition_started = 0; gmlan_switch_init(1); //init the gmlan switch with 1s timeout enabled - #ifdef PANDA - lline_relay_release(); - #endif } static int tesla_ign_hook() @@ -281,11 +272,10 @@ static int tesla_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) } const safety_hooks tesla_hooks = { - .init = tesla_init, - .rx = tesla_rx_hook, - .tx = tesla_tx_hook, - .tx_lin = tesla_tx_lin_hook, - .ignition = tesla_ign_hook, - .fwd = tesla_fwd_hook, - .relay = nooutput_relay_hook, + .init = tesla_init, + .rx = tesla_rx_hook, + .tx = tesla_tx_hook, + .tx_lin = nooutput_tx_lin_hook, + .ignition = tesla_ign_hook, + .fwd = tesla_fwd_hook, }; diff --git a/panda/board/safety/safety_toyota.h b/panda/board/safety/safety_toyota.h index cbc83860875fde..2c9e062f797d1e 100644 --- a/panda/board/safety/safety_toyota.h +++ b/panda/board/safety/safety_toyota.h @@ -1,6 +1,3 @@ -int toyota_giraffe_switch_1 = 0; // is giraffe switch 1 high? -int toyota_camera_forwarded = 0; // should we forward the camera bus? - // global torque limit const int TOYOTA_MAX_TORQUE = 1500; // max torque cmd allowed ever @@ -19,15 +16,19 @@ const int TOYOTA_RT_INTERVAL = 250000; // 250ms between real time checks const int TOYOTA_MAX_ACCEL = 1500; // 1.5 m/s2 const int TOYOTA_MIN_ACCEL = -3000; // 3.0 m/s2 -// global actuation limit state -int toyota_actuation_limits = 1; // by default steer limits are imposed +const int TOYOTA_GAS_INTERCEPTOR_THRESHOLD = 475; // ratio between offset and gain from dbc file + +// global actuation limit states int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file -// state of torque limits +// states +int toyota_giraffe_switch_1 = 0; // is giraffe switch 1 high? +int toyota_camera_forwarded = 0; // should we forward the camera bus? int toyota_desired_torque_last = 0; // last desired steer torque int toyota_rt_torque_last = 0; // last desired torque for real time check uint32_t toyota_ts_last = 0; int toyota_cruise_engaged_last = 0; // cruise state +int toyota_gas_prev = 0; struct sample_t toyota_torque_meas; // last 3 motor torques produced by the eps @@ -40,23 +41,40 @@ static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // scale by dbc_factor torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100; - // increase torque_meas by 1 to be conservative on rounding - torque_meas_new += (torque_meas_new > 0 ? 1 : -1); - // update array of sample update_sample(&toyota_torque_meas, torque_meas_new); + + // increase torque_meas by 1 to be conservative on rounding + toyota_torque_meas.min--; + toyota_torque_meas.max++; } // enter controls on rising edge of ACC, exit controls on ACC off if ((to_push->RIR>>21) == 0x1D2) { // 5th bit is CRUISE_ACTIVE int cruise_engaged = to_push->RDLR & 0x20; - if (cruise_engaged && !toyota_cruise_engaged_last) { - controls_allowed = 1; - } else if (!cruise_engaged) { + // 4th bit is GAS_RELEASED + int gas = !(to_push->RDLR & 0x10); + if (!cruise_engaged || + (gas && !toyota_gas_prev && !gas_interceptor_detected && long_controls_allowed)) { controls_allowed = 0; + } else if (cruise_engaged && !toyota_cruise_engaged_last) { + controls_allowed = 1; } toyota_cruise_engaged_last = cruise_engaged; + toyota_gas_prev = gas; + } + + // exit controls on rising edge of gas press if interceptor (0x201) + if ((to_push->RIR>>21) == 0x201) { + gas_interceptor_detected = 1; + int gas_interceptor = ((to_push->RDLR & 0xFF) << 8) | ((to_push->RDLR & 0xFF00) >> 8); + if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRESHOLD) && + (gas_interceptor_prev <= TOYOTA_GAS_INTERCEPTOR_THRESHOLD) && + long_controls_allowed) { + controls_allowed = 0; + } + gas_interceptor_prev = gas_interceptor; } int bus = (to_push->RDTR >> 4) & 0xF; @@ -81,7 +99,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { // GAS PEDAL: safety check if ((to_send->RIR>>21) == 0x200) { - if (controls_allowed && toyota_actuation_limits) { + if (controls_allowed && long_controls_allowed) { // all messages are fine here } else { if ((to_send->RDLR & 0xFFFF0000) != to_send->RDLR) return 0; @@ -92,10 +110,10 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { if ((to_send->RIR>>21) == 0x343) { int desired_accel = ((to_send->RDLR & 0xFF) << 8) | ((to_send->RDLR >> 8) & 0xFF); desired_accel = to_signed(desired_accel, 16); - if (controls_allowed && toyota_actuation_limits) { + if (controls_allowed && long_controls_allowed) { int violation = max_limit_check(desired_accel, TOYOTA_MAX_ACCEL, TOYOTA_MIN_ACCEL); if (violation) return 0; - } else if (!controls_allowed && (desired_accel != 0)) { + } else if (desired_accel != 0) { return 0; } } @@ -108,8 +126,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { uint32_t ts = TIM2->CNT; - // only check if controls are allowed and actuation_limits are imposed - if (controls_allowed && toyota_actuation_limits) { + if (controls_allowed) { // *** global torque limit check *** violation |= max_limit_check(desired_torque, TOYOTA_MAX_TORQUE, -TOYOTA_MAX_TORQUE); @@ -156,25 +173,27 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) { static void toyota_init(int16_t param) { controls_allowed = 0; - toyota_actuation_limits = 1; toyota_giraffe_switch_1 = 0; toyota_camera_forwarded = 0; toyota_dbc_eps_torque_factor = param; - #ifdef PANDA - lline_relay_release(); - #endif } static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) { - // forward cam to radar and viceversa if car, except lkas cmd and hud - // don't forward when switch 1 is high - if ((bus_num == 0 || bus_num == 2) && toyota_camera_forwarded && !toyota_giraffe_switch_1) { + if (toyota_camera_forwarded && !toyota_giraffe_switch_1) { int addr = to_fwd->RIR>>21; - bool is_lkas_msg = (addr == 0x2E4 || addr == 0x412) && bus_num == 2; - // in TSSP 2.0 the camera does ACC as well, so filter 0x343 - bool is_acc_msg = (addr == 0x343 && bus_num == 2); - return (is_lkas_msg || is_acc_msg)? -1 : (uint8_t)(~bus_num & 0x2); + if (bus_num == 0) { + return 2; + } else if (bus_num == 2) { + // block stock lkas messages and stock acc messages (if OP is doing ACC) + int is_lkas_msg = (addr == 0x2E4 || addr == 0x412); + // in TSSP 2.0 the camera does ACC as well, so filter 0x343 + int is_acc_msg = (addr == 0x343); + if (is_lkas_msg || (is_acc_msg && long_controls_allowed)) { + return -1; + } + return 0; + } } return -1; } @@ -186,26 +205,4 @@ const safety_hooks toyota_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = toyota_fwd_hook, - .relay = nooutput_relay_hook, -}; - -static void toyota_nolimits_init(int16_t param) { - controls_allowed = 0; - toyota_actuation_limits = 0; - toyota_giraffe_switch_1 = 0; - toyota_camera_forwarded = 0; - toyota_dbc_eps_torque_factor = param; - #ifdef PANDA - lline_relay_release(); - #endif -} - -const safety_hooks toyota_nolimits_hooks = { - .init = toyota_nolimits_init, - .rx = toyota_rx_hook, - .tx = toyota_tx_hook, - .tx_lin = nooutput_tx_lin_hook, - .ignition = default_ign_hook, - .fwd = toyota_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/safety/safety_toyota_ipas.h b/panda/board/safety/safety_toyota_ipas.h index 13e664c0f9d88e..2f0b42f649319b 100644 --- a/panda/board/safety/safety_toyota_ipas.h +++ b/panda/board/safety/safety_toyota_ipas.h @@ -152,5 +152,4 @@ const safety_hooks toyota_ipas_hooks = { .tx_lin = nooutput_tx_lin_hook, .ignition = default_ign_hook, .fwd = toyota_fwd_hook, - .relay = nooutput_relay_hook, }; diff --git a/panda/board/spi_flasher.h b/panda/board/spi_flasher.h index 179a095b970ef9..48e00aa2292956 100644 --- a/panda/board/spi_flasher.h +++ b/panda/board/spi_flasher.h @@ -2,7 +2,9 @@ uint32_t *prog_ptr = NULL; int unlocked = 0; +#ifdef uart_ring void debug_ring_callback(uart_ring *ring) {} +#endif int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { int resp_len = 0; @@ -46,7 +48,7 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { break; // **** 0xd0: fetch serial number case 0xd0: - #ifdef PANDA + #ifdef STM32F4 // addresses are OTP if (setup->b.wValue.w == 1) { memcpy(resp, (void *)0x1fff79c0, 0x10); @@ -132,6 +134,7 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { #ifdef PEDAL +#include "drivers/llcan.h" #define CAN CAN1 #define CAN_BL_INPUT 0x1 @@ -239,7 +242,7 @@ void CAN1_RX0_IRQHandler() { } void CAN1_SCE_IRQHandler() { - can_sce(CAN); + llcan_clear_send(CAN); } #endif @@ -264,8 +267,8 @@ void soft_flasher_start() { set_can_enable(CAN1, 1); // init can - can_silent = ALL_CAN_LIVE; - can_init(0); + llcan_set_speed(CAN1, 5000, false, false); + llcan_init(CAN1); #endif // A4,A5,A6,A7: setup SPI diff --git a/panda/buy.png b/panda/buy.png index 72c70574225173..a4a9e0fd40a426 100644 Binary files a/panda/buy.png and b/panda/buy.png differ diff --git a/panda/examples/query_vin_and_stats.py b/panda/examples/query_vin_and_stats.py index 09a6289bf2a05f..f3d6c198aff9f1 100755 --- a/panda/examples/query_vin_and_stats.py +++ b/panda/examples/query_vin_and_stats.py @@ -3,7 +3,7 @@ import struct from panda import Panda from hexdump import hexdump -from panda.isotp import isotp_send, isotp_recv +from panda.python.isotp import isotp_send, isotp_recv # 0x7e0 = Toyota # 0x18DB33F1 for Honda? @@ -33,7 +33,7 @@ def get_supported_pids(): panda.can_clear(0) # 09 02 = Get VIN - isotp_send(panda, "\x09\x02", 0x7e0) + isotp_send(panda, "\x09\x02", 0x7df) ret = isotp_recv(panda, 0x7e8) hexdump(ret) print "VIN: %s" % ret[2:] diff --git a/panda/python/__init__.py b/panda/python/__init__.py index 8c0bc5a9a2ae2d..bfca642e8256f7 100644 --- a/panda/python/__init__.py +++ b/panda/python/__init__.py @@ -392,9 +392,6 @@ def set_gmlan(self, bus=2): elif bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]: self._handle.controlWrite(Panda.REQUEST_OUT, 0xdb, 1, bus, b'') - def set_lline_relay(self, enable): - self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, int(enable), 0, b'') - def set_can_loopback(self, enable): # set can loopback mode for all buses self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'') diff --git a/panda/run_automated_tests.sh b/panda/run_automated_tests.sh index 63d9b6531b3266..4e07d329cace20 100755 --- a/panda/run_automated_tests.sh +++ b/panda/run_automated_tests.sh @@ -6,4 +6,9 @@ else TESTSUITE_NAME="Panda_Test-DEV" fi -PYTHONPATH="." nosetests -v --with-xunit --xunit-file=./$TEST_FILENAME --xunit-testsuite-name=$TESTSUITE_NAME -s tests/automated/$1*.py +cd boardesp +make flashall +cd .. + + +PYTHONPATH="." python $(which nosetests) -v --with-xunit --xunit-file=./$TEST_FILENAME --xunit-testsuite-name=$TESTSUITE_NAME -s tests/automated/$1*.py diff --git a/panda/tests/automated/0_builds.py b/panda/tests/automated/0_builds.py index d5e434a2c22876..df4186cce4e6f6 100644 --- a/panda/tests/automated/0_builds.py +++ b/panda/tests/automated/0_builds.py @@ -1,12 +1,6 @@ import os from panda import build_st -def test_build_legacy(): - build_st("obj/comma.bin", "Makefile.legacy") - -def test_build_bootstub_legacy(): - build_st("obj/bootstub.comma.bin", "Makefile.legacy") - def test_build_panda(): build_st("obj/panda.bin") diff --git a/panda/tests/automated/3_wifi.py b/panda/tests/automated/3_wifi.py index 6578903aa8cb51..1251663ba5838d 100644 --- a/panda/tests/automated/3_wifi.py +++ b/panda/tests/automated/3_wifi.py @@ -29,7 +29,7 @@ def test_connect_wifi(serial=None): @panda_color_to_serial def test_flash_wifi(serial=None): connect_wifi(serial) - assert Panda.flash_ota_wifi(release=True), "OTA Wifi Flash Failed" + assert Panda.flash_ota_wifi(release=False), "OTA Wifi Flash Failed" connect_wifi(serial) @test_white diff --git a/panda/tests/build_strict/Dockerfile b/panda/tests/build_strict/Dockerfile new file mode 100644 index 00000000000000..b1c75c0258ef64 --- /dev/null +++ b/panda/tests/build_strict/Dockerfile @@ -0,0 +1,9 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y gcc-arm-none-eabi libnewlib-arm-none-eabi python python-pip gcc g++ + +RUN pip install pycrypto==2.6.1 + +COPY . /panda + +WORKDIR /panda diff --git a/panda/tests/misra/Dockerfile b/panda/tests/misra/Dockerfile new file mode 100644 index 00000000000000..e63cc7e9e151ed --- /dev/null +++ b/panda/tests/misra/Dockerfile @@ -0,0 +1,6 @@ +FROM ubuntu:16.04 + +RUN apt-get update && apt-get install -y make python python-pip git +COPY tests/safety/requirements.txt /panda/tests/safety/requirements.txt +RUN pip install -r /panda/tests/safety/requirements.txt +COPY . /panda diff --git a/panda/tests/misra/test_misra.sh b/panda/tests/misra/test_misra.sh new file mode 100755 index 00000000000000..5d2650dc003662 --- /dev/null +++ b/panda/tests/misra/test_misra.sh @@ -0,0 +1,8 @@ +#!/bin/bash -e +git clone https://github.com/danmar/cppcheck.git || true +cd cppcheck +git checkout 29e5992e51ecf1ddba469c73a0eed0b28b131de5 +make -j4 +cd ../../../ +tests/misra/cppcheck/cppcheck --dump board/main.c +python tests/misra/cppcheck/addons/misra.py board/main.c.dump 2>/tmp/misra/output.txt || true diff --git a/panda/tests/safety/libpandasafety_py.py b/panda/tests/safety/libpandasafety_py.py index d8cb27cf8c8092..84f3b00d0532a3 100644 --- a/panda/tests/safety/libpandasafety_py.py +++ b/panda/tests/safety/libpandasafety_py.py @@ -32,6 +32,11 @@ void set_controls_allowed(int c); int get_controls_allowed(void); +void set_long_controls_allowed(int c); +int get_long_controls_allowed(void); +void set_gas_interceptor_detected(int c); +int get_gas_interceptor_detetcted(void); +int get_gas_interceptor_prev(void); void set_timer(int t); void reset_angle_control(void); @@ -41,19 +46,20 @@ void toyota_init(int16_t param); int get_toyota_torque_meas_min(void); int get_toyota_torque_meas_max(void); +int get_toyota_gas_prev(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); +int get_honda_ego_speed(void); void honda_init(int16_t param); void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push); int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send); -int get_brake_prev(void); -int get_gas_prev(void); +int get_honda_brake_prev(void); +int get_honda_gas_prev(void); void set_honda_alt_brake_msg(bool); -void set_bosch_hardware(bool); +void set_honda_bosch_hardware(bool); void init_tests_cadillac(void); void cadillac_init(int16_t param); diff --git a/panda/tests/safety/test.c b/panda/tests/safety/test.c index 04e6576fb8072c..ce75df82a54014 100644 --- a/panda/tests/safety/test.c +++ b/panda/tests/safety/test.c @@ -51,6 +51,14 @@ void set_controls_allowed(int c){ controls_allowed = c; } +void set_long_controls_allowed(int c){ + long_controls_allowed = c; +} + +void set_gas_interceptor_detected(int c){ + gas_interceptor_detected = c; +} + void reset_angle_control(void){ angle_control = 0; } @@ -59,6 +67,18 @@ int get_controls_allowed(void){ return controls_allowed; } +int get_long_controls_allowed(void){ + return long_controls_allowed; +} + +int get_gas_interceptor_detected(void){ + return gas_interceptor_detected; +} + +int get_gas_interceptor_prev(void){ + return gas_interceptor_prev; +} + void set_timer(int t){ timer.CNT = t; } @@ -101,6 +121,10 @@ int get_chrysler_torque_meas_max(void){ return chrysler_torque_meas.max; } +int get_toyota_gas_prev(void){ + return toyota_gas_prev; +} + int get_toyota_torque_meas_min(void){ return toyota_torque_meas.min; } @@ -157,24 +181,24 @@ void set_subaru_desired_torque_last(int t){ subaru_desired_torque_last = t; } -int get_ego_speed(void){ - return ego_speed; +int get_honda_ego_speed(void){ + return honda_ego_speed; } -int get_brake_prev(void){ - return brake_prev; +int get_honda_brake_prev(void){ + return honda_brake_prev; } -int get_gas_prev(void){ - return gas_prev; +int get_honda_gas_prev(void){ + return honda_gas_prev; } void set_honda_alt_brake_msg(bool c){ honda_alt_brake_msg = c; } -void set_bosch_hardware(bool c){ - bosch_hardware = c; +void set_honda_bosch_hardware(bool c){ + honda_bosch_hardware = c; } void init_tests_toyota(void){ @@ -232,10 +256,9 @@ void init_tests_subaru(void){ } void init_tests_honda(void){ - ego_speed = 0; - gas_interceptor_detected = 0; - brake_prev = 0; - gas_prev = 0; + honda_ego_speed = 0; + honda_brake_prev = 0; + honda_gas_prev = 0; } void set_gmlan_digital_output(int to_set){ @@ -247,11 +270,3 @@ void reset_gmlan_switch_timeout(void){ void gmlan_switch_init(int timeout_enable){ } -void lline_relay_init (void) { -} - -void lline_relay_release (void) { -} - -void set_lline_output(int to_set) { -} diff --git a/panda/tests/safety/test_gm.py b/panda/tests/safety/test_gm.py index 299de5a7e9ff51..ecdf40feddf937 100644 --- a/panda/tests/safety/test_gm.py +++ b/panda/tests/safety/test_gm.py @@ -138,10 +138,15 @@ def test_not_allow_brake_when_moving(self): self.safety.gm_rx_hook(self._brake_msg(False)) def test_disengage_on_gas(self): - self.safety.set_controls_allowed(1) - self.safety.gm_rx_hook(self._gas_msg(True)) - self.assertFalse(self.safety.get_controls_allowed()) - self.safety.gm_rx_hook(self._gas_msg(False)) + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + self.safety.set_controls_allowed(1) + self.safety.gm_rx_hook(self._gas_msg(True)) + if long_controls_allowed: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.gm_rx_hook(self._gas_msg(False)) def test_allow_engage_with_gas_pressed(self): self.safety.gm_rx_hook(self._gas_msg(True)) @@ -151,22 +156,28 @@ def test_allow_engage_with_gas_pressed(self): self.safety.gm_rx_hook(self._gas_msg(False)) def test_brake_safety_check(self): - for enabled in [0, 1]: - for b in range(0, 500): - self.safety.set_controls_allowed(enabled) - if abs(b) > MAX_BRAKE or (not enabled and b != 0): - self.assertFalse(self.safety.gm_tx_hook(self._send_brake_msg(b))) - else: - self.assertTrue(self.safety.gm_tx_hook(self._send_brake_msg(b))) + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + for enabled in [0, 1]: + for b in range(0, 500): + self.safety.set_controls_allowed(enabled) + if abs(b) > MAX_BRAKE or ((not enabled or not long_controls_allowed) and b != 0): + self.assertFalse(self.safety.gm_tx_hook(self._send_brake_msg(b))) + else: + self.assertTrue(self.safety.gm_tx_hook(self._send_brake_msg(b))) + self.safety.set_long_controls_allowed(True) def test_gas_safety_check(self): - for enabled in [0, 1]: - for g in range(0, 2**12-1): - self.safety.set_controls_allowed(enabled) - if abs(g) > MAX_GAS or (not enabled and g != MAX_REGEN): - self.assertFalse(self.safety.gm_tx_hook(self._send_gas_msg(g))) - else: - self.assertTrue(self.safety.gm_tx_hook(self._send_gas_msg(g))) + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + for enabled in [0, 1]: + for g in range(0, 2**12-1): + self.safety.set_controls_allowed(enabled) + if abs(g) > MAX_GAS or ((not enabled or not long_controls_allowed) and g != MAX_REGEN): + self.assertFalse(self.safety.gm_tx_hook(self._send_gas_msg(g))) + else: + self.assertTrue(self.safety.gm_tx_hook(self._send_gas_msg(g))) + self.safety.set_long_controls_allowed(True) def test_steer_safety_check(self): for enabled in [0, 1]: diff --git a/panda/tests/safety/test_honda.py b/panda/tests/safety/test_honda.py index 48b678eaaec43e..4e131f2fc0fd4f 100755 --- a/panda/tests/safety/test_honda.py +++ b/panda/tests/safety/test_honda.py @@ -3,6 +3,7 @@ import numpy as np import libpandasafety_py +MAX_BRAKE = 255 class TestHondaSafety(unittest.TestCase): @classmethod @@ -49,14 +50,15 @@ def _gas_msg(self, gas): def _send_brake_msg(self, brake): to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') to_send[0].RIR = 0x1FA << 21 - to_send[0].RDLR = brake + to_send[0].RDLR = ((brake & 0x3) << 8) | ((brake & 0x3FF) >> 2) return to_send - def _send_gas_msg(self, gas): + def _send_interceptor_msg(self, gas, addr): to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') - to_send[0].RIR = 0x200 << 21 - to_send[0].RDLR = gas + to_send[0].RIR = addr << 21 + to_send[0].RDTR = 6 + to_send[0].RDLR = ((gas & 0xff) << 8) | ((gas & 0xff00) >> 8) return to_send @@ -89,14 +91,14 @@ def test_cancel_button(self): self.assertFalse(self.safety.get_controls_allowed()) def test_sample_speed(self): - self.assertEqual(0, self.safety.get_ego_speed()) + self.assertEqual(0, self.safety.get_honda_ego_speed()) self.safety.honda_rx_hook(self._speed_msg(100)) - self.assertEqual(100, self.safety.get_ego_speed()) + self.assertEqual(100, self.safety.get_honda_ego_speed()) def test_prev_brake(self): - self.assertFalse(self.safety.get_brake_prev()) + self.assertFalse(self.safety.get_honda_brake_prev()) self.safety.honda_rx_hook(self._brake_msg(True)) - self.assertTrue(self.safety.get_brake_prev()) + self.assertTrue(self.safety.get_honda_brake_prev()) def test_disengage_on_brake(self): self.safety.set_controls_allowed(1) @@ -133,14 +135,30 @@ def test_not_allow_brake_when_moving(self): self.assertFalse(self.safety.get_controls_allowed()) def test_prev_gas(self): - self.assertFalse(self.safety.get_gas_prev()) + self.safety.honda_rx_hook(self._gas_msg(False)) + self.assertFalse(self.safety.get_honda_gas_prev()) self.safety.honda_rx_hook(self._gas_msg(True)) - self.assertTrue(self.safety.get_gas_prev()) + self.assertTrue(self.safety.get_honda_gas_prev()) + + def test_prev_gas_interceptor(self): + self.safety.honda_rx_hook(self._send_interceptor_msg(0x0, 0x201)) + self.assertFalse(self.safety.get_gas_interceptor_prev()) + self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + self.assertTrue(self.safety.get_gas_interceptor_prev()) + self.safety.honda_rx_hook(self._send_interceptor_msg(0x0, 0x201)) + self.safety.set_gas_interceptor_detected(False) def test_disengage_on_gas(self): - self.safety.set_controls_allowed(1) - self.safety.honda_rx_hook(self._gas_msg(1)) - self.assertFalse(self.safety.get_controls_allowed()) + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + self.safety.honda_rx_hook(self._gas_msg(0)) + self.safety.set_controls_allowed(1) + self.safety.honda_rx_hook(self._gas_msg(1)) + if long_controls_allowed: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.set_long_controls_allowed(True) def test_allow_engage_with_gas_pressed(self): self.safety.honda_rx_hook(self._gas_msg(1)) @@ -148,18 +166,53 @@ def test_allow_engage_with_gas_pressed(self): self.safety.honda_rx_hook(self._gas_msg(1)) self.assertTrue(self.safety.get_controls_allowed()) - def test_brake_safety_check(self): - self.assertTrue(self.safety.honda_tx_hook(self._send_brake_msg(0x0000))) - self.assertFalse(self.safety.honda_tx_hook(self._send_brake_msg(0x1000))) - + def test_disengage_on_gas_interceptor(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_controls_allowed(1) + self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + if long_controls_allowed: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_gas_interceptor_detected(False) + self.safety.set_long_controls_allowed(True) + + def test_allow_engage_with_gas_interceptor_pressed(self): + self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) self.safety.set_controls_allowed(1) - self.assertTrue(self.safety.honda_tx_hook(self._send_brake_msg(0x1000))) - self.assertFalse(self.safety.honda_tx_hook(self._send_brake_msg(0x00F0))) + self.safety.honda_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.honda_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_gas_interceptor_detected(False) - def test_gas_safety_check(self): - self.safety.set_controls_allowed(0) - self.assertTrue(self.safety.honda_tx_hook(self._send_gas_msg(0x0000))) - self.assertFalse(self.safety.honda_tx_hook(self._send_gas_msg(0x1000))) + def test_brake_safety_check(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + for brake in np.arange(0, MAX_BRAKE + 10, 1): + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + if controls_allowed and long_controls_allowed: + send = MAX_BRAKE >= brake >= 0 + else: + send = brake == 0 + self.assertEqual(send, self.safety.honda_tx_hook(self._send_brake_msg(brake))) + self.safety.set_long_controls_allowed(True) + + def test_gas_interceptor_safety_check(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + for gas in np.arange(0, 4000, 100): + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + if controls_allowed and long_controls_allowed: + send = True + else: + send = gas == 0 + self.assertEqual(send, self.safety.honda_tx_hook(self._send_interceptor_msg(gas, 0x200))) + self.safety.set_long_controls_allowed(True) def test_steer_safety_check(self): self.safety.set_controls_allowed(0) @@ -171,7 +224,7 @@ def test_spam_cancel_safety_check(self): SET_BTN = 3 CANCEL_BTN = 2 BUTTON_MSG = 0x296 - self.safety.set_bosch_hardware(1) + self.safety.set_honda_bosch_hardware(1) self.safety.set_controls_allowed(0) self.assertTrue(self.safety.honda_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG))) self.assertFalse(self.safety.honda_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG))) diff --git a/panda/tests/safety/test_toyota.py b/panda/tests/safety/test_toyota.py index 52c7015af3e5bc..9badaec0f6959d 100644 --- a/panda/tests/safety/test_toyota.py +++ b/panda/tests/safety/test_toyota.py @@ -119,13 +119,28 @@ def _accel_msg(self, accel): to_send[0].RDLR = (a & 0xFF) << 8 | (a >> 8) return to_send - def _gas_msg(self, gas): + def _send_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 _send_interceptor_msg(self, gas, addr): + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = addr << 21 + to_send[0].RDTR = 6 + to_send[0].RDLR = ((gas & 0xff) << 8) | ((gas & 0xff00) >> 8) + + return to_send + + def _pcm_cruise_msg(self, cruise_on, gas_pressed): + to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *') + to_send[0].RIR = 0x1D2 << 21 + to_send[0].RDLR = (cruise_on << 5) | ((not gas_pressed) << 4 ) + + return to_send + def test_default_controls_not_allowed(self): self.assertFalse(self.safety.get_controls_allowed()) @@ -134,32 +149,84 @@ def test_manually_enable_controls_allowed(self): self.assertTrue(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 = 0x1D2 << 21 - to_push[0].RDLR = 0x20 - - self.safety.toyota_rx_hook(to_push) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False)) + self.assertFalse(self.safety.get_controls_allowed()) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, False)) 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 = 0x1D2 << 21 - to_push[0].RDLR = 0 - self.safety.set_controls_allowed(1) - self.safety.toyota_rx_hook(to_push) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False)) self.assertFalse(self.safety.get_controls_allowed()) - def test_accel_actuation_limits(self): - for accel in np.arange(MIN_ACCEL - 1000, MAX_ACCEL + 1000, 100): - for controls_allowed in [True, False]: - self.safety.set_controls_allowed(controls_allowed) + def test_prev_gas(self): + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False)) + self.assertFalse(self.safety.get_toyota_gas_prev()) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, True)) + self.assertTrue(self.safety.get_toyota_gas_prev()) + + def test_prev_gas_interceptor(self): + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x0, 0x201)) + self.assertFalse(self.safety.get_gas_interceptor_prev()) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + self.assertTrue(self.safety.get_gas_interceptor_prev()) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x0, 0x201)) + self.safety.set_gas_interceptor_detected(False) + + def test_disengage_on_gas(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, False)) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, False)) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True)) + if long_controls_allowed: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.set_long_controls_allowed(True) - if controls_allowed: - send = MIN_ACCEL <= accel <= MAX_ACCEL - else: - send = accel == 0 - self.assertEqual(send, self.safety.toyota_tx_hook(self._accel_msg(accel))) + def test_allow_engage_with_gas_pressed(self): + self.safety.toyota_rx_hook(self._pcm_cruise_msg(False, True)) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True)) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.toyota_rx_hook(self._pcm_cruise_msg(True, True)) + self.assertTrue(self.safety.get_controls_allowed()) + + def test_disengage_on_gas_interceptor(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_controls_allowed(1) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + if long_controls_allowed: + self.assertFalse(self.safety.get_controls_allowed()) + else: + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_gas_interceptor_detected(False) + self.safety.set_long_controls_allowed(True) + + def test_allow_engage_with_gas_interceptor_pressed(self): + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + self.safety.set_controls_allowed(1) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0x1000, 0x201)) + self.assertTrue(self.safety.get_controls_allowed()) + self.safety.toyota_rx_hook(self._send_interceptor_msg(0, 0x201)) + self.safety.set_gas_interceptor_detected(False) + + def test_accel_actuation_limits(self): + for long_controls_allowed in [0, 1]: + self.safety.set_long_controls_allowed(long_controls_allowed) + for accel in np.arange(MIN_ACCEL - 1000, MAX_ACCEL + 1000, 100): + for controls_allowed in [True, False]: + self.safety.set_controls_allowed(controls_allowed) + if controls_allowed and long_controls_allowed: + send = MIN_ACCEL <= accel <= MAX_ACCEL + else: + send = accel == 0 + self.assertEqual(send, self.safety.toyota_tx_hook(self._accel_msg(accel))) + self.safety.set_long_controls_allowed(True) def test_torque_absolute_limits(self): for controls_allowed in [True, False]: @@ -244,11 +311,11 @@ def test_torque_measurements(self): self.assertEqual(51, self.safety.get_toyota_torque_meas_max()) self.safety.toyota_rx_hook(self._torque_meas_msg(0)) - self.assertEqual(-1, self.safety.get_toyota_torque_meas_max()) + self.assertEqual(1, self.safety.get_toyota_torque_meas_max()) self.assertEqual(-51, self.safety.get_toyota_torque_meas_min()) self.safety.toyota_rx_hook(self._torque_meas_msg(0)) - self.assertEqual(-1, self.safety.get_toyota_torque_meas_max()) + self.assertEqual(1, self.safety.get_toyota_torque_meas_max()) self.assertEqual(-1, self.safety.get_toyota_torque_meas_min()) def test_ipas_override(self): @@ -416,12 +483,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): + def test_gas_interceptor_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.assertTrue(self.safety.toyota_tx_hook(self._send_interceptor_msg(0, 0x200))) + self.assertFalse(self.safety.toyota_tx_hook(self._send_interceptor_msg(0x1000, 0x200))) self.safety.set_controls_allowed(1) - self.assertTrue(self.safety.honda_tx_hook(self._gas_msg(0x1000))) + self.assertTrue(self.safety.toyota_tx_hook(self._send_interceptor_msg(0x1000, 0x200))) if __name__ == "__main__":