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.
 
 
 
 
 
 

122 lines
2.9 KiB

// IRQs: DMA2_Stream2, DMA2_Stream3, EXTI4
#define SPI_BUF_SIZE 256
uint8_t spi_buf[SPI_BUF_SIZE];
int spi_buf_count = 0;
int spi_total_count = 0;
void spi_init() {
//puts("SPI init\n");
SPI1->CR1 = SPI_CR1_SPE;
// enable SPI interrupts
//SPI1->CR2 = SPI_CR2_RXNEIE | SPI_CR2_ERRIE | SPI_CR2_TXEIE;
SPI1->CR2 = SPI_CR2_RXNEIE;
NVIC_EnableIRQ(DMA2_Stream2_IRQn);
NVIC_EnableIRQ(DMA2_Stream3_IRQn);
//NVIC_EnableIRQ(SPI1_IRQn);
// reset handshake back to pull up
set_gpio_mode(GPIOB, 0, MODE_INPUT);
set_gpio_pullup(GPIOB, 0, PULL_UP);
// setup interrupt on falling edge of SPI enable (on PA4)
SYSCFG->EXTICR[2] = SYSCFG_EXTICR2_EXTI4_PA;
EXTI->IMR = (1 << 4);
EXTI->FTSR = (1 << 4);
NVIC_EnableIRQ(EXTI4_IRQn);
}
void spi_tx_dma(void *addr, int len) {
// disable DMA
SPI1->CR2 &= ~SPI_CR2_TXDMAEN;
DMA2_Stream3->CR &= ~DMA_SxCR_EN;
// DMA2, stream 3, channel 3
DMA2_Stream3->M0AR = (uint32_t)addr;
DMA2_Stream3->NDTR = len;
DMA2_Stream3->PAR = (uint32_t)&(SPI1->DR);
// channel3, increment memory, memory -> periph, enable
DMA2_Stream3->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_DIR_0 | DMA_SxCR_EN;
delay(0);
DMA2_Stream3->CR |= DMA_SxCR_TCIE;
SPI1->CR2 |= SPI_CR2_TXDMAEN;
// signal data is ready by driving low
// esp must be configured as input by this point
set_gpio_output(GPIOB, 0, 0);
}
void spi_rx_dma(void *addr, int len) {
// disable DMA
SPI1->CR2 &= ~SPI_CR2_RXDMAEN;
DMA2_Stream2->CR &= ~DMA_SxCR_EN;
// drain the bus
volatile uint8_t dat = SPI1->DR;
(void)dat;
// DMA2, stream 2, channel 3
DMA2_Stream2->M0AR = (uint32_t)addr;
DMA2_Stream2->NDTR = len;
DMA2_Stream2->PAR = (uint32_t)&(SPI1->DR);
// channel3, increment memory, periph -> memory, enable
DMA2_Stream2->CR = DMA_SxCR_CHSEL_1 | DMA_SxCR_CHSEL_0 | DMA_SxCR_MINC | DMA_SxCR_EN;
delay(0);
DMA2_Stream2->CR |= DMA_SxCR_TCIE;
SPI1->CR2 |= SPI_CR2_RXDMAEN;
}
// ***************************** SPI IRQs *****************************
// can't go on the stack cause it's DMAed
uint8_t spi_tx_buf[0x44];
// SPI RX
void DMA2_Stream2_IRQHandler(void) {
int *resp_len = (int*)spi_tx_buf;
memset(spi_tx_buf, 0xaa, 0x44);
*resp_len = spi_cb_rx(spi_buf, 0x14, spi_tx_buf+4);
#ifdef DEBUG_SPI
puts("SPI write: ");
puth(*resp_len);
puts("\n");
#endif
spi_tx_dma(spi_tx_buf, *resp_len + 4);
// ack
DMA2->LIFCR = DMA_LIFCR_CTCIF2;
}
// SPI TX
void DMA2_Stream3_IRQHandler(void) {
#ifdef DEBUG_SPI
puts("SPI handshake\n");
#endif
// reset handshake back to pull up
set_gpio_mode(GPIOB, 0, MODE_INPUT);
set_gpio_pullup(GPIOB, 0, PULL_UP);
// ack
DMA2->LIFCR = DMA_LIFCR_CTCIF3;
}
void EXTI4_IRQHandler(void) {
volatile int pr = EXTI->PR;
#ifdef DEBUG_SPI
puts("exti4\n");
#endif
// SPI CS falling
if (pr & (1 << 4)) {
spi_total_count = 0;
spi_rx_dma(spi_buf, 0x14);
}
EXTI->PR = pr;
}