From d346d2ec33fc53a7731bf5f5a547db3c8c4ac2c1 Mon Sep 17 00:00:00 2001 From: Jeff Palmer Date: Mon, 31 Jul 2017 11:21:30 -0400 Subject: [PATCH 01/16] Add DKMS support This will add dkms support, and make installations easier. Especially when upgrading the system from one kernel version to another. DKMS will handle kernel upgrades automatically. --- drivers/linux/Makefile | 20 ++++++++++++++++---- drivers/linux/README.md | 14 ++++++++++++++ drivers/linux/dkms.conf | 6 ++++++ 3 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 drivers/linux/README.md create mode 100644 drivers/linux/dkms.conf diff --git a/drivers/linux/Makefile b/drivers/linux/Makefile index 33bdb3f0af1fdc..e5b1ec4219ea92 100644 --- a/drivers/linux/Makefile +++ b/drivers/linux/Makefile @@ -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 + diff --git a/drivers/linux/README.md b/drivers/linux/README.md new file mode 100644 index 00000000000000..26019d63b07f9d --- /dev/null +++ b/drivers/linux/README.md @@ -0,0 +1,14 @@ +Installs the panda linux kernel driver using DKMS. + +This will allow the panda to work with tools such as `can-utils` + + +installation: + - make link + - make all + - make install + +uninstall: + - make uninstall + + diff --git a/drivers/linux/dkms.conf b/drivers/linux/dkms.conf new file mode 100644 index 00000000000000..da9cba04a28bb7 --- /dev/null +++ b/drivers/linux/dkms.conf @@ -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" + From 798f94234627efb50315361aced0bbf8af2b0d3c Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Tue, 1 Aug 2017 03:00:53 +0200 Subject: [PATCH 02/16] fix legacy build issue, add build test, fix warnings --- board/build.mk | 2 +- board/drivers/usb.h | 5 ++--- board/main.c | 2 +- panda/__init__.py | 7 ++++--- tests/automated/0_builds.py | 20 ++++++++++++++++++++ 5 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 tests/automated/0_builds.py diff --git a/board/build.mk b/board/build.mk index 33450b995b989c..a65bd54d4f92f6 100644 --- a/board/build.mk +++ b/board/build.mk @@ -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/* diff --git a/board/drivers/usb.h b/board/drivers/usb.h index e54e2eed8c3921..fee222186be3b5 100644 --- a/board/drivers/usb.h +++ b/board/drivers/usb.h @@ -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) { @@ -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'; @@ -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: diff --git a/board/main.c b/board/main.c index f6fdc9c86f0143..0b4cf3db1af8e9 100644 --- a/board/main.c +++ b/board/main.c @@ -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 diff --git a/panda/__init__.py b/panda/__init__.py index 0dbe706b443261..8cae8736e51574 100644 --- a/panda/__init__.py +++ b/panda/__init__.py @@ -156,9 +156,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() diff --git a/tests/automated/0_builds.py b/tests/automated/0_builds.py new file mode 100644 index 00000000000000..8e2bf55dd82648 --- /dev/null +++ b/tests/automated/0_builds.py @@ -0,0 +1,20 @@ +import os + +BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../") +os.chdir(os.path.join(BASEDIR, "../board")) + +def build(target, mkfile="Makefile"): + assert(os.system('make -f %s clean && make -f %s %s >/dev/null' % (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") + From 3902720851215f4d99ac982ba4c31c2e8033c8ef Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Tue, 1 Aug 2017 03:08:34 +0200 Subject: [PATCH 03/16] don't chdir in global context --- run_automated_tests.sh | 2 +- tests/automated/0_builds.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/run_automated_tests.sh b/run_automated_tests.sh index 16e69f17487478..23d8048c46da53 100755 --- a/run_automated_tests.sh +++ b/run_automated_tests.sh @@ -1,3 +1,3 @@ #!/bin/bash -nosetests -x -s tests/automated/*.py +nosetests -x -s tests/automated/$1*.py diff --git a/tests/automated/0_builds.py b/tests/automated/0_builds.py index 8e2bf55dd82648..d15a57fb768af7 100644 --- a/tests/automated/0_builds.py +++ b/tests/automated/0_builds.py @@ -1,10 +1,9 @@ import os BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../") -os.chdir(os.path.join(BASEDIR, "../board")) def build(target, mkfile="Makefile"): - assert(os.system('make -f %s clean && make -f %s %s >/dev/null' % (mkfile, mkfile, target)) == 0) + 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") From 61b57685de1f74e878b66c1bc90cf29bd542a222 Mon Sep 17 00:00:00 2001 From: Riccardo Date: Mon, 7 Aug 2017 11:57:32 -0700 Subject: [PATCH 04/16] SAFETY: disallowing controls on brake switch as this is the main cancellation bit considered by cruise in pcm --- board/safety/safety_honda.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h index 0297f79b21fc18..690207e041a72c 100644 --- a/board/safety/safety_honda.h +++ b/board/safety/safety_honda.h @@ -27,8 +27,8 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // exit controls on brake press if ((to_push->RIR>>21) == 0x17C) { - // bit 50 - if (to_push->RDHR & 0x200000) { + // bit 32 or 53 + if (to_push->RDHR & 0x200001) { controls_allowed = 0; } } From b3694bfc42a2cd8c27672bc1171ae31365a9e417 Mon Sep 17 00:00:00 2001 From: Riccardo Date: Thu, 10 Aug 2017 17:28:42 -0700 Subject: [PATCH 05/16] safety_honda: reverting change to disallow controls when brake switch is triggered. Such bit appears to have spurious activations, so it will only be considered by controls --- board/safety/safety_honda.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h index 690207e041a72c..a95bfdcc36029b 100644 --- a/board/safety/safety_honda.h +++ b/board/safety/safety_honda.h @@ -27,8 +27,8 @@ static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) { // exit controls on brake press if ((to_push->RIR>>21) == 0x17C) { - // bit 32 or 53 - if (to_push->RDHR & 0x200001) { + // bit 53 + if (to_push->RDHR & 0x200000) { controls_allowed = 0; } } From c8432f037884e23499399aafadb2106d7f1ec0b0 Mon Sep 17 00:00:00 2001 From: Null Man Date: Sun, 13 Aug 2017 00:32:36 +0100 Subject: [PATCH 06/16] Should fix loopback test --- tests/loopback_test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/loopback_test.py b/tests/loopback_test.py index 7cd9b08cdb3a31..1e13ea33a7fecb 100755 --- a/tests/loopback_test.py +++ b/tests/loopback_test.py @@ -33,7 +33,7 @@ def run_test_w_pandas(pandas, sleep_duration): print("H", h) for hh in h: - hh.set_controls_allowed(True) + hh.set_safety_mode(Panda.SAFETY_ALLOUTPUT) # test both directions for ho in permutations(range(len(h)), r=2): @@ -79,10 +79,11 @@ def run_test_w_pandas(pandas, sleep_duration): if gmlan is not None: panda0.set_gmlan(gmlan, bus) panda1.set_gmlan(gmlan, bus) + if gmlan: + bus = 3 # send the characters - # pick addresses high enough to not conflict with honda code - at = random.randint(1024, 2000) + at = random.randint(1, 2000) st = get_test_string()[0:8] panda0.can_send(at, st, bus) time.sleep(0.1) From d7f47cc4c077d5c91e25226738d2c81805cb7a32 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 00:32:36 +0100 Subject: [PATCH 07/16] Should fix loopback test --- tests/loopback_test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/loopback_test.py b/tests/loopback_test.py index 7cd9b08cdb3a31..1e13ea33a7fecb 100755 --- a/tests/loopback_test.py +++ b/tests/loopback_test.py @@ -33,7 +33,7 @@ def run_test_w_pandas(pandas, sleep_duration): print("H", h) for hh in h: - hh.set_controls_allowed(True) + hh.set_safety_mode(Panda.SAFETY_ALLOUTPUT) # test both directions for ho in permutations(range(len(h)), r=2): @@ -79,10 +79,11 @@ def run_test_w_pandas(pandas, sleep_duration): if gmlan is not None: panda0.set_gmlan(gmlan, bus) panda1.set_gmlan(gmlan, bus) + if gmlan: + bus = 3 # send the characters - # pick addresses high enough to not conflict with honda code - at = random.randint(1024, 2000) + at = random.randint(1, 2000) st = get_test_string()[0:8] panda0.can_send(at, st, bus) time.sleep(0.1) From 790e820819026cddc5c74fa2e96e1e1c0c9c2239 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 01:17:22 +0100 Subject: [PATCH 08/16] hack around gmlan brokenness --- tests/loopback_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/loopback_test.py b/tests/loopback_test.py index ffac584348c36c..a871295ad6fd83 100755 --- a/tests/loopback_test.py +++ b/tests/loopback_test.py @@ -76,13 +76,13 @@ def run_test_w_pandas(pandas, sleep_duration): cans_echo = panda0.can_recv() cans_loop = panda1.can_recv() + panda0.set_gmlan(None) + panda1.set_gmlan(None) + if gmlan is True: panda0.set_gmlan(bus) panda1.set_gmlan(bus) bus = 3 - else: - panda0.set_gmlan(None) - panda1.set_gmlan(None) # send the characters at = random.randint(1, 2000) From f832f344135dcd50666edcd88f04b4c2f05e6083 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 01:28:23 +0100 Subject: [PATCH 09/16] fix GMLAN bad toggle issue --- board/drivers/can.h | 6 ++++-- tests/automated/2_usb_to_can.py | 33 ++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/board/drivers/can.h b/board/drivers/can.h index 4328d5c547da57..0061c4cdfa18d4 100644 --- a/board/drivers/can.h +++ b/board/drivers/can.h @@ -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: @@ -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); diff --git a/tests/automated/2_usb_to_can.py b/tests/automated/2_usb_to_can.py index 4135d7a06c6039..481564240752a2 100644 --- a/tests/automated/2_usb_to_can.py +++ b/tests/automated/2_usb_to_can.py @@ -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() @@ -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) @@ -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() From c536a8333c5e39b9315b93c9d4e65873aa906a03 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 02:01:56 +0100 Subject: [PATCH 10/16] begin to address UDP reliability issues --- __init__.py | 2 +- panda/__init__.py | 6 +++- tests/automated/5_wifi_throughput.py | 41 ++++++++++++++++++++++++++++ tests/automated/helpers.py | 17 ++++++------ 4 files changed, 56 insertions(+), 10 deletions(-) create mode 100644 tests/automated/5_wifi_throughput.py diff --git a/__init__.py b/__init__.py index 37143b3c4d7b29..1f72be4f90eb1a 100644 --- a/__init__.py +++ b/__init__.py @@ -1 +1 @@ -from .panda import Panda +from .panda import Panda, PandaWifiStreaming diff --git a/panda/__init__.py b/panda/__init__.py index 8cae8736e51574..678a0d7c54a124 100644 --- a/panda/__init__.py +++ b/panda/__init__.py @@ -28,10 +28,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 = [] diff --git a/tests/automated/5_wifi_throughput.py b/tests/automated/5_wifi_throughput.py new file mode 100644 index 00000000000000..c65b779a5dbeb3 --- /dev/null +++ b/tests/automated/5_wifi_throughput.py @@ -0,0 +1,41 @@ +from __future__ import print_function +import sys +import time +from helpers import time_many_sends +from panda import Panda, PandaWifiStreaming + +def test_high_throughput(): + 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)) + +def test_udp_doesnt_drop(): + p = Panda() + p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) + p.set_can_loopback(True) + + pwifi = PandaWifiStreaming() + + for i in range(30): + pwifi.kick() + + speed = 500 + p.set_can_speed_kbps(0, speed) + comp_kbps = time_many_sends(p, 0, pwifi, msg_count=10) + saturation_pct = (comp_kbps/speed) * 100.0 + + sys.stdout.write(".") + sys.stdout.flush() + + + diff --git a/tests/automated/helpers.py b/tests/automated/helpers.py index b4bb3afd27a617..4109e40c7009b9 100644 --- a/tests/automated/helpers.py +++ b/tests/automated/helpers.py @@ -27,24 +27,25 @@ def connect_wifi(): # TODO: Ubuntu os.system("networksetup -setairportnetwork en0 %s %s" % (ssid, pw)) -def time_many_sends(p, bus): - MSG_COUNT = 100 +def time_many_sends(p, bus, precv=None, msg_count=100): + if precv == None: + precv = p st = time.time() - p.can_send_many([(0x1aa, 0, "\xaa"*8, bus)]*MSG_COUNT) + p.can_send_many([(0x1aa, 0, "\xaa"*8, bus)]*msg_count) r = [] - while len(r) < 200 and (time.time() - st) < 3: - r.extend(p.can_recv()) + while len(r) < (msg_count*2) and (time.time() - st) < 3: + r.extend(precv.can_recv()) sent_echo = filter(lambda x: x[3] == 0x80 | bus, r) loopback_resp = filter(lambda x: x[3] == bus, r) - assert_equal(len(sent_echo), 100) - assert_equal(len(loopback_resp), 100) + assert_equal(len(sent_echo), msg_count) + assert_equal(len(loopback_resp), msg_count) et = (time.time()-st)*1000.0 - comp_kbps = (1+11+1+1+1+4+8*8+15+1+1+1+7)*MSG_COUNT / et + comp_kbps = (1+11+1+1+1+4+8*8+15+1+1+1+7)*msg_count / et return comp_kbps From 0b6012545d6d251ebcb98f5328cb250acd691b7e Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 02:03:45 +0100 Subject: [PATCH 11/16] test 5 is failing --- tests/automated/4_wifi_functionality.py | 14 ++++++++++++++ .../{5_wifi_throughput.py => 5_wifi_udp.py} | 15 --------------- 2 files changed, 14 insertions(+), 15 deletions(-) rename tests/automated/{5_wifi_throughput.py => 5_wifi_udp.py} (50%) diff --git a/tests/automated/4_wifi_functionality.py b/tests/automated/4_wifi_functionality.py index 56f3a0c979694f..6fa3c92aa73461 100644 --- a/tests/automated/4_wifi_functionality.py +++ b/tests/automated/4_wifi_functionality.py @@ -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)) diff --git a/tests/automated/5_wifi_throughput.py b/tests/automated/5_wifi_udp.py similarity index 50% rename from tests/automated/5_wifi_throughput.py rename to tests/automated/5_wifi_udp.py index c65b779a5dbeb3..b041d0b89d24bb 100644 --- a/tests/automated/5_wifi_throughput.py +++ b/tests/automated/5_wifi_udp.py @@ -4,21 +4,6 @@ from helpers import time_many_sends from panda import Panda, PandaWifiStreaming -def test_high_throughput(): - 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)) - def test_udp_doesnt_drop(): p = Panda() p.set_safety_mode(Panda.SAFETY_ALLOUTPUT) From 7a6e6e917626e9dcf553a9c0a44a0abe76cec1d7 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 02:42:24 +0100 Subject: [PATCH 12/16] adding delay made it much better --- boardesp/proxy.c | 5 +++++ panda/__init__.py | 5 ++++- tests/automated/5_wifi_udp.py | 31 ++++++++++++++++++++----------- tests/automated/helpers.py | 11 +++++++---- 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/boardesp/proxy.c b/boardesp/proxy.c index 8f4ee0cdfe952f..40e5cd906c7294 100644 --- a/boardesp/proxy.c +++ b/boardesp/proxy.c @@ -326,6 +326,11 @@ void ICACHE_FLASH_ATTR loop(os_event_t *events) { } } } + + // 5ms pause = 200 hz polling + // TODO: Ratekeeperize this + os_delay_us(5000); + system_os_post(LOOP_PRIO, 0, 0); } diff --git a/panda/__init__.py b/panda/__init__.py index 678a0d7c54a124..5cd61ac18d264c 100644 --- a/panda/__init__.py +++ b/panda/__init__.py @@ -7,6 +7,7 @@ import usb1 import os import time +import traceback __version__ = '0.0.3' @@ -44,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 diff --git a/tests/automated/5_wifi_udp.py b/tests/automated/5_wifi_udp.py index b041d0b89d24bb..340ea7e11bb3a2 100644 --- a/tests/automated/5_wifi_udp.py +++ b/tests/automated/5_wifi_udp.py @@ -3,6 +3,7 @@ import time from helpers import time_many_sends from panda import Panda, PandaWifiStreaming +from nose.tools import timed, assert_equal, assert_less, assert_greater def test_udp_doesnt_drop(): p = Panda() @@ -10,17 +11,25 @@ def test_udp_doesnt_drop(): p.set_can_loopback(True) pwifi = PandaWifiStreaming() - - for i in range(30): - pwifi.kick() - - speed = 500 - p.set_can_speed_kbps(0, speed) - comp_kbps = time_many_sends(p, 0, pwifi, msg_count=10) - saturation_pct = (comp_kbps/speed) * 100.0 - - sys.stdout.write(".") - sys.stdout.flush() + pwifi.can_recv() + + for msg_count in [1, 100]: + for i in range({1: 0x80, 100: 0x10}[msg_count]): + pwifi.kick() + + speed = 500 + p.set_can_speed_kbps(0, speed) + comp_kbps = time_many_sends(p, 0, pwifi, msg_count=msg_count, msg_id=0x100+i) + saturation_pct = (comp_kbps/speed) * 100.0 + + if msg_count == 1: + sys.stdout.write(".") + sys.stdout.flush() + else: + print("UDP WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct)) + assert_greater(saturation_pct, 60) + assert_less(saturation_pct, 100) + print("") diff --git a/tests/automated/helpers.py b/tests/automated/helpers.py index 4109e40c7009b9..7a75b7a3511714 100644 --- a/tests/automated/helpers.py +++ b/tests/automated/helpers.py @@ -2,6 +2,7 @@ from nose.tools import timed, assert_equal, assert_less, assert_greater import time import os +import random def connect_wo_esp(): # connect to the panda @@ -27,19 +28,21 @@ def connect_wifi(): # TODO: Ubuntu os.system("networksetup -setairportnetwork en0 %s %s" % (ssid, pw)) -def time_many_sends(p, bus, precv=None, msg_count=100): +def time_many_sends(p, bus, precv=None, msg_count=100, msg_id=None): if precv == None: precv = p + if msg_id == None: + msg_id = random.randint(0x100, 0x200) st = time.time() - p.can_send_many([(0x1aa, 0, "\xaa"*8, bus)]*msg_count) + p.can_send_many([(msg_id, 0, "\xaa"*8, bus)]*msg_count) r = [] while len(r) < (msg_count*2) and (time.time() - st) < 3: r.extend(precv.can_recv()) - sent_echo = filter(lambda x: x[3] == 0x80 | bus, r) - loopback_resp = filter(lambda x: x[3] == bus, r) + sent_echo = filter(lambda x: x[3] == 0x80 | bus and x[0] == msg_id, r) + loopback_resp = filter(lambda x: x[3] == bus and x[0] == msg_id, r) assert_equal(len(sent_echo), msg_count) assert_equal(len(loopback_resp), msg_count) From 1c14b8bed880b26597e74adcaac5f0ffac195e7f Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 02:55:43 +0100 Subject: [PATCH 13/16] test is passing sometime --- boardesp/proxy.c | 45 ++++++++++++++++------------------- tests/automated/5_wifi_udp.py | 6 +++-- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/boardesp/proxy.c b/boardesp/proxy.c index 40e5cd906c7294..6018ffd78e892f 100644 --- a/boardesp/proxy.c +++ b/boardesp/proxy.c @@ -152,18 +152,28 @@ 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--; + } } 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]; @@ -171,9 +181,10 @@ void ICACHE_FLASH_ATTR inter_recv_cb(void *arg, char *pusrdata, unsigned short l 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); + os_timer_disarm(&udp_callback); + udp_countdown = 200*5; + os_timer_setfn(&udp_callback, (os_timer_func_t *)udp_callback_func, NULL); + os_timer_arm(&udp_callback, 5, 0); } } @@ -255,8 +266,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(); @@ -316,21 +326,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; - } - } - } - - // 5ms pause = 200 hz polling - // TODO: Ratekeeperize this - os_delay_us(5000); - system_os_post(LOOP_PRIO, 0, 0); } diff --git a/tests/automated/5_wifi_udp.py b/tests/automated/5_wifi_udp.py index 340ea7e11bb3a2..46891e3e2f883d 100644 --- a/tests/automated/5_wifi_udp.py +++ b/tests/automated/5_wifi_udp.py @@ -11,7 +11,9 @@ def test_udp_doesnt_drop(): p.set_can_loopback(True) pwifi = PandaWifiStreaming() - pwifi.can_recv() + while 1: + if len(pwifi.can_recv()) == 0: + break for msg_count in [1, 100]: for i in range({1: 0x80, 100: 0x10}[msg_count]): @@ -27,7 +29,7 @@ def test_udp_doesnt_drop(): sys.stdout.flush() else: print("UDP WIFI loopback %d messages at speed %d, comp speed is %.2f, percent %.2f" % (msg_count, speed, comp_kbps, saturation_pct)) - assert_greater(saturation_pct, 60) + assert_greater(saturation_pct, 50) assert_less(saturation_pct, 100) print("") From 37b3327c289d4ca9f019ad110a92bb56312b0db4 Mon Sep 17 00:00:00 2001 From: Firmware Batman Date: Sun, 13 Aug 2017 12:31:03 +0100 Subject: [PATCH 14/16] test 5 still SPI receive failed sometimes --- board/drivers/spi.h | 2 +- boardesp/proxy.c | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index dc46249e99e99d..8285d776425f9c 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -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); diff --git a/boardesp/proxy.c b/boardesp/proxy.c index 6018ffd78e892f..c862c3a6c75dcd 100644 --- a/boardesp/proxy.c +++ b/boardesp/proxy.c @@ -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); @@ -167,11 +169,12 @@ void ICACHE_FLASH_ATTR udp_callback_func(void *arg) { 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) { inter_conn.proto.udp->remote_port = premot->remote_port; @@ -180,11 +183,18 @@ void ICACHE_FLASH_ATTR inter_recv_cb(void *arg, char *pusrdata, unsigned short l 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_callback); - udp_countdown = 200*5; - os_timer_setfn(&udp_callback, (os_timer_func_t *)udp_callback_func, NULL); - os_timer_arm(&udp_callback, 5, 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; + } } } From f969b80a0efaf28a8b50efb232af380bd5f466cf Mon Sep 17 00:00:00 2001 From: Jeff Palmer Date: Tue, 15 Aug 2017 19:23:24 -0400 Subject: [PATCH 15/16] Update the README for 'make link' --- drivers/linux/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/linux/README.md b/drivers/linux/README.md index 26019d63b07f9d..df36acc34faec2 100644 --- a/drivers/linux/README.md +++ b/drivers/linux/README.md @@ -4,7 +4,7 @@ This will allow the panda to work with tools such as `can-utils` installation: - - make link + - make link (only needed the first time. It will report an error on subsequent attempts to link) - make all - make install From cf0885d03dca8599a11fb81eb7af763c882105eb Mon Sep 17 00:00:00 2001 From: Jeff Palmer Date: Tue, 15 Aug 2017 19:47:46 -0400 Subject: [PATCH 16/16] Add prereqs to setup the environment. --- drivers/linux/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/linux/README.md b/drivers/linux/README.md index df36acc34faec2..ebb7abb84b3e8f 100644 --- a/drivers/linux/README.md +++ b/drivers/linux/README.md @@ -2,6 +2,8 @@ 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)