support can speed, and test it

This commit is contained in:
Firmware Batman 2017-07-17 19:43:30 -07:00
parent 9f7bbcf487
commit 85c0940cf9
6 changed files with 106 additions and 102 deletions

View File

@ -1,3 +1 @@
""" Hack to support openpilot import scheme """
from .panda import Panda, PandaHashMismatchException
from .panda import Panda

View File

@ -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) {

View File

@ -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;

View File

@ -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'')

View File

@ -1,3 +1,3 @@
#!/bin/bash
nosetests -s tests/automated/*.py
nosetests -x -s tests/automated/*.py

View File

@ -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)