Skip to content

Commit

Permalink
Merge pull request commaai#29 from palmerit/dkms
Browse files Browse the repository at this point in the history
Add DKMS support
  • Loading branch information
geohot authored Aug 23, 2017
2 parents 50357ad + cf0885d commit e900a30
Show file tree
Hide file tree
Showing 19 changed files with 221 additions and 64 deletions.
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
from .panda import Panda
from .panda import Panda, PandaWifiStreaming
2 changes: 1 addition & 1 deletion board/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ obj/bootstub.$(PROJ_NAME).bin: obj/$(STARTUP_FILE).o obj/bootstub.$(PROJ_NAME).o
$(OBJCOPY) -v -O binary obj/bootstub.$(PROJ_NAME).elf $@

clean:
rm -f obj/*
@rm -f obj/*
6 changes: 4 additions & 2 deletions board/drivers/can.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ void can_init_all() {
}

void can_set_gmlan(int bus) {
if (bus == -1) {
if (bus == -1 || bus != can_num_lookup[3]) {
// GMLAN OFF
switch (can_num_lookup[3]) {
case 1:
Expand All @@ -213,7 +213,9 @@ void can_set_gmlan(int bus) {
can_init(2);
break;
}
} else if (bus == 1) {
}

if (bus == 1) {
puts("GMLAN on CAN2\n");
// GMLAN on CAN2
set_can_mode(1, 1);
Expand Down
2 changes: 1 addition & 1 deletion board/drivers/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void DMA2_Stream2_IRQHandler(void) {
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
int *resp_len = (int*)spi_tx_buf;
memset(spi_tx_buf, 0xaa, 0x44);
*resp_len = spi_cb_rx(spi_buf, 0x13, spi_tx_buf+4);
*resp_len = spi_cb_rx(spi_buf, 0x14, spi_tx_buf+4);
#ifdef DEBUG_SPI
puts("SPI write: ");
puth(*resp_len);
Expand Down
5 changes: 2 additions & 3 deletions board/drivers/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ char to_hex_char(int a) {
}

void usb_setup() {
int i;
int resp_len;
// setup packet is ready
switch (setup.b.bRequest) {
Expand Down Expand Up @@ -332,7 +331,7 @@ void usb_setup() {
resp[1] = 0x03;

// 96 bits = 12 bytes
for (i = 0; i < 12; i++){
for (int i = 0; i < 12; i++){
uint8_t cc = ((uint8_t *)UID_BASE)[i];
resp[2 + i*4 + 0] = to_hex_char((cc>>4)&0xF);
resp[2 + i*4 + 1] = '\0';
Expand All @@ -342,7 +341,7 @@ void usb_setup() {

USB_WritePacket(resp, min(resp[0], setup.b.wLength.w), 0);
#else
USB_WritePacket(string_3_desc, min(sizeof(string_3_desc), setup.b.wLength.w), 0);
USB_WritePacket((const uint8_t *)string_3_desc, min(sizeof(string_3_desc), setup.b.wLength.w), 0);
#endif
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion board/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) {

#else

int spi_cb_rx(uint8_t *data, int len) { return 0; };
int spi_cb_rx(uint8_t *data, int len, uint8_t *data_out) { return 0; };

#endif

Expand Down
2 changes: 1 addition & 1 deletion board/safety/safety_honda.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {

// exit controls on brake press
if ((to_push->RIR>>21) == 0x17C) {
// bit 50
// bit 53
if (to_push->RDHR & 0x200000) {
controls_allowed = 0;
}
Expand Down
58 changes: 34 additions & 24 deletions boardesp/proxy.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,16 @@ static int ICACHE_FLASH_ATTR __spi_comm(char *dat, int len, uint32_t *recvData,
spiData.dataLen = 0x14;
SPIMasterSendData(SpiNum_HSPI, &spiData);

#define SPI_TIMEOUT 50000
// give the ST time to be ready, up to 500ms
for (int i = 0;(gpio_input_get() & (1 << 4)) && i < 50000; i++) {
int i;
for (i = 0; (gpio_input_get() & (1 << 4)) && i < SPI_TIMEOUT; i++) {
os_delay_us(10);
system_soft_wdt_feed();
}

// TODO: handle this better
if (gpio_input_get() & (1 << 4)) os_printf("ERROR: SPI receive failed\n");
if (i == SPI_TIMEOUT) os_printf("ERROR: SPI receive failed\n");

// blank out recvData
memset(recvData, 0xBB, 0x44);
Expand Down Expand Up @@ -152,28 +154,47 @@ void ICACHE_FLASH_ATTR poll_can(void *arg) {
}
}

int udp_sending = 0;
int udp_countdown = 0;

static volatile os_timer_t udp_timeout;
void ICACHE_FLASH_ATTR udp_timeout_func(void *arg) {
udp_sending = 0;
static volatile os_timer_t udp_callback;
void ICACHE_FLASH_ATTR udp_callback_func(void *arg) {
if (queue_send_len == -1) {
poll_can(NULL);
} else {
int ret = espconn_sendto(&inter_conn, buf, queue_send_len);
if (ret == 0) {
queue_send_len = -1;
}
}
if (udp_countdown > 0) {
os_timer_arm(&udp_callback, 5, 0);
udp_countdown--;
} else {
os_printf("UDP timeout\n");
}
}

void ICACHE_FLASH_ATTR inter_recv_cb(void *arg, char *pusrdata, unsigned short length) {
os_printf("UDP recv\n");
remot_info *premot = NULL;
if (espconn_get_connection_info(&inter_conn,&premot,0) == ESPCONN_OK) {
udp_sending = 1;
inter_conn.proto.udp->remote_port = premot->remote_port;
inter_conn.proto.udp->remote_ip[0] = premot->remote_ip[0];
inter_conn.proto.udp->remote_ip[1] = premot->remote_ip[1];
inter_conn.proto.udp->remote_ip[2] = premot->remote_ip[2];
inter_conn.proto.udp->remote_ip[3] = premot->remote_ip[3];

// start 5 second timer
os_timer_disarm(&udp_timeout);
os_timer_setfn(&udp_timeout, (os_timer_func_t *)udp_timeout_func, NULL);
os_timer_arm(&udp_timeout, 5*1000, 0);

if (udp_countdown == 0) {
os_printf("UDP recv\n");
udp_countdown = 200*5;

// start 5 second timer
os_timer_disarm(&udp_callback);
os_timer_setfn(&udp_callback, (os_timer_func_t *)udp_callback_func, NULL);
os_timer_arm(&udp_callback, 5, 0);
} else {
udp_countdown = 200*5;
}
}
}

Expand Down Expand Up @@ -255,8 +276,7 @@ void loop();
void ICACHE_FLASH_ATTR web_init();
void ICACHE_FLASH_ATTR elm327_init();

void ICACHE_FLASH_ATTR user_init()
{
void ICACHE_FLASH_ATTR user_init() {
// init gpio subsystem
gpio_init();

Expand Down Expand Up @@ -316,16 +336,6 @@ void ICACHE_FLASH_ATTR user_init()


void ICACHE_FLASH_ATTR loop(os_event_t *events) {
if (udp_sending) {
if (queue_send_len == -1) {
poll_can(NULL);
} else {
int ret = espconn_sendto(&inter_conn, buf, queue_send_len);
if (ret == 0) {
queue_send_len = -1;
}
}
}
system_os_post(LOOP_PRIO, 0, 0);
}

20 changes: 16 additions & 4 deletions drivers/linux/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
VERSION=0.0.1
obj-m+=panda.o

all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) clean
link:
sudo dkms add `pwd`

build:
sudo dkms build panda/$(VERSION)

install:
sudo dkms install panda/$(VERSION)

all: build install

uninstall:
sudo dkms uninstall panda/$(VERSION)
sudo dkms remove panda/$(VERSION) --all

16 changes: 16 additions & 0 deletions drivers/linux/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Installs the panda linux kernel driver using DKMS.

This will allow the panda to work with tools such as `can-utils`

prerequisites:
- apt-get install dkms gcc linux-headers-$(uname -r) make sudo

installation:
- make link (only needed the first time. It will report an error on subsequent attempts to link)
- make all
- make install

uninstall:
- make uninstall


6 changes: 6 additions & 0 deletions drivers/linux/dkms.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
PACKAGE_NAME="panda"
PACKAGE_VERSION="0.0.1"
BUILT_MODULE_NAME[0]="panda"
DEST_MODULE_LOCATION[0]="/kernel/drivers/net/panda/"
AUTOINSTALL="yes"

18 changes: 13 additions & 5 deletions panda/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import usb1
import os
import time
import traceback

__version__ = '0.0.3'

Expand All @@ -28,10 +29,14 @@ def parse_can_buffer(dat):
class PandaWifiStreaming(object):
def __init__(self, ip="192.168.0.10", port=1338):
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.sendto("hello", (ip, port))
self.sock.setblocking(0)
self.ip = ip
self.port = port
self.kick()

def kick(self):
# must be called at least every 5 seconds
self.sock.sendto("hello", (self.ip, self.port))

def can_recv(self):
ret = []
Expand All @@ -40,7 +45,9 @@ def can_recv(self):
dat, addr = self.sock.recvfrom(0x200*0x10)
if addr == (self.ip, self.port):
ret += parse_can_buffer(dat)
except socket.error:
except socket.error as e:
if e.errno != 35:
traceback.print_exc()
break
return ret

Expand Down Expand Up @@ -156,9 +163,10 @@ def flash(self, fn=None):
assert(self.bootstub)

if fn is None:
ret = os.system("cd %s && make clean && make -f %s bin" % (os.path.join(BASEDIR, "board"),
"Makefile.legacy" if self.legacy else "Makefile"))
fn = os.path.join(BASEDIR, "board", "obj", "code.bin" if self.legacy else "panda.bin")
ret = os.system("cd %s && make clean && make -f %s %s" % (os.path.join(BASEDIR, "board"),
"Makefile.legacy" if self.legacy else "Makefile",
"obj/comma.bin" if self.legacy else "obj/panda.bin"))
fn = os.path.join(BASEDIR, "board", "obj", "comma.bin" if self.legacy else "panda.bin")

with open(fn) as f:
dat = f.read()
Expand Down
2 changes: 1 addition & 1 deletion run_automated_tests.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash
nosetests -x -s tests/automated/*.py
nosetests -x -s tests/automated/$1*.py

19 changes: 19 additions & 0 deletions tests/automated/0_builds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os

BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")

def build(target, mkfile="Makefile"):
assert(os.system('cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "../board"), mkfile, mkfile, target)) == 0)

def test_build_legacy():
build("obj/comma.bin", "Makefile.legacy")

def test_build_bootstub_legacy():
build("obj/bootstub.comma.bin", "Makefile.legacy")

def test_build_panda():
build("obj/panda.bin")

def test_build_bootstub_panda():
build("obj/bootstub.panda.bin")

33 changes: 30 additions & 3 deletions tests/automated/2_usb_to_can.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
from nose.tools import timed, assert_equal, assert_less, assert_greater
from helpers import time_many_sends, connect_wo_esp

SPEED_NORMAL = 500
SPEED_GMLAN = 33.3

def test_can_loopback():
p = connect_wo_esp()

Expand Down Expand Up @@ -129,9 +132,6 @@ def test_gmlan():
# enable CAN loopback mode
p.set_can_loopback(True)

SPEED_NORMAL = 500
SPEED_GMLAN = 33.3

p.set_can_speed_kbps(1, SPEED_NORMAL)
p.set_can_speed_kbps(2, SPEED_NORMAL)
p.set_can_speed_kbps(3, SPEED_GMLAN)
Expand All @@ -150,6 +150,33 @@ def test_gmlan():

print("%d: %.2f kbps vs %.2f kbps" % (bus, comp_kbps_gmlan, comp_kbps_normal))

def test_gmlan_bad_toggle():
p = connect_wo_esp()

if p.legacy:
return

# enable output mode
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)

# enable CAN loopback mode
p.set_can_loopback(True)

# GMLAN_CAN2
for bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]:
p.set_gmlan(bus)
comp_kbps_gmlan = time_many_sends(p, 3)
assert_greater(comp_kbps_gmlan, 0.6 * SPEED_GMLAN)
assert_less(comp_kbps_gmlan, 1.0 * SPEED_GMLAN)

# normal
for bus in [Panda.GMLAN_CAN2, Panda.GMLAN_CAN3]:
p.set_gmlan(None)
comp_kbps_normal = time_many_sends(p, bus)
assert_greater(comp_kbps_normal, 0.6 * SPEED_NORMAL)
assert_less(comp_kbps_normal, 1.0 * SPEED_NORMAL)


# this will fail if you have hardware serial connected
def test_serial_debug():
p = connect_wo_esp()
Expand Down
14 changes: 14 additions & 0 deletions tests/automated/4_wifi_functionality.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,18 @@ def test_throughput():

print("WIFI loopback 100 messages at speed %d, comp speed is %.2f, percent %.2f" % (speed, comp_kbps, saturation_pct))

def test_recv_only():
p = Panda()
p.set_safety_mode(Panda.SAFETY_ALLOUTPUT)
p.set_can_loopback(True)
pwifi = Panda("WIFI")

# TODO: msg_count=1000 drops packets, is this fixable?
for msg_count in [10,100,200]:
speed = 500
p.set_can_speed_kbps(0, speed)
comp_kbps = time_many_sends(p, 0, pwifi, msg_count)
saturation_pct = (comp_kbps/speed) * 100.0

print("HT WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct))

Loading

0 comments on commit e900a30

Please sign in to comment.