mirror of
https://github.com/goldenfishs/MRobot.git
synced 2026-02-04 18:00:19 +08:00
313 lines
9.5 KiB
C
313 lines
9.5 KiB
C
/**
|
||
* @file mrobot.h
|
||
* @brief MRobot CLI - 基于 FreeRTOS CLI 的嵌入式调试命令行系统
|
||
*
|
||
* 功能特性:
|
||
* - 设备注册与监控(IMU、电机、传感器等)
|
||
* - 类 Unix 文件系统命令(cd, ls, pwd)
|
||
* - htop 风格的任务监控
|
||
* - 自定义命令扩展
|
||
* - 线程安全设计
|
||
*
|
||
* @example IMU 设备注册示例
|
||
* @code
|
||
* // 1. 定义 IMU 数据结构
|
||
* typedef struct {
|
||
* bool online;
|
||
* float accl[3];
|
||
* float gyro[3];
|
||
* float euler[3]; // roll, pitch, yaw (deg)
|
||
* float temp;
|
||
* } MyIMU_t;
|
||
*
|
||
* MyIMU_t my_imu;
|
||
*
|
||
* // 2. 实现打印回调
|
||
* static int print_imu(const void *data, char *buf, size_t size) {
|
||
* const MyIMU_t *imu = (const MyIMU_t *)data;
|
||
* return MRobot_Snprintf(buf, size,
|
||
* " Status: %s\r\n"
|
||
* " Accel : X=%.3f Y=%.3f Z=%.3f\r\n"
|
||
* " Euler : R=%.2f P=%.2f Y=%.2f\r\n"
|
||
* " Temp : %.1f C\r\n",
|
||
* imu->online ? "Online" : "Offline",
|
||
* imu->accl[0], imu->accl[1], imu->accl[2],
|
||
* imu->euler[0], imu->euler[1], imu->euler[2],
|
||
* imu->temp);
|
||
* }
|
||
*
|
||
* // 3. 注册设备
|
||
* MRobot_RegisterDevice("imu", &my_imu, print_imu);
|
||
* @endcode
|
||
*
|
||
* @example 电机设备注册示例
|
||
* @code
|
||
* typedef struct {
|
||
* bool online;
|
||
* float angle; // deg
|
||
* float speed; // RPM
|
||
* float current; // A
|
||
* } MyMotor_t;
|
||
*
|
||
* MyMotor_t motor[4];
|
||
*
|
||
* static int print_motor(const void *data, char *buf, size_t size) {
|
||
* const MyMotor_t *m = (const MyMotor_t *)data;
|
||
* return MRobot_Snprintf(buf, size,
|
||
* " Status : %s\r\n"
|
||
* " Angle : %.2f deg\r\n"
|
||
* " Speed : %.1f RPM\r\n"
|
||
* " Current: %.3f A\r\n",
|
||
* m->online ? "Online" : "Offline",
|
||
* m->angle, m->speed, m->current);
|
||
* }
|
||
*
|
||
* // 注册 4 个电机
|
||
* MRobot_RegisterDevice("motor0", &motor[0], print_motor);
|
||
* MRobot_RegisterDevice("motor1", &motor[1], print_motor);
|
||
* MRobot_RegisterDevice("motor2", &motor[2], print_motor);
|
||
* MRobot_RegisterDevice("motor3", &motor[3], print_motor);
|
||
* @endcode
|
||
*
|
||
* @example 自定义校准命令示例
|
||
* @code
|
||
* // 校准数据
|
||
* static float gyro_offset[3] = {0};
|
||
*
|
||
* // 命令回调: cali gyro / cali accel / cali save
|
||
* static long cmd_cali(char *buf, size_t size, const char *cmd) {
|
||
* const char *param = FreeRTOS_CLIGetParameter(cmd, 1, NULL);
|
||
*
|
||
* if (param == NULL) {
|
||
* return MRobot_Snprintf(buf, size, "Usage: cali <gyro|accel|save>\r\n");
|
||
* }
|
||
* if (strncmp(param, "gyro", 4) == 0) {
|
||
* // 采集 1000 次陀螺仪数据求平均
|
||
* MRobot_Snprintf(buf, size, "Calibrating gyro... keep IMU still!\r\n");
|
||
* // ... 校准逻辑 ...
|
||
* return 0;
|
||
* }
|
||
* if (strncmp(param, "save", 4) == 0) {
|
||
* // 保存到 Flash
|
||
* MRobot_Snprintf(buf, size, "Calibration saved to flash.\r\n");
|
||
* return 0;
|
||
* }
|
||
* return MRobot_Snprintf(buf, size, "Unknown: %s\r\n", param);
|
||
* }
|
||
*
|
||
* // 注册命令
|
||
* MRobot_RegisterCommand("cali", "cali <gyro|accel|save>: IMU calibration\r\n", cmd_cali, -1);
|
||
* @endcode
|
||
*/
|
||
|
||
#pragma once
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* Includes ----------------------------------------------------------------- */
|
||
#include <stdint.h>
|
||
#include <stdbool.h>
|
||
#include <stddef.h>
|
||
#include "bsp/uart.h"
|
||
|
||
/* Configuration ------------------------------------------------------------ */
|
||
/* 可在编译时通过 -D 选项覆盖这些默认值 */
|
||
|
||
#ifndef MROBOT_MAX_DEVICES
|
||
#define MROBOT_MAX_DEVICES 64 /* 最大设备数 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_MAX_CUSTOM_COMMANDS
|
||
#define MROBOT_MAX_CUSTOM_COMMANDS 16 /* 最大自定义命令数 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_CMD_BUFFER_SIZE
|
||
#define MROBOT_CMD_BUFFER_SIZE 128 /* 命令缓冲区大小 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_OUTPUT_BUFFER_SIZE
|
||
#define MROBOT_OUTPUT_BUFFER_SIZE 512 /* 输出缓冲区大小 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_DEVICE_NAME_LEN
|
||
#define MROBOT_DEVICE_NAME_LEN 32 /* 设备名最大长度 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_PATH_MAX_LEN
|
||
#define MROBOT_PATH_MAX_LEN 64 /* 路径最大长度 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_HTOP_REFRESH_MS
|
||
#define MROBOT_HTOP_REFRESH_MS 200 /* htop 刷新间隔 (ms) */
|
||
#endif
|
||
|
||
#ifndef MROBOT_USER_NAME
|
||
#define MROBOT_USER_NAME "root" /* CLI 用户名 */
|
||
#endif
|
||
|
||
#ifndef MROBOT_HOST_NAME
|
||
#define MROBOT_HOST_NAME "MRobot" /* CLI 主机名 */
|
||
#endif
|
||
|
||
/* Error codes -------------------------------------------------------------- */
|
||
typedef enum {
|
||
MROBOT_OK = 0, /* 成功 */
|
||
MROBOT_ERR_FULL = -1, /* 容量已满 */
|
||
MROBOT_ERR_NULL_PTR = -2, /* 空指针 */
|
||
MROBOT_ERR_INVALID_ARG = -3, /* 无效参数 */
|
||
MROBOT_ERR_NOT_FOUND = -4, /* 未找到 */
|
||
MROBOT_ERR_ALLOC = -5, /* 内存分配失败 */
|
||
MROBOT_ERR_BUSY = -6, /* 设备忙 */
|
||
MROBOT_ERR_NOT_INIT = -7, /* 未初始化 */
|
||
} MRobot_Error_t;
|
||
|
||
/* CLI 运行状态 */
|
||
typedef enum {
|
||
MROBOT_STATE_IDLE, /* 空闲状态,等待输入 */
|
||
MROBOT_STATE_HTOP, /* htop 模式 */
|
||
MROBOT_STATE_PROCESSING, /* 正在处理命令 */
|
||
} MRobot_State_t;
|
||
|
||
/* Callback types ----------------------------------------------------------- */
|
||
|
||
/**
|
||
* @brief 设备打印回调函数类型
|
||
* @param device_data 用户注册时传入的设备数据指针
|
||
* @param buffer 输出缓冲区
|
||
* @param buffer_size 缓冲区大小
|
||
* @return 实际写入的字节数
|
||
* @note 用户需要自行实现此函数来格式化设备数据
|
||
*/
|
||
typedef int (*MRobot_PrintCallback_t)(const void *device_data, char *buffer, size_t buffer_size);
|
||
|
||
/**
|
||
* @brief 命令处理回调函数类型(与 FreeRTOS CLI 兼容)
|
||
*/
|
||
typedef long (*MRobot_CommandCallback_t)(char *pcWriteBuffer, size_t xWriteBufferLen, const char *pcCommandString);
|
||
|
||
/* Device structure --------------------------------------------------------- */
|
||
typedef struct {
|
||
char name[MROBOT_DEVICE_NAME_LEN]; /* 设备名称 */
|
||
void *data; /* 用户设备数据指针 */
|
||
MRobot_PrintCallback_t print_cb; /* 用户打印回调函数 */
|
||
} MRobot_Device_t;
|
||
|
||
/* Public API --------------------------------------------------------------- */
|
||
|
||
/**
|
||
* @brief 初始化 MRobot CLI 系统
|
||
* @note 必须在 FreeRTOS 调度器启动后调用
|
||
*/
|
||
void MRobot_Init(void);
|
||
|
||
/**
|
||
* @brief 反初始化 MRobot CLI 系统,释放资源
|
||
*/
|
||
void MRobot_DeInit(void);
|
||
|
||
/**
|
||
* @brief 获取当前 CLI 状态
|
||
* @return MRobot_State_t 当前状态
|
||
*/
|
||
MRobot_State_t MRobot_GetState(void);
|
||
|
||
/**
|
||
* @brief 注册设备到 MRobot 系统
|
||
* @param name 设备名称(会被截断到 MROBOT_DEVICE_NAME_LEN-1)
|
||
* @param data 设备数据指针(不能为 NULL)
|
||
* @param print_cb 打印回调函数(可为 NULL,但无法用 show 命令查看)
|
||
* @return MRobot_Error_t 错误码
|
||
*/
|
||
MRobot_Error_t MRobot_RegisterDevice(const char *name, void *data, MRobot_PrintCallback_t print_cb);
|
||
|
||
/**
|
||
* @brief 注销设备
|
||
* @param name 设备名称
|
||
* @return MRobot_Error_t 错误码
|
||
*/
|
||
MRobot_Error_t MRobot_UnregisterDevice(const char *name);
|
||
|
||
/**
|
||
* @brief 注册自定义命令
|
||
* @param command 命令名称
|
||
* @param help_text 帮助文本
|
||
* @param callback 命令回调函数
|
||
* @param param_count 参数个数(-1 表示可变参数)
|
||
* @return MRobot_Error_t 错误码
|
||
*/
|
||
MRobot_Error_t MRobot_RegisterCommand(const char *command, const char *help_text,
|
||
MRobot_CommandCallback_t callback, int8_t param_count);
|
||
|
||
/**
|
||
* @brief 获取已注册设备数量
|
||
* @return 设备数量
|
||
*/
|
||
uint8_t MRobot_GetDeviceCount(void);
|
||
|
||
/**
|
||
* @brief 根据名称查找设备
|
||
* @param name 设备名称
|
||
* @return 设备指针,未找到返回 NULL
|
||
*/
|
||
const MRobot_Device_t *MRobot_FindDevice(const char *name);
|
||
|
||
/**
|
||
* @brief MRobot 主循环,在 CLI 任务中周期性调用
|
||
* @note 建议调用周期 10ms
|
||
*/
|
||
void MRobot_Run(void);
|
||
|
||
/**
|
||
* @brief 格式化输出到 CLI 终端(线程安全,支持浮点数)
|
||
* @param fmt 格式字符串
|
||
* @param ... 可变参数
|
||
* @return 实际输出的字符数,失败返回负数
|
||
*
|
||
* @note 支持的格式说明符:
|
||
* - %d, %i, %u, %x, %X, %ld, %lu, %lx : 整数
|
||
* - %s, %c : 字符串/字符
|
||
* - %f : 浮点数 (默认2位小数)
|
||
* - %.Nf : 浮点数 (N位小数, N=0-6)
|
||
* - %% : 百分号
|
||
*
|
||
* @example
|
||
* MRobot_Printf("Euler: R=%.2f P=%.2f Y=%.2f\\r\\n", roll, pitch, yaw);
|
||
*/
|
||
int MRobot_Printf(const char *fmt, ...);
|
||
|
||
/**
|
||
* @brief 格式化到缓冲区(用于回调函数,支持浮点数)
|
||
* @note 格式说明符同 MRobot_Printf
|
||
*
|
||
* @example
|
||
* static int print_imu(const void *data, char *buf, size_t size) {
|
||
* const BMI088_t *imu = (const BMI088_t *)data;
|
||
* return MRobot_Snprintf(buf, size,
|
||
* " Accel: X=%.3f Y=%.3f Z=%.3f\\r\\n",
|
||
* imu->accl.x, imu->accl.y, imu->accl.z);
|
||
* }
|
||
*/
|
||
int MRobot_Snprintf(char *buf, size_t size, const char *fmt, ...);
|
||
|
||
/* Utility functions -------------------------------------------------------- */
|
||
|
||
/**
|
||
* @brief 格式化浮点数为字符串(嵌入式环境不支持 %f)
|
||
* @param buf 输出缓冲区
|
||
* @param size 缓冲区大小
|
||
* @param val 要格式化的浮点数
|
||
* @param precision 小数位数 (0-6)
|
||
* @return 写入的字符数
|
||
*
|
||
* @example
|
||
* char buf[16];
|
||
* MRobot_FormatFloat(buf, sizeof(buf), 3.14159f, 2); // "3.14"
|
||
* MRobot_FormatFloat(buf, sizeof(buf), -0.001f, 4); // "-0.0010"
|
||
*/
|
||
int MRobot_FormatFloat(char *buf, size_t size, float val, int precision);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif |