在RT-Thread中,control函数是设备驱动框架中的一个重要接口,用于对设备进行控制。它类似于Linux中的ioctl函数,可以执行一系列设备特定的操作,例如配置设备参数、发送控制命令等。

函数原型:
rt_err_t (*control)(rt_device_t dev, int cmd, void *args);

参数:
dev: 设备句柄
cmd: 控制命令,由设备驱动定义
args: 控制参数,根据不同的命令传入不同的参数

设计mydev_control()函数时,我们需要考虑以下几个方面:

  1. 命令设计:定义一系列控制命令,通常使用宏定义,并确保每个命令有唯一的整数值。

  2. 参数设计:对于每个命令,确定其参数类型(可能是一个整数、一个结构体指针等)。

  3. 错误处理:对于无效命令或参数,返回错误码。

下面是一个示例,假设我们有一个LED设备,我们可以通过控制函数来开关LED、设置亮度、设置闪烁模式等。

步骤:

  1. 定义控制命令宏。

  2. 在驱动中实现control函数,根据cmd执行相应的操作。

  3. 在应用程序中通过rt_device_control()调用这些命令。

一、control()函数的核心地位

1. 在设备框架中的位置

struct rt_device_ops {
    rt_err_t  (*init)(rt_device_t dev);
    rt_err_t  (*open)(rt_device_t dev, rt_uint16_t oflag);
    rt_err_t  (*close)(rt_device_t dev);
    rt_ssize_t (*read)(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);
    rt_ssize_t (*write)(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);
    rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);  // ← 核心控制接口
};

2. 与FreeRTOS的对比

系统 类似功能 特点
FreeRTOS 任务通知、队列消息 分散,需要自行封装
RT-Thread control()函数 统一接口,标准化控制

二、control()函数设计模式

1. 基础模板

static rt_err_t mydev_control(rt_device_t dev, int cmd, void *args)
{
    struct my_device *mydev = (struct my_device *)dev->user_data;
    rt_err_t ret = RT_EOK;
    
    RT_ASSERT(dev != RT_NULL);
    RT_ASSERT(mydev != RT_NULL);
    
    switch (cmd) {
        /* 通用控制命令(所有设备都应支持) */
        case RT_DEVICE_CTRL_SUSPEND:  /* 挂起设备 */
            ret = mydev_suspend(mydev);
            break;
            
        case RT_DEVICE_CTRL_RESUME:   /* 恢复设备 */
            ret = mydev_resume(mydev);
            break;
            
        case RT_DEVICE_CTRL_CLOSE:    /* 准备关闭 */
            ret = mydev_prepare_close(mydev);
            break;
            
        /* 设备特定控制命令 */
        case MYDEV_CTRL_SET_MODE:     /* 设置工作模式 */
            ret = mydev_set_mode(mydev, *(uint32_t *)args);
            break;
            
        case MYDEV_CTRL_GET_STATUS:   /* 获取状态 */
            *(uint32_t *)args = mydev_get_status(mydev);
            break;
            
        /* 批量配置命令 */
        case MYDEV_CTRL_CONFIG:       /* 配置多个参数 */
            ret = mydev_apply_config(mydev, (struct mydev_config *)args);
            break;
            
        default:
            ret = -RT_EINVAL;  /* 无效命令 */
            rt_kprintf("Unknown control command: 0x%X\n", cmd);
            break;
    }
    
    return ret;
}

2. 命令编码规范

A. 分层命令编码
/* RT-Thread标准命令 (0x00-0x7F) */
#define RT_DEVICE_CTRL_BASE           0x00
#define RT_DEVICE_CTRL_SUSPEND        0x01
#define RT_DEVICE_CTRL_RESUME         0x02
#define RT_DEVICE_CTRL_CLOSE          0x03
#define RT_DEVICE_CTRL_CONFIG         0x04
#define RT_DEVICE_CTRL_SET_BAUDRATE   0x05
#define RT_DEVICE_CTRL_GET_BAUDRATE   0x06

/* 设备类标准命令 (0x80-0xBF) */
#define CHAR_DEVICE_CTRL_BASE         0x80
#define CHAR_CTRL_FLUSH_RX            0x81
#define CHAR_CTRL_FLUSH_TX            0x82

#define BLOCK_DEVICE_CTRL_BASE        0x90
#define BLOCK_CTRL_ERASE_SECTOR       0x91
#define BLOCK_CTRL_GET_SECTOR_SIZE    0x92

