|
|
|
@ -29,8 +29,7 @@ struct __attribute__((packed)) spi_header { |
|
|
|
|
uint16_t max_rx_len; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
const int SPI_MAX_RETRIES = 5; |
|
|
|
|
const int SPI_ACK_TIMEOUT = 50; // milliseconds
|
|
|
|
|
const int SPI_ACK_TIMEOUT = 500; // milliseconds
|
|
|
|
|
const std::string SPI_DEVICE = "/dev/spidev0.0"; |
|
|
|
|
|
|
|
|
|
class LockEx { |
|
|
|
@ -89,7 +88,7 @@ PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// get hw UID/serial
|
|
|
|
|
ret = control_read(0xc3, 0, 0, uid, uid_len); |
|
|
|
|
ret = control_read(0xc3, 0, 0, uid, uid_len, 1000); |
|
|
|
|
if (ret == uid_len) { |
|
|
|
|
std::stringstream stream; |
|
|
|
|
for (int i = 0; i < uid_len; i++) { |
|
|
|
@ -127,37 +126,33 @@ void PandaSpiHandle::cleanup() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int PandaSpiHandle::control_write(uint8_t request, uint16_t param1, uint16_t param2, unsigned int timeout) { |
|
|
|
|
LockEx lock(spi_fd, hw_lock); |
|
|
|
|
ControlPacket_t packet = { |
|
|
|
|
.request = request, |
|
|
|
|
.param1 = param1, |
|
|
|
|
.param2 = param2, |
|
|
|
|
.length = 0 |
|
|
|
|
}; |
|
|
|
|
return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), NULL, 0); |
|
|
|
|
return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), NULL, 0, timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int PandaSpiHandle::control_read(uint8_t request, uint16_t param1, uint16_t param2, unsigned char *data, uint16_t length, unsigned int timeout) { |
|
|
|
|
LockEx lock(spi_fd, hw_lock); |
|
|
|
|
ControlPacket_t packet = { |
|
|
|
|
.request = request, |
|
|
|
|
.param1 = param1, |
|
|
|
|
.param2 = param2, |
|
|
|
|
.length = length |
|
|
|
|
}; |
|
|
|
|
return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), data, length); |
|
|
|
|
return spi_transfer_retry(0, (uint8_t *) &packet, sizeof(packet), data, length, timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int PandaSpiHandle::bulk_write(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { |
|
|
|
|
LockEx lock(spi_fd, hw_lock); |
|
|
|
|
return bulk_transfer(endpoint, data, length, NULL, 0); |
|
|
|
|
return bulk_transfer(endpoint, data, length, NULL, 0, timeout); |
|
|
|
|
} |
|
|
|
|
int PandaSpiHandle::bulk_read(unsigned char endpoint, unsigned char* data, int length, unsigned int timeout) { |
|
|
|
|
LockEx lock(spi_fd, hw_lock); |
|
|
|
|
return bulk_transfer(endpoint, NULL, 0, data, length); |
|
|
|
|
return bulk_transfer(endpoint, NULL, 0, data, length, timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t rx_len) { |
|
|
|
|
int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t rx_len, unsigned int timeout) { |
|
|
|
|
const int xfer_size = 0x40 * 15; |
|
|
|
|
|
|
|
|
|
int ret = 0; |
|
|
|
@ -166,10 +161,10 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t |
|
|
|
|
int d; |
|
|
|
|
if (tx_data != NULL) { |
|
|
|
|
int len = std::min(xfer_size, tx_len - (xfer_size * i)); |
|
|
|
|
d = spi_transfer_retry(endpoint, tx_data + (xfer_size * i), len, NULL, 0); |
|
|
|
|
d = spi_transfer_retry(endpoint, tx_data + (xfer_size * i), len, NULL, 0, timeout); |
|
|
|
|
} else { |
|
|
|
|
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); |
|
|
|
|
d = spi_transfer_retry(endpoint, NULL, 0, rx_data + (xfer_size * i), to_read, timeout); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (d < 0) { |
|
|
|
@ -213,15 +208,13 @@ 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 PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len, unsigned int timeout) { |
|
|
|
|
int ret; |
|
|
|
|
|
|
|
|
|
int count = SPI_MAX_RETRIES; |
|
|
|
|
double start_time = millis_since_boot(); |
|
|
|
|
do { |
|
|
|
|
// TODO: handle error
|
|
|
|
|
ret = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len); |
|
|
|
|
count--; |
|
|
|
|
} while (ret < 0 && connected && count > 0); |
|
|
|
|
} while (ret < 0 && connected && ((timeout == 0) || (millis_since_boot() - start_time) < timeout)); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
@ -238,7 +231,7 @@ int PandaSpiHandle::wait_for_ack(spi_ioc_transfer &transfer, uint8_t ack) { |
|
|
|
|
if (rx_buf[0] == ack) { |
|
|
|
|
break; |
|
|
|
|
} else if (rx_buf[0] == SPI_NACK) { |
|
|
|
|
LOGW("SPI: got NACK"); |
|
|
|
|
LOGD("SPI: got NACK"); |
|
|
|
|
return -1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -255,6 +248,7 @@ int PandaSpiHandle::wait_for_ack(spi_ioc_transfer &transfer, uint8_t ack) { |
|
|
|
|
int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx_len, uint8_t *rx_data, uint16_t max_rx_len) { |
|
|
|
|
int ret; |
|
|
|
|
uint16_t rx_data_len; |
|
|
|
|
LockEx lock(spi_fd, hw_lock); |
|
|
|
|
|
|
|
|
|
// needs to be less, since we need to have space for the checksum
|
|
|
|
|
assert(tx_len < SPI_BUF_SIZE); |
|
|
|
|