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