diff --git a/board/drivers/can.h b/board/drivers/can.h index 0061c4cd..18be3356 100644 --- a/board/drivers/can.h +++ b/board/drivers/can.h @@ -53,6 +53,12 @@ int can_push(can_ring *q, CAN_FIFOMailBox_TypeDef *elem) { return ret; } +void can_clear(can_ring *q) { + enter_critical_section(); + q->w_ptr = 0; + q->r_ptr = 0; + exit_critical_section(); +} // assign CAN numbering // bus num: Can bus number on ODB connector. Sent to/from USB @@ -393,4 +399,3 @@ 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/board/drivers/uart.h b/board/drivers/uart.h index 0bf35eb2..85bab0e7 100644 --- a/board/drivers/uart.h +++ b/board/drivers/uart.h @@ -126,6 +126,15 @@ int putc(uart_ring *q, char elem) { return ret; } +void clear_uart_buff(uart_ring *q) { + enter_critical_section(); + q->w_ptr_tx = 0; + q->r_ptr_tx = 0; + q->w_ptr_rx = 0; + q->r_ptr_rx = 0; + exit_critical_section(); +} + // ***************************** start UART code ***************************** #define __DIV(_PCLK_, _BAUD_) (((_PCLK_)*25)/(4*(_BAUD_))) @@ -146,7 +155,7 @@ void uart_init(USART_TypeDef *u, int baud) { // enable uart and tx+rx mode u->CR1 = USART_CR1_UE; uart_set_baud(u, baud); - + u->CR1 |= USART_CR1_TE | USART_CR1_RE; //u->CR2 = USART_CR2_STOP_0 | USART_CR2_STOP_1; //u->CR2 = USART_CR2_STOP_0; @@ -213,4 +222,3 @@ void hexdump(const void *a, int l) { } puts("\n"); } - diff --git a/board/main.c b/board/main.c index bd4a461c..b6db54c3 100644 --- a/board/main.c +++ b/board/main.c @@ -117,12 +117,11 @@ int usb_cb_ep1_in(uint8_t *usbdata, int len, int hardwired) { // send on serial, first byte to select the ring void usb_cb_ep2_out(uint8_t *usbdata, int len, int hardwired) { - int i; if (len == 0) return; 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)) { - for (i = 1; i < len; i++) while (!putc(ur, usbdata[i])); + for (int i = 1; i < len; i++) while (!putc(ur, usbdata[i])); } } @@ -359,6 +358,26 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { delay(140 * 9000); break; + // **** 0xf1: Clear CAN ring buffer. + case 0xf1: + if (setup->b.wValue.w == 0xFFFF) { + puts("Clearing CAN Rx queue\n"); + can_clear(&can_rx_q); + } else if (setup->b.wValue.w < BUS_MAX) { + puts("Clearing CAN Tx queue\n"); + can_clear(can_queues[setup->b.wValue.w]); + } + break; + // **** 0xf2: Clear UART ring buffer. + case 0xf2: + { + uart_ring * rb = get_ring_by_number(setup->b.wValue.w); + if (rb) { + puts("Clearing UART queue.\n"); + clear_uart_buff(rb); + } + break; + } default: puts("NO HANDLER "); puth(setup->b.bRequest); diff --git a/boardesp/elm327.c b/boardesp/elm327.c index c85adbeb..81ed58ae 100644 --- a/boardesp/elm327.c +++ b/boardesp/elm327.c @@ -213,6 +213,8 @@ static int ICACHE_FLASH_ATTR panda_usbemu_ctrl_write(uint8_t request_type, uint8 #define panda_set_can0_kbaud(kbps) panda_usbemu_ctrl_write(0x40, 0xde, 0, kbps*10, 0) #define panda_set_safety_mode(mode) panda_usbemu_ctrl_write(0x40, 0xdc, mode, 0, 0) #define panda_kline_wakeup_pulse() panda_usbemu_ctrl_write(0x40, 0xf0, 0, 0, 0) +#define panda_clear_can_rx() panda_usbemu_ctrl_write(0x40, 0xf1, 0xFFFF, 0, 0) +#define panda_clear_lin_txrx() panda_usbemu_ctrl_write(0x40, 0xf2, 2, 0, 0) static int ICACHE_FLASH_ATTR panda_usbemu_can_read(panda_can_msg_t** can_msgs) { int returned_count = spi_comm((uint8_t *)((const uint16 []){1,0}), 4, pandaRecvData, 0x40); @@ -773,21 +775,12 @@ static void ICACHE_FLASH_ATTR elm_process_obd_cmd_LINFast(const elm_protocol_t* return; } + panda_clear_lin_txrx(); + if(!lin_bus_initialized) { if(!is_auto_detecting) elm_append_rsp_const("BUS INIT: "); - // Kind of a hack to deal with Panda resending data - // that could not be sent asap. Try to clear it away. - // TODO: A better solution would be to clear out the - // CAN mailboxes on the MCU when the speed changes. - for(int pass = 0; pass < 32; pass++){ - int num_can_msgs = panda_usbemu_kline_read(0x40); - if(num_can_msgs < 0) continue; - if(!num_can_msgs) break; - for(int j=0; j<1000; j++) __asm__(""); //Small Delay - } - lin_cmd_backup = cmd; lin_cmd_backup_len = len; @@ -992,19 +985,6 @@ void ICACHE_FLASH_ATTR elm_ISO15765_timer_cb(void *arg){ static void ICACHE_FLASH_ATTR elm_init_ISO15765(const elm_protocol_t* proto){ panda_set_can0_cbaud(proto->cbaud); - - // Kind of a hack to deal with Panda resending data - // that could not be sent asap. Try to clear it away. - // TODO: A better solution would be to clear out the - // CAN mailboxes on the MCU when the speed changes. - for(int pass = 0; pass < 32; pass++){ - panda_can_msg_t *can_msgs; - int num_can_msgs = panda_usbemu_can_read(&can_msgs); - if(num_can_msgs < 0) continue; - //if(!num_can_msgs) break; - //os_delay_us(1000); - for(int j=0; j<1000; j++) __asm__(""); //Small Delay - } } static void ICACHE_FLASH_ATTR elm_process_obd_cmd_ISO15765(const elm_protocol_t* proto, @@ -1031,6 +1011,8 @@ static void ICACHE_FLASH_ATTR elm_process_obd_cmd_ISO15765(const elm_protocol_t* os_printf("\n"); #endif + panda_clear_can_rx(); + panda_usbemu_can_write(0, (proto->type==CAN11) ? 0x7DF : 0x18DB33F1, (uint8_t*)&msg, msg.len+1); diff --git a/panda/__init__.py b/panda/__init__.py index 1a8fdd98..7aa3d035 100644 --- a/panda/__init__.py +++ b/panda/__init__.py @@ -331,6 +331,17 @@ class Panda(object): print("CAN: BAD RECV, RETRYING") return parse_can_buffer(dat) + def can_clear(self, bus): + """Clears all messages from the specified internal CAN ringbuffer as + though it were drained. + + Args: + bus (int): can bus number to clear a tx queue, or 0xFFFF to clear the + global can rx queue. + + """ + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf1, bus, 0, b'') + # ******************* serial ******************* def serial_read(self, port_number): @@ -345,6 +356,16 @@ class Panda(object): def serial_write(self, port_number, ln): return self._handle.bulkWrite(2, struct.pack("B", port_number) + ln) + def serial_clear(self, port_number): + """Clears all messages (tx and rx) from the specified internal uart + ringbuffer as though it were drained. + + Args: + port_number (int): port number of the uart to clear. + + """ + self._handle.controlWrite(Panda.REQUEST_OUT, 0xf2, port_number, 0, b'') + # ******************* kline ******************* # pulse low for wakeup