@@ -50,8 +50,9 @@ class LockEx {
5050
5151#define SPILOG (fn, fmt, ...) do { \
5252 fn (fmt, ## __VA_ARGS__); \
53- fn (" %d / 0x%x / %d / %d" , \
54- xfer_count, header.endpoint , header.tx_len , header.max_rx_len ); \
53+ fn (" %d / 0x%x / %d / %d / tx: %s" , \
54+ xfer_count, header.endpoint , header.tx_len , header.max_rx_len , \
55+ util::hexdump (tx_buf, std::min ((int )header.tx_len , 8 )).c_str ()); \
5556 } while (0 )
5657
5758PandaSpiHandle::PandaSpiHandle (std::string serial) : PandaCommsHandle(serial) {
@@ -238,6 +239,7 @@ int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint1
238239 // due to full TX buffers
239240 nack_count += 1 ;
240241 if (nack_count > 3 ) {
242+ SPILOG (LOGE, " NACK sleep %d" , nack_count);
241243 usleep (std::clamp (nack_count*10 , 200 , 2000 ));
242244 }
243245 }
@@ -256,14 +258,14 @@ int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout,
256258 if (timeout == 0 ) {
257259 timeout = SPI_ACK_TIMEOUT;
258260 }
259- timeout = std::clamp (timeout, 100U , SPI_ACK_TIMEOUT);
261+ timeout = std::clamp (timeout, 20U , SPI_ACK_TIMEOUT);
260262
261263 spi_ioc_transfer transfer = {
262264 .tx_buf = (uint64_t )tx_buf,
263265 .rx_buf = (uint64_t )rx_buf,
264- .len = length
266+ .len = length,
265267 };
266- tx_buf[ 0 ] = tx ;
268+ memset ( tx_buf, tx, length) ;
267269
268270 while (true ) {
269271 int ret = lltransfer (transfer);
@@ -275,13 +277,13 @@ int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout,
275277 if (rx_buf[0 ] == ack) {
276278 break ;
277279 } else if (rx_buf[0 ] == SPI_NACK) {
278- SPILOG (LOGD, " SPI: got NACK" );
280+ SPILOG (LOGD, " SPI: got NACK, waiting for 0x%x " , ack );
279281 return SpiError::NACK;
280282 }
281283
282284 // handle timeout
283285 if (millis_since_boot () - start_millis > timeout) {
284- SPILOG (LOGW, " SPI: timed out waiting for ACK" );
286+ SPILOG (LOGW, " SPI: timed out waiting for ACK, waiting for 0x%x " , ack );
285287 return SpiError::ACK_TIMEOUT;
286288 }
287289 }
@@ -352,13 +354,13 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx
352354 ret = lltransfer (transfer);
353355 if (ret < 0 ) {
354356 SPILOG (LOGE, " SPI: failed to send header" );
355- return ret ;
357+ goto fail ;
356358 }
357359
358360 // Wait for (N)ACK
359361 ret = wait_for_ack (SPI_HACK, 0x11 , timeout, 1 );
360362 if (ret < 0 ) {
361- return ret ;
363+ goto fail ;
362364 }
363365
364366 // Send data
@@ -370,38 +372,53 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx
370372 ret = lltransfer (transfer);
371373 if (ret < 0 ) {
372374 SPILOG (LOGE, " SPI: failed to send data" );
373- return ret ;
375+ goto fail ;
374376 }
375377
376378 // Wait for (N)ACK
377379 ret = wait_for_ack (SPI_DACK, 0x13 , timeout, 3 );
378380 if (ret < 0 ) {
379- return ret ;
381+ goto fail ;
380382 }
381383
382384 // Read data
383385 rx_data_len = *(uint16_t *)(rx_buf+1 );
384386 if (rx_data_len >= SPI_BUF_SIZE) {
385387 SPILOG (LOGE, " SPI: RX data len larger than buf size %d" , rx_data_len);
386- return - 1 ;
388+ goto fail ;
387389 }
388390
389391 transfer.len = rx_data_len + 1 ;
390392 transfer.rx_buf = (uint64_t )(rx_buf + 2 + 1 );
391393 ret = lltransfer (transfer);
392394 if (ret < 0 ) {
393395 SPILOG (LOGE, " SPI: failed to read rx data" );
394- return ret ;
396+ goto fail ;
395397 }
396398 if (!check_checksum (rx_buf, rx_data_len + 4 )) {
397399 SPILOG (LOGE, " SPI: bad checksum" );
398- return - 1 ;
400+ goto fail ;
399401 }
400402
401403 if (rx_data != NULL ) {
402404 memcpy (rx_data, rx_buf + 3 , rx_data_len);
403405 }
404406
405407 return rx_data_len;
408+
409+ fail:
410+ // ensure slave is in a consistent state
411+ // and ready for the next transfer
412+ int nack_cnt = 0 ;
413+ while (nack_cnt < 3 ) {
414+ if (wait_for_ack (SPI_NACK, 0x14 , 1 , SPI_BUF_SIZE/2 ) == 0 ) {
415+ nack_cnt += 1 ;
416+ } else {
417+ nack_cnt = 0 ;
418+ }
419+ }
420+
421+ if (ret > 0 ) ret = -1 ;
422+ return ret;
406423}
407424#endif
0 commit comments