#include "uart_driver.h" #include "py32md530.h" #include "system_py32md530.h" #include "system_driver.h" #include "config.h" #include #define UART_FIFO_SIZE 256 typedef struct { uint8_t buffer[UART_FIFO_SIZE]; volatile uint32_t head; volatile uint32_t tail; uint8_t initialized; } uart_fifo_t; static uart_fifo_t uart_fifos[UART_ID_COUNT]; static uart_stats_t uart_statistics[UART_ID_COUNT]; static void uart_fifo_init(uart_fifo_t *fifo) { fifo->head = 0; fifo->tail = 0; fifo->initialized = 1; } static void uart_stats_init(void) { uint32_t i; for (i = 0; i < UART_ID_COUNT; i++) { uart_statistics[i].tx_bytes = 0; uart_statistics[i].rx_bytes = 0; uart_statistics[i].overflow_errors = 0; } } static void uart_fifo_push(uart_fifo_t *fifo, uint8_t data) { uint32_t next = (fifo->head + 1) % UART_FIFO_SIZE; if (next != fifo->tail) { fifo->buffer[fifo->head] = data; fifo->head = next; } } static uint32_t uart_fifo_pop(uart_fifo_t *fifo, uint8_t *data) { if (fifo->tail == fifo->head) { return 0; } *data = fifo->buffer[fifo->tail]; fifo->tail = (fifo->tail + 1) % UART_FIFO_SIZE; return 1; } static uint32_t uart_fifo_count(uart_fifo_t *fifo) { return (fifo->head - fifo->tail) % UART_FIFO_SIZE; } void USART1_IRQHandler(void) { if (USART1->SR & USART_SR_RXNE_Msk) { uint8_t data = (uint8_t)(USART1->DR & 0xFF); uart_statistics[UART_ID_USART1].rx_bytes++; { uint32_t next = (uart_fifos[UART_ID_USART1].head + 1) % UART_FIFO_SIZE; if (next == uart_fifos[UART_ID_USART1].tail) { uart_statistics[UART_ID_USART1].overflow_errors++; } } uart_fifo_push(&uart_fifos[UART_ID_USART1], data); } if (USART1->SR & USART_SR_TC_Msk) { USART1->SR &= ~USART_SR_TC_Msk; } } void UART1_IRQHandler(void) { if (UART1->SR & USART_SR_RXNE_Msk) { uint8_t data = (uint8_t)(UART1->DR & 0xFF); uart_statistics[UART_ID_UART1].rx_bytes++; { uint32_t next = (uart_fifos[UART_ID_UART1].head + 1) % UART_FIFO_SIZE; if (next == uart_fifos[UART_ID_UART1].tail) { uart_statistics[UART_ID_UART1].overflow_errors++; } } uart_fifo_push(&uart_fifos[UART_ID_UART1], data); } if (UART1->SR & USART_SR_TC_Msk) { UART1->SR &= ~USART_SR_TC_Msk; } } void LPUART1_IRQHandler(void) { if (LPUART1->ISR & (1UL << 5)) { uint8_t data = (uint8_t)(LPUART1->DR & 0xFF); uart_statistics[UART_ID_LPUART1].rx_bytes++; { uint32_t next = (uart_fifos[UART_ID_LPUART1].head + 1) % UART_FIFO_SIZE; if (next == uart_fifos[UART_ID_LPUART1].tail) { uart_statistics[UART_ID_LPUART1].overflow_errors++; } } uart_fifo_push(&uart_fifos[UART_ID_LPUART1], data); } } static ret_code_t usart1_init(const uart_config_t *config) { uint32_t brr; RCC->APB2ENR |= RCC_APB2ENR_USART1EN; USART1->CR1 &= ~USART_CR1_UE_Msk; brr = (SystemCoreClock + config->baudrate / 2) / config->baudrate; USART1->BRR = brr; USART1->CR1 = USART_CR1_UE_Msk | USART_CR1_TE_Msk | USART_CR1_RE_Msk | USART_CR1_RXNEIE_Msk; USART1->CR3 = USART_CR3_DMAR_Msk | USART_CR3_DMAT_Msk; NVIC_SetPriority(USART1_IRQn, 0x08); NVIC_EnableIRQ(USART1_IRQn); uart_stats_init(); uart_fifo_init(&uart_fifos[UART_ID_USART1]); return RET_OK; } static ret_code_t uart1_init(const uart_config_t *config) { uint32_t brr; RCC->APB1ENR |= RCC_APB1ENR_UART1EN; UART1->CR1 &= ~USART_CR1_UE_Msk; brr = (SystemCoreClock + config->baudrate / 2) / config->baudrate; UART1->BRR = brr; UART1->CR1 = USART_CR1_UE_Msk | USART_CR1_TE_Msk | USART_CR1_RE_Msk | USART_CR1_RXNEIE_Msk; UART1->CR3 = USART_CR3_DMAR_Msk | USART_CR3_DMAT_Msk; NVIC_SetPriority(UART1_IRQn, 0x08); NVIC_EnableIRQ(UART1_IRQn); uart_fifo_init(&uart_fifos[UART_ID_UART1]); return RET_OK; } static ret_code_t lpuart1_init(const uart_config_t *config) { RCC->APB1ENR |= RCC_APB1ENR_LPUART1EN; LPUART1->CR1 &= ~(1UL << 0); LPUART1->BRR = (256 * SystemCoreClock + config->baudrate / 2) / config->baudrate; LPUART1->CR1 = (1UL << 0) | (1UL << 2) | (1UL << 3) | (1UL << 5); NVIC_SetPriority(LPUART1_IRQn, 0x08); NVIC_EnableIRQ(LPUART1_IRQn); uart_fifo_init(&uart_fifos[UART_ID_LPUART1]); return RET_OK; } ret_code_t uart_init(uart_id_t id, const uart_config_t *config) { if (id >= UART_ID_COUNT || config == NULL) { return RET_INVALID_PARAM; } switch (id) { case UART_ID_USART1: return usart1_init(config); case UART_ID_UART1: return uart1_init(config); case UART_ID_LPUART1: return lpuart1_init(config); default: return RET_ERROR; } } ret_code_t uart_deinit(uart_id_t id) { switch (id) { case UART_ID_USART1: NVIC_DisableIRQ(USART1_IRQn); USART1->CR1 = 0; RCC->APB2ENR &= ~RCC_APB2ENR_USART1EN; break; case UART_ID_UART1: NVIC_DisableIRQ(UART1_IRQn); UART1->CR1 = 0; RCC->APB1ENR &= ~RCC_APB1ENR_UART1EN; break; case UART_ID_LPUART1: NVIC_DisableIRQ(LPUART1_IRQn); LPUART1->CR1 = 0; RCC->APB1ENR &= ~RCC_APB1ENR_LPUART1EN; break; default: return RET_INVALID_PARAM; } return RET_OK; } ret_code_t uart_send(uart_id_t id, const uint8_t *data, uint32_t len) { uint32_t i; if (id == UART_ID_USART1) { uart_set_rs485_dir(UART_ID_USART1, 1); } for (i = 0; i < len; i++) { switch (id) { case UART_ID_USART1: while (!(USART1->SR & USART_SR_TXE_Msk)); USART1->DR = data[i]; while (!(USART1->SR & USART_SR_TC_Msk)); uart_statistics[UART_ID_USART1].tx_bytes++; break; case UART_ID_UART1: while (!(UART1->SR & USART_SR_TXE_Msk)); UART1->DR = data[i]; while (!(UART1->SR & USART_SR_TC_Msk)); uart_statistics[UART_ID_UART1].tx_bytes++; break; case UART_ID_LPUART1: while (!(LPUART1->ISR & (1UL << 0))); LPUART1->DR = data[i]; uart_statistics[UART_ID_LPUART1].tx_bytes++; break; default: return RET_INVALID_PARAM; } } if (id == UART_ID_USART1) { volatile uint32_t delay = (SystemCoreClock / 1000000) * 2; while (delay--); uart_set_rs485_dir(UART_ID_USART1, 0); } return RET_OK; } ret_code_t uart_receive(uart_id_t id, uint8_t *data, uint32_t len, uint32_t timeout) { uint32_t i; uint32_t tick_start = 0; if (timeout > 0) { tick_start = system_get_tick(); } for (i = 0; i < len; i++) { while (uart_fifo_count(&uart_fifos[id]) == 0) { if (timeout > 0) { if ((system_get_tick() - tick_start) >= timeout) { return RET_TIMEOUT; } } } uart_fifo_pop(&uart_fifos[id], &data[i]); } return RET_OK; } ret_code_t uart_send_dma(uart_id_t id, const uint8_t *data, uint32_t len) { return uart_send(id, data, len); } ret_code_t uart_receive_dma(uart_id_t id, uint8_t *data, uint32_t len) { return uart_receive(id, data, len, 0); } uint32_t uart_available(uart_id_t id) { return uart_fifo_count(&uart_fifos[id]); } ret_code_t uart_set_rs485_dir(uart_id_t id, uint8_t tx_mode) { if (id != UART_ID_USART1) { return RET_NOT_SUPPORTED; } if (tx_mode) { USART1_RS485_DIR_PORT->BSRR = (1UL << USART1_RS485_DIR_PIN); } else { USART1_RS485_DIR_PORT->BRR = (1UL << USART1_RS485_DIR_PIN); } return RET_OK; } const uart_stats_t* uart_get_stats(uart_id_t id) { if (id >= UART_ID_COUNT) { return NULL; } return &uart_statistics[id]; } void uart_reset_stats(uart_id_t id) { if (id >= UART_ID_COUNT) { return; } uart_statistics[id].tx_bytes = 0; uart_statistics[id].rx_bytes = 0; uart_statistics[id].overflow_errors = 0; }