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.
344 lines
7.0 KiB
344 lines
7.0 KiB
|
3 days ago
|
#include "bsp_config.h"
|
||
|
|
#ifdef USE_PRINT
|
||
|
|
#include <stdio.h>
|
||
|
|
#include <stdint.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include <unistd.h>
|
||
|
|
#include <errno.h>
|
||
|
|
#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
|