2022-11-15 05:52:52 +08:00
|
|
|
void llspi_miso_dma(uint8_t *addr, int len) {
|
2017-07-13 02:25:10 +08:00
|
|
|
// disable DMA
|
2022-11-10 10:46:20 +08:00
|
|
|
DMA2_Stream3->CR &= ~DMA_SxCR_EN;
|
2019-12-06 06:19:29 +08:00
|
|
|
register_clear_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
|
2017-07-13 02:25:10 +08:00
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// setup source and length
|
2019-12-06 06:19:29 +08:00
|
|
|
register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
|
2017-07-13 02:25:10 +08:00
|
|
|
DMA2_Stream3->NDTR = len;
|
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// enable DMA
|
2019-12-06 06:19:29 +08:00
|
|
|
register_set_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
|
2022-11-10 10:46:20 +08:00
|
|
|
DMA2_Stream3->CR |= DMA_SxCR_EN;
|
2017-07-13 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
2022-11-15 05:52:52 +08:00
|
|
|
void llspi_mosi_dma(uint8_t *addr, int len) {
|
2017-07-13 02:25:10 +08:00
|
|
|
// disable DMA
|
2019-12-06 06:19:29 +08:00
|
|
|
register_clear_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
|
2022-11-10 10:46:20 +08:00
|
|
|
DMA2_Stream2->CR &= ~DMA_SxCR_EN;
|
2017-07-13 02:25:10 +08:00
|
|
|
|
|
|
|
// drain the bus
|
2017-07-30 10:19:33 +08:00
|
|
|
volatile uint8_t dat = SPI1->DR;
|
2017-07-13 02:25:10 +08:00
|
|
|
(void)dat;
|
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// setup destination and length
|
2019-12-06 06:19:29 +08:00
|
|
|
register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
|
2017-07-13 02:25:10 +08:00
|
|
|
DMA2_Stream2->NDTR = len;
|
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// enable DMA
|
|
|
|
DMA2_Stream2->CR |= DMA_SxCR_EN;
|
2019-12-06 06:19:29 +08:00
|
|
|
register_set_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
|
2017-07-13 02:25:10 +08:00
|
|
|
}
|
2017-04-18 16:12:04 +08:00
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// SPI MOSI DMA FINISHED
|
2019-11-28 10:11:21 +08:00
|
|
|
void DMA2_Stream2_IRQ_Handler(void) {
|
2022-11-10 10:46:20 +08:00
|
|
|
// Clear interrupt flag
|
|
|
|
ENTER_CRITICAL();
|
2017-08-22 07:40:38 +08:00
|
|
|
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
|
2017-07-21 14:14:27 +08:00
|
|
|
|
2022-11-15 05:52:52 +08:00
|
|
|
spi_handle_rx();
|
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
EXIT_CRITICAL();
|
|
|
|
}
|
2017-08-22 07:40:38 +08:00
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// SPI MISO DMA FINISHED
|
|
|
|
void DMA2_Stream3_IRQ_Handler(void) {
|
|
|
|
// Clear interrupt flag
|
2017-08-22 07:40:38 +08:00
|
|
|
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
|
2017-07-21 14:14:27 +08:00
|
|
|
|
2022-11-10 10:46:20 +08:00
|
|
|
// Wait until the transaction is actually finished and clear the DR
|
2023-01-24 20:50:51 +08:00
|
|
|
// Timeout to prevent hang when the master clock stops.
|
|
|
|
bool timed_out = false;
|
|
|
|
uint32_t start_time = microsecond_timer_get();
|
|
|
|
while (!(SPI1->SR & SPI_SR_TXE)) {
|
|
|
|
if (get_ts_elapsed(microsecond_timer_get(), start_time) > SPI_TIMEOUT_US) {
|
|
|
|
timed_out = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-10 10:46:20 +08:00
|
|
|
volatile uint8_t dat = SPI1->DR;
|
|
|
|
(void)dat;
|
|
|
|
SPI1->DR = 0U;
|
|
|
|
|
2023-01-24 20:50:51 +08:00
|
|
|
spi_handle_tx(timed_out);
|
2017-07-21 14:14:27 +08:00
|
|
|
}
|
|
|
|
|
2019-11-28 10:11:21 +08:00
|
|
|
// ***************************** SPI init *****************************
|
2022-11-15 05:52:52 +08:00
|
|
|
void llspi_init(void) {
|
2022-11-10 10:46:20 +08:00
|
|
|
// We expect less than 50 transactions (including control messages and CAN buffers) at the 100Hz boardd interval. Can be raised if needed.
|
|
|
|
REGISTER_INTERRUPT(DMA2_Stream2_IRQn, DMA2_Stream2_IRQ_Handler, 5000U, FAULT_INTERRUPT_RATE_SPI_DMA)
|
|
|
|
REGISTER_INTERRUPT(DMA2_Stream3_IRQn, DMA2_Stream3_IRQ_Handler, 5000U, FAULT_INTERRUPT_RATE_SPI_DMA)
|
|
|
|
|
|
|
|
// Setup MOSI DMA
|
|
|
|
register_set(&(DMA2_Stream2->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_TCIE), 0x1E077EFEU);
|
|
|
|
register_set(&(DMA2_Stream2->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
|
|
|
|
|
|
|
|
// Setup MISO DMA
|
|
|
|
register_set(&(DMA2_Stream3->CR), (DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_TCIE), 0x1E077EFEU);
|
|
|
|
register_set(&(DMA2_Stream3->PAR), (uint32_t)&(SPI1->DR), 0xFFFFFFFFU);
|
|
|
|
|
|
|
|
// Enable SPI and the error interrupts
|
|
|
|
// TODO: verify clock phase and polarity
|
2019-12-06 06:19:29 +08:00
|
|
|
register_set(&(SPI1->CR1), SPI_CR1_SPE, 0xFFFFU);
|
2022-11-10 10:46:20 +08:00
|
|
|
register_set(&(SPI1->CR2), 0U, 0xF7U);
|
2019-11-28 10:11:21 +08:00
|
|
|
|
|
|
|
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
|
|
|
|
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
|
2021-07-03 09:25:35 +08:00
|
|
|
}
|