boardd: connect to SPI panda by UID (#27035)

* move list

* connect by serial

* cleanup hw serial

* little more

* rm excessive print

Co-authored-by: Comma Device <device@comma.ai>
old-commit-hash: 66ff2de0a2
beeps
Adeeb Shihadeh 2 years ago committed by GitHub
parent fc2743e9df
commit bf804f25bf
  1. 4
      selfdrive/boardd/boardd.cc
  2. 31
      selfdrive/boardd/panda.cc
  3. 2
      selfdrive/boardd/panda.h
  4. 2
      selfdrive/boardd/panda_comms.cc
  5. 1
      selfdrive/boardd/panda_comms.h
  6. 50
      selfdrive/boardd/spi.cc

@ -225,9 +225,9 @@ void can_send_thread(std::vector<Panda *> pandas, bool fake_send) {
//Dont send if older than 1 second //Dont send if older than 1 second
if ((nanos_since_boot() - event.getLogMonoTime() < 1e9) && !fake_send) { if ((nanos_since_boot() - event.getLogMonoTime() < 1e9) && !fake_send) {
for (const auto& panda : pandas) { for (const auto& panda : pandas) {
LOGT("sending sendcan to panda: %s", (panda->hw_serial).c_str()); LOGT("sending sendcan to panda: %s", (panda->hw_serial()).c_str());
panda->can_send(event.getSendcan()); panda->can_send(event.getSendcan());
LOGT("sendcan sent to panda: %s", (panda->hw_serial).c_str()); LOGT("sendcan sent to panda: %s", (panda->hw_serial()).c_str());
} }
} }
} }

