/** ****************************************************************************** * @file uart2_print.c * @brief UART2调试打印模块实现 * @author Application Layer * @version 1.1 ****************************************************************************** * @attention * 本模块实现基于环形缓冲区的非阻塞调试信息输出 * 关键特性: * 1. 环形缓冲区避免数据丢失 * 2. 中断安全,支持ISR中调用 * 3. 非阻塞发送,不影响实时性 * * 修订历史: * v1.1 - 修复审查报告高危-1/2/3,中危-4 ****************************************************************************** */ #include "uart2_print.h" #include "usart.h" #include #include #define DEBUG_PRINT_ENABLED 1 #if DEBUG_PRINT_ENABLED #define DEBUG_LOG(fmt, ...) UART2_Print_Printf("[UART2] " fmt "\r\n", ##__VA_ARGS__) #else #define DEBUG_LOG(fmt, ...) #endif typedef struct { uint8_t buffer[UART2_TX_BUFFER_SIZE]; volatile uint16_t head; volatile uint16_t tail; volatile uint16_t count; volatile bool is_sending; volatile uint16_t overflow_count; } ring_buffer_t; static ring_buffer_t tx_ring = {0}; void UART2_Print_Init(void) { tx_ring.head = 0; tx_ring.tail = 0; tx_ring.count = 0; tx_ring.is_sending = false; tx_ring.overflow_count = 0; DEBUG_LOG("Init OK, buffer size: %d", UART2_TX_BUFFER_SIZE); } void UART2_Print_Send(const uint8_t *data, uint16_t len) { if (len == 0 || data == NULL) { return; } uint16_t written = 0; bool needs_kickoff = false; __disable_irq(); for (uint16_t i = 0; i < len; i++) { if (tx_ring.count >= UART2_TX_BUFFER_SIZE) { tx_ring.overflow_count++; break; } tx_ring.buffer[tx_ring.head] = data[i]; tx_ring.head = (tx_ring.head + 1) % UART2_TX_BUFFER_SIZE; tx_ring.count++; written++; } if (written > 0 && !tx_ring.is_sending) { tx_ring.is_sending = true; needs_kickoff = true; } __enable_irq(); if (needs_kickoff) { uint8_t byte; __disable_irq(); byte = tx_ring.buffer[tx_ring.tail]; __enable_irq(); HAL_UART_Transmit_IT(&huart2, &byte, 1); } } void UART2_Print_String(const char *str) { if (str == NULL) { return; } UART2_Print_Send((const uint8_t *)str, strlen(str)); } void UART2_Print_Printf(const char *fmt, ...) { if (fmt == NULL) { return; } char buffer[128]; va_list args; va_start(args, fmt); int len = vsnprintf(buffer, sizeof(buffer), fmt, args); va_end(args); if (len >= 0) { if (len >= (int)sizeof(buffer)) { len = sizeof(buffer) - 1; } UART2_Print_Send((const uint8_t *)buffer, len); } } void UART2_Print_Task(void) { uint8_t byte; uint16_t current_tail; __disable_irq(); if (tx_ring.is_sending || tx_ring.count == 0) { __enable_irq(); return; } current_tail = tx_ring.tail; tx_ring.tail = (tx_ring.tail + 1) % UART2_TX_BUFFER_SIZE; tx_ring.count--; tx_ring.is_sending = true; byte = tx_ring.buffer[current_tail]; __enable_irq(); HAL_UART_Transmit_IT(&huart2, &byte, 1); } void UART2_Print_TxCpltCallback(void) { uint8_t byte; uint16_t current_tail; bool has_more = false; __disable_irq(); tx_ring.is_sending = false; if (tx_ring.count > 0) { current_tail = tx_ring.tail; tx_ring.tail = (tx_ring.tail + 1) % UART2_TX_BUFFER_SIZE; tx_ring.count--; tx_ring.is_sending = true; byte = tx_ring.buffer[current_tail]; has_more = true; } __enable_irq(); if (has_more) { HAL_UART_Transmit_IT(&huart2, &byte, 1); } } bool UART2_Print_IsBusy(void) { bool busy; __disable_irq(); busy = tx_ring.is_sending || (tx_ring.count > 0); __enable_irq(); return busy; } uint16_t UART2_Print_Available(void) { uint16_t available; __disable_irq(); available = UART2_TX_BUFFER_SIZE - tx_ring.count; __enable_irq(); return available; } uint16_t UART2_Print_GetOverflowCount(void) { return tx_ring.overflow_count; } /** * @brief printf重定向函数 (Keil MDK) * @note 重定向标准库printf到UART2 * @param ch: 待发送字符 * @param f: 文件指针(未使用) * @retval 发送的字符 */ #if defined(__CC_ARM) || defined(__ARMCC_VERSION) int fputc(int ch, FILE *f) { (void)f; UART2_Print_Send((uint8_t *)&ch, 1); return ch; } #endif /** * @brief printf重定向函数 (GCC) * @note 重定向标准库printf到UART2 * @param ch: 待发送字符 * @retval 发送的字符 */ #if defined(__GNUC__) int __io_putchar(int ch) { UART2_Print_Send((uint8_t *)&ch, 1); return ch; } int _write(int file, char *ptr, int len) { (void)file; UART2_Print_Send((uint8_t *)ptr, len); return len; } #endif