diff --git a/__init__.py b/__init__.py index 6849cc29..37143b3c 100644 --- a/__init__.py +++ b/__init__.py @@ -1,3 +1 @@ -""" Hack to support openpilot import scheme """ - -from .panda import Panda, PandaHashMismatchException +from .panda import Panda diff --git a/board/can.h b/board/can.h index f042db4f..ec9d446e 100644 --- a/board/can.h +++ b/board/can.h @@ -1,3 +1,47 @@ +// assign CAN numbering +// bus num: Can bus number on ODB connector. Sent to/from USB +// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) +// cans: Look up MCU can interface from bus number +// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); +// bus_lookup: Translates from 'can number' to 'bus number'. +// can_num_lookup: Translates from 'bus number' to 'can number'. +// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward. + + +// 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}; //bus num -> can num + int8_t can_forwarding[] = {-1,-1,-1}; + uint32_t can_speed[] = {5000, 5000, 5000}; // 500 kbps + #define CAN_MAX 3 +#else + CAN_TypeDef *cans[] = {CAN2, CAN1}; + uint8_t bus_lookup[] = {1,0}; + uint8_t can_num_lookup[] = {1,0}; //bus num -> can num + int8_t can_forwarding[] = {-1,-1}; + uint32_t can_speed[] = {5000, 5000}; + #define CAN_MAX 2 +#endif + +#define NO_ACTIVE_GMLAN -1 +int active_gmlan_port_id = NO_ACTIVE_GMLAN; + +#define CANIF_FROM_CAN_NUM(num) (cans[bus_lookup[num]]) +#define CANIF_FROM_BUS_NUM(num) (cans[num]) +#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num]) +#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num]) + +#define CAN_BUS_RET_FLAG 0x80 +#define CAN_BUS_NUM_MASK 0x7F + +#define CAN_PCLK 24000 +// 333 = 33.3 kbps +// 5000 = 500 kbps +#define can_speed_to_prescaler(x) (CAN_PCLK / 16 * 10 / x) + void can_init(uint8_t bus_number) { CAN_TypeDef *CAN = CANIF_FROM_BUS_NUM(bus_number); set_can_enable(CAN, 1); @@ -5,17 +49,9 @@ void can_init(uint8_t bus_number) { CAN->MCR = CAN_MCR_TTCM | CAN_MCR_INRQ; while((CAN->MSR & CAN_MSR_INAK) != CAN_MSR_INAK); - // http://www.bittiming.can-wiki.info/ - // PCLK = 24 MHz - uint32_t pclk = 24000; - uint32_t num_time_quanta = 16; - - // 500 kbps - uint32_t prescaler = pclk / num_time_quanta / 500; - // seg 1: 13 time quanta, seg 2: 2 time quanta CAN->BTR = (CAN_BTR_TS1_0 * 12) | - CAN_BTR_TS2_0 | (prescaler - 1); + CAN_BTR_TS2_0 | (can_speed_to_prescaler(can_speed[bus_number]) - 1); // silent loopback mode for debugging if (can_loopback) { diff --git a/board/main.c b/board/main.c index 4c74634e..d1ed6a13 100644 --- a/board/main.c +++ b/board/main.c @@ -7,39 +7,6 @@ #define COMPILE_TIME_ASSERT(pred) \ switch(0){case 0:case pred:;} -// assign CAN numbering -// bus num: Can bus number on ODB connector. Sent to/from USB -// Min: 0; Max: 127; Bit 7 marks message as receipt (bus 129 is receipt for but 1) -// cans: Look up MCU can interface from bus number -// can number: numeric lookup for MCU CAN interfaces (0 = CAN1, 1 = CAN2, etc); -// bus_lookup: Translates from 'can number' to 'bus number'. -// can_num_lookup: Translates from 'bus number' to 'can number'. -// can_forwarding: Given a bus num, lookup bus num to forward to. -1 means no forward. - -// 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}; //bus num -> can num - int8_t can_forwarding[] = {-1,-1,-1}; - #define CAN_MAX 3 -#else - CAN_TypeDef *cans[] = {CAN2, CAN1}; - uint8_t bus_lookup[] = {1,0}; - uint8_t can_num_lookup[] = {1,0}; //bus num -> can num - int8_t can_forwarding[] = {-1,-1}; - #define CAN_MAX 2 -#endif - -#define CANIF_FROM_CAN_NUM(num) (cans[bus_lookup[num]]) -#define CANIF_FROM_BUS_NUM(num) (cans[num]) -#define BUS_NUM_FROM_CAN_NUM(num) (bus_lookup[num]) -#define CAN_NUM_FROM_BUS_NUM(num) (can_num_lookup[num]) - -#define CAN_BUS_RET_FLAG 0x80 -#define CAN_BUS_NUM_MASK 0x7F - // *** end config *** #include "obj/gitversion.h" @@ -312,21 +279,6 @@ void process_can(uint8_t can_number) { CAN->TSR |= CAN_TSR_RQCP0; } -// send more, possible for these to not trigger? - - -void CAN1_TX_IRQHandler() { - process_can(0); -} - -void CAN2_TX_IRQHandler() { - process_can(1); -} - -void CAN3_TX_IRQHandler() { - process_can(2); -} - void send_can(CAN_FIFOMailBox_TypeDef *to_push, uint8_t bus_number); // CAN receive handlers @@ -372,39 +324,18 @@ void can_rx(uint8_t can_number) { } } -void CAN1_RX0_IRQHandler() { - //puts("CANRX1"); - //delay(10000); - can_rx(0); -} +void CAN1_TX_IRQHandler() { process_can(0); } +void CAN1_RX0_IRQHandler() { can_rx(0); } +void CAN1_SCE_IRQHandler() { can_sce(CAN1); } -void CAN2_RX0_IRQHandler() { - //puts("CANRX0"); - //delay(10000); - can_rx(1); -} - -void CAN3_RX0_IRQHandler() { - //puts("CANRX0"); - //delay(10000); - can_rx(2); -} - -void CAN1_SCE_IRQHandler() { - //puts("CAN1_SCE\n"); - can_sce(CAN1); -} - -void CAN2_SCE_IRQHandler() { - //puts("CAN2_SCE\n"); - can_sce(CAN2); -} +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_SCE_IRQHandler() { - //puts("CAN3_SCE\n"); - can_sce(CAN3); -} +void CAN3_TX_IRQHandler() { process_can(2); } +void CAN3_RX0_IRQHandler() { can_rx(2); } +void CAN3_SCE_IRQHandler() { can_sce(CAN3); } #endif @@ -603,6 +534,13 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { can_forwarding[setup->b.wValue.w] = -1; } break; + // **** 0xde: set can bitrate + case 0xde: + if (setup->b.wValue.w < CAN_MAX) { + can_speed[setup->b.wValue.w] = setup->b.wIndex.w; + can_init(setup->b.wValue.w); + } + break; // **** 0xe0: uart read case 0xe0: ur = get_ring_by_number(setup->b.wValue.w); @@ -652,7 +590,8 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, int hardwired) { can_loopback = (setup->b.wValue.w > 0); can_init_all(); break; - case 0xf0: // k-line wValue pulse on uart2 + // **** 0xf0: do k-line wValue pulse on uart2 for Acura + case 0xf0: if (setup->b.wValue.w == 1) { GPIOC->ODR &= ~(1 << 10); GPIOC->MODER &= ~GPIO_MODER_MODER10_1; diff --git a/panda/__init__.py b/panda/__init__.py index 1d15a6dc..85983d51 100644 --- a/panda/__init__.py +++ b/panda/__init__.py @@ -10,12 +10,6 @@ import time __version__ = '0.0.3' -class PandaHashMismatchException(Exception): - def __init__(self, hash_, expected_hash): - super(PandaHashMismatchException, self).__init__( - "Hash '%s' did not match the expected hash '%s'"%\ - (binascii.hexlify(hash_), binascii.hexlify(expected_hash))) - def parse_can_buffer(dat): ret = [] for j in range(0, len(dat), 0x10): @@ -153,8 +147,7 @@ class Panda(object): def get_serial(self): dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 0, 0, 0x20) hashsig, calc_hash = dat[0x1c:], hashlib.sha1(dat[0:0x1c]).digest()[0:4] - if hashsig != calc_hash: - raise PandaHashMismatchException(calc_hash, hashsig) + assert(hashsig == calc_hash) return [dat[0:0x10], dat[0x10:0x10+10]] def get_secret(self): @@ -179,6 +172,9 @@ class Panda(object): # set can loopback mode for all buses self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'') + def set_can_speed_kbps(self, bus, speed): + self._handle.controlWrite(Panda.REQUEST_OUT, 0xde, bus, int(speed*10), b'') + def set_uart_baud(self, uart, rate): self._handle.controlWrite(Panda.REQUEST_OUT, 0xe1, uart, rate, b'') diff --git a/run_automated_tests.sh b/run_automated_tests.sh index 366ed174..16e69f17 100755 --- a/run_automated_tests.sh +++ b/run_automated_tests.sh @@ -1,3 +1,3 @@ #!/bin/bash -nosetests -s tests/automated/*.py +nosetests -x -s tests/automated/*.py diff --git a/tests/automated/local.py b/tests/automated/local.py index 10375f44..47fd0170 100644 --- a/tests/automated/local.py +++ b/tests/automated/local.py @@ -1,6 +1,7 @@ import os import time from panda import Panda +from nose.tools import timed, assert_equal, assert_less # must run first def test_build_download_connect(): @@ -27,11 +28,14 @@ def test_can_loopback(): # enable CAN loopback mode p.set_can_loopback(True) + # set bus 0 speed to 250 + p.set_can_speed_kbps(0, 250) + # send a message on bus 0 p.can_send(0x1aa, "message", 0) # confirm receive both on loopback and send receipt - time.sleep(0.1) + time.sleep(0.05) r = p.can_recv() sr = filter(lambda x: x[3] == 0x80, r) lb = filter(lambda x: x[3] == 0, r) @@ -55,7 +59,38 @@ def test_safety_nooutput(): p.can_send(0x1aa, "message", 0) # confirm receive nothing - time.sleep(0.1) + time.sleep(0.05) r = p.can_recv() assert len(r) == 0 +def test_throughput(): + p = connect_wo_esp() + + # enable output mode + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + + # enable CAN loopback mode + p.set_can_loopback(True) + + for speed in [100,250,500,1000]: + # set bus 0 speed to speed + p.set_can_speed_kbps(0, speed) + time.sleep(0.05) + + st = time.time() + for i in range(100): + # send a message on bus 0 + p.can_send(0x1aa, "message", 0) + r = [] + while len(r) < 200 and (time.time() - st) < 3: + r.extend(p.can_recv()) + assert_equal(len(r), 200) + et = (time.time()-st)*1000.0 + mt = (20000.0/speed) + assert_less(et, mt) + print "loopback 100 messages at speed %d in %.2f ms < %.2f ms" % (speed, et, mt) + + + + +