@ -3,20 +3,18 @@
#include <unistd.h> #include <unistd.h>
#include <cassert> #include <cassert>
#include <iomanip>
#include <stdexcept> #include <stdexcept>
#include <sstream>
#include "cereal/messaging/messaging.h" #include "cereal/messaging/messaging.h"
#include "common/swaglog.h" #include "common/swaglog.h"
#include "common/util.h" #include "common/util.h"
Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) { Panda::Panda(std::string serial, uint32_t bus_offset) : bus_offset(bus_offset) {
// TODO: support SPI here one day... // try USB first, then SPI
if (serial.find("spi") != std::string::npos) { try {
handle = std::make_unique<PandaSpiHandle>(serial);
} else {
handle = std::make_unique<PandaUsbHandle>(serial); handle = std::make_unique<PandaUsbHandle>(serial);
} catch (std::exception &e) {
handle = std::make_unique<PandaSpiHandle>(serial);
} }
hw_type = get_hw_type(); hw_type = get_hw_type();
@ -41,23 +39,16 @@ bool Panda::comms_healthy() {
return handle->comms_healthy; return handle->comms_healthy;
} }
std::string Panda::hw_serial() {
return handle->hw_serial;
}
std::vector<std::string> Panda::list() { std::vector<std::string> Panda::list() {
std::vector<std::string> serials = PandaUsbHandle::list(); std::vector<std::string> serials = PandaUsbHandle::list();
// check SPI for (auto s : PandaSpiHandle::list()) {
const int uid_len = 12; if (std::find(serials.begin(), serials.end(), s) == serials.end()) {
uint8_t uid[uid_len] = {0}; serials.push_back(s);
PandaSpiHandle spi_handle("/dev/spidev0.0");
int ret = spi_handle.control_read(0xc3, 0, 0, uid, uid_len);
if (ret == uid_len) {
std::stringstream stream;
for (int i = 0; i < uid_len; i++) {
stream << std::hex << std::setw(2) << std::setfill('0') << int(uid[i]);
}
// might be on USB too
if (std::find(serials.begin(), serials.end(), stream.str()) == serials.end()) {
serials.push_back(stream.str());
} }
} }

@ -48,13 +48,13 @@ private:
public: public:
Panda(std::string serial="", uint32_t bus_offset=0); Panda(std::string serial="", uint32_t bus_offset=0);
std::string hw_serial;
cereal::PandaState::PandaType hw_type = cereal::PandaState::PandaType::UNKNOWN; cereal::PandaState::PandaType hw_type = cereal::PandaState::PandaType::UNKNOWN;
bool has_rtc = false; bool has_rtc = false;
const uint32_t bus_offset; const uint32_t bus_offset;
bool connected(); bool connected();
bool comms_healthy(); bool comms_healthy();
std::string hw_serial();
// Static functions // Static functions
static std::vector<std::string> list(); static std::vector<std::string> list();

@ -44,7 +44,7 @@ PandaUsbHandle::PandaUsbHandle(std::string serial) : PandaCommsHandle(serial) {
ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, desc_serial, std::size(desc_serial)); ret = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, desc_serial, std::size(desc_serial));
if (ret < 0) { goto fail; } if (ret < 0) { goto fail; }
auto hw_serial = std::string((char *)desc_serial, ret); hw_serial = std::string((char *)desc_serial, ret);
if (serial.empty() || serial == hw_serial) { if (serial.empty() || serial == hw_serial) {
break; break;
} }

@ -21,6 +21,7 @@ public:
virtual ~PandaCommsHandle() {}; virtual ~PandaCommsHandle() {};
virtual void cleanup() = 0; virtual void cleanup() = 0;
std::string hw_serial;
std::atomic<bool> connected = true; std::atomic<bool> connected = true;
std::atomic<bool> comms_healthy = true; std::atomic<bool> comms_healthy = true;
static std::vector<std::string> list(); static std::vector<std::string> list();

@ -5,6 +5,8 @@
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
#include <iomanip>
#include <sstream>
#include "common/util.h" #include "common/util.h"
#include "common/timing.h" #include "common/timing.h"
@ -28,6 +30,7 @@ struct __attribute__((packed)) spi_header {
const int SPI_MAX_RETRIES = 5; const int SPI_MAX_RETRIES = 5;
const int SPI_ACK_TIMEOUT = 50; // milliseconds const int SPI_ACK_TIMEOUT = 50; // milliseconds
const std::string SPI_DEVICE = "/dev/spidev0.0";
class LockEx { class LockEx {
public: public:
@ -48,38 +51,56 @@ private:
PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) {
LOGD("opening SPI panda: %s", serial.c_str()); int ret;
const int uid_len = 12;
uint8_t uid[uid_len] = {0};
int err;
uint32_t spi_mode = SPI_MODE_0; uint32_t spi_mode = SPI_MODE_0;
uint32_t spi_speed = 30000000; uint32_t spi_speed = 30000000;
uint8_t spi_bits_per_word = 8; uint8_t spi_bits_per_word = 8;
spi_fd = open(serial.c_str(), O_RDWR); spi_fd = open(SPI_DEVICE.c_str(), O_RDWR);
if (spi_fd < 0) { if (spi_fd < 0) {
LOGE("failed opening SPI device %d", err); LOGE("failed opening SPI device %d", spi_fd);
goto fail; goto fail;
} }
// SPI settings // SPI settings
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode); ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode);
if (err < 0) { if (ret < 0) {
LOGE("failed setting SPI mode %d", err); LOGE("failed setting SPI mode %d", ret);
goto fail; goto fail;
} }
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed); ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);
if (err < 0) { if (ret < 0) {
LOGE("failed setting SPI speed"); LOGE("failed setting SPI speed");
goto fail; goto fail;
} }
err = util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word); ret = util::safe_ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits_per_word);
if (err < 0) { if (ret < 0) {
LOGE("failed setting SPI bits per word"); LOGE("failed setting SPI bits per word");
goto fail; goto fail;
} }
// get hw UID/serial
ret = control_read(0xc3, 0, 0, uid, uid_len);
if (ret == uid_len) {
std::stringstream stream;
for (int i = 0; i < uid_len; i++) {
stream << std::hex << std::setw(2) << std::setfill('0') << int(uid[i]);
}
hw_serial = stream.str();
} else {
LOGD("failed to get serial %d", ret);
goto fail;
}
if (!serial.empty() && (serial != hw_serial)) {
goto fail;
}
return; return;
fail: fail:
@ -163,7 +184,12 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t
} }
std::vector<std::string> PandaSpiHandle::list() { std::vector<std::string> PandaSpiHandle::list() {
// TODO: list all pandas available over SPI try {
PandaSpiHandle sh("");
return {sh.hw_serial};
} catch (std::exception &e) {
// no panda on SPI
}
return {}; return {};
} }

Loading…
Cancel
Save