/* 具体设备命令 (0xC0-0xFF) */
#define MYDEV_CTRL_BASE               0xC0
#define MYDEV_CTRL_SET_MODE           (MYDEV_CTRL_BASE + 0x01)
#define MYDEV_CTRL_GET_STATUS         (MYDEV_CTRL_BASE + 0x02)
#define MYDEV_CTRL_CALIBRATE          (MYDEV_CTRL_BASE + 0x03)
#define MYDEV_CTRL_SELF_TEST          (MYDEV_CTRL_BASE + 0x04)
B. 命令位域设计(高级技巧)
/* 32位命令编码: [类型(8)][子类(8)][操作(8)][参数(8)] */
#define CMD_TYPE_SHIFT    24
#define CMD_SUB_SHIFT     16
#define CMD_OP_SHIFT       8
#define CMD_PARAM_SHIFT    0

/* 构建命令宏 */
#define MAKE_CMD(type, sub, op, param) \
    (((type) << CMD_TYPE_SHIFT) | \
     ((sub) << CMD_SUB_SHIFT) | \
     ((op) << CMD_OP_SHIFT) | \
     ((param) << CMD_PARAM_SHIFT))

/* 解码宏 */
#define CMD_TYPE(cmd)   (((cmd) >> CMD_TYPE_SHIFT) & 0xFF)
#define CMD_SUB(cmd)    (((cmd) >> CMD_SUB_SHIFT) & 0xFF)
#define CMD_OP(cmd)     (((cmd) >> CMD_OP_SHIFT) & 0xFF)
#define CMD_PARAM(cmd)  ((cmd) & 0xFF)

/* 使用示例 */
#define DEV_TYPE_SENSOR     0x01
#define SENSOR_SUB_TEMP     0x01
#define OP_READ             0x01
#define PARAM_RAW           0x00
#define PARAM_FILTERED      0x01

#define SENSOR_READ_RAW     MAKE_CMD(DEV_TYPE_SENSOR, SENSOR_SUB_TEMP, OP_READ, PARAM_RAW)
#define SENSOR_READ_FILTER  MAKE_CMD(DEV_TYPE_SENSOR, SENSOR_SUB_TEMP, OP_READ, PARAM_FILTERED)

三、实际应用案例:智能传感器驱动

1. 完整传感器控制接口

/* sensor_driver.h */
#ifndef __SENSOR_DRIVER_H__
#define __SENSOR_DRIVER_H__

#include <rtthread.h>
#include <rtdevice.h>

/* 传感器类型 */
typedef enum {
    SENSOR_TYPE_TEMPERATURE = 0x01,
    SENSOR_TYPE_HUMIDITY    = 0x02,
    SENSOR_TYPE_PRESSURE    = 0x03,
    SENSOR_TYPE_LIGHT       = 0x04,
    SENSOR_TYPE_ACCEL       = 0x05,
    SENSOR_TYPE_GYRO        = 0x06,
} sensor_type_t;

/* 传感器工作模式 */
typedef enum {
    SENSOR_MODE_SLEEP       = 0x00,  /* 睡眠模式 */
    SENSOR_MODE_STANDBY     = 0x01,  /* 待机模式 */
    SENSOR_MODE_NORMAL      = 0x02,  /* 正常工作 */
    SENSOR_MODE_HIGH_PREC   = 0x03,  /* 高精度模式 */
    SENSOR_MODE_LOW_POWER   = 0x04,  /* 低功耗模式 */
    SENSOR_MODE_FAST        = 0x05,  /* 快速模式 */
} sensor_mode_t;

/* 传感器配置结构 */
struct sensor_config {
    sensor_mode_t mode;          /* 工作模式 */
    uint32_t sample_rate;        /* 采样率 (Hz) */
    uint32_t filter_coef;        /* 滤波器系数 */
    uint16_t range;              /* 量程 */
    uint8_t  resolution;         /* 分辨率 (位) */
    uint8_t  oversampling;       /* 过采样倍数 */
};

/* 传感器数据 */
struct sensor_data {
    float value;                 /* 测量值 */
    float raw_value;             /* 原始值 */
    uint32_t timestamp;          /* 时间戳 */
    uint8_t  status;             /* 状态 */
    uint8_t  accuracy;           /* 精度等级 (0-3) */
};

/* 传感器控制命令 */
#define SENSOR_CTRL_BASE                  0xC000

/* 基础控制命令 */
#define SENSOR_CTRL_SET_MODE              (SENSOR_CTRL_BASE + 0x01)
#define SENSOR_CTRL_GET_MODE              (SENSOR_CTRL_BASE + 0x02)
#define SENSOR_CTRL_SET_SAMPLE_RATE       (SENSOR_CTRL_BASE + 0x03)
#define SENSOR_CTRL_GET_SAMPLE_RATE       (SENSOR_CTRL_BASE + 0x04)
#define SENSOR_CTRL_SET_RANGE             (SENSOR_CTRL_BASE + 0x05)
#define SENSOR_CTRL_GET_RANGE             (SENSOR_CTRL_BASE + 0x06)

/* 校准命令 */
#define SENSOR_CTRL_CALIBRATE_ZERO        (SENSOR_CTRL_BASE + 0x10)
#define SENSOR_CTRL_CALIBRATE_SPAN        (SENSOR_CTRL_BASE + 0x11)
#define SENSOR_CTRL_SAVE_CALIBRATION      (SENSOR_CTRL_BASE + 0x12)
#define SENSOR_CTRL_LOAD_CALIBRATION      (SENSOR_CTRL_BASE + 0x13)

/* 诊断命令 */
#define SENSOR_CTRL_SELF_TEST             (SENSOR_CTRL_BASE + 0x20)
#define SENSOR_CTRL_GET_DIAGNOSTIC        (SENSOR_CTRL_BASE + 0x21)
#define SENSOR_CTRL_RESET                 (SENSOR_CTRL_BASE + 0x22)

/* 高级功能命令 */
#define SENSOR_CTRL_ENABLE_INTERRUPT      (SENSOR_CTRL_BASE + 0x30)
#define SENSOR_CTRL_DISABLE_INTERRUPT     (SENSOR_CTRL_BASE + 0x31)
#define SENSOR_CTRL_SET_THRESHOLD         (SENSOR_CTRL_BASE + 0x32)
#define SENSOR_CTRL_SET_ALARM             (SENSOR_CTRL_BASE + 0x33)

/* 批量配置命令 */
#define SENSOR_CTRL_CONFIG_ALL            (SENSOR_CTRL_BASE + 0x40)
#define SENSOR_CTRL_GET_CONFIG            (SENSOR_CTRL_BASE + 0x41)

#endif /* __SENSOR_DRIVER_H__ */

2. 完整的control()实现

/* sensor_driver.c */

/* 传感器设备私有结构 */
struct sensor_device {
    struct rt_device parent;      /* 继承设备基类 */
    
    /* 硬件接口 */
    struct rt_i2c_bus_device *i2c;
    rt_base_t int_pin;
    
    /* 设备状态 */
    sensor_mode_t mode;
    struct sensor_config config;
    rt_bool_t is_calibrated;
    rt_bool_t is_initialized;
    
    /* 数据缓冲区 */
    struct sensor_data buffer[10];
    rt_uint8_t buf_idx;
    rt_mutex_t data_lock;
    
    /* 校准数据 */
    struct {
        float offset;
        float scale_factor;
        float temperature_coef;
    } calibration;
    
    /* 中断处理 */
    void (*data_ready_cb)(void *arg);
    void *cb_arg;
};

