Simple CAN chunks (#25373)

* simple chunks

* more sizeofs

* fix unit tests

* bump panda

* bump panda

* don't fail for too little data

* bump panda

* bump panda

* bump panda

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: fee6f2efac
taco
Robbe Derks 2 years ago committed by GitHub
parent bec9751d00
commit d00e7ee24b
  1. 2
      panda
  2. 55
      selfdrive/boardd/panda.cc
  3. 19
      selfdrive/boardd/tests/test_boardd_usbprotocol.cc

@ -1 +1 @@
Subproject commit 2ae7b9a4d59101c0a1a9015feb3e835763db5686 Subproject commit 288e14cde904a5755ebb32b0853631ac7fbf5968

@ -169,22 +169,15 @@ static uint8_t len_to_dlc(uint8_t len) {
} }
} }
static void write_packet(uint8_t *dest, int *write_pos, const uint8_t *src, size_t size) {
for (int i = 0, &pos = *write_pos; i < size; ++i, ++pos) {
// Insert counter every 64 bytes (first byte of 64 bytes USB packet)
if (pos % USBPACKET_MAX_SIZE == 0) {
dest[pos] = pos / USBPACKET_MAX_SIZE;
pos++;
}
dest[pos] = src[i];
}
}
void Panda::pack_can_buffer(const capnp::List<cereal::CanData>::Reader &can_data_list, void Panda::pack_can_buffer(const capnp::List<cereal::CanData>::Reader &can_data_list,
std::function<void(uint8_t *, size_t)> write_func) { std::function<void(uint8_t *, size_t)> write_func) {
int32_t pos = 0; int32_t pos = 0;
uint8_t send_buf[2 * USB_TX_SOFT_LIMIT]; uint8_t send_buf[2 * USB_TX_SOFT_LIMIT];
uint32_t magic = CAN_TRANSACTION_MAGIC;
memcpy(&send_buf[0], &magic, sizeof(uint32_t));
pos += sizeof(uint32_t);
for (auto cmsg : can_data_list) { for (auto cmsg : can_data_list) {
// check if the message is intended for this panda // check if the message is intended for this panda
uint8_t bus = cmsg.getSrc(); uint8_t bus = cmsg.getSrc();
@ -202,16 +195,19 @@ void Panda::pack_can_buffer(const capnp::List<cereal::CanData>::Reader &can_data
header.data_len_code = data_len_code; header.data_len_code = data_len_code;
header.bus = bus - bus_offset; header.bus = bus - bus_offset;
write_packet(send_buf, &pos, (uint8_t *)&header, sizeof(can_header)); memcpy(&send_buf[pos], (uint8_t *)&header, sizeof(can_header));
write_packet(send_buf, &pos, (uint8_t *)can_data.begin(), can_data.size()); pos += sizeof(can_header);
memcpy(&send_buf[pos], (uint8_t *)can_data.begin(), can_data.size());
pos += can_data.size();
if (pos >= USB_TX_SOFT_LIMIT) { if (pos >= USB_TX_SOFT_LIMIT) {
write_func(send_buf, pos); write_func(send_buf, pos);
pos = 0; pos = sizeof(uint32_t);
} }
} }
// send remaining packets // send remaining packets
if (pos > 0) write_func(send_buf, pos); if (pos > sizeof(uint32_t)) write_func(send_buf, pos);
} }
void Panda::can_send(capnp::List<cereal::CanData>::Reader can_data_list) { void Panda::can_send(capnp::List<cereal::CanData>::Reader can_data_list) {
@ -235,20 +231,23 @@ bool Panda::can_receive(std::vector<can_frame>& out_vec) {
bool Panda::unpack_can_buffer(uint8_t *data, int size, std::vector<can_frame> &out_vec) { bool Panda::unpack_can_buffer(uint8_t *data, int size, std::vector<can_frame> &out_vec) {
recv_buf.clear(); recv_buf.clear();
for (int i = 0; i < size; i += USBPACKET_MAX_SIZE) {
if (data[i] != i / USBPACKET_MAX_SIZE) { if (size < sizeof(uint32_t)) {
LOGE("CAN: MALFORMED USB RECV PACKET"); return true;
handle->comms_healthy = false; }
return false;
} uint32_t magic;
int chunk_len = std::min(USBPACKET_MAX_SIZE, (size - i)); memcpy(&magic, &data[0], sizeof(uint32_t));
recv_buf.insert(recv_buf.end(), &data[i + 1], &data[i + chunk_len]); if (magic != CAN_TRANSACTION_MAGIC) {
LOGE("CAN: MALFORMED CAN RECV PACKET");
handle->comms_healthy = false;
return false;
} }
int pos = 0; int pos = sizeof(uint32_t);
while (pos < recv_buf.size()) { while (pos < size) {
can_header header; can_header header;
memcpy(&header, &recv_buf[pos], CANPACKET_HEAD_SIZE); memcpy(&header, &data[pos], sizeof(can_header));
can_frame &canData = out_vec.emplace_back(); can_frame &canData = out_vec.emplace_back();
canData.busTime = 0; canData.busTime = 0;
@ -262,9 +261,9 @@ bool Panda::unpack_can_buffer(uint8_t *data, int size, std::vector<can_frame> &o
} }
const uint8_t data_len = dlc_to_len[header.data_len_code]; const uint8_t data_len = dlc_to_len[header.data_len_code];
canData.dat.assign((char *)&recv_buf[pos + CANPACKET_HEAD_SIZE], data_len); canData.dat.assign((char *)&data[pos + sizeof(can_header)], data_len);
pos += CANPACKET_HEAD_SIZE + data_len; pos += sizeof(can_header) + data_len;
} }
return true; return true;
} }

@ -48,7 +48,7 @@ PandaTest::PandaTest(uint32_t bus_offset_, int can_list_size, cereal::PandaState
can.setAddress(i); can.setAddress(i);
can.setSrc(random_int(0, 3) + bus_offset); can.setSrc(random_int(0, 3) + bus_offset);
can.setDat(kj::ArrayPtr((uint8_t *)dat.data(), dat.size())); can.setDat(kj::ArrayPtr((uint8_t *)dat.data(), dat.size()));
total_pakets_size += CANPACKET_HEAD_SIZE + dat.size(); total_pakets_size += sizeof(can_header) + dat.size();
} }
can_data_list = can_list.asReader(); can_data_list = can_list.asReader();
@ -58,14 +58,11 @@ PandaTest::PandaTest(uint32_t bus_offset_, int can_list_size, cereal::PandaState
void PandaTest::test_can_send() { void PandaTest::test_can_send() {
std::vector<uint8_t> unpacked_data; std::vector<uint8_t> unpacked_data;
this->pack_can_buffer(can_data_list, [&](uint8_t *chunk, size_t size) { this->pack_can_buffer(can_data_list, [&](uint8_t *chunk, size_t size) {
int size_left = size; uint32_t magic;
for (int i = 0, counter = 0; i < size; i += USBPACKET_MAX_SIZE, counter++) { memcpy(&magic, &chunk[0], sizeof(uint32_t));
REQUIRE(chunk[i] == counter);
REQUIRE(magic == CAN_TRANSACTION_MAGIC);
const int len = std::min(USBPACKET_MAX_SIZE, size_left); unpacked_data.insert(unpacked_data.end(), &chunk[sizeof(uint32_t)], &chunk[size]);
unpacked_data.insert(unpacked_data.end(), &chunk[i + 1], &chunk[i + len]);
size_left -= len;
}
}); });
REQUIRE(unpacked_data.size() == total_pakets_size); REQUIRE(unpacked_data.size() == total_pakets_size);
@ -73,9 +70,9 @@ void PandaTest::test_can_send() {
INFO("test can message integrity"); INFO("test can message integrity");
for (int pos = 0, pckt_len = 0; pos < unpacked_data.size(); pos += pckt_len) { for (int pos = 0, pckt_len = 0; pos < unpacked_data.size(); pos += pckt_len) {
can_header header; can_header header;
memcpy(&header, &unpacked_data[pos], CANPACKET_HEAD_SIZE); memcpy(&header, &unpacked_data[pos], sizeof(can_header));
const uint8_t data_len = dlc_to_len[header.data_len_code]; const uint8_t data_len = dlc_to_len[header.data_len_code];
pckt_len = CANPACKET_HEAD_SIZE + data_len; pckt_len = sizeof(can_header) + data_len;
REQUIRE(header.addr == cnt); REQUIRE(header.addr == cnt);
REQUIRE(test_data.find(data_len) != test_data.end()); REQUIRE(test_data.find(data_len) != test_data.end());

Loading…
Cancel
Save