openpilot v0.9.6 release
date: 2024-01-12T10:13:37 master commit: ba792d576a49a0899b88a753fa1c52956bedf9e6
This commit is contained in:
106
panda/board/stm32h7/lluart.h
Normal file
106
panda/board/stm32h7/lluart.h
Normal file
@@ -0,0 +1,106 @@
|
||||
void uart_rx_ring(uart_ring *q){
|
||||
// Do not read out directly if DMA enabled
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Read out RX buffer
|
||||
uint8_t c = q->uart->RDR; // This read after reading SR clears a bunch of interrupts
|
||||
|
||||
uint16_t next_w_ptr = (q->w_ptr_rx + 1U) % q->rx_fifo_size;
|
||||
|
||||
if ((next_w_ptr == q->r_ptr_rx) && q->overwrite) {
|
||||
// overwrite mode: drop oldest byte
|
||||
q->r_ptr_rx = (q->r_ptr_rx + 1U) % q->rx_fifo_size;
|
||||
}
|
||||
|
||||
// Do not overwrite buffer data
|
||||
if (next_w_ptr != q->r_ptr_rx) {
|
||||
q->elems_rx[q->w_ptr_rx] = c;
|
||||
q->w_ptr_rx = next_w_ptr;
|
||||
if (q->callback != NULL) {
|
||||
q->callback(q);
|
||||
}
|
||||
}
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void uart_tx_ring(uart_ring *q){
|
||||
ENTER_CRITICAL();
|
||||
// Send out next byte of TX buffer
|
||||
if (q->w_ptr_tx != q->r_ptr_tx) {
|
||||
// Only send if transmit register is empty (aka last byte has been sent)
|
||||
if ((q->uart->ISR & USART_ISR_TXE_TXFNF) != 0) {
|
||||
q->uart->TDR = q->elems_tx[q->r_ptr_tx]; // This clears TXE
|
||||
q->r_ptr_tx = (q->r_ptr_tx + 1U) % q->tx_fifo_size;
|
||||
}
|
||||
|
||||
// Enable TXE interrupt if there is still data to be sent
|
||||
if(q->r_ptr_tx != q->w_ptr_tx){
|
||||
q->uart->CR1 |= USART_CR1_TXEIE;
|
||||
} else {
|
||||
q->uart->CR1 &= ~USART_CR1_TXEIE;
|
||||
}
|
||||
}
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void uart_set_baud(USART_TypeDef *u, unsigned int baud) {
|
||||
// UART7 is connected to APB1 at 60MHz
|
||||
u->BRR = 60000000U / baud;
|
||||
}
|
||||
|
||||
// This read after reading ISR clears all error interrupts. We don't want compiler warnings, nor optimizations
|
||||
#define UART_READ_RDR(uart) volatile uint8_t t = (uart)->RDR; UNUSED(t);
|
||||
|
||||
void uart_interrupt_handler(uart_ring *q) {
|
||||
ENTER_CRITICAL();
|
||||
|
||||
// Read UART status. This is also the first step necessary in clearing most interrupts
|
||||
uint32_t status = q->uart->ISR;
|
||||
|
||||
// If RXFNE is set, perform a read. This clears RXFNE, ORE, IDLE, NF and FE
|
||||
if((status & USART_ISR_RXNE_RXFNE) != 0U){
|
||||
uart_rx_ring(q);
|
||||
}
|
||||
|
||||
// Detect errors and clear them
|
||||
uint32_t err = (status & USART_ISR_ORE) | (status & USART_ISR_NE) | (status & USART_ISR_FE) | (status & USART_ISR_PE);
|
||||
if(err != 0U){
|
||||
#ifdef DEBUG_UART
|
||||
print("Encountered UART error: "); puth(err); print("\n");
|
||||
#endif
|
||||
UART_READ_RDR(q->uart)
|
||||
}
|
||||
|
||||
if ((err & USART_ISR_ORE) != 0U) {
|
||||
q->uart->ICR |= USART_ICR_ORECF;
|
||||
} else if ((err & USART_ISR_NE) != 0U) {
|
||||
q->uart->ICR |= USART_ICR_NECF;
|
||||
} else if ((err & USART_ISR_FE) != 0U) {
|
||||
q->uart->ICR |= USART_ICR_FECF;
|
||||
} else if ((err & USART_ISR_PE) != 0U) {
|
||||
q->uart->ICR |= USART_ICR_PECF;
|
||||
} else {}
|
||||
|
||||
// Send if necessary
|
||||
uart_tx_ring(q);
|
||||
|
||||
EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
void UART7_IRQ_Handler(void) { uart_interrupt_handler(&uart_ring_som_debug); }
|
||||
|
||||
void uart_init(uart_ring *q, int baud) {
|
||||
if (q->uart == UART7) {
|
||||
REGISTER_INTERRUPT(UART7_IRQn, UART7_IRQ_Handler, 150000U, FAULT_INTERRUPT_RATE_UART_7)
|
||||
|
||||
uart_set_baud(q->uart, baud);
|
||||
q->uart->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE;
|
||||
|
||||
// Enable interrupt on RX not empty
|
||||
q->uart->CR1 |= USART_CR1_RXNEIE;
|
||||
|
||||
// Enable UART interrupts
|
||||
NVIC_EnableIRQ(UART7_IRQn);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user