/* 控制函数实现 */
static rt_err_t sensor_control(rt_device_t dev, int cmd, void *args)
{
    struct sensor_device *sensor = (struct sensor_device *)dev->user_data;
    rt_err_t ret = RT_EOK;
    
    RT_ASSERT(dev != RT_NULL);
    RT_ASSERT(sensor != RT_NULL);
    
    switch (cmd) {
        /* ========== RT-Thread标准命令 ========== */
        case RT_DEVICE_CTRL_SUSPEND: {
            /* 挂起设备:进入低功耗模式 */
            ret = sensor_enter_sleep_mode(sensor);
            if (ret == RT_EOK) {
                rt_kprintf("[Sensor] Entered sleep mode\n");
            }
            break;
        }
        
        case RT_DEVICE_CTRL_RESUME: {
            /* 恢复设备:唤醒 */
            ret = sensor_wakeup(sensor);
            if (ret == RT_EOK) {
                rt_kprintf("[Sensor] Woke up from sleep\n");
            }
            break;
        }
        
        case RT_DEVICE_CTRL_CLOSE: {
            /* 准备关闭:保存状态 */
            ret = sensor_save_state(sensor);
            break;
        }
        
        /* ========== 模式控制命令 ========== */
        case SENSOR_CTRL_SET_MODE: {
            sensor_mode_t new_mode = *(sensor_mode_t *)args;
            
            if (new_mode >= SENSOR_MODE_SLEEP && new_mode <= SENSOR_MODE_FAST) {
                ret = sensor_set_mode(sensor, new_mode);
                if (ret == RT_EOK) {
                    sensor->mode = new_mode;
                    rt_kprintf("[Sensor] Mode changed to %d\n", new_mode);
                }
            } else {
                ret = -RT_EINVAL;
            }
            break;
        }
        
        case SENSOR_CTRL_GET_MODE: {
            *(sensor_mode_t *)args = sensor->mode;
            break;
        }
        
        /* ========== 采样率控制 ========== */
        case SENSOR_CTRL_SET_SAMPLE_RATE: {
            uint32_t rate = *(uint32_t *)args;
            
            if (rate >= 1 && rate <= 1000) {  /* 1Hz到1000Hz */
                rt_mutex_take(sensor->data_lock, RT_WAITING_FOREVER);
                sensor->config.sample_rate = rate;
                ret = sensor_apply_sample_rate(sensor, rate);
                rt_mutex_release(sensor->data_lock);
                
                if (ret == RT_EOK) {
                    rt_kprintf("[Sensor] Sample rate set to %d Hz\n", rate);
                }
            } else {
                ret = -RT_EINVAL;
            }
            break;
        }
        
        case SENSOR_CTRL_GET_SAMPLE_RATE: {
            *(uint32_t *)args = sensor->config.sample_rate;
            break;
        }
        
        /* ========== 校准命令 ========== */
        case SENSOR_CTRL_CALIBRATE_ZERO: {
            /* 零位校准:参数为参考值 */
            float reference = *(float *)args;
            ret = sensor_calibrate_zero(sensor, reference);
            
            if (ret == RT_EOK) {
                sensor->is_calibrated = RT_TRUE;
                rt_kprintf("[Sensor] Zero calibration completed\n");
            }
            break;
        }
        
        case SENSOR_CTRL_CALIBRATE_SPAN: {
            /* 满量程校准 */
            struct {
                float zero_ref;
                float span_ref;
            } *cal = (struct { float zero_ref; float span_ref; } *)args;
            
            ret = sensor_calibrate_span(sensor, cal->zero_ref, cal->span_ref);
            
            if (ret == RT_EOK) {
                sensor->is_calibrated = RT_TRUE;
                rt_kprintf("[Sensor] Span calibration completed\n");
            }
            break;
        }
        
        case SENSOR_CTRL_SAVE_CALIBRATION: {
            /* 保存校准数据到非易失存储 */
            ret = sensor_save_calibration(sensor);
            break;
        }
        
        case SENSOR_CTRL_LOAD_CALIBRATION: {
            /* 从非易失存储加载校准数据 */
            ret = sensor_load_calibration(sensor);
            if (ret == RT_EOK) {
                sensor->is_calibrated = RT_TRUE;
            }
            break;
        }
        
        /* ========== 诊断命令 ========== */
        case SENSOR_CTRL_SELF_TEST: {
            /* 自检:返回自检结果 */
            uint32_t *result = (uint32_t *)args;
            *result = sensor_self_test(sensor);
            
            if (*result == 0) {
                rt_kprintf("[Sensor] Self-test PASSED\n");
            } else {
                rt_kprintf("[Sensor] Self-test FAILED: 0x%08X\n", *result);
            }
            break;
        }
        
        case SENSOR_CTRL_GET_DIAGNOSTIC: {
            /* 获取诊断信息 */
            struct {
                uint32_t error_code;
                uint32_t operation_count;
                uint32_t uptime;
                uint8_t  temperature;
            } *diag = (struct {
                uint32_t error_code;
                uint32_t operation_count;
                uint32_t uptime;
                uint8_t  temperature;
            } *)args;
            
            diag->error_code = sensor_get_error_code(sensor);
            diag->operation_count = sensor_get_op_count(sensor);
            diag->uptime = sensor_get_uptime(sensor);
            diag->temperature = sensor_get_internal_temp(sensor);
            break;
        }
        
        case SENSOR_CTRL_RESET: {
            /* 软复位设备 */
            ret = sensor_soft_reset(sensor);
            if (ret == RT_EOK) {
                rt_kprintf("[Sensor] Software reset completed\n");
            }
            break;
        }
        
        /* ========== 中断控制 ========== */
        case SENSOR_CTRL_ENABLE_INTERRUPT: {
            struct {
                void (*callback)(void *);
                void *arg;
            } *int_cfg = (struct {
                void (*callback)(void *);
                void *arg;
            } *)args;
            
            sensor->data_ready_cb = int_cfg->callback;
            sensor->cb_arg = int_cfg->arg;
            ret = sensor_enable_interrupt(sensor, RT_TRUE);
            break;
        }
        
        case SENSOR_CTRL_DISABLE_INTERRUPT: {
            ret = sensor_enable_interrupt(sensor, RT_FALSE);
            sensor->data_ready_cb = RT_NULL;
            sensor->cb_arg = RT_NULL;
            break;
        }
        
        case SENSOR_CTRL_SET_THRESHOLD: {
            /* 设置阈值,用于报警 */
            struct {
                float low_threshold;
                float high_threshold;
                uint8_t hysteresis;
            } *thr = (struct {
                float low_threshold;
                float high_threshold;
                uint8_t hysteresis;
            } *)args;
            
            ret = sensor_set_threshold(sensor, thr->low_threshold, 
                                      thr->high_threshold, thr->hysteresis);
            break;
        }
        
        /* ========== 批量配置 ========== */
        case SENSOR_CTRL_CONFIG_ALL: {
            /* 一次性配置所有参数 */
            struct sensor_config *cfg = (struct sensor_config *)args;
            
            if (cfg != RT_NULL) {
                rt_mutex_take(sensor->data_lock, RT_WAITING_FOREVER);
                
                /* 验证配置参数 */
                if (sensor_validate_config(cfg) != RT_EOK) {
                    rt_mutex_release(sensor->data_lock);
                    return -RT_EINVAL;
                }
                
                /* 应用新配置 */
                rt_memcpy(&sensor->config, cfg, sizeof(struct sensor_config));
                ret = sensor_apply_config(sensor);
                
                rt_mutex_release(sensor->data_lock);
                
                if (ret == RT_EOK) {
                    rt_kprintf("[Sensor] Configuration applied successfully\n");
                }
            } else {
                ret = -RT_EINVAL;
            }
            break;
        }
        
        case SENSOR_CTRL_GET_CONFIG: {
            /* 获取当前配置 */
            struct sensor_config *cfg = (struct sensor_config *)args;
            
            if (cfg != RT_NULL) {
                rt_mutex_take(sensor->data_lock, RT_WAITING_FOREVER);
                rt_memcpy(cfg, &sensor->config, sizeof(struct sensor_config));
                rt_mutex_release(sensor->data_lock);
            } else {
                ret = -RT_EINVAL;
            }
            break;
        }
        
        /* ========== 默认处理 ========== */
        default: {
            /* 尝试处理通用传感器命令 */
            if (cmd >= SENSOR_CTRL_BASE && cmd < (SENSOR_CTRL_BASE + 0x100)) {
                ret = sensor_handle_generic_command(sensor, cmd, args);
            } else {
                /* 未知命令 */
                rt_kprintf("[Sensor] Unknown control command: 0x%08X\n", cmd);
                ret = -RT_ENOSYS;  /* 功能未实现 */
            }
            break;
        }
    }
    
    /* 记录操作日志(可选) */
    if (sensor_log_enabled) {
        sensor_log_command(cmd, ret);
    }
    
    return ret;
}

