rm_balance/User/device/mrobot.c
2026-02-04 12:43:11 +08:00

644 lines
25 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* Includes ----------------------------------------------------------------- */
#include "device/mrobot.h"
#include "device/device.h"
#include "device/motor.h"
#include "component/freertos_cli.h"
#include "bsp/uart.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <FreeRTOS.h>
#include <task.h>
#include <cmsis_os2.h>
/* Private constants -------------------------------------------------------- */
static const char *const CLI_WELCOME_MESSAGE =
"\r\n"
" ______ __ _______ __ \r\n"
" | __ \\.-----.| |--.-----.| | |.---.-.-----.| |-.-----.-----.\r\n"
" | <| _ || _ | _ || || _ |__ --|| _| -__| _|\r\n"
" |___|__||_____||_____|_____||__|_|__||___._|_____||____|_____|__| \r\n"
" -------------------------------------------------------------------\r\n"
" FreeRTOS CLI. Type 'help' to view a list of registered commands. \r\n"
"\r\n";
/* Private variables -------------------------------------------------------- */
static MRobot_Device_t devices[MROBOT_MAX_DEVICES];
static uint8_t device_count = 0;
static char current_path[64] = "/";
static char output_buffer[MROBOT_MAX_OUTPUT_LEN];
/* 自定义命令存储最多16个 */
#define MROBOT_MAX_CUSTOM_COMMANDS 16
static CLI_Command_Definition_t *custom_commands[MROBOT_MAX_CUSTOM_COMMANDS];
static uint8_t custom_command_count = 0;
/* UART 相关变量 */
static uint8_t uart_rx_char;
static uint8_t cmd_buffer[128];
static volatile uint8_t cmd_index = 0;
static volatile bool cmd_ready = false;
static volatile bool htop_mode = false;
static volatile bool htop_exit = false;
static volatile bool tx_complete = true;
/* Private function prototypes ---------------------------------------------- */
static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
static BaseType_t cmd_htop(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
static BaseType_t cmd_ls(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
static BaseType_t cmd_pwd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
/* CLI 命令定义 */
static const CLI_Command_Definition_t cmd_def_help = {
"help",
"help: 显示所有可用命令\r\n",
cmd_help,
0
};
static const CLI_Command_Definition_t cmd_def_htop = {
"htop",
"htop: 动态显示 FreeRTOS 任务状态 (按 'q' 退出)\r\n",
cmd_htop,
0
};
static const CLI_Command_Definition_t cmd_def_cd = {
"cd",
"cd <path>: 切换目录\r\n",
cmd_cd,
1
};
static const CLI_Command_Definition_t cmd_def_ls = {
"ls",
"ls: 列出当前目录内容\r\n",
cmd_ls,
0
};
static const CLI_Command_Definition_t cmd_def_show = {
"show",
"show [device] [count]: 显示设备信息count 默认为 1\r\n",
cmd_show,
-1 /* 可变参数 */
};
static const CLI_Command_Definition_t cmd_def_pwd = {
"pwd",
"pwd: 显示当前目录\r\n",
cmd_pwd,
0
};
/* Private functions -------------------------------------------------------- */
/* 通用 IMU 设备打印函数 */
static void mrobot_print_imu(void *device_data, char *buffer, uint16_t buffer_size) {
DEVICE_IMU_t *imu = (DEVICE_IMU_t *)device_data;
/* 将浮点数转换为整数和小数部分,避免 printf 浮点数支持问题 */
int accl_x_int = (int)(imu->accl.x);
int accl_x_frac = (int)((imu->accl.x - accl_x_int) * 1000);
int accl_y_int = (int)(imu->accl.y);
int accl_y_frac = (int)((imu->accl.y - accl_y_int) * 1000);
int accl_z_int = (int)(imu->accl.z);
int accl_z_frac = (int)((imu->accl.z - accl_z_int) * 1000);
int gyro_x_int = (int)(imu->gyro.x);
int gyro_x_frac = (int)((imu->gyro.x - gyro_x_int) * 1000);
int gyro_y_int = (int)(imu->gyro.y);
int gyro_y_frac = (int)((imu->gyro.y - gyro_y_int) * 1000);
int gyro_z_int = (int)(imu->gyro.z);
int gyro_z_frac = (int)((imu->gyro.z - gyro_z_int) * 1000);
int temp_int = (int)(imu->temp);
int temp_frac = (int)((imu->temp - temp_int) * 100);
float roll_deg = imu->euler.rol * 57.2958f;
float pitch_deg = imu->euler.pit * 57.2958f;
float yaw_deg = imu->euler.yaw * 57.2958f;
int roll_int = (int)roll_deg;
int roll_frac = (int)((roll_deg - roll_int) * 100);
int pitch_int = (int)pitch_deg;
int pitch_frac = (int)((pitch_deg - pitch_int) * 100);
int yaw_int = (int)yaw_deg;
int yaw_frac = (int)((yaw_deg - yaw_int) * 100);
snprintf(buffer, buffer_size,
"状态: %s\r\n"
"加速度计: X=%d.%03d Y=%d.%03d Z=%d.%03d m/s²\r\n"
"陀螺仪: X=%d.%03d Y=%d.%03d Z=%d.%03d rad/s\r\n"
"温度: %d.%02d °C\r\n"
"欧拉角: Roll=%d.%02d Pitch=%d.%02d Yaw=%d.%02d °\r\n",
imu->header.online ? "在线" : "离线",
accl_x_int, abs(accl_x_frac), accl_y_int, abs(accl_y_frac), accl_z_int, abs(accl_z_frac),
gyro_x_int, abs(gyro_x_frac), gyro_y_int, abs(gyro_y_frac), gyro_z_int, abs(gyro_z_frac),
temp_int, abs(temp_frac),
roll_int, abs(roll_frac), pitch_int, abs(pitch_frac), yaw_int, abs(yaw_frac));
}
/* 通用电机设备打印函数 */
static void mrobot_print_motor(void *device_data, char *buffer, uint16_t buffer_size) {
MOTOR_t *motor = (MOTOR_t *)device_data;
int angle_int = (int)(motor->feedback.rotor_abs_angle);
int angle_frac = (int)((motor->feedback.rotor_abs_angle - angle_int) * 100);
int speed_int = (int)(motor->feedback.rotor_speed);
int speed_frac = (int)((motor->feedback.rotor_speed - speed_int) * 100);
int current_int = (int)(motor->feedback.torque_current);
int current_frac = (int)((motor->feedback.torque_current - current_int) * 100);
int temp_int = (int)(motor->feedback.temp);
int temp_frac = (int)((motor->feedback.temp - temp_int) * 10);
snprintf(buffer, buffer_size,
"状态: %s\r\n"
"反装: %s\r\n"
"角度: %d.%02d °\r\n"
"转速: %d.%02d RPM\r\n"
"电流: %d.%02d A\r\n"
"温度: %d.%01d °C\r\n",
motor->header.online ? "在线" : "离线",
motor->reverse ? "" : "",
angle_int, abs(angle_frac),
speed_int, abs(speed_frac),
current_int, abs(current_frac),
temp_int, abs(temp_frac));
}
/* help 命令实现 */
static BaseType_t cmd_help(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
(void)pcCommandString;
snprintf(pcWriteBuffer, xWriteBufferLen,
"MRobot CLI v1.0\r\n"
"可用命令:\r\n"
" help - 显示帮助信息\r\n"
" htop - 动态显示任务状态 (按 'q' 退出)\r\n"
" cd - 切换目录\r\n"
" ls - 列出目录内容\r\n"
" pwd - 显示当前路径\r\n"
" show - 显示设备信息\r\n"
"\r\n");
return pdFALSE;
}
/* htop 命令实现 - 由 cli.c 处理动态显示 */
static BaseType_t cmd_htop(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
(void)pcCommandString;
(void)pcWriteBuffer;
(void)xWriteBufferLen;
/* htop 命令在 cli.c 中被特殊处理,这里返回空 */
return pdFALSE;
}
/* pwd 命令实现 */
static BaseType_t cmd_pwd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
(void)pcCommandString;
snprintf(pcWriteBuffer, xWriteBufferLen, "%s\r\n", current_path);
return pdFALSE;
}
/* cd 命令实现 */
static BaseType_t cmd_cd(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
const char *param;
BaseType_t param_len;
param = FreeRTOS_CLIGetParameter(pcCommandString, 1, &param_len);
if (param != NULL) {
char path[64];
strncpy(path, param, param_len);
path[param_len] = '\0';
if (strcmp(path, "/") == 0 || strcmp(path, "..") == 0) {
strcpy(current_path, "/");
} else if (strcmp(path, "dev") == 0 || strcmp(path, "/dev") == 0) {
strcpy(current_path, "/dev");
} else if (strcmp(path, "modules") == 0 || strcmp(path, "/modules") == 0) {
strcpy(current_path, "/modules");
} else {
snprintf(pcWriteBuffer, xWriteBufferLen, "错误: 目录不存在\r\n");
return pdFALSE;
}
snprintf(pcWriteBuffer, xWriteBufferLen, "切换到: %s\r\n", current_path);
} else {
snprintf(pcWriteBuffer, xWriteBufferLen, "错误: 缺少路径参数\r\n");
}
return pdFALSE;
}
/* ls 命令实现 */
static BaseType_t cmd_ls(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
(void)pcCommandString;
int offset = 0;
if (strcmp(current_path, "/") == 0) {
offset = snprintf(pcWriteBuffer, xWriteBufferLen, "dev/\r\nmodules/\r\n");
} else if (strcmp(current_path, "/dev") == 0) {
offset = snprintf(pcWriteBuffer, xWriteBufferLen, "设备列表:\r\n");
for (uint8_t i = 0; i < device_count && offset < (int)xWriteBufferLen; i++) {
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
" %s\r\n", devices[i].name);
}
if (device_count == 0) {
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
" (无设备)\r\n");
}
} else if (strcmp(current_path, "/modules") == 0) {
offset = snprintf(pcWriteBuffer, xWriteBufferLen, "(模块功能暂未实现)\r\n");
}
return pdFALSE;
}
/* show 命令实现 */
static BaseType_t cmd_show(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString) {
const char *param;
const char *count_param;
BaseType_t param_len, count_param_len;
static uint32_t print_count = 0;
static uint32_t current_iteration = 0;
static char saved_device_name[32] = {0};
/* 首次调用时解析参数 */
if (current_iteration == 0) {
param = FreeRTOS_CLIGetParameter(pcCommandString, 1, &param_len);
count_param = FreeRTOS_CLIGetParameter(pcCommandString, 2, &count_param_len);
if (strcmp(current_path, "/dev") != 0) {
snprintf(pcWriteBuffer, xWriteBufferLen, "错误: show 命令仅在 /dev 目录下可用\r\n");
return pdFALSE;
}
/* 解析打印次数,默认为 1 */
print_count = 1;
if (count_param != NULL) {
char count_str[16];
strncpy(count_str, count_param, count_param_len < 15 ? count_param_len : 15);
count_str[count_param_len < 15 ? count_param_len : 15] = '\0';
int parsed_count = atoi(count_str);
if (parsed_count > 0 && parsed_count <= 100) {
print_count = parsed_count;
}
}
/* 保存设备名称 */
if (param != NULL) {
strncpy(saved_device_name, param, param_len);
saved_device_name[param_len] = '\0';
} else {
saved_device_name[0] = '\0';
}
}
/* 执行打印 */
int offset = 0;
/* 多次打印时清屏像htop一样 */
if (print_count > 1) {
const char *clear = "\033[2J\033[H"; /* ANSI清屏 + 光标归位 */
offset = snprintf(pcWriteBuffer, xWriteBufferLen, "%s", clear);
}
if (saved_device_name[0] == '\0') {
/* 显示所有设备 */
if (print_count > 1) {
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
"[第 %lu/%lu 次]\r\n", (unsigned long)(current_iteration + 1), (unsigned long)print_count);
}
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset, "所有设备信息:\r\n");
for (uint8_t i = 0; i < device_count && offset < (int)xWriteBufferLen; i++) {
offset += snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
"\r\n=== %s ===\r\n", devices[i].name);
if (devices[i].print_callback != NULL) {
devices[i].print_callback(devices[i].data,
pcWriteBuffer + offset,
xWriteBufferLen - offset);
offset = strlen(pcWriteBuffer);
}
}
} else {
/* 显示特定设备 */
bool found = false;
for (uint8_t i = 0; i < device_count; i++) {
if (strcmp(devices[i].name, saved_device_name) == 0) {
found = true;
int offset = 0;
if (print_count > 1) {
offset = snprintf(pcWriteBuffer, xWriteBufferLen,
"[第 %lu/%lu 次] === %s ===\r\n",
(unsigned long)(current_iteration + 1), (unsigned long)print_count, devices[i].name);
} else {
offset = snprintf(pcWriteBuffer, xWriteBufferLen,
"=== %s ===\r\n", devices[i].name);
}
if (devices[i].print_callback != NULL) {
devices[i].print_callback(devices[i].data,
pcWriteBuffer + offset,
xWriteBufferLen - offset);
} else {
snprintf(pcWriteBuffer + offset, xWriteBufferLen - offset,
"无打印函数\r\n");
}
break;
}
}
if (!found && current_iteration == 0) {
snprintf(pcWriteBuffer, xWriteBufferLen, "错误: 设备 '%s' 未找到\r\n", saved_device_name);
current_iteration = 0;
return pdFALSE;
}
}
/* 判断是否需要继续打印 */
current_iteration++;
if (current_iteration < print_count) {
osDelay(200); /* 延时 200ms 再打印下一次 */
return pdTRUE; /* 返回 pdTRUE 表示还有更多输出 */
} else {
current_iteration = 0; /* 重置计数器 */
return pdFALSE;
}
}
/* UART 发送完成回调 */
static void mrobot_uart_tx_callback(void) {
tx_complete = true;
}
/* UART 接收中断回调 */
static void mrobot_uart_rx_callback(void) {
uint8_t ch = uart_rx_char;
/* 如果在 htop 模式,检查退出键 */
if (htop_mode) {
if (ch == 'q' || ch == 'Q' || ch == 27) { /* q 或 ESC */
htop_exit = true;
}
/* 重新启动接收 */
BSP_UART_Receive(BSP_UART_VOFA, &uart_rx_char, 1, false);
return;
}
if (ch == '\r' || ch == '\n') {
if (cmd_index > 0) {
cmd_buffer[cmd_index] = '\0';
cmd_ready = true;
/* 换行使用中断方式发送(数据量小) */
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)"\r\n", 2, false);
}
} else if (ch == 127 || ch == 8) { /* 退格键 */
if (cmd_index > 0) {
cmd_index--;
/* 回显退格(中断方式) */
const char *backspace = "\b \b";
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)backspace, 3, false);
}
} else if (ch >= 32 && ch < 127 && cmd_index < sizeof(cmd_buffer) - 1) {
/* 只接受可打印字符 */
cmd_buffer[cmd_index++] = ch;
/* 回显字符(中断方式) */
BSP_UART_Transmit(BSP_UART_VOFA, &ch, 1, false);
}
/* 重新启动接收 */
BSP_UART_Receive(BSP_UART_VOFA, &uart_rx_char, 1, false);
}
/* Exported functions ------------------------------------------------------- */
void MRobot_Init(void) {
/* 初始化设备数组 */
memset(devices, 0, sizeof(devices));
device_count = 0;
/* 注册 CLI 命令 */
FreeRTOS_CLIRegisterCommand(&cmd_def_help);
FreeRTOS_CLIRegisterCommand(&cmd_def_htop);
FreeRTOS_CLIRegisterCommand(&cmd_def_cd);
FreeRTOS_CLIRegisterCommand(&cmd_def_ls);
FreeRTOS_CLIRegisterCommand(&cmd_def_show);
FreeRTOS_CLIRegisterCommand(&cmd_def_pwd);
/* 注册 UART 回调 */
BSP_UART_RegisterCallback(BSP_UART_VOFA, BSP_UART_RX_CPLT_CB, mrobot_uart_rx_callback);
BSP_UART_RegisterCallback(BSP_UART_VOFA, BSP_UART_TX_CPLT_CB, mrobot_uart_tx_callback);
/* 启动 UART 接收 */
BSP_UART_Receive(BSP_UART_VOFA, &uart_rx_char, 1, false);
/* 等待用户按下回车键再显示欢迎消息 */
volatile bool enter_pressed = false;
while (!enter_pressed) {
if (uart_rx_char == '\r' || uart_rx_char == '\n') {
enter_pressed = true;
}
osDelay(10);
}
/* 发送欢迎消息 */
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)CLI_WELCOME_MESSAGE, strlen(CLI_WELCOME_MESSAGE), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
/* 发送提示符 */
const char *prompt = "root@mrobot:~$ ";
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)prompt, strlen(prompt), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
}
int8_t MRobot_RegisterDevice(const char *name, MRobot_DeviceType_t type,
void *data, MRobot_PrintCallback_t print_callback) {
if (device_count >= MROBOT_MAX_DEVICES) {
return -1;
}
if (name == NULL || data == NULL) {
return -1;
}
strncpy(devices[device_count].name, name, sizeof(devices[device_count].name) - 1);
devices[device_count].type = type;
devices[device_count].data = data;
devices[device_count].print_callback = print_callback;
device_count++;
return 0;
}
int8_t MRobot_RegisterIMU(const char *name, void *imu_device) {
return MRobot_RegisterDevice(name, MROBOT_DEVICE_TYPE_IMU, imu_device, mrobot_print_imu);
}
int8_t MRobot_RegisterMotor(const char *name, void *motor) {
return MRobot_RegisterDevice(name, MROBOT_DEVICE_TYPE_MOTOR, motor, mrobot_print_motor);
}
int8_t MRobot_RegisterCommand(const char *command, const char *help_text,
MRobot_CommandCallback_t callback, int8_t param_count) {
if (custom_command_count >= MROBOT_MAX_CUSTOM_COMMANDS) {
return -1; /* 命令数量已达上限 */
}
if (command == NULL || help_text == NULL || callback == NULL) {
return -1; /* 参数无效 */
}
/* 动态分配命令定义结构体 */
CLI_Command_Definition_t *cmd_def = (CLI_Command_Definition_t *)pvPortMalloc(sizeof(CLI_Command_Definition_t));
if (cmd_def == NULL) {
return -1; /* 内存分配失败 */
}
/* 强制转换以移除 const 限制(仅用于初始化) */
*(const char **)&cmd_def->pcCommand = command;
*(const char **)&cmd_def->pcHelpString = help_text;
*(pdCOMMAND_LINE_CALLBACK *)&cmd_def->pxCommandInterpreter = (pdCOMMAND_LINE_CALLBACK)callback;
cmd_def->cExpectedNumberOfParameters = param_count;
/* 注册到 FreeRTOS CLI */
FreeRTOS_CLIRegisterCommand(cmd_def);
/* 保存指针以便后续可能的清理(虽然一般不需要) */
custom_commands[custom_command_count] = cmd_def;
custom_command_count++;
return 0;
}
void MRobot_Run(void) {
/* 动态 htop 模式 */
if (htop_mode) {
/* 清屏并重置光标 */
const char *clear = "\033[2J\033[H";
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)clear, strlen(clear), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
/* 显示 htop 头部 */
const char *header =
"MRobot Task Monitor (按 'q' 退出)\r\n"
"================================================================================\r\n";
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)header, strlen(header), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
/* 获取任务列表 */
char task_buffer[1024];
vTaskList(task_buffer);
/* 格式化输出 */
char display_buffer[1536];
int offset = snprintf(display_buffer, sizeof(display_buffer),
"%-16s %-8s %-4s %-8s %-4s\r\n"
"--------------------------------------------------------------------------------\r\n",
"Task Name", "State", "Prio", "Stack", "Num");
/* 解析并美化任务列表 */
char *line = strtok(task_buffer, "\r\n");
while (line != NULL && offset < (int)sizeof(display_buffer) - 100) {
char name[17] = {0};
char state[9] = {0};
int prio = 0;
int stack = 0;
int num = 0;
if (sscanf(line, "%16s %c %d %d %d", name, &state[0], &prio, &stack, &num) == 5) {
/* 状态字符转换 */
const char *state_str = "?";
switch(state[0]) {
case 'R': state_str = "Running"; break;
case 'B': state_str = "Blocked"; break;
case 'S': state_str = "Suspend"; break;
case 'D': state_str = "Deleted"; break;
default: state_str = "Unknown"; break;
}
offset += snprintf(display_buffer + offset, sizeof(display_buffer) - offset,
"%-16s %-8s %-4d %-8d %-4d\r\n",
name, state_str, prio, stack, num);
}
line = strtok(NULL, "\r\n");
}
/* 添加运行时统计 */
offset += snprintf(display_buffer + offset, sizeof(display_buffer) - offset,
"--------------------------------------------------------------------------------\r\n"
"System Tick: %lu\r\n",
(unsigned long)xTaskGetTickCount());
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)display_buffer, strlen(display_buffer), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
/* 检查退出标志 */
if (htop_exit) {
htop_mode = false;
htop_exit = false;
/* 清屏 */
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)clear, strlen(clear), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
/* 显示提示符 */
char prompt[128];
snprintf(prompt, sizeof(prompt), "root@mrobot:%s$ ", current_path);
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)prompt, strlen(prompt), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
}
osDelay(200); /* 每 200ms 刷新一次5fps */
return;
}
/* 检查是否有命令需要处理 */
if (cmd_ready) {
/* 检查是否是 htop 命令 */
if (strcmp((char *)cmd_buffer, "htop") == 0) {
htop_mode = true;
htop_exit = false;
} else {
/* 处理其他命令 */
BaseType_t result;
output_buffer[0] = '\0'; /* 清空输出缓冲区 */
do {
result = FreeRTOS_CLIProcessCommand((char *)cmd_buffer,
output_buffer,
sizeof(output_buffer));
/* 立即发送输出 */
if (strlen(output_buffer) > 0) {
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)output_buffer, strlen(output_buffer), true);
while (!tx_complete) { osDelay(1); }
output_buffer[0] = '\0'; /* 清空缓冲区准备下一次 */
}
} while (result != pdFALSE);
/* 发送提示符 */
char prompt[128];
snprintf(prompt, sizeof(prompt), "root@mrobot:%s$ ", current_path);
tx_complete = false;
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)prompt, strlen(prompt), true);
while (!tx_complete) { osDelay(1); } /* 等待发送完成 */
}
/* 重置状态 */
cmd_index = 0;
cmd_ready = false;
}
osDelay(10);
}