|  |  | @ -28,13 +28,6 @@ enum SpiError { | 
			
		
	
		
		
			
				
					
					|  |  |  |   ACK_TIMEOUT = -3, |  |  |  |   ACK_TIMEOUT = -3, | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | struct __attribute__((packed)) spi_header { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint8_t sync; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint8_t endpoint; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint16_t tx_len; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   uint16_t max_rx_len; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | const unsigned int SPI_ACK_TIMEOUT = 500; // milliseconds
 |  |  |  | const unsigned int SPI_ACK_TIMEOUT = 500; // milliseconds
 | 
			
		
	
		
		
			
				
					
					|  |  |  | const std::string SPI_DEVICE = "/dev/spidev0.0"; |  |  |  | const std::string SPI_DEVICE = "/dev/spidev0.0"; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -55,6 +48,11 @@ private: | 
			
		
	
		
		
			
				
					
					|  |  |  |   std::recursive_mutex &m; |  |  |  |   std::recursive_mutex &m; | 
			
		
	
		
		
			
				
					
					|  |  |  | }; |  |  |  | }; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | #define SPILOG(fn, fmt, ...) do {  \ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       fn(fmt, ## __VA_ARGS__);     \
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       fn("  %d / 0x%x / %d / %d", \
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |          xfer_count, header.endpoint, header.tx_len, header.max_rx_len); \
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |       } while(0) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { |  |  |  | PandaSpiHandle::PandaSpiHandle(std::string serial) : PandaCommsHandle(serial) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   int ret; |  |  |  |   int ret; | 
			
		
	
	
		
		
			
				
					|  |  | @ -178,7 +176,7 @@ int PandaSpiHandle::bulk_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t t | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (d < 0) { |  |  |  |     if (d < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       LOGE("SPI: bulk transfer failed with %d", d); |  |  |  |       SPILOG(LOGE, "SPI: bulk transfer failed with %d", d); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       comms_healthy = false; |  |  |  |       comms_healthy = false; | 
			
		
	
		
		
			
				
					
					|  |  |  |       return d; |  |  |  |       return d; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
	
		
		
			
				
					|  |  | @ -247,7 +245,7 @@ int PandaSpiHandle::spi_transfer_retry(uint8_t endpoint, uint8_t *tx_data, uint1 | 
			
		
	
		
		
			
				
					
					|  |  |  |   } 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", timeout_count, millis_since_boot() - start_time); |  |  |  |     SPILOG(LOGE, "transfer failed, after %d tries, %.2fms", timeout_count, millis_since_boot() - start_time); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   return ret; |  |  |  |   return ret; | 
			
		
	
	
		
		
			
				
					|  |  | @ -270,20 +268,20 @@ int PandaSpiHandle::wait_for_ack(uint8_t ack, uint8_t tx, unsigned int timeout, | 
			
		
	
		
		
			
				
					
					|  |  |  |   while (true) { |  |  |  |   while (true) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     int ret = lltransfer(transfer); |  |  |  |     int ret = lltransfer(transfer); | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (ret < 0) { |  |  |  |     if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       LOGE("SPI: failed to send ACK request"); |  |  |  |       SPILOG(LOGE, "SPI: failed to send ACK request"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       return ret; |  |  |  |       return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (rx_buf[0] == ack) { |  |  |  |     if (rx_buf[0] == ack) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       break; |  |  |  |       break; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } else if (rx_buf[0] == SPI_NACK) { |  |  |  |     } else if (rx_buf[0] == SPI_NACK) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       LOGD("SPI: got NACK"); |  |  |  |       SPILOG(LOGD, "SPI: got NACK"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       return SpiError::NACK; |  |  |  |       return SpiError::NACK; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // handle timeout
 |  |  |  |     // handle timeout
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (millis_since_boot() - start_millis > timeout) { |  |  |  |     if (millis_since_boot() - start_millis > timeout) { | 
			
		
	
		
		
			
				
					
					|  |  |  |       LOGD("SPI: timed out waiting for ACK"); |  |  |  |       SPILOG(LOGW, "SPI: timed out waiting for ACK"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |       return SpiError::ACK_TIMEOUT; |  |  |  |       return SpiError::ACK_TIMEOUT; | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |     } | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
	
		
		
			
				
					|  |  | @ -334,7 +332,8 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
			
		
	
		
		
			
				
					
					|  |  |  |   assert(tx_len < SPI_BUF_SIZE); |  |  |  |   assert(tx_len < SPI_BUF_SIZE); | 
			
		
	
		
		
			
				
					
					|  |  |  |   assert(max_rx_len < SPI_BUF_SIZE); |  |  |  |   assert(max_rx_len < SPI_BUF_SIZE); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   spi_header header = { |  |  |  |   xfer_count++; | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   header = { | 
			
		
	
		
		
			
				
					
					|  |  |  |     .sync = SPI_SYNC, |  |  |  |     .sync = SPI_SYNC, | 
			
		
	
		
		
			
				
					
					|  |  |  |     .endpoint = endpoint, |  |  |  |     .endpoint = endpoint, | 
			
		
	
		
		
			
				
					
					|  |  |  |     .tx_len = tx_len, |  |  |  |     .tx_len = tx_len, | 
			
		
	
	
		
		
			
				
					|  |  | @ -352,7 +351,7 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
			
		
	
		
		
			
				
					
					|  |  |  |   transfer.len = sizeof(header) + 1; |  |  |  |   transfer.len = sizeof(header) + 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = lltransfer(transfer); |  |  |  |   ret = lltransfer(transfer); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ret < 0) { |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("SPI: failed to send header"); |  |  |  |     SPILOG(LOGE, "SPI: failed to send header"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return ret; |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -370,7 +369,7 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
			
		
	
		
		
			
				
					
					|  |  |  |   transfer.len = tx_len + 1; |  |  |  |   transfer.len = tx_len + 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = lltransfer(transfer); |  |  |  |   ret = lltransfer(transfer); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ret < 0) { |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("SPI: failed to send data"); |  |  |  |     SPILOG(LOGE, "SPI: failed to send data"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return ret; |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -383,7 +382,7 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Read data
 |  |  |  |   // Read data
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   rx_data_len = *(uint16_t *)(rx_buf+1); |  |  |  |   rx_data_len = *(uint16_t *)(rx_buf+1); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (rx_data_len >= SPI_BUF_SIZE) { |  |  |  |   if (rx_data_len >= SPI_BUF_SIZE) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("SPI: RX data len larger than buf size %d", rx_data_len); |  |  |  |     SPILOG(LOGE, "SPI: RX data len larger than buf size %d", rx_data_len); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return -1; |  |  |  |     return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -391,11 +390,11 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx | 
			
		
	
		
		
			
				
					
					|  |  |  |   transfer.rx_buf = (uint64_t)(rx_buf + 2 + 1); |  |  |  |   transfer.rx_buf = (uint64_t)(rx_buf + 2 + 1); | 
			
		
	
		
		
			
				
					
					|  |  |  |   ret = lltransfer(transfer); |  |  |  |   ret = lltransfer(transfer); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (ret < 0) { |  |  |  |   if (ret < 0) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("SPI: failed to read rx data"); |  |  |  |     SPILOG(LOGE, "SPI: failed to read rx data"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return ret; |  |  |  |     return ret; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!check_checksum(rx_buf, rx_data_len + 4)) { |  |  |  |   if (!check_checksum(rx_buf, rx_data_len + 4)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     LOGE("SPI: bad checksum"); |  |  |  |     SPILOG(LOGE, "SPI: bad checksum"); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |     return -1; |  |  |  |     return -1; | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | 
 |