3. 应用层调用示例

/* 应用层代码示例 */

/* 示例1:配置传感器 */
void configure_sensor_example(void)
{
    rt_device_t sensor = rt_device_find("sensor1");
    if (sensor == RT_NULL) return;
    
    /* 打开设备 */
    if (rt_device_open(sensor, RT_DEVICE_FLAG_RDWR) != RT_EOK) {
        rt_kprintf("Failed to open sensor\n");
        return;
    }
    
    /* 1. 单个参数配置 */
    sensor_mode_t mode = SENSOR_MODE_HIGH_PREC;
    rt_device_control(sensor, SENSOR_CTRL_SET_MODE, &mode);
    
    uint32_t sample_rate = 100;  /* 100Hz */
    rt_device_control(sensor, SENSOR_CTRL_SET_SAMPLE_RATE, &sample_rate);
    
    /* 2. 批量配置 */
    struct sensor_config cfg = {
        .mode = SENSOR_MODE_NORMAL,
        .sample_rate = 50,
        .filter_coef = 0x3F,
        .range = 1000,
        .resolution = 16,
        .oversampling = 4,
    };
    rt_device_control(sensor, SENSOR_CTRL_CONFIG_ALL, &cfg);
    
    /* 3. 校准 */
    float zero_ref = 25.0f;  /* 25°C参考温度 */
    rt_device_control(sensor, SENSOR_CTRL_CALIBRATE_ZERO, &zero_ref);
    
    /* 4. 设置中断回调 */
    struct {
        void (*callback)(void *);
        void *arg;
    } int_cfg = {
        .callback = sensor_data_ready_callback,
        .arg = (void *)sensor,
    };
    rt_device_control(sensor, SENSOR_CTRL_ENABLE_INTERRUPT, &int_cfg);
    
    /* 5. 诊断 */
    uint32_t self_test_result;
    rt_device_control(sensor, SENSOR_CTRL_SELF_TEST, &self_test_result);
    
    rt_kprintf("Self-test result: 0x%08X\n", self_test_result);
    
    /* 关闭设备 */
    rt_device_close(sensor);
}

