From 1d917f81cd7e7ded3e0ce93fc0497be2760ec61e Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 21:45:07 -0800 Subject: [PATCH 1/7] split gas set into 2 values, and have a fault state --- board/pedal/main.c | 56 ++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 19 deletions(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index d49f04601778f1..23ab220ec5fee7 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -107,10 +107,17 @@ void CAN1_TX_IRQHandler() { CAN->TSR |= CAN_TSR_RQCP0; } -uint16_t gas_set = 0; + +// two independent values +uint16_t gas_set_0 = 0; +uint16_t gas_set_1 = 0; + +#define MAX_TIMEOUT 10 uint32_t timeout = 0; uint32_t current_index = 0; +uint8_t fault = 0; + void CAN1_RX0_IRQHandler() { while (CAN->RF0R & CAN_RF0R_FMP0) { #ifdef DEBUG @@ -119,21 +126,28 @@ void CAN1_RX0_IRQHandler() { uint32_t address = CAN->sFIFOMailBox[0].RIR>>21; if (address == CAN_GAS_INPUT) { uint8_t *dat = (uint8_t *)&CAN->sFIFOMailBox[0].RDLR; - uint16_t value = (dat[0] << 8) | dat[1]; - uint8_t index = (dat[2] >> 4) & 3; - if (can_cksum(dat, 2, CAN_GAS_INPUT, index) == (dat[2] & 0xF)) { + uint8_t *dat2 = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR; + uint16_t value_0 = (dat[0] << 8) | dat[1]; + uint16_t value_1 = (dat[2] << 8) | dat[3]; + uint8_t index = (dat2[0] >> 4) & 3; + if (can_cksum(dat, 4, CAN_GAS_INPUT, index) == (dat2[0] & 0xF)) { if (((current_index+1)&3) == index) { - // TODO: set and start timeout #ifdef DEBUG puts("setting gas "); puth(value); puts("\n"); #endif - gas_set = value; + gas_set_0 = value_0; + gas_set_1 = value_1; + // clear the timeout and fault timeout = 0; + fault = 0; } // TODO: better lockout? prevents same spam current_index = index; + } else { + // wrong checksum = fault + fault = 1; } } // next @@ -142,6 +156,7 @@ void CAN1_RX0_IRQHandler() { } void CAN1_SCE_IRQHandler() { + fault = 1; can_sce(CAN); } @@ -162,25 +177,28 @@ void TIM3_IRQHandler() { // check timer for sending the user pedal and clearing the CAN if ((CAN->TSR & CAN_TSR_TME0) == CAN_TSR_TME0) { - uint8_t *dat = (uint8_t *)&CAN->sTxMailBox[0].TDLR; - CAN->sTxMailBox[0].TDLR = (((pdl0>>8)&0xFF)<<0) | - (((pdl0>>0)&0xFF)<<8) | - (((pdl1>>8)&0xFF)<<16) | - (((pdl1>>0)&0xFF)<<24); - CAN->sTxMailBox[0].TDHR = can_cksum(dat, 4, CAN_GAS_OUTPUT, pkt_idx) | (pkt_idx << 4); - CAN->sTxMailBox[0].TDTR = 5; // len of packet is 4 + uint8_t dat[8]; + dat[0] = (pdl0>>8)&0xFF; + dat[1] = (pdl0>>0)&0xFF; + dat[2] = (pdl1>>8)&0xFF; + dat[3] = (pdl1>>0)&0xFF; + dat[4] = fault; + dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT, pkt_idx); + dat[6] = dat[7] = 0; + CAN->sTxMailBox[0].TDLR = ((uint32_t*)dat)[0]; + CAN->sTxMailBox[0].TDHR = ((uint32_t*)dat)[1]; + CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5 CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1; ++pkt_idx; pkt_idx &= 3; } else { // old can packet hasn't sent! - // TODO: do something? + fault = 1; #ifdef DEBUG puts("CAN MISS\n"); #endif } - // blink the LED set_led(LED_GREEN, led_value); led_value = !led_value; @@ -188,7 +206,7 @@ void TIM3_IRQHandler() { TIM3->SR = 0; // up timeout for gas set - timeout++; + timeout = min(timeout+1, MAX_TIMEOUT); } // ***************************** main code ***************************** @@ -199,9 +217,9 @@ void pedal() { pdl1 = adc_get(ADCCHAN_ACCEL1); // write the pedal to the DAC - if (timeout < 10) { - dac_set(0, max(gas_set, pdl0)); - dac_set(1, max(gas_set*2, pdl1)); + if (timeout < MAX_TIMEOUT && !fault) { + dac_set(0, max(gas_set_0, pdl0)); + dac_set(1, max(gas_set_1, pdl1)); } else { dac_set(0, pdl0); dac_set(1, pdl1); From 8f0add974a7e257de8f258a877aabdb6406c22a1 Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 21:59:21 -0800 Subject: [PATCH 2/7] handle faults --- board/pedal/main.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index 23ab220ec5fee7..e4e68fce8c1ddd 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -116,7 +116,11 @@ uint16_t gas_set_1 = 0; uint32_t timeout = 0; uint32_t current_index = 0; -uint8_t fault = 0; +#define STATE_GOOD 0 +#define STATE_FAULT_CHECKSUM 1 +#define STATE_FAULT_SEND 2 +#define STATE_FAULT_SCE 3 +uint8_t state = STATE_NONE; void CAN1_RX0_IRQHandler() { while (CAN->RF0R & CAN_RF0R_FMP0) { @@ -129,6 +133,7 @@ void CAN1_RX0_IRQHandler() { uint8_t *dat2 = (uint8_t *)&CAN->sFIFOMailBox[0].RDHR; uint16_t value_0 = (dat[0] << 8) | dat[1]; uint16_t value_1 = (dat[2] << 8) | dat[3]; + uint8_t enable = (dat2[0] >> 7) & 1; uint8_t index = (dat2[0] >> 4) & 3; if (can_cksum(dat, 4, CAN_GAS_INPUT, index) == (dat2[0] & 0xF)) { if (((current_index+1)&3) == index) { @@ -137,17 +142,22 @@ void CAN1_RX0_IRQHandler() { puth(value); puts("\n"); #endif - gas_set_0 = value_0; - gas_set_1 = value_1; - // clear the timeout and fault - timeout = 0; - fault = 0; + if (enable) { + gas_set_0 = value_0; + gas_set_1 = value_1; + // clear the timeout + timeout = 0; + } else { + gas_set_0 = gas_set_1 = 0; + // clear the fault state + state = STATE_GOOD; + } } // TODO: better lockout? prevents same spam current_index = index; } else { // wrong checksum = fault - fault = 1; + state = STATE_FAULT_CHECKSUM; } } // next @@ -156,7 +166,7 @@ void CAN1_RX0_IRQHandler() { } void CAN1_SCE_IRQHandler() { - fault = 1; + state = STATE_FAULT_SCE; can_sce(CAN); } @@ -182,7 +192,7 @@ void TIM3_IRQHandler() { dat[1] = (pdl0>>0)&0xFF; dat[2] = (pdl1>>8)&0xFF; dat[3] = (pdl1>>0)&0xFF; - dat[4] = fault; + dat[4] = state; dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT, pkt_idx); dat[6] = dat[7] = 0; CAN->sTxMailBox[0].TDLR = ((uint32_t*)dat)[0]; @@ -193,7 +203,7 @@ void TIM3_IRQHandler() { pkt_idx &= 3; } else { // old can packet hasn't sent! - fault = 1; + state = STATE_FAULT_SEND; #ifdef DEBUG puts("CAN MISS\n"); #endif @@ -217,7 +227,7 @@ void pedal() { pdl1 = adc_get(ADCCHAN_ACCEL1); // write the pedal to the DAC - if (timeout < MAX_TIMEOUT && !fault) { + if (timeout < MAX_TIMEOUT && state == STATE_GOOD) { dac_set(0, max(gas_set_0, pdl0)); dac_set(1, max(gas_set_1, pdl1)); } else { From 9b8472e56acdf10ea6248677faf77e65316689b1 Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 22:09:35 -0800 Subject: [PATCH 3/7] add watchdog support --- board/pedal/main.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index e4e68fce8c1ddd..5664e6804d48f0 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -117,10 +117,11 @@ uint32_t timeout = 0; uint32_t current_index = 0; #define STATE_GOOD 0 -#define STATE_FAULT_CHECKSUM 1 +#define STATE_FAULT_BAD_CHECKSUM 1 #define STATE_FAULT_SEND 2 #define STATE_FAULT_SCE 3 -uint8_t state = STATE_NONE; +#define STATE_FAULT_STARTUP 4 +uint8_t state = STATE_FAULT_STARTUP; void CAN1_RX0_IRQHandler() { while (CAN->RF0R & CAN_RF0R_FMP0) { @@ -157,7 +158,7 @@ void CAN1_RX0_IRQHandler() { current_index = index; } else { // wrong checksum = fault - state = STATE_FAULT_CHECKSUM; + state = STATE_FAULT_BAD_CHECKSUM; } } // next @@ -234,6 +235,9 @@ void pedal() { dac_set(0, pdl0); dac_set(1, pdl1); } + + // feed the watchdog + IWDG->KR = 0xAAAA; } int main() { @@ -267,6 +271,13 @@ int main() { NVIC_EnableIRQ(TIM3_IRQn); + // setup watchdog + IWDG->KR = 0x5555; + IWDG->PR = 0; // divider /4 + // 0 = 0.125 ms, let's have a 50ms watchdog + IWDG->RLR = 400 - 1; + IWDG->KR = 0xCCCC; + puts("**** INTERRUPTS ON ****\n"); __enable_irq(); From 986a14c5ded4484968d1c8d6e719b066b4adda23 Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 22:25:47 -0800 Subject: [PATCH 4/7] don't alias pointers --- board/pedal/README | 22 ++++++++++++++++++++++ board/pedal/main.c | 21 ++++++++++++--------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/board/pedal/README b/board/pedal/README index 06a386b1e7fe64..89cad0a05c1d94 100644 --- a/board/pedal/README +++ b/board/pedal/README @@ -4,3 +4,25 @@ The comma pedal is a gas pedal interceptor for Honda/Acura. It allows you to "vi This is the open source software. Open source hardware coming soon. +== Test Plan == + +* Startup +** Confirm STATE_FAULT_STARTUP +* Timeout +** Send value +** Confirm value is output +** Stop sending messages +** Confirm value is passthru after 100ms +** Confirm STATE_FAULT_TIMEOUT +* Random values +** Send random 6 byte messages +** Confirm random values cause passthru +** Confirm STATE_FAULT_BAD_CHECKSUM +* Same message lockout +** Send same message repeated +** Confirm timeout behavior +* Don't set enable +** Confirm no output +* Set enable and values +** Confirm output + diff --git a/board/pedal/main.c b/board/pedal/main.c index 5664e6804d48f0..81246e6177512c 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -121,6 +121,7 @@ uint32_t current_index = 0; #define STATE_FAULT_SEND 2 #define STATE_FAULT_SCE 3 #define STATE_FAULT_STARTUP 4 +#define STATE_FAULT_TIMEOUT 5 uint8_t state = STATE_FAULT_STARTUP; void CAN1_RX0_IRQHandler() { @@ -146,15 +147,14 @@ void CAN1_RX0_IRQHandler() { if (enable) { gas_set_0 = value_0; gas_set_1 = value_1; - // clear the timeout - timeout = 0; } else { + // clear the fault state if values are 0 + if (value_0 == 0 && value_1 == 0) state = STATE_GOOD; gas_set_0 = gas_set_1 = 0; - // clear the fault state - state = STATE_GOOD; } + // clear the timeout + timeout = 0; } - // TODO: better lockout? prevents same spam current_index = index; } else { // wrong checksum = fault @@ -195,9 +195,8 @@ void TIM3_IRQHandler() { dat[3] = (pdl1>>0)&0xFF; dat[4] = state; dat[5] = can_cksum(dat, 5, CAN_GAS_OUTPUT, pkt_idx); - dat[6] = dat[7] = 0; - CAN->sTxMailBox[0].TDLR = ((uint32_t*)dat)[0]; - CAN->sTxMailBox[0].TDHR = ((uint32_t*)dat)[1]; + CAN->sTxMailBox[0].TDLR = dat[0] | (dat[1]<<8) | (dat[2]<<16) | (dat[3]<<24); + CAN->sTxMailBox[0].TDHR = dat[4] | (dat[5]<<8); CAN->sTxMailBox[0].TDTR = 6; // len of packet is 5 CAN->sTxMailBox[0].TIR = (CAN_GAS_OUTPUT << 21) | 1; ++pkt_idx; @@ -217,7 +216,11 @@ void TIM3_IRQHandler() { TIM3->SR = 0; // up timeout for gas set - timeout = min(timeout+1, MAX_TIMEOUT); + if (timeout == MAX_TIMEOUT) { + state = STATE_FAULT_TIMEOUT; + } else { + timeout += 1; + } } // ***************************** main code ***************************** From f8ed9fa7b1c010d4bec26dbdf3b9d2ae780c09aa Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 22:29:08 -0800 Subject: [PATCH 5/7] better names --- board/pedal/main.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index 81246e6177512c..fc7d6c664c6b97 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -107,7 +107,6 @@ void CAN1_TX_IRQHandler() { CAN->TSR |= CAN_TSR_RQCP0; } - // two independent values uint16_t gas_set_0 = 0; uint16_t gas_set_1 = 0; @@ -116,13 +115,13 @@ uint16_t gas_set_1 = 0; uint32_t timeout = 0; uint32_t current_index = 0; -#define STATE_GOOD 0 -#define STATE_FAULT_BAD_CHECKSUM 1 -#define STATE_FAULT_SEND 2 -#define STATE_FAULT_SCE 3 -#define STATE_FAULT_STARTUP 4 -#define STATE_FAULT_TIMEOUT 5 -uint8_t state = STATE_FAULT_STARTUP; +#define NO_FAULT 0 +#define FAULT_BAD_CHECKSUM 1 +#define FAULT_SEND 2 +#define FAULT_SCE 3 +#define FAULT_STARTUP 4 +#define FAULT_TIMEOUT 5 +uint8_t state = FAULT_STARTUP; void CAN1_RX0_IRQHandler() { while (CAN->RF0R & CAN_RF0R_FMP0) { @@ -149,7 +148,7 @@ void CAN1_RX0_IRQHandler() { gas_set_1 = value_1; } else { // clear the fault state if values are 0 - if (value_0 == 0 && value_1 == 0) state = STATE_GOOD; + if (value_0 == 0 && value_1 == 0) state = NO_FAULT; gas_set_0 = gas_set_1 = 0; } // clear the timeout @@ -158,7 +157,7 @@ void CAN1_RX0_IRQHandler() { current_index = index; } else { // wrong checksum = fault - state = STATE_FAULT_BAD_CHECKSUM; + state = FAULT_BAD_CHECKSUM; } } // next @@ -167,7 +166,7 @@ void CAN1_RX0_IRQHandler() { } void CAN1_SCE_IRQHandler() { - state = STATE_FAULT_SCE; + state = FAULT_SCE; can_sce(CAN); } @@ -203,7 +202,7 @@ void TIM3_IRQHandler() { pkt_idx &= 3; } else { // old can packet hasn't sent! - state = STATE_FAULT_SEND; + state = FAULT_SEND; #ifdef DEBUG puts("CAN MISS\n"); #endif @@ -217,7 +216,7 @@ void TIM3_IRQHandler() { // up timeout for gas set if (timeout == MAX_TIMEOUT) { - state = STATE_FAULT_TIMEOUT; + state = FAULT_TIMEOUT; } else { timeout += 1; } @@ -231,7 +230,7 @@ void pedal() { pdl1 = adc_get(ADCCHAN_ACCEL1); // write the pedal to the DAC - if (timeout < MAX_TIMEOUT && state == STATE_GOOD) { + if (timeout < MAX_TIMEOUT && state == NO_FAULT) { dac_set(0, max(gas_set_0, pdl0)); dac_set(1, max(gas_set_1, pdl1)); } else { From d5a9e1eea245ba2a54d2000bbc3ead7b8f6b127c Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 23:14:56 -0800 Subject: [PATCH 6/7] correct checksum --- board/pedal/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index fc7d6c664c6b97..1e6788e9398ef4 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -136,7 +136,7 @@ void CAN1_RX0_IRQHandler() { uint16_t value_1 = (dat[2] << 8) | dat[3]; uint8_t enable = (dat2[0] >> 7) & 1; uint8_t index = (dat2[0] >> 4) & 3; - if (can_cksum(dat, 4, CAN_GAS_INPUT, index) == (dat2[0] & 0xF)) { + if (can_cksum(dat, 4, CAN_GAS_INPUT, (enable<<3) | index) == (dat2[0] & 0xF)) { if (((current_index+1)&3) == index) { #ifdef DEBUG puts("setting gas "); From e2f73d2a4b950718d874983b12668c795acce57d Mon Sep 17 00:00:00 2001 From: Jennifer Strange Date: Fri, 2 Mar 2018 23:24:35 -0800 Subject: [PATCH 7/7] enable has a whole byte to itself --- board/pedal/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/board/pedal/main.c b/board/pedal/main.c index 1e6788e9398ef4..0e338db501cfe0 100644 --- a/board/pedal/main.c +++ b/board/pedal/main.c @@ -135,8 +135,8 @@ void CAN1_RX0_IRQHandler() { uint16_t value_0 = (dat[0] << 8) | dat[1]; uint16_t value_1 = (dat[2] << 8) | dat[3]; uint8_t enable = (dat2[0] >> 7) & 1; - uint8_t index = (dat2[0] >> 4) & 3; - if (can_cksum(dat, 4, CAN_GAS_INPUT, (enable<<3) | index) == (dat2[0] & 0xF)) { + uint8_t index = (dat2[1] >> 4) & 3; + if (can_cksum(dat, 5, CAN_GAS_INPUT, index) == (dat2[1] & 0xF)) { if (((current_index+1)&3) == index) { #ifdef DEBUG puts("setting gas ");