#include "bsp_config.h" #ifdef USE_PRINT #include #include #include #include #include #include "main.h" #include "bsp_uart.h" #include "rd_time.h" #include "bsp_config.h" #ifdef USE_FREERTOS #include "cmsis_os.h" #endif #ifndef PRINT_ID #include "bsp_usb.h" #endif #ifdef USE_LUA_ST extern volatile uint8_t g_lua_stop_request; #endif // 定义流控字符 #define CHAR_XOFF 0x13 #define CHAR_XON 0x11 #define RINGBUF_LOW_WATER_MARK 64 // 全局标志:是否已经发送了 XOFF volatile uint8_t g_flow_control_paused = 0; TComCtrl *g_ptUartCtrl; int USART_Send(char *_pBuffer, uint32_t _iSize) { HAL_GPIO_WritePin(GPIOD, GPIO_PIN_10,GPIO_PIN_SET); TUartUserData *ptUartUserData = (TUartUserData *)g_ptUartCtrl->m_pUserData; int iRet = HAL_UART_Transmit(ptUartUserData->m_uart, (uint8_t *)_pBuffer, _iSize, 100); HAL_GPIO_WritePin(GPIOD, GPIO_PIN_10,GPIO_PIN_RESET); return iRet; } /*int Dev01check(char *_pBuffer, uint32_t _iSize) { static int iStat = 0; for (int i = 0; i < _iSize; i++) { switch (iStat) { case 0: if (_pBuffer[i] == 0x10) { iStat = 1; continue; } return -1; case 1: if (_pBuffer[i] == 0x11) { iStat = 2; continue; } else { iStat = 0; return 0; } case 2: if (_pBuffer[i] == 0x12) { iStat = 0; return 3; } else { iStat = 0; return 0; } break; default: break; } } return -1; } void Dev01decode(const char *_pBuffer, uint32_t _iSize) { printf("This is dev 01 \r\n"); } int Dev02check(char *_pBuffer, uint32_t _iSize) { if (_iSize < 3) return 0; if (_pBuffer[0] != 0x20) { return -1; } if (_pBuffer[1] != 0x21) { return -1; } if (_pBuffer[2] == 0x22) { return 3; } else { return -1; } } void Dev02decode(const char *_pBuffer, uint32_t _iSize) { printf("This is dev 02 \r\n"); } int Dev03check(char *_pBuffer, uint32_t _iSize) { if (_iSize < 2) return 0; // 至少要有头和长度域 // 1. 找头 if (_pBuffer[0] != 0xAA) return -1; // 2. 读长度 (假设第2个字节是长度) uint8_t len = _pBuffer[1]; uint32_t total_len = 2 + len + 1; // 头+长度域+数据+尾 // 3. 检查数据够不够 if (_iSize < total_len) return 0; // 数据没到齐,继续等 // 4. 验尾 if (_pBuffer[total_len - 1] == 0x55) // 检查最后一个字节 { return total_len; // 成功 } else { return -1; // 尾不对,丢弃头,重新找 } } void Dev03decode(const char *_pBuffer, uint32_t _iSize) { printf("This is dev 03 \r\n"); }*/ WEAK void Myprint_Init(void) { #ifdef PRINT_ID TUartUserData *ptUartUserData = UART_userdata_init(PRINT_ID, 115200, 4096); g_ptUartCtrl = rd_ComCreate(NULL, NULL, USART_Send, ptUartUserData->m_buf_size, ptUartUserData); UART_IT_init(g_ptUartCtrl); #else g_ptUartCtrl = bsp_usb_init(); #endif // g_ptUartCtrl = rd_ComCreate(Dev01check, Dev01decode, USART_Send, ptUartUserData->m_buf_size, ptUartUserData); // rd_ComAddDev(g_ptUartCtrl, Dev02check, Dev02decode); // rd_ComAddDev(g_ptUartCtrl, Dev03check, Dev03decode); } WEAK void Myprint_timer(void) { //rd_ComSendProc(g_ptUartCtrl); } WEAK void Myprint_IRQHandler(void) { #ifdef PRINT_ID UART_DMA_RX_IRQHandler(g_ptUartCtrl); #endif } /** * @brief 底层单字符发送 (带 \n -> \r\n 转换) * 这是发送端的“原子操作”,其他发送函数都基于它 */ WEAK int Myprint_putchar(uint8_t ch) { char tx_buf[2]; if (ch == '\n') { // 遇到换行,发送 \r\n tx_buf[0] = '\r'; tx_buf[1] = '\n'; if (rd_ComSend(g_ptUartCtrl, tx_buf, 2) < 0) return EOF; return 2; } else { // 普通字符 tx_buf[0] = ch; if (rd_ComSend(g_ptUartCtrl, tx_buf, 1) < 0) return EOF; return 1; } } /** * @brief 重定向 fputc (单字符输出) * 用于 printf, putchar 等 */ int fputc(int ch, FILE *f) { if (Myprint_putchar((uint8_t)ch) == EOF) { return EOF; } return ch; } /** * @brief 重定向 _write (块输出) * 用于 fwrite, 以及某些库的 printf 实现 * 策略:循环调用 fputc,确保行为完全一致(包括换行处理) */ ssize_t _write(int file, char *ptr, ssize_t len) { if (file == STDOUT_FILENO || file == STDERR_FILENO || file == STDIN_FILENO) { ssize_t i; for (i = 0; i < len; i++) { if (fputc(ptr[i], stdout) == EOF) { break; } } return i; } errno = EBADF; return -1; } /** * @brief 底层单字符读取 (从 RingBuffer) * 阻塞直到有数据,支持 0x04 作为 EOF */ WEAK void Myprint_getchar(char *ch) { while (1) { int ret; __disable_irq(); ret = rd_ComRead(g_ptUartCtrl, ch, 1); __enable_irq(); if (ret == 1) { return; } #ifdef USE_FREERTOS osDelay(1); #endif #ifdef USE_TIMER // 轮询发送 void tim_main_loop(void); tim_main_loop(); #endif // 无数据,低功耗等待 (确保 SysTick 或其他中断能唤醒) //__WFI(); } } /** * @brief 重定向 fgetc (单字符输入) * 用于 getchar, fgetc */ int fgetc(FILE *f) { char ch; Myprint_getchar(&ch); if ((uint8_t)ch == 0x04) { #ifdef USE_LUA_ST g_lua_stop_request = 1; #endif return EOF; } return (int)(unsigned char)ch; } /** * @brief 重定向 _read (块输入) * 用于 fread, scanf, read * 策略:循环调用底层读取逻辑,确保与 fgetc 行为一致 */ ssize_t _read(int file, char *ptr, ssize_t len) { if (file == STDIN_FILENO) { int i = 0; while (i < len) { char ch; Myprint_getchar(&ch); ptr[i++] = ch; // 遇到换行符,通常认为一行结束 (配合 scanf) // 注意:这里不自动丢弃 \r 后的 \n,由上层应用决定 if (ch == '\r' || ch == '\n') { break; } } return i; } errno = EBADF; return -1; } void Flow_control_before(void) { TUartUserData *ptUartUserData = (TUartUserData *)g_ptUartCtrl->m_pUserData; int space_left = ptUartUserData->m_buf_size - rd_RingbufferDataLen(g_ptUartCtrl->m_stComBuf.m_ptRecv); if (space_left < RINGBUF_LOW_WATER_MARK && !g_flow_control_paused) { fputc(CHAR_XOFF, stdout); g_flow_control_paused = 1; Rd_Delay(1); } } void Flow_control_after(void) { if (g_flow_control_paused) { fputc(CHAR_XON, stdout); g_flow_control_paused = 0; Rd_Delay(1); } } #endif