/* 示例2:MSH命令行控制 */
static void sensor_cmd(int argc, char **argv)
{
    static rt_device_t sensor = RT_NULL;
    
    if (argc < 2) {
        rt_kprintf("Usage:\n");
        rt_kprintf("sensor open               - Open sensor device\n");
        rt_kprintf("sensor close              - Close sensor device\n");
        rt_kprintf("sensor mode <0-5>         - Set working mode\n");
        rt_kprintf("sensor rate <Hz>          - Set sample rate\n");
        rt_kprintf("sensor calibrate          - Perform calibration\n");
        rt_kprintf("sensor test               - Run self-test\n");
        rt_kprintf("sensor config             - Show current config\n");
        rt_kprintf("sensor sleep              - Enter sleep mode\n");
        rt_kprintf("sensor wake               - Wake up from sleep\n");
        return;
    }
    
    if (rt_strcmp(argv[1], "open") == 0) {
        sensor = rt_device_find("sensor1");
        if (sensor) {
            rt_device_open(sensor, RT_DEVICE_FLAG_RDWR);
            rt_kprintf("Sensor opened\n");
        }
    }
    else if (rt_strcmp(argv[1], "close") == 0) {
        if (sensor) {
            rt_device_close(sensor);
            rt_kprintf("Sensor closed\n");
        }
    }
    else if (rt_strcmp(argv[1], "mode") == 0 && argc == 3) {
        if (sensor) {
            sensor_mode_t mode = atoi(argv[2]);
            rt_device_control(sensor, SENSOR_CTRL_SET_MODE, &mode);
        }
    }
    else if (rt_strcmp(argv[1], "rate") == 0 && argc == 3) {
        if (sensor) {
            uint32_t rate = atoi(argv[2]);
            rt_device_control(sensor, SENSOR_CTRL_SET_SAMPLE_RATE, &rate);
        }
    }
    else if (rt_strcmp(argv[1], "calibrate") == 0) {
        if (sensor) {
            float ref = 25.0f;
            rt_device_control(sensor, SENSOR_CTRL_CALIBRATE_ZERO, &ref);
        }
    }
    else if (rt_strcmp(argv[1], "test") == 0) {
        if (sensor) {
            uint32_t result;
            rt_device_control(sensor, SENSOR_CTRL_SELF_TEST, &result);
            rt_kprintf("Self-test: 0x%08X\n", result);
        }
    }
    else if (rt_strcmp(argv[1], "config") == 0) {
        if (sensor) {
            struct sensor_config cfg;
            rt_device_control(sensor, SENSOR_CTRL_GET_CONFIG, &cfg);
            rt_kprintf("Mode: %d, Rate: %dHz, Range: %d\n", 
                      cfg.mode, cfg.sample_rate, cfg.range);
        }
    }
    else if (rt_strcmp(argv[1], "sleep") == 0) {
        if (sensor) {
            rt_device_control(sensor, RT_DEVICE_CTRL_SUSPEND, RT_NULL);
        }
    }
    else if (rt_strcmp(argv[1], "wake") == 0) {
        if (sensor) {
            rt_device_control(sensor, RT_DEVICE_CTRL_RESUME, RT_NULL);
        }
    }
}
MSH_CMD_EXPORT(sensor_cmd, Sensor device control commands);

四、高级控制模式

1. 异步控制模式

