diff --git a/panda/board/drivers/gmlan_alt.h b/panda/board/drivers/gmlan_alt.h index 6d4ba12b8..2f2e56805 100644 --- a/panda/board/drivers/gmlan_alt.h +++ b/panda/board/drivers/gmlan_alt.h @@ -122,7 +122,12 @@ int get_bit_message(char *out, CAN_FIFOMailBox_TypeDef *to_bang) { return len; } +void TIM4_IRQ_Handler(void); + void setup_timer4(void) { + // register interrupt + REGISTER_INTERRUPT(TIM4_IRQn, TIM4_IRQ_Handler, 40000U, FAULT_INTERRUPT_RATE_GMLAN) + // setup register_set(&(TIM4->PSC), (48-1), 0xFFFFU); // Tick on 1 us register_set(&(TIM4->CR1), TIM_CR1_CEN, 0x3FU); // Enable @@ -236,7 +241,6 @@ void TIM4_IRQ_Handler(void) { gmlan_sendmax = -1; // exit } } - TIM4->SR = 0; } else if (gmlan_alt_mode == GPIO_SWITCH) { if ((TIM4->SR & TIM_SR_UIF) && (gmlan_switch_below_timeout != -1)) { if ((can_timeout_counter == 0) && gmlan_switch_timeout_enable) { @@ -259,10 +263,10 @@ void TIM4_IRQ_Handler(void) { } } } - TIM4->SR = 0; } else { - puts("invalid gmlan_alt_mode\n"); + // Invalid GMLAN mode. Do not put a print statement here, way too fast to keep up with } + TIM4->SR = 0; } bool bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) { @@ -280,7 +284,6 @@ bool bitbang_gmlan(CAN_FIFOMailBox_TypeDef *to_bang) { set_gpio_mode(GPIOB, 13, MODE_OUTPUT); // 33kbps - REGISTER_INTERRUPT(TIM4_IRQn, TIM4_IRQ_Handler, 40000U, FAULT_INTERRUPT_RATE_GMLAN) setup_timer4(); } return gmlan_send_ok; diff --git a/panda/board/main.c b/panda/board/main.c index a758bf705..8bc4ac78f 100644 --- a/panda/board/main.c +++ b/panda/board/main.c @@ -294,19 +294,11 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired) break; // **** 0xb0: set IR power case 0xb0: - if(power_save_status == POWER_SAVE_STATUS_DISABLED){ - current_board->set_ir_power(setup->b.wValue.w); - } else { - puts("Setting IR power not allowed in power saving mode\n"); - } + current_board->set_ir_power(setup->b.wValue.w); break; // **** 0xb1: set fan power case 0xb1: - if(power_save_status == POWER_SAVE_STATUS_DISABLED){ - current_board->set_fan_power(setup->b.wValue.w); - } else { - puts("Setting fan power not allowed in power saving mode\n"); - } + current_board->set_fan_power(setup->b.wValue.w); break; // **** 0xb2: get fan rpm case 0xb2: @@ -716,6 +708,10 @@ void TIM1_BRK_TIM9_IRQ_Handler(void) { if (power_save_status != POWER_SAVE_STATUS_ENABLED) { set_power_save_state(POWER_SAVE_STATUS_ENABLED); } + + // Also disable fan and IR when the heartbeat goes missing + current_board->set_fan_power(0U); + current_board->set_ir_power(0U); } // enter CDP mode when car starts to ensure we are charging a turned off EON diff --git a/panda/board/power_saving.h b/panda/board/power_saving.h index 3ee2170d7..f7e42371a 100644 --- a/panda/board/power_saving.h +++ b/panda/board/power_saving.h @@ -49,10 +49,9 @@ void set_power_save_state(int state) { set_gpio_output(GPIOA, 14, enable); } - // Switch off IR and fan when in power saving + // Switch off IR when in power saving if(!enable){ current_board->set_ir_power(0U); - current_board->set_fan_power(0U); } power_save_status = state; diff --git a/panda/python/uds.py b/panda/python/uds.py index 96d07e1a7..548f1bcce 100644 --- a/panda/python/uds.py +++ b/panda/python/uds.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import time import struct +from collections import deque from typing import Callable, NamedTuple, Tuple, List from enum import IntEnum @@ -275,11 +276,12 @@ class CanClient(): self.rx = can_recv self.tx_addr = tx_addr self.rx_addr = rx_addr + self.rx_buff = deque() self.sub_addr = sub_addr self.bus = bus self.debug = debug - def _recv_filter(self, bus, addr): + def _recv_filter(self, bus: int, addr: int) -> bool: # handle functional addresses (switch to first addr to respond) if self.tx_addr == 0x7DF: is_response = addr >= 0x7E8 and addr <= 0x7EF @@ -296,12 +298,12 @@ class CanClient(): self.rx_addr = addr return bus == self.bus and addr == self.rx_addr - def recv(self, drain=False) -> List[bytes]: - msg_array = [] + def _recv_buffer(self, drain: bool=False) -> None: while True: msgs = self.rx() if drain: if self.debug: print("CAN-RX: drain - {}".format(len(msgs))) + self.rx_buff.clear() else: for rx_addr, rx_ts, rx_data, rx_bus in msgs or []: if self._recv_filter(rx_bus, rx_addr) and len(rx_data) > 0: @@ -313,15 +315,24 @@ class CanClient(): if self.sub_addr is not None: rx_data = rx_data[1:] - msg_array.append(rx_data) + self.rx_buff.append(rx_data) # break when non-full buffer is processed if len(msgs) < 254: - return msg_array + return + + def recv(self, drain: bool=False) -> List[bytes]: + # buffer rx messages in case two response messages are received at once + # (e.g. response pending and success/failure response) + self._recv_buffer(drain) + try: + while True: + yield self.rx_buff.popleft() + except IndexError: + pass # empty def send(self, msgs: List[bytes], delay: float=0) -> None: - first = True - for msg in msgs: - if delay and not first: + for i, msg in enumerate(msgs): + if delay and i != 0: if self.debug: print(f"CAN-TX: delay - {delay}") time.sleep(delay) @@ -332,8 +343,9 @@ class CanClient(): assert len(msg) <= 8 self.tx(self.tx_addr, msg, self.bus) - first = False - + # prevent rx buffer from overflowing on large tx + if i % 10 == 9: + self._recv_buffer() class IsoTpMessage(): def __init__(self, can_client: CanClient, timeout: float=1, debug: bool=False, max_len: int=8):