|
|
|
@ -6,6 +6,7 @@ |
|
|
|
|
#include <cstring> |
|
|
|
|
|
|
|
|
|
#include "common/util.h" |
|
|
|
|
#include "common/timing.h" |
|
|
|
|
#include "common/swaglog.h" |
|
|
|
|
#include "panda/board/comms_definitions.h" |
|
|
|
|
#include "selfdrive/boardd/panda_comms.h" |
|
|
|
@ -24,6 +25,9 @@ struct __attribute__((packed)) spi_header { |
|
|
|
|
uint16_t max_rx_len; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const int SPI_MAX_RETRIES = 5; |
|
|
|
|
const int SPI_ACK_TIMEOUT = 50; // milliseconds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { |
|
|
|
|
LOGD("opening SPI panda: %s", serial.c_str()); |
|
|
|
@ -109,7 +113,7 @@ int PandaSpiHandle::bulk_read(unsigned char endpoint, unsigned char* data, int l |
|
|
|
|
int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t rx_len) { |
|
|
|
|
std::lock_guard lk(hw_lock); |
|
|
|
|
|
|
|
|
|
const int xfer_size = 0x40; |
|
|
|
|
const int xfer_size = 0x40 * 15; |
|
|
|
|
|
|
|
|
|
int ret = 0; |
|
|
|
|
uint16_t length = (tx_data != NULL) ? tx_len : rx_len; |
|
|
|
@ -119,7 +123,8 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t |
|
|
|
|
int len = std::min(xfer_size, tx_len - (xfer_size * i)); |
|
|
|
|
d = spi_transfer_retry(endpoint, tx_data + (xfer_size * i), len, NULL, 0); |
|
|
|
|
} else { |
|
|
|
|
d = spi_transfer_retry(endpoint, NULL, 0, rx_data + (xfer_size * i), xfer_size); |
|
|
|
|
uint16_t to_read = std::min(xfer_size, rx_len - ret); |
|
|
|
|
d = spi_transfer_retry(endpoint, NULL, 0, rx_data + (xfer_size * i), to_read); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (d < 0) { |
|
|
|
@ -137,15 +142,11 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<std::string> PandaSpiHandle::list() { |
|
|
|
|
// TODO: list all pandas available over SPI
|
|
|
|
|
return {}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void add_checksum(uint8_t *data, int data_len) { |
|
|
|
|
data[data_len] = SPI_CHECKSUM_START; |
|
|
|
|
for (int i=0; i < data_len; i++) { |
|
|
|
@ -165,17 +166,19 @@ bool check_checksum(uint8_t *data, int data_len) { |
|
|
|
|
int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
int count = SPI_MAX_RETRIES; |
|
|
|
|
std::lock_guard lk(hw_lock); |
|
|
|
|
do { |
|
|
|
|
// TODO: handle error
|
|
|
|
|
ret = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len); |
|
|
|
|
} while (ret < 0 && connected && !PANDA_NO_RETRY); |
|
|
|
|
count--; |
|
|
|
|
} while (ret < 0 && connected && count > 0); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int PandaSpiHandle::wait_for_ack(spi_ioc_transfer &transfer, uint8_t ack) { |
|
|
|
|
// TODO: add timeout?
|
|
|
|
|
double start_millis = millis_since_boot(); |
|
|
|
|
while (true) { |
|
|
|
|
int ret = util::safe_ioctl(spi_fd, SPI_IOC_MESSAGE(1), &transfer); |
|
|
|
|
if (ret < 0) { |
|
|
|
@ -189,6 +192,12 @@ int PandaSpiHandle::wait_for_ack(spi_ioc_transfer &transfer, uint8_t ack) { |
|
|
|
|
LOGW("SPI: got NACK"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// handle timeout
|
|
|
|
|
if (millis_since_boot() - start_millis > SPI_ACK_TIMEOUT) { |
|
|
|
|
LOGE("SPI: timed out waiting for ACK"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|