openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

91 lines
2.7 KiB

#if defined(ENABLE_SPI) || defined(BOOTSTUB)
void llspi_miso_dma(uint8_t *addr, int len) {
// disable DMA
DMA2_Stream3->CR &= ~DMA_SxCR_EN;
register_clear_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
// setup source and length
register_set(&(DMA2_Stream3->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
DMA2_Stream3->NDTR = len;
// enable DMA
register_set_bits(&(SPI1->CR2), SPI_CR2_TXDMAEN);
DMA2_Stream3->CR |= DMA_SxCR_EN;
}
void llspi_mosi_dma(uint8_t *addr, int len) {
// disable DMA
register_clear_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
DMA2_Stream2->CR &= ~DMA_SxCR_EN;
// drain the bus
volatile uint8_t dat = SPI1->DR;
(void)dat;
// setup destination and length
register_set(&(DMA2_Stream2->M0AR), (uint32_t)addr, 0xFFFFFFFFU);
DMA2_Stream2->NDTR = len;
// enable DMA
DMA2_Stream2->CR |= DMA_SxCR_EN;
register_set_bits(&(SPI1->CR2), SPI_CR2_RXDMAEN);
}
// SPI MOSI DMA FINISHED
static void DMA2_Stream2_IRQ_Handler(void) {
// Clear interrupt flag
ENTER_CRITICAL();
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
spi_rx_done();
EXIT_CRITICAL();
}
// SPI MISO DMA FINISHED
static void DMA2_Stream3_IRQ_Handler(void) {
// Clear interrupt flag
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
// Wait until the transaction is actually finished and clear the DR
// 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;
}
}
volatile uint8_t dat = SPI1->DR;
(void)dat;
SPI1->DR = 0U;
if (timed_out) {
print("SPI: TX timeout\n");
}
spi_tx_done(timed_out);
}
// ***************************** SPI init *****************************
void llspi_init(void) {
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(&(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
register_set(&(SPI1->CR1), SPI_CR1_SPE, 0xFFFFU);
register_set(&(SPI1->CR2), 0U, 0xF7U);
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
}
#endif