Skip to content

Commit

Permalink
Merge branch 'master' into forester-2022-PR
Browse files Browse the repository at this point in the history
  • Loading branch information
jnewb1 committed Jul 17, 2023
2 parents 735dc70 + 5d87344 commit e32e39c
Show file tree
Hide file tree
Showing 16 changed files with 1,460 additions and 112 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.tmp
*.pyc
.*.swp
.*.swo
Expand Down
1 change: 1 addition & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .python.constants import McuType, BASEDIR, FW_PATH # noqa: F401
from .python.spi import PandaSpiException, PandaProtocolMismatch # noqa: F401
from .python.serial import PandaSerial # noqa: F401
from .python import (Panda, PandaDFU, # noqa: F401
pack_can_buffer, unpack_can_buffer, calculate_checksum, unpack_log,
Expand Down
5 changes: 3 additions & 2 deletions board/drivers/spi.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,18 @@

#include "crc.h"

#define SPI_BUF_SIZE 1024U
#define SPI_TIMEOUT_US 10000U

// got max rate from hitting a non-existent endpoint
// in a tight loop, plus some buffer
#define SPI_IRQ_RATE 16000U

#ifdef STM32H7
#define SPI_BUF_SIZE 2048U
__attribute__((section(".ram_d1"))) uint8_t spi_buf_rx[SPI_BUF_SIZE];
__attribute__((section(".ram_d1"))) uint8_t spi_buf_tx[SPI_BUF_SIZE];
__attribute__((section(".ram_d2"))) uint8_t spi_buf_tx[SPI_BUF_SIZE];
#else
#define SPI_BUF_SIZE 1024U
uint8_t spi_buf_rx[SPI_BUF_SIZE];
uint8_t spi_buf_tx[SPI_BUF_SIZE];
#endif
Expand Down
197 changes: 127 additions & 70 deletions board/safety/safety_ford.h

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions drivers/spi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
spidev.c
*.ko
*.cmd
*.mod
*.symvers
*.order
*.mod.c
14 changes: 14 additions & 0 deletions drivers/spi/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
obj-m += spidev_panda.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

# GCC9 bug, apply kernel patch instead?
# https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b999ae3614d09d97a1575936bcee884f912b10e
ccflags-y := -Wno-missing-attributes

default:
$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:
$(MAKE) -C $(KDIR) M=$(PWD) clean
27 changes: 27 additions & 0 deletions drivers/spi/load.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash
set -e

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd $DIR

make -j8

sudo su -c "echo spi0.0 > /sys/bus/spi/drivers/spidev/unbind" || true

sudo dmesg -C

#sudo rmmod -f spidev_panda
sudo rmmod spidev_panda || true
sudo insmod spidev_panda.ko

sudo su -c "echo 'file $DIR/spidev_panda.c +p' > /sys/kernel/debug/dynamic_debug/control"
sudo su -c "echo 'file $DIR/spi_panda.h +p' > /sys/kernel/debug/dynamic_debug/control"

sudo lsmod

echo "loaded"
ls -la /dev/spi*
sudo chmod 666 /dev/spi*
ipython -c "from panda import Panda; print(Panda.list())"
KERN=1 ipython -c "from panda import Panda; print(Panda.list())"
dmesg
33 changes: 33 additions & 0 deletions drivers/spi/patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
53c53,54
< #define SPIDEV_MAJOR 153 /* assigned */
---
> int SPIDEV_MAJOR = 0;
> //#define SPIDEV_MAJOR 153 /* assigned */
354a356,358
>
> #include "spi_panda.h"
>
413,414c417,419
< retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
< (__u8 __user *)arg);
---
> retval = panda_transfer(spidev, spi, arg);
> //retval = __put_user((spi->mode & SPI_LSB_FIRST) ? 1 : 0,
> // (__u8 __user *)arg);
697,698d701
< { .compatible = "rohm,dh2228fv" },
< { .compatible = "lineartechnology,ltc2488" },
831c834
< .name = "spidev",
---
> .name = "spidev_panda",
856c859
< status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops);
---
> status = register_chrdev(0, "spi", &spidev_fops);
860c863,865
< spidev_class = class_create(THIS_MODULE, "spidev");
---
> SPIDEV_MAJOR = status;
>
> spidev_class = class_create(THIS_MODULE, "spidev_panda");
12 changes: 12 additions & 0 deletions drivers/spi/pull-src.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/bash
set -e

DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
cd $DIR

rm -f spidev.c
wget https://raw.githubusercontent.com/commaai/agnos-kernel-sdm845/master/drivers/spi/spidev.c

# diff spidev.c spidev_panda.c > patch
# git diff --no-index spidev.c spidev_panda.c
patch -o spidev_panda.c spidev.c -i patch
160 changes: 160 additions & 0 deletions drivers/spi/spi_panda.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#include <linux/delay.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>

#define SPI_SYNC 0x5AU
#define SPI_HACK 0x79U
#define SPI_DACK 0x85U
#define SPI_NACK 0x1FU
#define SPI_CHECKSUM_START 0xABU

struct __attribute__((packed)) spi_header {
u8 sync;
u8 endpoint;
uint16_t tx_len;
uint16_t max_rx_len;
};

struct spi_panda_transfer {
__u64 rx_buf;
__u64 tx_buf;
__u32 tx_length;
__u32 rx_length_max;
__u32 timeout;
__u8 endpoint;
__u8 expect_disconnect;
};

static u8 panda_calc_checksum(u8 *buf, u16 length) {
int i;
u8 checksum = SPI_CHECKSUM_START;
for (i = 0U; i < length; i++) {
checksum ^= buf[i];
}
return checksum;
}

static long panda_wait_for_ack(struct spidev_data *spidev, u8 ack_val, u8 length) {
int i;
int ret;
for (i = 0; i < 1000; i++) {
ret = spidev_sync_read(spidev, length);
if (ret < 0) {
return ret;
}

if (spidev->rx_buffer[0] == ack_val) {
return 0;
} else if (spidev->rx_buffer[0] == SPI_NACK) {
return -2;
}
if (i > 20) usleep_range(10, 20);
}
return -1;
}

static long panda_transfer_raw(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) {
u16 rx_len;
long retval = -1;
struct spi_header header;
struct spi_panda_transfer pt;

struct spi_transfer t = {
.len = 0,
.tx_buf = spidev->tx_buffer,
.rx_buf = spidev->rx_buffer,
.speed_hz = spidev->spi->max_speed_hz,
};

struct spi_message m;
spi_message_init(&m);
spi_message_add_tail(&t, &m);

// read struct from user
if (!access_ok(VERIFY_WRITE, arg, sizeof(pt))) {
return -1;
}
if (copy_from_user(&pt, (void __user *)arg, sizeof(pt))) {
return -1;
}
dev_dbg(&spi->dev, "ep: %d, tx len: %d\n", pt.endpoint, pt.tx_length);

// send header
header.sync = 0x5a;
header.endpoint = pt.endpoint;
header.tx_len = pt.tx_length;
header.max_rx_len = pt.rx_length_max;
memcpy(spidev->tx_buffer, &header, sizeof(header));
spidev->tx_buffer[sizeof(header)] = panda_calc_checksum(spidev->tx_buffer, sizeof(header));

t.len = sizeof(header) + 1;
retval = spidev_sync(spidev, &m);
if (retval < 0) {
dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval);
return retval;
}

// wait for ACK
retval = panda_wait_for_ack(spidev, SPI_HACK, 1);
if (retval < 0) {
dev_dbg(&spi->dev, "no header ack %ld\n", retval);
return retval;
}

// send data
dev_dbg(&spi->dev, "sending data\n");
retval = copy_from_user(spidev->tx_buffer, (const u8 __user *)(uintptr_t)pt.tx_buf, pt.tx_length);
spidev->tx_buffer[pt.tx_length] = panda_calc_checksum(spidev->tx_buffer, pt.tx_length);
t.len = pt.tx_length + 1;
retval = spidev_sync(spidev, &m);

if (pt.expect_disconnect) {
return 0;
}

// wait for ACK
retval = panda_wait_for_ack(spidev, SPI_DACK, 3);
if (retval < 0) {
dev_dbg(&spi->dev, "no data ack\n");
return retval;
}

// get response
t.rx_buf = spidev->rx_buffer + 3;
rx_len = (spidev->rx_buffer[2] << 8) | (spidev->rx_buffer[1]);
dev_dbg(&spi->dev, "rx len %u\n", rx_len);
if (rx_len > pt.rx_length_max) {
dev_dbg(&spi->dev, "RX len greater than max\n");
return -1;
}

// do the read
t.len = rx_len + 1;
retval = spidev_sync(spidev, &m);
if (retval < 0) {
dev_dbg(&spi->dev, "spi xfer failed %ld\n", retval);
return retval;
}
if (panda_calc_checksum(spidev->rx_buffer, 3 + rx_len + 1) != 0) {
dev_dbg(&spi->dev, "bad checksum\n");
return -1;
}

retval = copy_to_user((u8 __user *)(uintptr_t)pt.rx_buf, spidev->rx_buffer + 3, rx_len);

return rx_len;
}

static long panda_transfer(struct spidev_data *spidev, struct spi_device *spi, unsigned long arg) {
int i;
int ret;
dev_dbg(&spi->dev, "=== XFER start ===\n");
for (i = 0; i < 20; i++) {
ret = panda_transfer_raw(spidev, spi, arg);
if (ret >= 0) {
break;
}
}
dev_dbg(&spi->dev, "took %d tries\n", i+1);
return ret;
}
Loading

0 comments on commit e32e39c

Please sign in to comment.