mirror of https://github.com/commaai/panda.git
support can speed, and test it
This commit is contained in:
parent
9f7bbcf487
commit
85c0940cf9
|
@ -1,3 +1 @@
|
|||
""" Hack to support openpilot import scheme """
|
||||
|
||||
from .panda import Panda, PandaHashMismatchException
|
||||
from .panda import Panda
|
||||
|
|
54
board/can.h
54
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) {
|
||||
|
|
97
board/main.c
97
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;
|
||||
|
|
|
@ -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'')
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/bash
|
||||
nosetests -s tests/automated/*.py
|
||||
nosetests -x -s tests/automated/*.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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue