Skip to content

Commit

Permalink
CAN comms test (commaai#1181)
Browse files Browse the repository at this point in the history
* CAN comms test

* remove those

* cleanup

* little more
  • Loading branch information
adeebshihadeh authored Dec 1, 2022
1 parent b238d41 commit 88b30e1
Show file tree
Hide file tree
Showing 15 changed files with 297 additions and 128 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,10 @@ jobs:
- uses: actions/checkout@v2
- name: Build Docker image
run: eval "$BUILD"
- name: Build panda
run: $RUN "scons -j4"
- name: Test communication protocols
run: $RUN "cd tests/usbprotocol && python -m unittest discover ."
run: $RUN "cd tests/usbprotocol && ./test.sh"

safety:
name: safety
Expand Down
2 changes: 1 addition & 1 deletion __init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from .python import (Panda, PandaDFU, # noqa: F401
BASEDIR, pack_can_buffer, unpack_can_buffer,
DEFAULT_FW_FN, DEFAULT_H7_FW_FN, MCU_TYPE_H7, MCU_TYPE_F4, DLC_TO_LEN, LEN_TO_DLC,
ALTERNATIVE_EXPERIENCE)
ALTERNATIVE_EXPERIENCE, USBPACKET_MAX_SIZE)

from .python.serial import PandaSerial # noqa: F401

Expand Down
110 changes: 110 additions & 0 deletions board/can_comms.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
typedef struct {
uint32_t ptr;
uint32_t tail_size;
uint8_t data[72];
uint8_t counter;
} asm_buffer;

asm_buffer can_read_buffer = {.ptr = 0U, .tail_size = 0U, .counter = 0U};
uint32_t total_rx_size = 0U;

int comms_can_read(uint8_t *data, uint32_t max_len) {
uint32_t pos = 1;
data[0] = can_read_buffer.counter;
// Send tail of previous message if it is in buffer
if (can_read_buffer.ptr > 0U) {
if (can_read_buffer.ptr <= 63U) {
(void)memcpy(&data[pos], can_read_buffer.data, can_read_buffer.ptr);
pos += can_read_buffer.ptr;
can_read_buffer.ptr = 0U;
} else {
(void)memcpy(&data[pos], can_read_buffer.data, 63U);
can_read_buffer.ptr = can_read_buffer.ptr - 63U;
(void)memcpy(can_read_buffer.data, &can_read_buffer.data[63], can_read_buffer.ptr);
pos += 63U;
}
}

if (total_rx_size > MAX_EP1_CHUNK_PER_BULK_TRANSFER) {
total_rx_size = 0U;
can_read_buffer.counter = 0U;
} else {
CANPacket_t can_packet;
while ((pos < max_len) && can_pop(&can_rx_q, &can_packet)) {
uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[can_packet.data_len_code];
if ((pos + pckt_len) <= max_len) {
(void)memcpy(&data[pos], &can_packet, pckt_len);
pos += pckt_len;
} else {
(void)memcpy(&data[pos], &can_packet, max_len - pos);
can_read_buffer.ptr = pckt_len - (max_len - pos);
// cppcheck-suppress objectIndex
(void)memcpy(can_read_buffer.data, &((uint8_t*)&can_packet)[(max_len - pos)], can_read_buffer.ptr);
pos = max_len;
}
}
can_read_buffer.counter++;
total_rx_size += pos;
}
if (pos != max_len) {
can_read_buffer.counter = 0U;
total_rx_size = 0U;
}
if (pos <= 1U) { pos = 0U; }
return pos;
}

asm_buffer can_write_buffer = {.ptr = 0U, .tail_size = 0U, .counter = 0U};

// send on CAN
void comms_can_write(uint8_t *data, uint32_t len) {
// Got first packet from a stream, resetting buffer and counter
if (data[0] == 0U) {
can_write_buffer.counter = 0U;
can_write_buffer.ptr = 0U;
can_write_buffer.tail_size = 0U;
}
// Assembling can message with data from buffer
if (data[0] == can_write_buffer.counter) {
uint32_t pos = 1U;
can_write_buffer.counter++;
if (can_write_buffer.ptr != 0U) {
if (can_write_buffer.tail_size <= 63U) {
CANPacket_t to_push;
(void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], can_write_buffer.tail_size);
(void)memcpy(&to_push, can_write_buffer.data, can_write_buffer.ptr + can_write_buffer.tail_size);
can_send(&to_push, to_push.bus, false);
pos += can_write_buffer.tail_size;
can_write_buffer.ptr = 0U;
can_write_buffer.tail_size = 0U;
} else {
(void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], len - pos);
can_write_buffer.tail_size -= 63U;
can_write_buffer.ptr += 63U;
pos += 63U;
}
}

while (pos < len) {
uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[(data[pos] >> 4U)];
if ((pos + pckt_len) <= len) {
CANPacket_t to_push;
(void)memcpy(&to_push, &data[pos], pckt_len);
can_send(&to_push, to_push.bus, false);
pos += pckt_len;
} else {
(void)memcpy(can_write_buffer.data, &data[pos], len - pos);
can_write_buffer.ptr = len - pos;
can_write_buffer.tail_size = pckt_len - can_write_buffer.ptr;
pos += can_write_buffer.ptr;
}
}
}
}

// TODO: make this more general!
void usb_cb_ep3_out_complete(void) {
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
usb_outep3_resume_if_paused();
}
}
5 changes: 4 additions & 1 deletion board/fake_stm.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
#define ALLOW_DEBUG
#define PANDA

#define ENTER_CRITICAL() 0
#define EXIT_CRITICAL() 0

void print(const char *a) {
printf(a);
printf("%s", a);
}

void puth(unsigned int i) {
Expand Down
1 change: 1 addition & 0 deletions board/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "obj/gitversion.h"

#include "can_comms.h"
#include "main_comms.h"


Expand Down
111 changes: 0 additions & 111 deletions board/main_comms.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,110 +47,6 @@ int get_rtc_pkt(void *dat) {
return sizeof(t);
}

typedef struct {
uint32_t ptr;
uint32_t tail_size;
uint8_t data[72];
uint8_t counter;
} asm_buffer;

asm_buffer can_read_buffer = {.ptr = 0U, .tail_size = 0U, .counter = 0U};
uint32_t total_rx_size = 0U;

int comms_can_read(uint8_t *data, uint32_t max_len) {
uint32_t pos = 1;
data[0] = can_read_buffer.counter;
// Send tail of previous message if it is in buffer
if (can_read_buffer.ptr > 0U) {
if (can_read_buffer.ptr <= 63U) {
(void)memcpy(&data[pos], can_read_buffer.data, can_read_buffer.ptr);
pos += can_read_buffer.ptr;
can_read_buffer.ptr = 0U;
} else {
(void)memcpy(&data[pos], can_read_buffer.data, 63U);
can_read_buffer.ptr = can_read_buffer.ptr - 63U;
(void)memcpy(can_read_buffer.data, &can_read_buffer.data[63], can_read_buffer.ptr);
pos += 63U;
}
}

if (total_rx_size > MAX_EP1_CHUNK_PER_BULK_TRANSFER) {
total_rx_size = 0U;
can_read_buffer.counter = 0U;
} else {
CANPacket_t can_packet;
while ((pos < max_len) && can_pop(&can_rx_q, &can_packet)) {
uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[can_packet.data_len_code];
if ((pos + pckt_len) <= max_len) {
(void)memcpy(&data[pos], &can_packet, pckt_len);
pos += pckt_len;
} else {
(void)memcpy(&data[pos], &can_packet, max_len - pos);
can_read_buffer.ptr = pckt_len - (max_len - pos);
// cppcheck-suppress objectIndex
(void)memcpy(can_read_buffer.data, &((uint8_t*)&can_packet)[(max_len - pos)], can_read_buffer.ptr);
pos = max_len;
}
}
can_read_buffer.counter++;
total_rx_size += pos;
}
if (pos != max_len) {
can_read_buffer.counter = 0U;
total_rx_size = 0U;
}
if (pos <= 1U) { pos = 0U; }
return pos;
}

asm_buffer can_write_buffer = {.ptr = 0U, .tail_size = 0U, .counter = 0U};

// send on CAN
void comms_can_write(uint8_t *data, uint32_t len) {
// Got first packet from a stream, resetting buffer and counter
if (data[0] == 0U) {
can_write_buffer.counter = 0U;
can_write_buffer.ptr = 0U;
can_write_buffer.tail_size = 0U;
}
// Assembling can message with data from buffer
if (data[0] == can_write_buffer.counter) {
uint32_t pos = 1U;
can_write_buffer.counter++;
if (can_write_buffer.ptr != 0U) {
if (can_write_buffer.tail_size <= 63U) {
CANPacket_t to_push;
(void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], can_write_buffer.tail_size);
(void)memcpy(&to_push, can_write_buffer.data, can_write_buffer.ptr + can_write_buffer.tail_size);
can_send(&to_push, to_push.bus, false);
pos += can_write_buffer.tail_size;
can_write_buffer.ptr = 0U;
can_write_buffer.tail_size = 0U;
} else {
(void)memcpy(&can_write_buffer.data[can_write_buffer.ptr], &data[pos], len - pos);
can_write_buffer.tail_size -= 63U;
can_write_buffer.ptr += 63U;
pos += 63U;
}
}

while (pos < len) {
uint32_t pckt_len = CANPACKET_HEAD_SIZE + dlc_to_len[(data[pos] >> 4U)];
if ((pos + pckt_len) <= len) {
CANPacket_t to_push;
(void)memcpy(&to_push, &data[pos], pckt_len);
can_send(&to_push, to_push.bus, false);
pos += pckt_len;
} else {
(void)memcpy(can_write_buffer.data, &data[pos], len - pos);
can_write_buffer.ptr = len - pos;
can_write_buffer.tail_size = pckt_len - can_write_buffer.ptr;
pos += can_write_buffer.ptr;
}
}
}
}

// send on serial, first byte to select the ring
void comms_endpoint2_write(uint8_t *data, uint32_t len) {
uart_ring *ur = get_ring_by_number(data[0]);
Expand All @@ -165,13 +61,6 @@ void comms_endpoint2_write(uint8_t *data, uint32_t len) {
}
}

// TODO: make this more general!
void usb_cb_ep3_out_complete(void) {
if (can_tx_check_min_slots_free(MAX_CAN_MSGS_PER_BULK_TRANSFER)) {
usb_outep3_resume_if_paused();
}
}

int comms_control_handler(ControlPacket_t *req, uint8_t *resp) {
unsigned int resp_len = 0;
uart_ring *ur = NULL;
Expand Down
1 change: 1 addition & 0 deletions python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

DEBUG = os.getenv("PANDADEBUG") is not None

USBPACKET_MAX_SIZE = 0x40
CANPACKET_HEAD_SIZE = 0x5
DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)}
Expand Down
12 changes: 12 additions & 0 deletions tests/SConscript
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
env = Environment(
CC='gcc',
CFLAGS=[
'-nostdlib',
'-fno-builtin',
'-std=gnu11',
],
CPPPATH=[".", "../board"],
)

env.SharedLibrary("safety/libpandasafety.so", ["safety/test.c"])
env.SharedLibrary("usbprotocol/libpandaprotocol.so", ["usbprotocol/test.c"])
5 changes: 3 additions & 2 deletions tests/libpanda/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ env = Environment(
'-nostdlib',
'-fno-builtin',
'-std=gnu11',
'-Wfatal-errors',
],
CPPPATH=[".", "../../board"],
CPPPATH=[".", "#board/"],
)

env.SharedLibrary("libpanda.so", ["safety_helpers.c"])
env.SharedLibrary("libpanda.so", ["panda.c",])
21 changes: 21 additions & 0 deletions tests/libpanda/libpanda_py.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,27 @@
int set_safety_hooks(uint16_t mode, uint16_t param);
""")

ffi.cdef("""
typedef struct {
volatile uint32_t w_ptr;
volatile uint32_t r_ptr;
uint32_t fifo_size;
CANPacket_t *elems;
} can_ring;
extern can_ring *rx_q;
extern can_ring *txgmlan_q;
extern can_ring *tx1_q;
extern can_ring *tx2_q;
extern can_ring *tx3_q;
bool can_pop(can_ring *q, CANPacket_t *elem);
bool can_push(can_ring *q, CANPacket_t *elem);
int comms_can_read(uint8_t *data, uint32_t max_len);
void comms_can_write(uint8_t *data, uint32_t len);
uint32_t can_slots_empty(can_ring *q);
""")

setup_safety_helpers(ffi)

class CANPacket:
Expand Down
32 changes: 32 additions & 0 deletions tests/libpanda/panda.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include "fake_stm.h"
#include "config.h"
#include "can_definitions.h"

bool bitbang_gmlan(CANPacket_t *to_bang) { return true; }
bool can_init(uint8_t can_number) { return true; }
void process_can(uint8_t can_number) { }
//int safety_tx_hook(CANPacket_t *to_send) { return 1; }

typedef struct harness_configuration harness_configuration;
void usb_cb_ep3_out_complete(void);
void usb_outep3_resume_if_paused(void) { };

#include "health.h"
#include "faults.h"
#include "libc.h"
#include "boards/board_declarations.h"
#include "safety.h"
#include "main_declarations.h"
#include "drivers/can_common.h"

can_ring *rx_q = &can_rx_q;
can_ring *txgmlan_q = &can_txgmlan_q;
can_ring *tx1_q = &can_tx1_q;
can_ring *tx2_q = &can_tx2_q;
can_ring *tx3_q = &can_tx3_q;

#include "comms_definitions.h"
#include "can_comms.h"

// libpanda stuff
#include "safety_helpers.h"
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
#include "config.h"
#include "fake_stm.h"
#include "can_definitions.h"
#include "main_declarations.h"
#include "boards/board_declarations.h"

#include "faults.h"
#include "safety.h"

void safety_tick_current_rx_checks() {
safety_tick(current_rx_checks);
}
Expand Down
8 changes: 8 additions & 0 deletions tests/usbprotocol/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -e

# Loops over all HW_TYPEs, see board/boards/board_declarations.h
for hw_type in {0..7}; do
echo "Testing HW_TYPE: $hw_type"
HW_TYPE=$hw_type python -m unittest discover .
done
Loading

0 comments on commit 88b30e1

Please sign in to comment.