boardd spi: prevent busy wait when TX buffers full (#28599)

pull/28609/head
Adeeb Shihadeh 2 years ago committed by GitHub
parent bac193bdd5
commit 4c6f7b5c84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 23
      selfdrive/boardd/spi.cc

@ -220,21 +220,31 @@ 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, unsigned int timeout) { 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 ret;
int count = 0; int nack_count = 0;
int timeout_count = 0;
bool timed_out = false; bool timed_out = false;
double start_time = millis_since_boot(); double start_time = millis_since_boot();
do { do {
ret = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len, timeout); ret = spi_transfer(endpoint, tx_data, tx_len, rx_data, max_rx_len, timeout);
if (ret < 0) { if (ret < 0) {
timed_out = (timeout != 0) && (count > 5); timed_out = (timeout != 0) && (timeout_count > 5);
count += ret == SpiError::ACK_TIMEOUT; timeout_count += ret == SpiError::ACK_TIMEOUT;
// give other threads a chance to run
std::this_thread::yield(); std::this_thread::yield();
if (ret == SpiError::NACK) {
// prevent busy wait while the panda is NACK'ing
nack_count += 1;
usleep(std::clamp(nack_count*10, 200, 2000));
}
} }
} while (ret < 0 && connected && !timed_out); } while (ret < 0 && connected && !timed_out);
if (ret < 0) { if (ret < 0) {
LOGE("transfer failed, after %d tries, %.2fms", count, millis_since_boot() - start_time); LOGE("transfer failed, after %d tries, %.2fms", timeout_count, millis_since_boot() - start_time);
} }
return ret; return ret;
@ -250,7 +260,7 @@ int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout)
spi_ioc_transfer transfer = { spi_ioc_transfer transfer = {
.tx_buf = (uint64_t)tx_buf, .tx_buf = (uint64_t)tx_buf,
.rx_buf = (uint64_t)rx_buf, .rx_buf = (uint64_t)rx_buf,
.delay_usecs = 5, .delay_usecs = 10,
.len = 1 .len = 1
}; };
tx_buf[0] = tx; tx_buf[0] = tx;
@ -274,6 +284,9 @@ int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout)
LOGD("SPI: timed out waiting for ACK"); LOGD("SPI: timed out waiting for ACK");
return SpiError::ACK_TIMEOUT; return SpiError::ACK_TIMEOUT;
} }
// backoff
transfer.delay_usecs = std::clamp(transfer.delay_usecs*2, 10, 250);
} }
return 0; return 0;

Loading…
Cancel
Save