588 lines
22 KiB
C
588 lines
22 KiB
C
/* 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 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];
|
||
|
||
/* 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, ¶m_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, ¶m_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,
|
||
"[第 %u/%u 次]\r\n", current_iteration + 1, 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,
|
||
"[第 %u/%u 次] === %s ===\r\n",
|
||
current_iteration + 1, 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);
|
||
|
||
/* 发送欢迎消息 */
|
||
const char *welcome = "\r\n\r\n"
|
||
"================================\r\n"
|
||
" MRobot CLI v1.0\r\n"
|
||
" 输入 'help' 获取帮助\r\n"
|
||
"================================\r\n"
|
||
"root@mrobot:~$ ";
|
||
tx_complete = false;
|
||
BSP_UART_Transmit(BSP_UART_VOFA, (uint8_t *)welcome, strlen(welcome), 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);
|
||
}
|
||
|
||
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);
|
||
}
|