/* 异步控制命令处理 */
static rt_err_t sensor_control_async(rt_device_t dev, int cmd, void *args)
{
    struct sensor_device *sensor = (struct sensor_device *)dev->user_data;
    
    /* 创建异步控制请求 */
    struct async_control_request {
        int cmd;
        void *args;
        rt_completion_t completion;
        rt_err_t result;
    } *req;
    
    req = rt_malloc(sizeof(struct async_control_request));
    if (req == RT_NULL) {
        return -RT_ENOMEM;
    }
    
    req->cmd = cmd;
    req->args = args;
    rt_completion_init(&req->completion);
    
    /* 发送到控制队列 */
    if (rt_mq_send(sensor->control_queue, &req, sizeof(req)) != RT_EOK) {
        rt_free(req);
        return -RT_ERROR;
    }
    
    /* 等待完成(可设置超时) */
    if (rt_completion_wait(&req->completion, 1000) != RT_EOK) {
        rt_free(req);
        return -RT_ETIMEOUT;
    }
    
    rt_err_t result = req->result;
    rt_free(req);
    
    return result;
}

/* 控制线程处理异步请求 */
static void sensor_control_thread(void *param)
{
    struct sensor_device *sensor = (struct sensor_device *)param;
    
    while (1) {
        struct async_control_request *req;
        
        /* 从队列接收请求 */
        if (rt_mq_recv(sensor->control_queue, &req, sizeof(req), 
                      RT_WAITING_FOREVER) == RT_EOK) {
            
            /* 同步执行控制命令 */
            req->result = sensor_control_sync(&sensor->parent, req->cmd, req->args);
            
            /* 通知完成 */
            rt_completion_done(&req->completion);
        }
    }
}

2. 命令链(Command Chain)模式

/* 批量执行多个命令 */
rt_err_t execute_command_chain(rt_device_t dev, 
                               const struct command_entry *chain, 
                               size_t count)
{
    rt_err_t ret = RT_EOK;
    
    for (size_t i = 0; i < count; i++) {
        ret = rt_device_control(dev, chain[i].cmd, chain[i].args);
        
        if (ret != RT_EOK) {
            rt_kprintf("Command 0x%08X failed: %d\n", chain[i].cmd, ret);
            
            /* 执行回滚命令链 */
            if (chain[i].rollback_cmd != 0) {
                rt_device_control(dev, chain[i].rollback_cmd, chain[i].rollback_args);
            }
            
            return ret;
        }
    }
    
    return RT_EOK;
}

/* 命令链定义 */
static const struct command_entry sensor_init_chain[] = {
    {SENSOR_CTRL_RESET, NULL, 0, NULL},
    {SENSOR_CTRL_LOAD_CALIBRATION, NULL, SENSOR_CTRL_RESET, NULL},
    {SENSOR_CTRL_SET_MODE, &mode_normal, SENSOR_CTRL_SET_MODE, &mode_sleep},
    {SENSOR_CTRL_SET_SAMPLE_RATE, &rate_100hz, 0, NULL},
    {SENSOR_CTRL_ENABLE_INTERRUPT, &int_cfg, SENSOR_CTRL_DISABLE_INTERRUPT, NULL},
};

五、实践和注意事项

1. 参数验证策略

static rt_err_t validate_control_parameters(int cmd, void *args)
{
    switch (cmd) {
        case SENSOR_CTRL_SET_SAMPLE_RATE: {
            uint32_t *rate = (uint32_t *)args;
            if (rate == RT_NULL) return -RT_EINVAL;
            if (*rate < 1 || *rate > 1000) return -RT_EINVAL;
            break;
        }
        
        case SENSOR_CTRL_SET_MODE: {
            sensor_mode_t *mode = (sensor_mode_t *)args;
            if (mode == RT_NULL) return -RT_EINVAL;
            if (*mode > SENSOR_MODE_FAST) return -RT_EINVAL;
            break;
        }
        
        /* ... 其他命令验证 */
    }
    
    return RT_EOK;
}

2. 线程安全设计

static rt_err_t sensor_control_thread_safe(rt_device_t dev, int cmd, void *args)
{
    struct sensor_device *sensor = (struct sensor_device *)dev->user_data;
    rt_err_t ret;
    
    /* 根据命令类型选择合适的锁 */
    if (cmd & 0x80000000) {  /* 关键命令,需要互斥锁 */
        rt_mutex_take(sensor->config_lock, RT_WAITING_FOREVER);
        ret = sensor_control_internal(dev, cmd, args);
        rt_mutex_release(sensor->config_lock);
    } else {  /* 普通命令,使用读写锁 */
        rt_rwlock_rlock(sensor->data_lock);
        ret = sensor_control_internal(dev, cmd, args);
        rt_rwlock_runlock(sensor->data_lock);
    }
    
    return ret;
}

