From 480c0b7b1073763ac00303057be757293bee52ea Mon Sep 17 00:00:00 2001 From: Comma Device Date: Thu, 15 Jan 2026 17:00:10 +0000 Subject: [PATCH 01/17] working on debugging --- board/config.h | 2 +- board/drivers/spi.h | 1 + board/drivers/spi_declarations.h | 13 ++--- board/stm32h7/llspi.h | 83 ++++++++++++++++++++++++++------ 4 files changed, 76 insertions(+), 23 deletions(-) diff --git a/board/config.h b/board/config.h index 1b7d938cc81..d488a31f738 100644 --- a/board/config.h +++ b/board/config.h @@ -5,7 +5,7 @@ //#define DEBUG //#define DEBUG_UART //#define DEBUG_USB -//#define DEBUG_SPI +#define DEBUG_SPI //#define DEBUG_FAULTS //#define DEBUG_COMMS //#define DEBUG_FAN diff --git a/board/drivers/spi.h b/board/drivers/spi.h index d291fe06a8d..e155cb976a8 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -101,6 +101,7 @@ void spi_rx_done(void) { // response: NACK and reset state machine #ifdef DEBUG_SPI print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); + //llspi_dump_state(); #endif spi_buf_tx[0] = SPI_NACK; next_rx_state = SPI_STATE_HEADER_NACK; diff --git a/board/drivers/spi_declarations.h b/board/drivers/spi_declarations.h index 23254f0e87a..8926e7e2716 100644 --- a/board/drivers/spi_declarations.h +++ b/board/drivers/spi_declarations.h @@ -21,12 +21,12 @@ __attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE]; // SPI states enum { - SPI_STATE_HEADER, - SPI_STATE_HEADER_ACK, - SPI_STATE_HEADER_NACK, - SPI_STATE_DATA_RX, - SPI_STATE_DATA_RX_ACK, - SPI_STATE_DATA_TX + SPI_STATE_HEADER = 0U, + SPI_STATE_HEADER_ACK = 1U, + SPI_STATE_HEADER_NACK = 2U, + SPI_STATE_DATA_RX = 3U, + SPI_STATE_DATA_RX_ACK = 4U, + SPI_STATE_DATA_TX = 5U }; extern uint16_t spi_error_count; @@ -35,6 +35,7 @@ extern uint16_t spi_error_count; // low level SPI prototypes void llspi_init(void); +void llspi_dump_state(void); void llspi_mosi_dma(uint8_t *addr, int len); void llspi_miso_dma(uint8_t *addr, int len); diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 05f8e22f9a8..fd7ec750b94 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -1,10 +1,32 @@ -// master -> panda DMA start -void llspi_mosi_dma(uint8_t *addr, int len) { - // disable DMA + SPI - register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + +void llspi_dump_state(void){ + print(" STATE: "); puth(spi_state); print("\n"); + print(" SPI4 CR1: "); puth(SPI4->CR1); + print(" CR2: "); puth(SPI4->CR2); + print(" SR: "); puth(SPI4->SR); + print(" IER: "); puth(SPI4->IER); + print(" CFG1: "); puth(SPI4->CFG1); + print(" CFG2: "); puth(SPI4->CFG2); + print("\n"); + // print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); + // print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); + print(" DMA2 Stream3 CR: "); puth(DMA2_Stream3->CR); + print(" NDTR: "); puth(DMA2_Stream3->NDTR); + print("\n\n"); +} + +static void llspi_disable(void) { + // disable DMA + SPI DMA2_Stream2->CR &= ~DMA_SxCR_EN; + DMA2_Stream3->CR &= ~DMA_SxCR_EN; + while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); + while((DMA2_Stream3->CR & DMA_SxCR_EN) != 0U); register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); +} +// master -> panda DMA start +void llspi_mosi_dma(uint8_t *addr, int len) { // drain the bus while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; @@ -13,7 +35,10 @@ void llspi_mosi_dma(uint8_t *addr, int len) { // clear all pending SPI4->IFCR |= (0x1FFU << 3U); - register_set(&(SPI4->IER), 0, 0x3FFU); + register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); + + // simplex receive mode + register_set(&(SPI4->CFG2), (0b10 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); // setup destination and length register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); @@ -27,11 +52,6 @@ void llspi_mosi_dma(uint8_t *addr, int len) { // panda -> master DMA start void llspi_miso_dma(uint8_t *addr, int len) { - // disable DMA + SPI - DMA2_Stream3->CR &= ~DMA_SxCR_EN; - register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); - register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); - // setup source and length register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); DMA2_Stream3->NDTR = len; @@ -39,12 +59,15 @@ void llspi_miso_dma(uint8_t *addr, int len) { // clear under-run while we were reading SPI4->IFCR |= (0x1FFU << 3U); + // simplex transmit mode + register_set(&(SPI4->CFG2), (0b01 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); + // setup interrupt on TXC - register_set(&(SPI4->IER), (1U << SPI_IER_EOTIE_Pos), 0x3FFU); + register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); // enable DMA + SPI - register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); DMA2_Stream3->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); } @@ -54,6 +77,8 @@ static void DMA2_Stream2_IRQ_Handler(void) { // Clear interrupt flag DMA2->LIFCR = DMA_LIFCR_CTCIF2; + llspi_disable(); + spi_rx_done(); } @@ -72,9 +97,35 @@ static void SPI4_IRQ_Handler(void) { // clear flag SPI4->IFCR |= (0x1FFU << 3U); - if (spi_tx_dma_done && ((SPI4->SR & SPI_SR_TXC) != 0U)) { - spi_tx_dma_done = false; - spi_tx_done(false); + if ((SPI4->SR & SPI_SR_TXC) != 0U) { + if (spi_tx_dma_done) { + llspi_disable(); + + spi_tx_dma_done = false; + spi_tx_done(false); + } else if (spi_state == SPI_STATE_DATA_TX) { + // spurious TXC interrupt + #ifdef DEBUG_SPI + print("SPI: spurious TXC\n"); + llspi_dump_state(); + #endif + } + } + + if ((SPI4->SR & SPI_SR_UDR) != 0U) { + // under-run occurred + #ifdef DEBUG_SPI + print("SPI: underrun "); puth(spi_tx_dma_done); print("\n"); + llspi_dump_state(); + #endif + } + + if ((SPI4->SR & SPI_SR_OVR) != 0U) { + // over-run occurred + #ifdef DEBUG_SPI + print("SPI: overrun\n"); + llspi_dump_state(); + #endif } } @@ -95,7 +146,7 @@ void llspi_init(void) { register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); // Enable SPI - register_set(&(SPI4->IER), 0, 0x3FFU); + register_set(&(SPI4->IER), SPI_IER_OVRIE | SPI_IER_UDRIE, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging register_set(&(SPI4->CR1), SPI_CR1_SPE, 0xFFFFU); From 5c2a3ea18d53eb104243e99ddb81a2c229d3e3e0 Mon Sep 17 00:00:00 2001 From: Comma Device Date: Fri, 16 Jan 2026 15:24:36 +0000 Subject: [PATCH 02/17] makes it better --- board/drivers/spi.h | 2 ++ board/stm32h7/llspi.h | 34 +++++++++++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index e155cb976a8..21e85655547 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -201,6 +201,7 @@ void spi_rx_done(void) { llspi_miso_dma(spi_buf_tx, response_len); spi_state = next_rx_state; + //puth(spi_state); print(" RX\n"); if (!checksum_valid) { spi_error_count += 1U; } @@ -224,6 +225,7 @@ void spi_tx_done(bool reset) { llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); } + //puth(spi_state); print(" TX\n"); } void can_tx_comms_resume_spi(void) { diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index fd7ec750b94..0e55f93de40 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -8,8 +8,8 @@ void llspi_dump_state(void){ print(" CFG1: "); puth(SPI4->CFG1); print(" CFG2: "); puth(SPI4->CFG2); print("\n"); - // print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); - // print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); + print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); + print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); print(" DMA2 Stream3 CR: "); puth(DMA2_Stream3->CR); print(" NDTR: "); puth(DMA2_Stream3->NDTR); print("\n\n"); @@ -21,17 +21,22 @@ static void llspi_disable(void) { DMA2_Stream3->CR &= ~DMA_SxCR_EN; while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); while((DMA2_Stream3->CR & DMA_SxCR_EN) != 0U); - register_clear_bits(&(SPI4->CR1), SPI_CR1_SPE); + SPI4->CR1 &= ~SPI_CR1_SPE; register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); } // master -> panda DMA start void llspi_mosi_dma(uint8_t *addr, int len) { // drain the bus + bool found_any = false; while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; + puth(dat); print(" "); (void)dat; + found_any = true; } + if (found_any) + print("\n"); // clear all pending SPI4->IFCR |= (0x1FFU << 3U); @@ -42,19 +47,23 @@ void llspi_mosi_dma(uint8_t *addr, int len) { // setup destination and length register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + SPI4->CR2 = 0U; DMA2_Stream2->NDTR = len; // enable DMA + SPI DMA2_Stream2->CR |= DMA_SxCR_EN; register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); - register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); + SPI4->CR1 |= SPI_CR1_SPE; } // panda -> master DMA start void llspi_miso_dma(uint8_t *addr, int len) { // setup source and length register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); + //print("TX len "); puth(len); print("\n"); DMA2_Stream3->NDTR = len; + + // puth(len); print(" "); puth(SPI4->SR >> 16U); print("\n"); // clear under-run while we were reading SPI4->IFCR |= (0x1FFU << 3U); @@ -67,8 +76,9 @@ void llspi_miso_dma(uint8_t *addr, int len) { // enable DMA + SPI DMA2_Stream3->CR |= DMA_SxCR_EN; - register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); - register_set_bits(&(SPI4->CR1), SPI_CR1_SPE); + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + SPI4->CR2 = len; + SPI4->CR1 |= SPI_CR1_SPE; } static bool spi_tx_dma_done = false; @@ -94,10 +104,9 @@ static void DMA2_Stream3_IRQ_Handler(void) { // panda TX finished static void SPI4_IRQ_Handler(void) { - // clear flag - SPI4->IFCR |= (0x1FFU << 3U); + //print("IRQ SR: "); puth(SPI4->SR); print("\n"); - if ((SPI4->SR & SPI_SR_TXC) != 0U) { + if ((SPI4->SR & SPI_SR_EOT) != 0U) { if (spi_tx_dma_done) { llspi_disable(); @@ -127,6 +136,9 @@ static void SPI4_IRQ_Handler(void) { llspi_dump_state(); #endif } + + // clear flag + SPI4->IFCR |= (0x1FFU << 3U); } @@ -148,9 +160,9 @@ void llspi_init(void) { // Enable SPI register_set(&(SPI4->IER), SPI_IER_OVRIE | SPI_IER_UDRIE, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); + register_set_bits(&(SPI4->CFG2), SPI_CFG2_AFCNTR); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging - register_set(&(SPI4->CR1), SPI_CR1_SPE, 0xFFFFU); - register_set(&(SPI4->CR2), 0, 0xFFFFU); + SPI4->CR2 = 0U; NVIC_EnableIRQ(DMA2_Stream2_IRQn); NVIC_EnableIRQ(DMA2_Stream3_IRQn); From 3ae80eb1e2b83e2ee8dc33c02e166499fc87ff6b Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Mon, 19 Jan 2026 16:57:45 +0100 Subject: [PATCH 03/17] should be close --- board/drivers/spi.h | 215 +++++++++++++++++++++++------- board/drivers/spi_declarations.h | 12 +- board/stm32h7/llspi.h | 216 ++++++++++++++++++++----------- 3 files changed, 313 insertions(+), 130 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 21e85655547..fa8170e9ff9 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -63,7 +63,7 @@ void spi_init(void) { // Start the first packet! spi_state = SPI_STATE_HEADER; - llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); + llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); } static bool validate_checksum(const uint8_t *data, uint16_t len) { @@ -75,9 +75,161 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { return checksum == 0U; } -void spi_rx_done(void) { - uint16_t response_len = 0U; - uint8_t next_rx_state = SPI_STATE_HEADER_NACK; +// void spi_rx_done(void) { +// uint16_t response_len = 0U; +// uint8_t next_rx_state = SPI_STATE_HEADER_NACK; +// bool checksum_valid = false; +// static uint8_t spi_endpoint; +// static uint16_t spi_data_len_miso; + +// // parse header +// spi_endpoint = spi_buf_rx[1]; +// spi_data_len_mosi = (spi_buf_rx[3] << 8) | spi_buf_rx[2]; +// spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; + +// if (memcmp(spi_buf_rx, version_text, 7) == 0) { +// response_len = spi_version_packet(spi_buf_tx); +// next_rx_state = SPI_STATE_HEADER_NACK;; +// } else if (spi_state == SPI_STATE_HEADER) { +// checksum_valid = validate_checksum(spi_buf_rx, SPI_HEADER_SIZE); +// if ((spi_buf_rx[0] == SPI_SYNC_BYTE) && checksum_valid) { +// // response: ACK and start receiving data portion +// spi_buf_tx[0] = SPI_HACK; +// next_rx_state = SPI_STATE_HEADER_ACK; +// response_len = 1U; +// } else { +// // response: NACK and reset state machine +// #ifdef DEBUG_SPI +// print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); +// //llspi_dump_state(); +// #endif +// spi_buf_tx[0] = SPI_NACK; +// next_rx_state = SPI_STATE_HEADER_NACK; +// response_len = 1U; +// } +// } else if (spi_state == SPI_STATE_DATA_RX) { +// // We got everything! Based on the endpoint specified, call the appropriate handler +// bool response_ack = false; +// checksum_valid = validate_checksum(&(spi_buf_rx[SPI_HEADER_SIZE]), spi_data_len_mosi + 1U); +// if (checksum_valid) { +// if (spi_endpoint == 0U) { +// if (spi_data_len_mosi >= sizeof(ControlPacket_t)) { +// ControlPacket_t ctrl = {0}; +// (void)memcpy((uint8_t*)&ctrl, &spi_buf_rx[SPI_HEADER_SIZE], sizeof(ControlPacket_t)); +// response_len = comms_control_handler(&ctrl, &spi_buf_tx[3]); +// response_ack = true; +// } else { +// print("SPI: insufficient data for control handler\n"); +// } +// } else if ((spi_endpoint == 1U) || (spi_endpoint == 0x81U)) { +// if (spi_data_len_mosi == 0U) { +// response_len = comms_can_read(&(spi_buf_tx[3]), spi_data_len_miso); +// response_ack = true; +// } else { +// print("SPI: did not expect data for can_read\n"); +// } +// } else if (spi_endpoint == 2U) { +// comms_endpoint2_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); +// response_ack = true; +// } else if (spi_endpoint == 3U) { +// if (spi_data_len_mosi > 0U) { +// if (spi_can_tx_ready) { +// spi_can_tx_ready = false; +// comms_can_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); +// response_ack = true; +// } else { +// response_ack = false; +// print("SPI: CAN NACK\n"); +// } +// } else { +// print("SPI: did expect data for can_write\n"); +// } +// } else if (spi_endpoint == 0xABU) { +// // test endpoint: mimics panda -> device transfer +// response_len = spi_data_len_miso; +// response_ack = true; +// } else if (spi_endpoint == 0xACU) { +// // test endpoint: mimics device -> panda transfer (with NACK) +// response_ack = false; +// } else { +// print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n"); +// } +// } else { +// // Checksum was incorrect +// response_ack = false; +// #ifdef DEBUG_SPI +// print("- incorrect data checksum "); +// puth4(spi_data_len_mosi); +// print("\n"); +// hexdump(spi_buf_rx, SPI_HEADER_SIZE); +// hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); +// print("\n"); +// #endif +// } + +// if (!response_ack) { +// spi_buf_tx[0] = SPI_NACK; +// next_rx_state = SPI_STATE_HEADER_NACK; +// response_len = 1U; +// } else { +// // Setup response header +// spi_buf_tx[0] = SPI_DACK; +// spi_buf_tx[1] = response_len & 0xFFU; +// spi_buf_tx[2] = (response_len >> 8) & 0xFFU; + +// // Add checksum +// uint8_t checksum = SPI_CHECKSUM_START; +// for(uint16_t i = 0U; i < (response_len + 3U); i++) { +// checksum ^= spi_buf_tx[i]; +// } +// spi_buf_tx[response_len + 3U] = checksum; +// response_len += 4U; + +// next_rx_state = SPI_STATE_DATA_TX; +// } +// } else { +// print("SPI: RX unexpected state: "); puth(spi_state); print("\n"); +// } + +// // send out response +// if (response_len == 0U) { +// print("SPI: no response\n"); +// spi_buf_tx[0] = SPI_NACK; +// spi_state = SPI_STATE_HEADER_NACK; +// response_len = 1U; +// } +// llspi_miso_dma(spi_buf_tx, response_len); + +// spi_state = next_rx_state; +// //puth(spi_state); print(" RX\n"); +// if (!checksum_valid) { +// spi_error_count += 1U; +// } +// } + +// void spi_tx_done(bool reset) { +// if ((spi_state == SPI_STATE_HEADER_NACK) || reset) { +// // Reset state +// spi_state = SPI_STATE_HEADER; +// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); +// } else if (spi_state == SPI_STATE_HEADER_ACK) { +// // ACK was sent, queue up the RX buf for the data + checksum +// spi_state = SPI_STATE_DATA_RX; +// llspi_mosi_dma(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); +// } else if (spi_state == SPI_STATE_DATA_TX) { +// // Reset state +// spi_state = SPI_STATE_HEADER; +// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); +// } else { +// spi_state = SPI_STATE_HEADER; +// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); +// print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); +// } +// //puth(spi_state); print(" TX\n"); +// } + +void spi_done(void) { + uint8_t next_rx_state = SPI_STATE_HEADER; bool checksum_valid = false; static uint8_t spi_endpoint; static uint16_t spi_data_len_miso; @@ -88,15 +240,17 @@ void spi_rx_done(void) { spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; if (memcmp(spi_buf_rx, version_text, 7) == 0) { - response_len = spi_version_packet(spi_buf_tx); - next_rx_state = SPI_STATE_HEADER_NACK;; + print("GOT VERSION REQUEST\n"); + llspi_dma(spi_buf_tx, spi_version_packet(spi_buf_tx), spi_buf_rx, SPI_HEADER_SIZE); + next_rx_state = SPI_STATE_HEADER; } else if (spi_state == SPI_STATE_HEADER) { checksum_valid = validate_checksum(spi_buf_rx, SPI_HEADER_SIZE); if ((spi_buf_rx[0] == SPI_SYNC_BYTE) && checksum_valid) { // response: ACK and start receiving data portion spi_buf_tx[0] = SPI_HACK; - next_rx_state = SPI_STATE_HEADER_ACK; - response_len = 1U; + llspi_dma(spi_buf_tx, 1U, &spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); + next_rx_state = SPI_STATE_DATA; + } else { // response: NACK and reset state machine #ifdef DEBUG_SPI @@ -104,12 +258,13 @@ void spi_rx_done(void) { //llspi_dump_state(); #endif spi_buf_tx[0] = SPI_NACK; - next_rx_state = SPI_STATE_HEADER_NACK; - response_len = 1U; + llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); + next_rx_state = SPI_STATE_HEADER; } - } else if (spi_state == SPI_STATE_DATA_RX) { + } else if (spi_state == SPI_STATE_DATA) { // We got everything! Based on the endpoint specified, call the appropriate handler bool response_ack = false; + uint16_t response_len = 0U; checksum_valid = validate_checksum(&(spi_buf_rx[SPI_HEADER_SIZE]), spi_data_len_mosi + 1U); if (checksum_valid) { if (spi_endpoint == 0U) { @@ -169,8 +324,8 @@ void spi_rx_done(void) { if (!response_ack) { spi_buf_tx[0] = SPI_NACK; - next_rx_state = SPI_STATE_HEADER_NACK; - response_len = 1U; + llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); + next_rx_state = SPI_STATE_HEADER; } else { // Setup response header spi_buf_tx[0] = SPI_DACK; @@ -185,49 +340,19 @@ void spi_rx_done(void) { spi_buf_tx[response_len + 3U] = checksum; response_len += 4U; - next_rx_state = SPI_STATE_DATA_TX; + llspi_dma(spi_buf_tx, response_len, spi_buf_rx, SPI_HEADER_SIZE); + next_rx_state = SPI_STATE_HEADER; } } else { print("SPI: RX unexpected state: "); puth(spi_state); print("\n"); } - // send out response - if (response_len == 0U) { - print("SPI: no response\n"); - spi_buf_tx[0] = SPI_NACK; - spi_state = SPI_STATE_HEADER_NACK; - response_len = 1U; - } - llspi_miso_dma(spi_buf_tx, response_len); - spi_state = next_rx_state; - //puth(spi_state); print(" RX\n"); if (!checksum_valid) { spi_error_count += 1U; } } -void spi_tx_done(bool reset) { - if ((spi_state == SPI_STATE_HEADER_NACK) || reset) { - // Reset state - spi_state = SPI_STATE_HEADER; - llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); - } else if (spi_state == SPI_STATE_HEADER_ACK) { - // ACK was sent, queue up the RX buf for the data + checksum - spi_state = SPI_STATE_DATA_RX; - llspi_mosi_dma(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); - } else if (spi_state == SPI_STATE_DATA_TX) { - // Reset state - spi_state = SPI_STATE_HEADER; - llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); - } else { - spi_state = SPI_STATE_HEADER; - llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); - print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); - } - //puth(spi_state); print(" TX\n"); -} - void can_tx_comms_resume_spi(void) { spi_can_tx_ready = true; } diff --git a/board/drivers/spi_declarations.h b/board/drivers/spi_declarations.h index 8926e7e2716..8da191c4f56 100644 --- a/board/drivers/spi_declarations.h +++ b/board/drivers/spi_declarations.h @@ -22,11 +22,7 @@ __attribute__((section(".sram12"))) extern uint8_t spi_buf_tx[SPI_BUF_SIZE]; // SPI states enum { SPI_STATE_HEADER = 0U, - SPI_STATE_HEADER_ACK = 1U, - SPI_STATE_HEADER_NACK = 2U, - SPI_STATE_DATA_RX = 3U, - SPI_STATE_DATA_RX_ACK = 4U, - SPI_STATE_DATA_TX = 5U + SPI_STATE_DATA = 1U }; extern uint16_t spi_error_count; @@ -36,10 +32,8 @@ extern uint16_t spi_error_count; // low level SPI prototypes void llspi_init(void); void llspi_dump_state(void); -void llspi_mosi_dma(uint8_t *addr, int len); -void llspi_miso_dma(uint8_t *addr, int len); +void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len); void can_tx_comms_resume_spi(void); void spi_init(void); -void spi_rx_done(void); -void spi_tx_done(bool reset); +void spi_done(void); diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 0e55f93de40..ae78a729c64 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -11,12 +11,12 @@ void llspi_dump_state(void){ print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); print(" DMA2 Stream3 CR: "); puth(DMA2_Stream3->CR); - print(" NDTR: "); puth(DMA2_Stream3->NDTR); + print(" NDTR: "); puth(DMA2_Stream3->NDTR); print("\n\n"); } static void llspi_disable(void) { - // disable DMA + SPI + // disable DMA + SPI DMA2_Stream2->CR &= ~DMA_SxCR_EN; DMA2_Stream3->CR &= ~DMA_SxCR_EN; while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); @@ -25,118 +25,181 @@ static void llspi_disable(void) { register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); } -// master -> panda DMA start -void llspi_mosi_dma(uint8_t *addr, int len) { +static uint8_t *llspi_rx_addr; +static int llspi_rx_len, llspi_tx_len; + +void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { + print("\nLLSPI DMA TX len "); puth(tx_len); print(" RX len "); puth(rx_len); print("\n"); + + // set global for later use + llspi_rx_addr = rx_addr; + llspi_rx_len = rx_len; + llspi_tx_len = tx_len; + // drain the bus - bool found_any = false; while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; - puth(dat); print(" "); (void)dat; - found_any = true; } - if (found_any) - print("\n"); // clear all pending SPI4->IFCR |= (0x1FFU << 3U); register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); - // simplex receive mode - register_set(&(SPI4->CFG2), (0b10 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); + // setup destinations and length + int total_len = tx_len + rx_len; - // setup destination and length - register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); - SPI4->CR2 = 0U; - DMA2_Stream2->NDTR = len; - - // enable DMA + SPI - DMA2_Stream2->CR |= DMA_SxCR_EN; - register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); - SPI4->CR1 |= SPI_CR1_SPE; -} - -// panda -> master DMA start -void llspi_miso_dma(uint8_t *addr, int len) { - // setup source and length - register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); - //print("TX len "); puth(len); print("\n"); - DMA2_Stream3->NDTR = len; - - // puth(len); print(" "); puth(SPI4->SR >> 16U); print("\n"); + if (tx_len > 0) { + print("TX: "); hexdump(tx_addr, tx_len); + register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); + DMA2_Stream3->NDTR = tx_len; + } - // clear under-run while we were reading - SPI4->IFCR |= (0x1FFU << 3U); + register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = total_len; + //SPI4->CR2 = total_len; + SPI4->CR2 = 0U; - // simplex transmit mode - register_set(&(SPI4->CFG2), (0b01 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); + // setup interrupt on EOT + //register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); - // setup interrupt on TXC - register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); + // enable DMAs + SPI + DMA2_Stream2->CR |= DMA_SxCR_EN; + if (tx_len > 0) { + DMA2_Stream3->CR |= DMA_SxCR_EN; + } - // enable DMA + SPI - DMA2_Stream3->CR |= DMA_SxCR_EN; - register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); - SPI4->CR2 = len; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN); SPI4->CR1 |= SPI_CR1_SPE; + + // TODO: check that the rx buffer is large enough } -static bool spi_tx_dma_done = false; +// // master -> panda DMA start +// void llspi_mosi_dma(uint8_t *addr, int len) { +// // drain the bus +// bool found_any = false; +// while ((SPI4->SR & SPI_SR_RXP) != 0U) { +// volatile uint8_t dat = SPI4->RXDR; +// puth(dat); print(" "); +// (void)dat; +// found_any = true; +// } +// if (found_any) +// print("\n"); + +// // clear all pending +// SPI4->IFCR |= (0x1FFU << 3U); +// register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); + +// // simplex receive mode +// register_set(&(SPI4->CFG2), (0b10 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); + +// // setup destination and length +// register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); +// SPI4->CR2 = 0U; +// DMA2_Stream2->NDTR = len; + +// // enable DMA + SPI +// DMA2_Stream2->CR |= DMA_SxCR_EN; +// register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); +// SPI4->CR1 |= SPI_CR1_SPE; +// } + +// // panda -> master DMA start +// void llspi_miso_dma(uint8_t *addr, int len) { +// // setup source and length +// register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); +// //print("TX len "); puth(len); print("\n"); +// DMA2_Stream3->NDTR = len; + +// // puth(len); print(" "); puth(SPI4->SR >> 16U); print("\n"); + +// // clear under-run while we were reading +// SPI4->IFCR |= (0x1FFU << 3U); + +// // simplex transmit mode +// register_set(&(SPI4->CFG2), (0b01 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); + +// // setup interrupt on TXC +// register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); + +// // enable DMA + SPI +// DMA2_Stream3->CR |= DMA_SxCR_EN; +// register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); +// SPI4->CR2 = len; +// SPI4->CR1 |= SPI_CR1_SPE; +// } + +//static bool spi_tx_dma_done = false; // master -> panda DMA finished static void DMA2_Stream2_IRQ_Handler(void) { // Clear interrupt flag DMA2->LIFCR = DMA_LIFCR_CTCIF2; + print("RX DMA done\n"); llspi_disable(); - spi_rx_done(); + // shift any received data down in the rx buffer + // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + for(uint16_t i = 0U; i < llspi_rx_len; i++) { + ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; + } + + print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + + spi_done(); + + // llspi_disable(); + + // spi_rx_done(); } // panda -> master DMA finished static void DMA2_Stream3_IRQ_Handler(void) { - ENTER_CRITICAL(); + //ENTER_CRITICAL(); DMA2->LIFCR = DMA_LIFCR_CTCIF3; - spi_tx_dma_done = true; + print("TX DMA done\n"); + //spi_tx_dma_done = true; - EXIT_CRITICAL(); + //EXIT_CRITICAL(); } // panda TX finished static void SPI4_IRQ_Handler(void) { - //print("IRQ SR: "); puth(SPI4->SR); print("\n"); + print("IRQ SR: "); puth(SPI4->SR); print("\n"); if ((SPI4->SR & SPI_SR_EOT) != 0U) { - if (spi_tx_dma_done) { - llspi_disable(); - - spi_tx_dma_done = false; - spi_tx_done(false); - } else if (spi_state == SPI_STATE_DATA_TX) { - // spurious TXC interrupt - #ifdef DEBUG_SPI - print("SPI: spurious TXC\n"); - llspi_dump_state(); - #endif - } - } - - if ((SPI4->SR & SPI_SR_UDR) != 0U) { - // under-run occurred - #ifdef DEBUG_SPI - print("SPI: underrun "); puth(spi_tx_dma_done); print("\n"); - llspi_dump_state(); - #endif - } - - if ((SPI4->SR & SPI_SR_OVR) != 0U) { - // over-run occurred - #ifdef DEBUG_SPI - print("SPI: overrun\n"); - llspi_dump_state(); - #endif + // llspi_disable(); + + // // shift any received data down in the rx buffer + // // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + // for(uint16_t i = 0U; i < llspi_rx_len; i++) { + // ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; + // } + + // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + + // spi_done(); } + // if ((SPI4->SR & SPI_SR_UDR) != 0U) { + // // under-run occurred + // #ifdef DEBUG_SPI + // print("SPI: underrun "); puth(spi_tx_dma_done); print("\n"); + // llspi_dump_state(); + // #endif + // } + + // if ((SPI4->SR & SPI_SR_OVR) != 0U) { + // // over-run occurred + // #ifdef DEBUG_SPI + // print("SPI: overrun\n"); + // llspi_dump_state(); + // #endif + // } + // clear flag SPI4->IFCR |= (0x1FFU << 3U); } @@ -158,11 +221,12 @@ void llspi_init(void) { register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); // Enable SPI - register_set(&(SPI4->IER), SPI_IER_OVRIE | SPI_IER_UDRIE, 0x3FFU); + register_set(&(SPI4->IER), 0U, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); - register_set_bits(&(SPI4->CFG2), SPI_CFG2_AFCNTR); + register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging SPI4->CR2 = 0U; + llspi_disable(); NVIC_EnableIRQ(DMA2_Stream2_IRQn); NVIC_EnableIRQ(DMA2_Stream3_IRQn); From 8d0ca93def140bbe2d7fdda1ff98ced3ee3bc0af Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Mon, 19 Jan 2026 17:00:06 +0100 Subject: [PATCH 04/17] cleanup --- board/drivers/spi.h | 153 ------------------------------------------ board/stm32h7/llspi.h | 82 ---------------------- 2 files changed, 235 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index fa8170e9ff9..8ce38d799b6 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -75,159 +75,6 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { return checksum == 0U; } -// void spi_rx_done(void) { -// uint16_t response_len = 0U; -// uint8_t next_rx_state = SPI_STATE_HEADER_NACK; -// bool checksum_valid = false; -// static uint8_t spi_endpoint; -// static uint16_t spi_data_len_miso; - -// // parse header -// spi_endpoint = spi_buf_rx[1]; -// spi_data_len_mosi = (spi_buf_rx[3] << 8) | spi_buf_rx[2]; -// spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; - -// if (memcmp(spi_buf_rx, version_text, 7) == 0) { -// response_len = spi_version_packet(spi_buf_tx); -// next_rx_state = SPI_STATE_HEADER_NACK;; -// } else if (spi_state == SPI_STATE_HEADER) { -// checksum_valid = validate_checksum(spi_buf_rx, SPI_HEADER_SIZE); -// if ((spi_buf_rx[0] == SPI_SYNC_BYTE) && checksum_valid) { -// // response: ACK and start receiving data portion -// spi_buf_tx[0] = SPI_HACK; -// next_rx_state = SPI_STATE_HEADER_ACK; -// response_len = 1U; -// } else { -// // response: NACK and reset state machine -// #ifdef DEBUG_SPI -// print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); -// //llspi_dump_state(); -// #endif -// spi_buf_tx[0] = SPI_NACK; -// next_rx_state = SPI_STATE_HEADER_NACK; -// response_len = 1U; -// } -// } else if (spi_state == SPI_STATE_DATA_RX) { -// // We got everything! Based on the endpoint specified, call the appropriate handler -// bool response_ack = false; -// checksum_valid = validate_checksum(&(spi_buf_rx[SPI_HEADER_SIZE]), spi_data_len_mosi + 1U); -// if (checksum_valid) { -// if (spi_endpoint == 0U) { -// if (spi_data_len_mosi >= sizeof(ControlPacket_t)) { -// ControlPacket_t ctrl = {0}; -// (void)memcpy((uint8_t*)&ctrl, &spi_buf_rx[SPI_HEADER_SIZE], sizeof(ControlPacket_t)); -// response_len = comms_control_handler(&ctrl, &spi_buf_tx[3]); -// response_ack = true; -// } else { -// print("SPI: insufficient data for control handler\n"); -// } -// } else if ((spi_endpoint == 1U) || (spi_endpoint == 0x81U)) { -// if (spi_data_len_mosi == 0U) { -// response_len = comms_can_read(&(spi_buf_tx[3]), spi_data_len_miso); -// response_ack = true; -// } else { -// print("SPI: did not expect data for can_read\n"); -// } -// } else if (spi_endpoint == 2U) { -// comms_endpoint2_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); -// response_ack = true; -// } else if (spi_endpoint == 3U) { -// if (spi_data_len_mosi > 0U) { -// if (spi_can_tx_ready) { -// spi_can_tx_ready = false; -// comms_can_write(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi); -// response_ack = true; -// } else { -// response_ack = false; -// print("SPI: CAN NACK\n"); -// } -// } else { -// print("SPI: did expect data for can_write\n"); -// } -// } else if (spi_endpoint == 0xABU) { -// // test endpoint: mimics panda -> device transfer -// response_len = spi_data_len_miso; -// response_ack = true; -// } else if (spi_endpoint == 0xACU) { -// // test endpoint: mimics device -> panda transfer (with NACK) -// response_ack = false; -// } else { -// print("SPI: unexpected endpoint"); puth(spi_endpoint); print("\n"); -// } -// } else { -// // Checksum was incorrect -// response_ack = false; -// #ifdef DEBUG_SPI -// print("- incorrect data checksum "); -// puth4(spi_data_len_mosi); -// print("\n"); -// hexdump(spi_buf_rx, SPI_HEADER_SIZE); -// hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); -// print("\n"); -// #endif -// } - -// if (!response_ack) { -// spi_buf_tx[0] = SPI_NACK; -// next_rx_state = SPI_STATE_HEADER_NACK; -// response_len = 1U; -// } else { -// // Setup response header -// spi_buf_tx[0] = SPI_DACK; -// spi_buf_tx[1] = response_len & 0xFFU; -// spi_buf_tx[2] = (response_len >> 8) & 0xFFU; - -// // Add checksum -// uint8_t checksum = SPI_CHECKSUM_START; -// for(uint16_t i = 0U; i < (response_len + 3U); i++) { -// checksum ^= spi_buf_tx[i]; -// } -// spi_buf_tx[response_len + 3U] = checksum; -// response_len += 4U; - -// next_rx_state = SPI_STATE_DATA_TX; -// } -// } else { -// print("SPI: RX unexpected state: "); puth(spi_state); print("\n"); -// } - -// // send out response -// if (response_len == 0U) { -// print("SPI: no response\n"); -// spi_buf_tx[0] = SPI_NACK; -// spi_state = SPI_STATE_HEADER_NACK; -// response_len = 1U; -// } -// llspi_miso_dma(spi_buf_tx, response_len); - -// spi_state = next_rx_state; -// //puth(spi_state); print(" RX\n"); -// if (!checksum_valid) { -// spi_error_count += 1U; -// } -// } - -// void spi_tx_done(bool reset) { -// if ((spi_state == SPI_STATE_HEADER_NACK) || reset) { -// // Reset state -// spi_state = SPI_STATE_HEADER; -// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); -// } else if (spi_state == SPI_STATE_HEADER_ACK) { -// // ACK was sent, queue up the RX buf for the data + checksum -// spi_state = SPI_STATE_DATA_RX; -// llspi_mosi_dma(&spi_buf_rx[SPI_HEADER_SIZE], spi_data_len_mosi + 1U); -// } else if (spi_state == SPI_STATE_DATA_TX) { -// // Reset state -// spi_state = SPI_STATE_HEADER; -// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); -// } else { -// spi_state = SPI_STATE_HEADER; -// llspi_mosi_dma(spi_buf_rx, SPI_HEADER_SIZE); -// print("SPI: TX unexpected state: "); puth(spi_state); print("\n"); -// } -// //puth(spi_state); print(" TX\n"); -// } - void spi_done(void) { uint8_t next_rx_state = SPI_STATE_HEADER; bool checksum_valid = false; diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index ae78a729c64..1030aa5daa3 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -75,63 +75,6 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { // TODO: check that the rx buffer is large enough } -// // master -> panda DMA start -// void llspi_mosi_dma(uint8_t *addr, int len) { -// // drain the bus -// bool found_any = false; -// while ((SPI4->SR & SPI_SR_RXP) != 0U) { -// volatile uint8_t dat = SPI4->RXDR; -// puth(dat); print(" "); -// (void)dat; -// found_any = true; -// } -// if (found_any) -// print("\n"); - -// // clear all pending -// SPI4->IFCR |= (0x1FFU << 3U); -// register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); - -// // simplex receive mode -// register_set(&(SPI4->CFG2), (0b10 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); - -// // setup destination and length -// register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU); -// SPI4->CR2 = 0U; -// DMA2_Stream2->NDTR = len; - -// // enable DMA + SPI -// DMA2_Stream2->CR |= DMA_SxCR_EN; -// register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); -// SPI4->CR1 |= SPI_CR1_SPE; -// } - -// // panda -> master DMA start -// void llspi_miso_dma(uint8_t *addr, int len) { -// // setup source and length -// register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU); -// //print("TX len "); puth(len); print("\n"); -// DMA2_Stream3->NDTR = len; - -// // puth(len); print(" "); puth(SPI4->SR >> 16U); print("\n"); - -// // clear under-run while we were reading -// SPI4->IFCR |= (0x1FFU << 3U); - -// // simplex transmit mode -// register_set(&(SPI4->CFG2), (0b01 << SPI_CFG2_COMM_Pos), SPI_CFG2_COMM_Msk); - -// // setup interrupt on TXC -// register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); - -// // enable DMA + SPI -// DMA2_Stream3->CR |= DMA_SxCR_EN; -// register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); -// SPI4->CR2 = len; -// SPI4->CR1 |= SPI_CR1_SPE; -// } - -//static bool spi_tx_dma_done = false; // master -> panda DMA finished static void DMA2_Stream2_IRQ_Handler(void) { // Clear interrupt flag @@ -149,21 +92,12 @@ static void DMA2_Stream2_IRQ_Handler(void) { print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); spi_done(); - - // llspi_disable(); - - // spi_rx_done(); } // panda -> master DMA finished static void DMA2_Stream3_IRQ_Handler(void) { - //ENTER_CRITICAL(); - DMA2->LIFCR = DMA_LIFCR_CTCIF3; print("TX DMA done\n"); - //spi_tx_dma_done = true; - - //EXIT_CRITICAL(); } // panda TX finished @@ -184,22 +118,6 @@ static void SPI4_IRQ_Handler(void) { // spi_done(); } - // if ((SPI4->SR & SPI_SR_UDR) != 0U) { - // // under-run occurred - // #ifdef DEBUG_SPI - // print("SPI: underrun "); puth(spi_tx_dma_done); print("\n"); - // llspi_dump_state(); - // #endif - // } - - // if ((SPI4->SR & SPI_SR_OVR) != 0U) { - // // over-run occurred - // #ifdef DEBUG_SPI - // print("SPI: overrun\n"); - // llspi_dump_state(); - // #endif - // } - // clear flag SPI4->IFCR |= (0x1FFU << 3U); } From 0b1eeaf9aa5e0ceda65c9d7952476263ce95b0c9 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Mon, 19 Jan 2026 18:06:34 +0100 Subject: [PATCH 05/17] closer but still some weird stuff going on --- board/drivers/spi.h | 7 ++--- board/stm32h7/llspi.h | 63 ++++++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 8ce38d799b6..b485831cece 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -76,6 +76,7 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { } void spi_done(void) { + print("SPI DONE\n"); uint8_t next_rx_state = SPI_STATE_HEADER; bool checksum_valid = false; static uint8_t spi_endpoint; @@ -163,9 +164,9 @@ void spi_done(void) { print("- incorrect data checksum "); puth4(spi_data_len_mosi); print("\n"); - hexdump(spi_buf_rx, SPI_HEADER_SIZE); - hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); - print("\n"); + // hexdump(spi_buf_rx, SPI_HEADER_SIZE); + // hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); + // print("\n"); #endif } diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 1030aa5daa3..d881b755803 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -1,4 +1,9 @@ +static uint8_t *llspi_rx_addr; +static int llspi_rx_len, llspi_tx_len; +static bool llspi_pending = false; + + void llspi_dump_state(void){ print(" STATE: "); puth(spi_state); print("\n"); print(" SPI4 CR1: "); puth(SPI4->CR1); @@ -17,6 +22,7 @@ void llspi_dump_state(void){ static void llspi_disable(void) { // disable DMA + SPI + llspi_pending = false; DMA2_Stream2->CR &= ~DMA_SxCR_EN; DMA2_Stream3->CR &= ~DMA_SxCR_EN; while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); @@ -25,9 +31,6 @@ static void llspi_disable(void) { register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); } -static uint8_t *llspi_rx_addr; -static int llspi_rx_len, llspi_tx_len; - void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { print("\nLLSPI DMA TX len "); puth(tx_len); print(" RX len "); puth(rx_len); print("\n"); @@ -57,19 +60,23 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); DMA2_Stream2->NDTR = total_len; - //SPI4->CR2 = total_len; - SPI4->CR2 = 0U; + SPI4->CR2 = total_len; + //SPI4->CR2 = 0U; // setup interrupt on EOT - //register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); + register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); // enable DMAs + SPI DMA2_Stream2->CR |= DMA_SxCR_EN; if (tx_len > 0) { DMA2_Stream3->CR |= DMA_SxCR_EN; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + } else { + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); } - register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN); + register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + llspi_pending = true; SPI4->CR1 |= SPI_CR1_SPE; // TODO: check that the rx buffer is large enough @@ -81,17 +88,17 @@ static void DMA2_Stream2_IRQ_Handler(void) { DMA2->LIFCR = DMA_LIFCR_CTCIF2; print("RX DMA done\n"); - llspi_disable(); + // llspi_disable(); - // shift any received data down in the rx buffer - // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - for(uint16_t i = 0U; i < llspi_rx_len; i++) { - ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; - } + // // shift any received data down in the rx buffer + // // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + // for(uint16_t i = 0U; i < llspi_rx_len; i++) { + // ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; + // } - print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); - spi_done(); + // spi_done(); } // panda -> master DMA finished @@ -102,24 +109,24 @@ static void DMA2_Stream3_IRQ_Handler(void) { // panda TX finished static void SPI4_IRQ_Handler(void) { - print("IRQ SR: "); puth(SPI4->SR); print("\n"); + uint32_t sr = SPI4->SR; + SPI4->IFCR |= (0x1FFU << 3U); - if ((SPI4->SR & SPI_SR_EOT) != 0U) { - // llspi_disable(); + //print("IRQ SR: "); puth(sr); print("\n"); - // // shift any received data down in the rx buffer - // // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - // for(uint16_t i = 0U; i < llspi_rx_len; i++) { - // ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; - // } + if (((sr & SPI_SR_EOT) != 0U) && llspi_pending) { + llspi_disable(); - // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + // shift any received data down in the rx buffer + // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + for(uint16_t i = 0U; i < llspi_rx_len; i++) { + ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; + } - // spi_done(); - } + print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); - // clear flag - SPI4->IFCR |= (0x1FFU << 3U); + spi_done(); + } } From e0340ca09b3fa533101b975baabd99108a36ac52 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Tue, 20 Jan 2026 18:18:44 +0100 Subject: [PATCH 06/17] idk why it's still off by one --- board/drivers/spi.h | 3 ++- board/stm32h7/llspi.h | 21 +++++++++++++-------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index b485831cece..e6aa7585ec5 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -63,7 +63,8 @@ void spi_init(void) { // Start the first packet! spi_state = SPI_STATE_HEADER; - llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); + spi_buf_tx[0] = SPI_NACK; + llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); } static bool validate_checksum(const uint8_t *data, uint16_t len) { diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index d881b755803..9078fd7ca36 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -48,18 +48,23 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { // clear all pending SPI4->IFCR |= (0x1FFU << 3U); register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); + register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN); // setup destinations and length int total_len = tx_len + rx_len; + register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); + register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = total_len; + DMA2_Stream2->CR |= DMA_SxCR_EN; + if (tx_len > 0) { print("TX: "); hexdump(tx_addr, tx_len); register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); DMA2_Stream3->NDTR = tx_len; + DMA2_Stream3->CR |= DMA_SxCR_EN; } - register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); - DMA2_Stream2->NDTR = total_len; SPI4->CR2 = total_len; //SPI4->CR2 = 0U; @@ -67,15 +72,14 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); // enable DMAs + SPI - DMA2_Stream2->CR |= DMA_SxCR_EN; + if (tx_len > 0) { - DMA2_Stream3->CR |= DMA_SxCR_EN; register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); } else { - register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); + register_set(&(SPI4->CFG2), SPI_CFG2_COMM_1, 0xF7FE80FFU); } - register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); llspi_pending = true; SPI4->CR1 |= SPI_CR1_SPE; @@ -118,7 +122,7 @@ static void SPI4_IRQ_Handler(void) { llspi_disable(); // shift any received data down in the rx buffer - // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + //memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); for(uint16_t i = 0U; i < llspi_rx_len; i++) { ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; } @@ -148,7 +152,8 @@ void llspi_init(void) { // Enable SPI register_set(&(SPI4->IER), 0U, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); - register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); + //register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); + register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging SPI4->CR2 = 0U; llspi_disable(); From c5d9db387f20f7413c01501ca87f0cabaadd91e6 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 15:47:54 +0100 Subject: [PATCH 07/17] this is stable when requesting VERSION in a loop --- board/drivers/spi.h | 10 ++++----- board/stm32h7/llspi.h | 52 ++++++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index e6aa7585ec5..804a6c1bce2 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -61,10 +61,8 @@ void spi_init(void) { // platform init llspi_init(); - // Start the first packet! - spi_state = SPI_STATE_HEADER; - spi_buf_tx[0] = SPI_NACK; - llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); + // Start the first packet + llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); } static bool validate_checksum(const uint8_t *data, uint16_t len) { @@ -77,7 +75,7 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { } void spi_done(void) { - print("SPI DONE\n"); + //print("SPI DONE\n"); uint8_t next_rx_state = SPI_STATE_HEADER; bool checksum_valid = false; static uint8_t spi_endpoint; @@ -107,7 +105,7 @@ void spi_done(void) { //llspi_dump_state(); #endif spi_buf_tx[0] = SPI_NACK; - llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); + llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); next_rx_state = SPI_STATE_HEADER; } } else if (spi_state == SPI_STATE_DATA) { diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 9078fd7ca36..24136b72b95 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -16,7 +16,8 @@ void llspi_dump_state(void){ print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); print(" DMA2 Stream3 CR: "); puth(DMA2_Stream3->CR); - print(" NDTR: "); puth(DMA2_Stream3->NDTR); + print(" NDTR: "); puth(DMA2_Stream3->NDTR); print("\n"); + print(" LISR: "); puth(DMA2->LISR); print("\n\n"); } @@ -28,6 +29,7 @@ static void llspi_disable(void) { while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); while((DMA2_Stream3->CR & DMA_SxCR_EN) != 0U); SPI4->CR1 &= ~SPI_CR1_SPE; + DMA2->LIFCR = DMA_LIFCR_CTCIF2 | DMA_LIFCR_CTCIF3; register_clear_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN | SPI_CFG1_TXDMAEN); } @@ -39,6 +41,8 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { llspi_rx_len = rx_len; llspi_tx_len = tx_len; + // memset(rx_addr, 0xAA, 0x100); + // drain the bus while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; @@ -48,38 +52,38 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { // clear all pending SPI4->IFCR |= (0x1FFU << 3U); register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); - register_clear_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN | SPI_CFG1_RXDMAEN); // setup destinations and length int total_len = tx_len + rx_len; register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); - register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); - DMA2_Stream2->NDTR = total_len; - DMA2_Stream2->CR |= DMA_SxCR_EN; if (tx_len > 0) { - print("TX: "); hexdump(tx_addr, tx_len); + // print("TX: "); hexdump(tx_addr, tx_len); register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); DMA2_Stream3->NDTR = tx_len; DMA2_Stream3->CR |= DMA_SxCR_EN; + register_clear_bits(&(SPI4->CFG2), SPI_CFG2_COMM); + } else { + register_set(&(SPI4->CFG2), SPI_CFG2_COMM_1, SPI_CFG2_COMM); } + //llspi_dump_state(); + register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); + DMA2_Stream2->NDTR = total_len; + DMA2_Stream2->CR |= DMA_SxCR_EN; + //llspi_dump_state(); + SPI4->CR2 = total_len; //SPI4->CR2 = 0U; - // setup interrupt on EOT - register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); - - // enable DMAs + SPI - if (tx_len > 0) { register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); - register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); - } else { - register_set(&(SPI4->CFG2), SPI_CFG2_COMM_1, 0xF7FE80FFU); } + // setup interrupt on EOT + register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); + llspi_pending = true; SPI4->CR1 |= SPI_CR1_SPE; @@ -119,7 +123,11 @@ static void SPI4_IRQ_Handler(void) { //print("IRQ SR: "); puth(sr); print("\n"); if (((sr & SPI_SR_EOT) != 0U) && llspi_pending) { - llspi_disable(); + // print("RX 1: "); hexdump(llspi_rx_addr, llspi_rx_len); + + if (llspi_rx_addr[0] == 0xAA) { + llspi_dump_state(); + } // shift any received data down in the rx buffer //memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); @@ -127,8 +135,9 @@ static void SPI4_IRQ_Handler(void) { ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; } - print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + // print("RX 2: "); hexdump(llspi_rx_addr, llspi_rx_len); + llspi_disable(); spi_done(); } } @@ -141,19 +150,22 @@ void llspi_init(void) { // Setup MOSI DMA register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU); - register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); + //register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream2->CR), DMA_SxCR_MINC, 0x1E077EFEU); register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI4->RXDR), 0xFFFFFFFFU); // Setup MISO DMA, memory -> peripheral register_set(&(DMAMUX1_Channel11->CCR), 84U, 0xFFFFFFFFU); - register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); + //register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); + register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0), 0x1E077EFEU); register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); // Enable SPI register_set(&(SPI4->IER), 0U, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); - //register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); - register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); + register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); + //register_set(&(SPI4->CFG2), SPI_CFG2_SSM, 0xF7FE80FFU); + //register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging SPI4->CR2 = 0U; llspi_disable(); From f65f243bc9309a1826eadb1aaba8c51c9ed71379 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 15:56:42 +0100 Subject: [PATCH 08/17] this is stable? --- board/drivers/spi.h | 2 +- board/stm32h7/llspi.h | 2 +- python/spi.py | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 804a6c1bce2..99e5e142c38 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -87,7 +87,7 @@ void spi_done(void) { spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; if (memcmp(spi_buf_rx, version_text, 7) == 0) { - print("GOT VERSION REQUEST\n"); + //print("GOT VERSION REQUEST\n"); llspi_dma(spi_buf_tx, spi_version_packet(spi_buf_tx), spi_buf_rx, SPI_HEADER_SIZE); next_rx_state = SPI_STATE_HEADER; } else if (spi_state == SPI_STATE_HEADER) { diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 24136b72b95..3e5a8d28929 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -34,7 +34,7 @@ static void llspi_disable(void) { } void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { - print("\nLLSPI DMA TX len "); puth(tx_len); print(" RX len "); puth(rx_len); print("\n"); + //print("\nLLSPI DMA TX len "); puth(tx_len); print(" RX len "); puth(rx_len); print("\n"); // set global for later use llspi_rx_addr = rx_addr; diff --git a/python/spi.py b/python/spi.py index 4275017ed9d..67ba26907bd 100644 --- a/python/spi.py +++ b/python/spi.py @@ -159,18 +159,15 @@ def _transfer_spidev(self, spi, endpoint: int, data, timeout: int, max_rx_len: i return b"" else: logger.debug("- waiting for data ACK") - preread_len = USBPACKET_MAX_SIZE + 1 # read enough for a controlRead - dat = self._wait_for_ack(spi, DACK, timeout, 0x13, length=3 + preread_len) + dat = self._wait_for_ack(spi, DACK, timeout, 0x13, length=3) - # get response length, then response + # get response length response_len = struct.unpack(" max_rx_len: raise PandaSpiException(f"response length greater than max ({max_rx_len} {response_len})") # read rest - remaining = (response_len + 1) - preread_len - if remaining > 0: - dat += bytes(spi.readbytes(remaining)) + dat += bytes(spi.readbytes(response_len + 1)) dat = dat[:3 + response_len + 1] if self._calc_checksum(dat) != 0: From fe404ade7179c833513f0b2f04cc132f614240f3 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 16:00:41 +0100 Subject: [PATCH 09/17] cleanup --- board/drivers/spi.h | 8 ++-- board/stm32h7/llspi.h | 89 ++----------------------------------------- 2 files changed, 7 insertions(+), 90 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 99e5e142c38..ec9fe10e07d 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -87,7 +87,6 @@ void spi_done(void) { spi_data_len_miso = (spi_buf_rx[5] << 8) | spi_buf_rx[4]; if (memcmp(spi_buf_rx, version_text, 7) == 0) { - //print("GOT VERSION REQUEST\n"); llspi_dma(spi_buf_tx, spi_version_packet(spi_buf_tx), spi_buf_rx, SPI_HEADER_SIZE); next_rx_state = SPI_STATE_HEADER; } else if (spi_state == SPI_STATE_HEADER) { @@ -102,7 +101,6 @@ void spi_done(void) { // response: NACK and reset state machine #ifdef DEBUG_SPI print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); - //llspi_dump_state(); #endif spi_buf_tx[0] = SPI_NACK; llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); @@ -163,9 +161,9 @@ void spi_done(void) { print("- incorrect data checksum "); puth4(spi_data_len_mosi); print("\n"); - // hexdump(spi_buf_rx, SPI_HEADER_SIZE); - // hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); - // print("\n"); + hexdump(spi_buf_rx, SPI_HEADER_SIZE); + hexdump(&(spi_buf_rx[SPI_HEADER_SIZE]), MIN(spi_data_len_mosi, 64)); + print("\n"); #endif } diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 3e5a8d28929..8671384f322 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -1,29 +1,8 @@ - static uint8_t *llspi_rx_addr; static int llspi_rx_len, llspi_tx_len; -static bool llspi_pending = false; - - -void llspi_dump_state(void){ - print(" STATE: "); puth(spi_state); print("\n"); - print(" SPI4 CR1: "); puth(SPI4->CR1); - print(" CR2: "); puth(SPI4->CR2); - print(" SR: "); puth(SPI4->SR); - print(" IER: "); puth(SPI4->IER); - print(" CFG1: "); puth(SPI4->CFG1); - print(" CFG2: "); puth(SPI4->CFG2); - print("\n"); - print(" DMA2 Stream2 CR: "); puth(DMA2_Stream2->CR); - print(" NDTR: "); puth(DMA2_Stream2->NDTR); print("\n"); - print(" DMA2 Stream3 CR: "); puth(DMA2_Stream3->CR); - print(" NDTR: "); puth(DMA2_Stream3->NDTR); print("\n"); - print(" LISR: "); puth(DMA2->LISR); - print("\n\n"); -} static void llspi_disable(void) { // disable DMA + SPI - llspi_pending = false; DMA2_Stream2->CR &= ~DMA_SxCR_EN; DMA2_Stream3->CR &= ~DMA_SxCR_EN; while((DMA2_Stream2->CR & DMA_SxCR_EN) != 0U); @@ -34,15 +13,11 @@ static void llspi_disable(void) { } void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { - //print("\nLLSPI DMA TX len "); puth(tx_len); print(" RX len "); puth(rx_len); print("\n"); - // set global for later use llspi_rx_addr = rx_addr; llspi_rx_len = rx_len; llspi_tx_len = tx_len; - // memset(rx_addr, 0xAA, 0x100); - // drain the bus while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; @@ -54,12 +29,8 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); // setup destinations and length - int total_len = tx_len + rx_len; - register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); - if (tx_len > 0) { - // print("TX: "); hexdump(tx_addr, tx_len); register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); DMA2_Stream3->NDTR = tx_len; DMA2_Stream3->CR |= DMA_SxCR_EN; @@ -68,51 +39,20 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { register_set(&(SPI4->CFG2), SPI_CFG2_COMM_1, SPI_CFG2_COMM); } - //llspi_dump_state(); register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); + int total_len = tx_len + rx_len; DMA2_Stream2->NDTR = total_len; DMA2_Stream2->CR |= DMA_SxCR_EN; - //llspi_dump_state(); SPI4->CR2 = total_len; - //SPI4->CR2 = 0U; if (tx_len > 0) { register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); } - // setup interrupt on EOT + // setup interrupt on EOT and start transfer register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); - - llspi_pending = true; SPI4->CR1 |= SPI_CR1_SPE; - - // TODO: check that the rx buffer is large enough -} - -// master -> panda DMA finished -static void DMA2_Stream2_IRQ_Handler(void) { - // Clear interrupt flag - DMA2->LIFCR = DMA_LIFCR_CTCIF2; - print("RX DMA done\n"); - - // llspi_disable(); - - // // shift any received data down in the rx buffer - // // memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - // for(uint16_t i = 0U; i < llspi_rx_len; i++) { - // ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; - // } - - // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); - - // spi_done(); -} - -// panda -> master DMA finished -static void DMA2_Stream3_IRQ_Handler(void) { - DMA2->LIFCR = DMA_LIFCR_CTCIF3; - print("TX DMA done\n"); } // panda TX finished @@ -120,22 +60,9 @@ static void SPI4_IRQ_Handler(void) { uint32_t sr = SPI4->SR; SPI4->IFCR |= (0x1FFU << 3U); - //print("IRQ SR: "); puth(sr); print("\n"); - - if (((sr & SPI_SR_EOT) != 0U) && llspi_pending) { - // print("RX 1: "); hexdump(llspi_rx_addr, llspi_rx_len); - - if (llspi_rx_addr[0] == 0xAA) { - llspi_dump_state(); - } - + if (((sr & SPI_SR_EOT) != 0U)) { // shift any received data down in the rx buffer - //memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - for(uint16_t i = 0U; i < llspi_rx_len; i++) { - ((uint8_t *)llspi_rx_addr)[i] = ((uint8_t *)llspi_rx_addr)[i + llspi_tx_len]; - } - - // print("RX 2: "); hexdump(llspi_rx_addr, llspi_rx_len); + memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); llspi_disable(); spi_done(); @@ -145,18 +72,14 @@ static void SPI4_IRQ_Handler(void) { void llspi_init(void) { REGISTER_INTERRUPT(SPI4_IRQn, SPI4_IRQ_Handler, (SPI_IRQ_RATE * 2U), FAULT_INTERRUPT_RATE_SPI) - REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) - REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) // Setup MOSI DMA register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU); - //register_set(&(DMA2_Stream2->CR), (DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU); register_set(&(DMA2_Stream2->CR), DMA_SxCR_MINC, 0x1E077EFEU); register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI4->RXDR), 0xFFFFFFFFU); // Setup MISO DMA, memory -> peripheral register_set(&(DMAMUX1_Channel11->CCR), 84U, 0xFFFFFFFFU); - //register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU); register_set(&(DMA2_Stream3->CR), (DMA_SxCR_MINC | DMA_SxCR_DIR_0), 0x1E077EFEU); register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); @@ -164,13 +87,9 @@ void llspi_init(void) { register_set(&(SPI4->IER), 0U, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); - //register_set(&(SPI4->CFG2), SPI_CFG2_SSM, 0xF7FE80FFU); - //register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging SPI4->CR2 = 0U; llspi_disable(); - NVIC_EnableIRQ(DMA2_Stream2_IRQn); - NVIC_EnableIRQ(DMA2_Stream3_IRQn); NVIC_EnableIRQ(SPI4_IRQn); } From 94b4afb631e1542312494ddd3ad9a4506ed66ce8 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 16:03:01 +0100 Subject: [PATCH 10/17] diff reducal --- board/drivers/spi.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index ec9fe10e07d..cc85c2b8788 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -61,7 +61,7 @@ void spi_init(void) { // platform init llspi_init(); - // Start the first packet + // Start the first packet! llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); } @@ -75,7 +75,6 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { } void spi_done(void) { - //print("SPI DONE\n"); uint8_t next_rx_state = SPI_STATE_HEADER; bool checksum_valid = false; static uint8_t spi_endpoint; From c5d86b5d19430f50f910321cf1bcfa75e985cac1 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 16:03:24 +0100 Subject: [PATCH 11/17] no more debug --- board/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/config.h b/board/config.h index d488a31f738..1b7d938cc81 100644 --- a/board/config.h +++ b/board/config.h @@ -5,7 +5,7 @@ //#define DEBUG //#define DEBUG_UART //#define DEBUG_USB -#define DEBUG_SPI +//#define DEBUG_SPI //#define DEBUG_FAULTS //#define DEBUG_COMMS //#define DEBUG_FAN From 64247a69152cb68b53478e63d1e101efdcb63303 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 16:51:01 +0100 Subject: [PATCH 12/17] fix misra --- board/drivers/spi.h | 8 ++++---- board/stm32h7/llspi.h | 5 +++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index cc85c2b8788..df915790d81 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -8,8 +8,6 @@ uint8_t spi_buf_tx[SPI_BUF_SIZE]; uint16_t spi_error_count = 0; -static uint8_t spi_state = SPI_STATE_HEADER; -static uint16_t spi_data_len_mosi; static bool spi_can_tx_ready = false; static const unsigned char version_text[] = "VERSION"; @@ -75,10 +73,12 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { } void spi_done(void) { - uint8_t next_rx_state = SPI_STATE_HEADER; - bool checksum_valid = false; + static uint8_t spi_state = SPI_STATE_HEADER; static uint8_t spi_endpoint; static uint16_t spi_data_len_miso; + static uint16_t spi_data_len_mosi; + uint8_t next_rx_state = SPI_STATE_HEADER; + bool checksum_valid = false; // parse header spi_endpoint = spi_buf_rx[1]; diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 8671384f322..b9691b03254 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -1,5 +1,6 @@ static uint8_t *llspi_rx_addr; -static int llspi_rx_len, llspi_tx_len; +static int llspi_rx_len; +static int llspi_tx_len; static void llspi_disable(void) { // disable DMA + SPI @@ -62,7 +63,7 @@ static void SPI4_IRQ_Handler(void) { if (((sr & SPI_SR_EOT) != 0U)) { // shift any received data down in the rx buffer - memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + (void)memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); llspi_disable(); spi_done(); From 753c830bf0df6fdc06a818d90c6ef64cee164f02 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 17:10:36 +0100 Subject: [PATCH 13/17] it needs this for pandad --- board/drivers/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index df915790d81..46954d0f14e 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -102,7 +102,7 @@ void spi_done(void) { print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); #endif spi_buf_tx[0] = SPI_NACK; - llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); + llspi_dma(spi_buf_tx, SPI_NACK, spi_buf_rx, SPI_HEADER_SIZE); next_rx_state = SPI_STATE_HEADER; } } else if (spi_state == SPI_STATE_DATA) { From d51db8d976dafd008abc9494de1493baf56f7508 Mon Sep 17 00:00:00 2001 From: Robbe Derks Date: Wed, 21 Jan 2026 17:15:22 +0100 Subject: [PATCH 14/17] duh --- board/drivers/spi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index 46954d0f14e..dada878755b 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -102,7 +102,7 @@ void spi_done(void) { print("- incorrect header sync or checksum "); hexdump(spi_buf_rx, SPI_HEADER_SIZE); #endif spi_buf_tx[0] = SPI_NACK; - llspi_dma(spi_buf_tx, SPI_NACK, spi_buf_rx, SPI_HEADER_SIZE); + llspi_dma(spi_buf_tx, 1U, spi_buf_rx, SPI_HEADER_SIZE); next_rx_state = SPI_STATE_HEADER; } } else if (spi_state == SPI_STATE_DATA) { From 3f4942d086679c05f0aceda264a8e890ea46a34e Mon Sep 17 00:00:00 2001 From: Comma Device Date: Wed, 21 Jan 2026 16:40:15 +0000 Subject: [PATCH 15/17] this fixes python --- python/spi.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python/spi.py b/python/spi.py index 67ba26907bd..1efdf8c3102 100644 --- a/python/spi.py +++ b/python/spi.py @@ -211,7 +211,8 @@ def _transfer(self, endpoint: int, data, timeout: int, max_rx_len: int = 1000, e def get_protocol_version(self) -> bytes: vers_str = b"VERSION" def _get_version(spi) -> bytes: - spi.writebytes(vers_str) + # needs a dummy byte to get in sync + spi.writebytes(b"\x00" + vers_str) logger.debug("- waiting for echo") start = time.monotonic() From cad29e7bbbc2606a152bec83674f122ea42d31b3 Mon Sep 17 00:00:00 2001 From: Comma Device Date: Thu, 22 Jan 2026 14:00:50 +0000 Subject: [PATCH 16/17] this is better --- board/drivers/spi.h | 12 +++++++++--- board/drivers/spi_declarations.h | 1 + board/stm32h7/llspi.h | 24 +++++++++++++++++++----- python/spi.py | 3 +-- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index dada878755b..a3cfe8d7e4b 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -11,6 +11,8 @@ uint16_t spi_error_count = 0; static bool spi_can_tx_ready = false; static const unsigned char version_text[] = "VERSION"; +static uint8_t spi_state = SPI_STATE_HEADER; + static uint16_t spi_version_packet(uint8_t *out) { // this protocol version request is a stable portion of // the panda's SPI protocol. its contents match that of the @@ -55,12 +57,17 @@ static uint16_t spi_version_packet(uint8_t *out) { return resp_len; } +void spi_reset(void) { + spi_state = SPI_STATE_HEADER; + llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); +} + void spi_init(void) { // platform init llspi_init(); - // Start the first packet! - llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); + spi_error_count = 0U; + spi_reset(); } static bool validate_checksum(const uint8_t *data, uint16_t len) { @@ -73,7 +80,6 @@ static bool validate_checksum(const uint8_t *data, uint16_t len) { } void spi_done(void) { - static uint8_t spi_state = SPI_STATE_HEADER; static uint8_t spi_endpoint; static uint16_t spi_data_len_miso; static uint16_t spi_data_len_mosi; diff --git a/board/drivers/spi_declarations.h b/board/drivers/spi_declarations.h index 8da191c4f56..b11e8373f7a 100644 --- a/board/drivers/spi_declarations.h +++ b/board/drivers/spi_declarations.h @@ -36,4 +36,5 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len); void can_tx_comms_resume_spi(void); void spi_init(void); +void spi_reset(void); void spi_done(void); diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index b9691b03254..0a128ac669b 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -25,6 +25,10 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { (void)dat; } + // memset(llspi_rx_addr, 0xAA, 0x50); + + // print("TX: "); hexdump(tx_addr, tx_len); + // clear all pending SPI4->IFCR |= (0x1FFU << 3U); register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); @@ -62,11 +66,21 @@ static void SPI4_IRQ_Handler(void) { SPI4->IFCR |= (0x1FFU << 3U); if (((sr & SPI_SR_EOT) != 0U)) { - // shift any received data down in the rx buffer - (void)memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - + // print("RX DMA: "); puth4(DMA2_Stream2->NDTR); print(" CR: "); puth4(DMA2_Stream2->CR); print("\n"); llspi_disable(); - spi_done(); + // print("SR: "); puth4(sr); print("\n"); + + if ((((sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_Pos) == 0U) && (((sr & SPI_SR_RXWNE) == 0U))) { + // shift any received data down in the rx buffer + (void)memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + + // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); + spi_done(); + } else { + // print("HAVE TO RESET\n"); + // print("RX: "); hexdump(&((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); + spi_reset(); + } } } @@ -87,7 +101,7 @@ void llspi_init(void) { // Enable SPI register_set(&(SPI4->IER), 0U, 0x3FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); - register_set(&(SPI4->CFG2), SPI_CFG2_AFCNTR, 0xF7FE80FFU); + register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging SPI4->CR2 = 0U; llspi_disable(); diff --git a/python/spi.py b/python/spi.py index 1efdf8c3102..67ba26907bd 100644 --- a/python/spi.py +++ b/python/spi.py @@ -211,8 +211,7 @@ def _transfer(self, endpoint: int, data, timeout: int, max_rx_len: int = 1000, e def get_protocol_version(self) -> bytes: vers_str = b"VERSION" def _get_version(spi) -> bytes: - # needs a dummy byte to get in sync - spi.writebytes(b"\x00" + vers_str) + spi.writebytes(vers_str) logger.debug("- waiting for echo") start = time.monotonic() From 158062b50d076e7c9739ac35d2b6ab60e7fadc8a Mon Sep 17 00:00:00 2001 From: Comma Device Date: Thu, 22 Jan 2026 15:35:57 +0000 Subject: [PATCH 17/17] get rid of one more unnecessary interrupt call --- board/drivers/spi.h | 2 +- board/stm32h7/llspi.h | 43 +++++++++++++++++++------------------------ 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/board/drivers/spi.h b/board/drivers/spi.h index a3cfe8d7e4b..12071336600 100644 --- a/board/drivers/spi.h +++ b/board/drivers/spi.h @@ -59,7 +59,7 @@ static uint16_t spi_version_packet(uint8_t *out) { void spi_reset(void) { spi_state = SPI_STATE_HEADER; - llspi_dma(NULL, 0U, spi_buf_rx, SPI_HEADER_SIZE); + llspi_dma(spi_buf_tx, 0U, spi_buf_rx, SPI_HEADER_SIZE); } void spi_init(void) { diff --git a/board/stm32h7/llspi.h b/board/stm32h7/llspi.h index 0a128ac669b..1edb726833a 100644 --- a/board/stm32h7/llspi.h +++ b/board/stm32h7/llspi.h @@ -19,78 +19,72 @@ void llspi_dma(uint8_t *tx_addr, int tx_len, uint8_t *rx_addr, int rx_len) { llspi_rx_len = rx_len; llspi_tx_len = tx_len; + int total_len = tx_len + rx_len; + (void) memset(&tx_addr[tx_len], 0xcd, rx_len); + // drain the bus while ((SPI4->SR & SPI_SR_RXP) != 0U) { volatile uint8_t dat = SPI4->RXDR; (void)dat; } - // memset(llspi_rx_addr, 0xAA, 0x50); - - // print("TX: "); hexdump(tx_addr, tx_len); - // clear all pending SPI4->IFCR |= (0x1FFU << 3U); register_clear_bits(&(SPI4->IER), SPI_IER_EOTIE); // setup destinations and length register_set_bits(&(SPI4->CFG1), SPI_CFG1_RXDMAEN); - if (tx_len > 0) { - register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); - DMA2_Stream3->NDTR = tx_len; - DMA2_Stream3->CR |= DMA_SxCR_EN; - register_clear_bits(&(SPI4->CFG2), SPI_CFG2_COMM); - } else { - register_set(&(SPI4->CFG2), SPI_CFG2_COMM_1, SPI_CFG2_COMM); - } + register_set(&(DMA2_Stream3->M0AR), (uint32_t)tx_addr, 0xFFFFFFFFU); + DMA2_Stream3->NDTR = total_len; + DMA2_Stream3->CR |= DMA_SxCR_EN; + register_clear_bits(&(SPI4->CFG2), SPI_CFG2_COMM); - register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); - int total_len = tx_len + rx_len; + register_set(&(DMA2_Stream2->M0AR), (uint32_t)rx_addr, 0xFFFFFFFFU); DMA2_Stream2->NDTR = total_len; DMA2_Stream2->CR |= DMA_SxCR_EN; SPI4->CR2 = total_len; - if (tx_len > 0) { - register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); - } + register_set_bits(&(SPI4->CFG1), SPI_CFG1_TXDMAEN); // setup interrupt on EOT and start transfer register_set_bits(&(SPI4->IER), SPI_IER_EOTIE); SPI4->CR1 |= SPI_CR1_SPE; + print("B"); } // panda TX finished static void SPI4_IRQ_Handler(void) { uint32_t sr = SPI4->SR; - SPI4->IFCR |= (0x1FFU << 3U); + SPI4->IFCR |= (0x1FFU << 3U); if (((sr & SPI_SR_EOT) != 0U)) { - // print("RX DMA: "); puth4(DMA2_Stream2->NDTR); print(" CR: "); puth4(DMA2_Stream2->CR); print("\n"); llspi_disable(); - // print("SR: "); puth4(sr); print("\n"); if ((((sr & SPI_SR_RXPLVL) >> SPI_SR_RXPLVL_Pos) == 0U) && (((sr & SPI_SR_RXWNE) == 0U))) { // shift any received data down in the rx buffer (void)memcpy(llspi_rx_addr, &((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); - // print("RX: "); hexdump(llspi_rx_addr, llspi_rx_len); spi_done(); } else { - // print("HAVE TO RESET\n"); - // print("RX: "); hexdump(&((uint8_t *)llspi_rx_addr)[llspi_tx_len], llspi_rx_len); spi_reset(); } } } +// static void DMA2_Stream2_IRQ_Handler(void) { +// // Clear interrupt flag +// DMA2->LIFCR = DMA_LIFCR_CTCIF2; +// } void llspi_init(void) { REGISTER_INTERRUPT(SPI4_IRQn, SPI4_IRQ_Handler, (SPI_IRQ_RATE * 2U), FAULT_INTERRUPT_RATE_SPI) + // REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, SPI_IRQ_RATE, FAULT_INTERRUPT_RATE_SPI_DMA) // Setup MOSI DMA register_set(&(DMAMUX1_Channel10->CCR), 83U, 0xFFFFFFFFU); register_set(&(DMA2_Stream2->CR), DMA_SxCR_MINC, 0x1E077EFEU); + // register_set(&(DMA2_Stream2->CR), DMA_SxCR_MINC | DMA_SxCR_TCIE, 0x1E077EFEU); register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI4->RXDR), 0xFFFFFFFFU); // Setup MISO DMA, memory -> peripheral @@ -99,7 +93,7 @@ void llspi_init(void) { register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI4->TXDR), 0xFFFFFFFFU); // Enable SPI - register_set(&(SPI4->IER), 0U, 0x3FFU); + register_set(&(SPI4->IER), 0U, 0x7FFU); register_set(&(SPI4->CFG1), (7U << SPI_CFG1_DSIZE_Pos), SPI_CFG1_DSIZE_Msk); register_set(&(SPI4->CFG2), 0U, 0xF7FE80FFU); register_set(&(SPI4->UDRDR), 0xcd, 0xFFFFU); // set under-run value for debugging @@ -107,4 +101,5 @@ void llspi_init(void) { llspi_disable(); NVIC_EnableIRQ(SPI4_IRQn); + // NVIC_EnableIRQ(DMA2_Stream2_IRQn); }