3. 错误码标准化

/* 扩展错误码 */
#define RT_SENSOR_ERROR_BASE         0x1000
#define RT_SENSOR_ERROR_CALIBRATION  (RT_SENSOR_ERROR_BASE + 0x01)
#define RT_SENSOR_ERROR_OVER_RANGE   (RT_SENSOR_ERROR_BASE + 0x02)
#define RT_SENSOR_ERROR_SELF_TEST    (RT_SENSOR_ERROR_BASE + 0x03)
#define RT_SENSOR_ERROR_COMM         (RT_SENSOR_ERROR_BASE + 0x04)

static const char* sensor_error_to_string(rt_err_t err)
{
    switch (err) {
        case RT_SENSOR_ERROR_CALIBRATION:
            return "Calibration error";
        case RT_SENSOR_ERROR_OVER_RANGE:
            return "Measurement over range";
        case RT_SENSOR_ERROR_SELF_TEST:
            return "Self-test failed";
        case RT_SENSOR_ERROR_COMM:
            return "Communication error";
        default:
            return rt_strerror(err);
    }
}

六、调试和测试

1. 控制命令日志

static void log_control_command(int cmd, void *args, rt_err_t result)
{
#ifdef SENSOR_DEBUG_CONTROL
    static const char* cmd_names[] = {
        [SENSOR_CTRL_SET_MODE] = "SET_MODE",
        [SENSOR_CTRL_SET_SAMPLE_RATE] = "SET_SAMPLE_RATE",
        /* ... */
    };
    
    const char* name = "UNKNOWN";
    if (cmd >= 0 && cmd < sizeof(cmd_names)/sizeof(cmd_names[0])) {
        if (cmd_names[cmd]) name = cmd_names[cmd];
    }
    
    rt_kprintf("[CTRL] %s (0x%08X) -> %s\n", 
              name, cmd, 
              result == RT_EOK ? "OK" : rt_strerror(result));
#endif
}

2. 自动化测试框架

void test_sensor_control_commands(void)
{
    rt_device_t sensor = rt_device_find("sensor1");
    TEST_ASSERT_NOT_NULL(sensor);
    
    /* 测试用例1:基本功能 */
    TEST_CASE("Basic control commands") {
        sensor_mode_t mode;
        
        /* 获取当前模式 */
        TEST_CHECK(rt_device_control(sensor, SENSOR_CTRL_GET_MODE, &mode) == RT_EOK);
        
        /* 设置新模式 */
        sensor_mode_t new_mode = SENSOR_MODE_NORMAL;
        TEST_CHECK(rt_device_control(sensor, SENSOR_CTRL_SET_MODE, &new_mode) == RT_EOK);
        
        /* 验证设置成功 */
        sensor_mode_t verify_mode;
        rt_device_control(sensor, SENSOR_CTRL_GET_MODE, &verify_mode);
        TEST_CHECK(verify_mode == new_mode);
    }
    
    /* 测试用例2:错误处理 */
    TEST_CASE("Error handling") {
        /* 测试无效参数 */
        uint32_t invalid_rate = 2000;  /* 超出范围 */
        rt_err_t ret = rt_device_control(sensor, SENSOR_CTRL_SET_SAMPLE_RATE, &invalid_rate);
        TEST_CHECK(ret == -RT_EINVAL);
        
        /* 测试空指针 */
        ret = rt_device_control(sensor, SENSOR_CTRL_SET_MODE, RT_NULL);
        TEST_CHECK(ret == -RT_EINVAL);
    }
}

总结

mydev_control()函数是RT-Thread设备驱动设计的核心,与FreeRTOS相比,它提供了:

  1. 标准化接口:统一的设备控制范式

  2. 灵活扩展性:通过命令码分层设计支持无限扩展

  3. 类型安全:参数通过void指针传递,但可以通过结构体确保类型安全

  4. 异步支持:可扩展为异步控制模式

对于有FreeRTOS经验的工程师,掌握control()函数的关键是:

  • 理解命令编码策略

  • 设计合理的参数结构

  • 实现线程安全的控制逻辑

  • 提供良好的错误处理和调试支持

这种设计模式虽然初期学习成本较高,但长期来看大幅提升了代码的可维护性和可扩展性,特别适合复杂的物联网设备开发。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