在嵌入式系统开发中,处理来自用户输入、通信接口或定时任务等不同来源的命令请求是一项常见需求。命令模式(Command Pattern)作为一种行为设计模式,通过将请求封装为对象,为这类问题提供了优雅的解决方案,使命令的排队、撤销、日志记录和事务处理变得统一而简便。
命令模式的核心概念
命令模式的核心思想是将一个请求封装为一个对象,从而允许用户使用不同的请求对客户端进行参数化,支持对请求进行排队、记录日志,并提供可撤销的操作。
嵌入式系统中的命令模式应用场景
远程控制命令处理
在物联网设备和远程控制系统中,命令模式能够优雅地处理来自网络、蓝牙、红外等不同通信接口的控制指令。
// 远程命令类型定义
typedef enum {
CMD_LED_CONTROL,
CMD_MOTOR_CONTROL,
CMD_SENSOR_READ,
CMD_SYSTEM_CONFIG,
CMD_FIRMWARE_UPDATE,
CMD_EMERGENCY_STOP
} remote_command_type_t;
串口命令解析
对于需要通过串口进行调试和控制的嵌入式设备,命令模式提供了一个统一的命令处理框架。
// 串口命令结构
typedef struct {
char command_name[16];
char parameters[3][16];
uint8_t param_count;
} uart_command_t;
任务队列管理
在实时操作系统中,命令模式可用于构建灵活的任务调度系统。这与设计高效的算法与数据结构以管理任务执行顺序的理念是相通的。
// 任务优先级定义
typedef enum {
PRIORITY_LOW,
PRIORITY_NORMAL,
PRIORITY_HIGH,
PRIORITY_CRITICAL
} task_priority_t;
FreeRTOS 任务通知:命令模式的实践典范
FreeRTOS作为嵌入式领域广泛应用的实时操作系统,其任务通知机制与命令模式理念高度契合,为构建高效的任务调度系统提供了强大支持。
// FreeRTOS 命令模式架构
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
// 命令接口定义
typedef struct command {
void (*execute)(void *context);
void (*undo)(void *context);
void (*cleanup)(void *context);
uint32_t command_id;
task_priority_t priority;
} command_t;
// 命令执行结果
typedef struct {
uint32_t command_id;
bool success;
int32_t result_code;
void *result_data;
} command_result_t;
完整的命令系统实现示例
下面通过一个完整的智能设备控制系统来展示命令模式在FreeRTOS中的具体应用。
具体命令类型定义
typedef enum {
GPIO_CMD_SET_LEVEL,
GPIO_CMD_TOGGLE,
PWM_CMD_SET_DUTY,
PWM_CMD_SET_FREQUENCY,
SENSOR_CMD_READ,
SYSTEM_CMD_REBOOT,
SYSTEM_CMD_SLEEP
} concrete_command_type_t;
// GPIO控制命令
typedef struct {
command_t base;
gpio_num_t pin;
bool level;
bool previous_level; // 用于撤销操作
} gpio_command_t;
// PWM控制命令
typedef struct {
command_t base;
pwm_channel_t channel;
uint16_t duty_cycle;
uint32_t frequency;
uint16_t previous_duty; // 用于撤销操作
} pwm_command_t;
// 传感器读取命令
typedef struct {
command_t base;
sensor_type_t sensor_type;
sensor_data_t *result_buffer;
TaskHandle_t requester_task; // 请求任务句柄,用于通知完成
} sensor_command_t;
// 系统控制命令
typedef struct {
command_t base;
system_action_t action;
uint32_t parameter;
} system_command_t;
具体命令的实现
以下是GPIO控制命令的核心实现函数:
// GPIO命令实现
void gpio_command_execute(void *context) {
gpio_command_t *cmd = (gpio_command_t *)context;
// 保存当前状态用于撤销
cmd->previous_level = gpio_get_level(cmd->pin);
// 执行命令
gpio_set_level(cmd->pin, cmd->level);
printf("GPIO Command: Pin %d set to %s\n",
cmd->pin, cmd->level ? "HIGH" : "LOW");
}
void gpio_command_undo(void *context) {
gpio_command_t *cmd = (gpio_command_t *)context;
// 恢复到之前的状态
gpio_set_level(cmd->pin, cmd->previous_level);
printf("GPIO Command: Pin %d restored to %s\n",
cmd->pin, cmd->previous_level ? "HIGH" : "LOW");
}
void gpio_command_cleanup(void *context) {
gpio_command_t *cmd = (gpio_command_t *)context;
free(cmd);
}
// PWM命令实现(部分)
void pwm_command_execute(void *context) {
pwm_command_t *cmd = (pwm_command_t *)context;
cmd->previous_duty = pwm_get_duty(cmd->channel); // 保存当前状态
if (cmd->frequency > 0) {
pwm_set_frequency(cmd->channel, cmd->frequency);
}
pwm_set_duty(cmd->channel, cmd->duty_cycle);
pwm_start(cmd->channel);
printf("PWM Command: Channel %d, Duty: %d%%, Freq: %luHz\n",
cmd->channel, cmd->duty_cycle, cmd->frequency);
}
命令队列与分发器
// 命令队列管理器
typedef struct {
QueueHandle_t command_queue;
QueueHandle_t result_queue;
TaskHandle_t dispatcher_task;
SemaphoreHandle_t queue_mutex;
uint32_t command_counter;
bool running;
} command_dispatcher_t;
static command_dispatcher_t dispatcher;
// 命令分发器任务
void command_dispatcher_task(void *pvParameters) {
command_t *cmd = NULL;
command_result_t result = {0};
printf("Command Dispatcher: Started\n");
while (dispatcher.running) {
// 等待命令(最多等待100ms,以便检查running标志)
if (xQueueReceive(dispatcher.command_queue, &cmd, pdMS_TO_TICKS(100)) == pdTRUE) {
if (cmd != NULL && cmd->execute != NULL) {
result.command_id = cmd->command_id;
printf("Executing command ID: %lu\n", cmd->command_id);
cmd->execute(cmd); // 执行命令
result.success = true;
// 发送执行结果
if (dispatcher.result_queue != NULL) {
xQueueSend(dispatcher.result_queue, &result, portMAX_DELAY);
}
// 清理命令(如果不需要撤销功能)
if (cmd->cleanup != NULL) {
cmd->cleanup(cmd);
}
}
}
}
printf("Command Dispatcher: Stopped\n");
vTaskDelete(NULL);
}
// 命令系统初始化
bool command_system_init(uint32_t queue_size) {
dispatcher.command_queue = xQueueCreate(queue_size, sizeof(command_t*));
if (dispatcher.command_queue == NULL) return false;
dispatcher.result_queue = xQueueCreate(queue_size, sizeof(command_result_t));
if (dispatcher.result_queue == NULL) {
vQueueDelete(dispatcher.command_queue);
return false;
}
dispatcher.queue_mutex = xSemaphoreCreateMutex();
if (dispatcher.queue_mutex == NULL) {
vQueueDelete(dispatcher.command_queue);
vQueueDelete(dispatcher.result_queue);
return false;
}
dispatcher.command_counter = 0;
dispatcher.running = true;
// 创建命令分发器任务
if (xTaskCreate(command_dispatcher_task,
"CmdDispatcher",
4096,
NULL,
tskIDLE_PRIORITY + 2,
&dispatcher.dispatcher_task) != pdPASS) {
vQueueDelete(dispatcher.command_queue);
vQueueDelete(dispatcher.result_queue);
vSemaphoreDelete(dispatcher.queue_mutex);
return false;
}
printf("Command System: Initialized successfully\n");
return true;
}
工厂函数与应用示例
// 创建具体命令的工厂函数
gpio_command_t *create_gpio_command(gpio_num_t pin, bool level) {
gpio_command_t *cmd = malloc(sizeof(gpio_command_t));
if (cmd == NULL) return NULL;
cmd->base.execute = gpio_command_execute;
cmd->base.undo = gpio_command_undo;
cmd->base.cleanup = gpio_command_cleanup;
cmd->base.priority = PRIORITY_NORMAL;
cmd->pin = pin;
cmd->level = level;
return cmd;
}
// 应用层使用示例
void application_task(void *pvParameters) {
if (!command_system_init(20)) {
printf("Application: Failed to initialize command system\n");
vTaskDelete(NULL);
}
gpio_init();
pwm_init();
sensor_init();
printf("Application: Started\n");
while (1) {
// 示例:控制LED
gpio_command_t *led_cmd = create_gpio_command(GPIO_LED_PIN, true);
if (led_cmd != NULL) {
command_system_submit((command_t*)led_cmd);
}
vTaskDelay(pdMS_TO_TICKS(5000));
}
}
命令模式的高级特性
命令组合(宏命令)
复合命令允许将多个命令作为一个单元执行,这有助于理解网络与系统层面如何将复杂操作原子化。
// 复合命令 - 同时执行多个命令
typedef struct {
command_t base;
command_t **commands;
uint8_t command_count;
} composite_command_t;
void composite_command_execute(void *context) {
composite_command_t *comp = (composite_command_t *)context;
for (int i = 0; i < comp->command_count; i++) {
if (comp->commands[i] && comp->commands[i]->execute) {
comp->commands[i]->execute(comp->commands[i]);
}
}
printf("Composite Command: Executed %d commands\n", comp->command_count);
}
命令历史与撤销
// 命令历史管理器
typedef struct {
command_t **history;
uint32_t capacity;
uint32_t count;
uint32_t current;
} command_history_t;
static command_history_t cmd_history;
bool command_history_undo(void) {
if (cmd_history.current == 0) return false;
command_t *cmd = cmd_history.history[--cmd_history.current];
if (cmd && cmd->undo) {
cmd->undo(cmd);
return true;
}
return false;
}
优先级命令队列
// 支持优先级的命令队列
typedef struct {
QueueHandle_t high_priority_queue;
QueueHandle_t normal_priority_queue;
QueueHandle_t low_priority_queue;
} priority_command_dispatcher_t;
void priority_command_dispatcher_task(void *pvParameters) {
priority_command_dispatcher_t *dispatcher =
(priority_command_dispatcher_t *)pvParameters;
command_t *cmd = NULL;
TickType_t wait_time = portMAX_DELAY;
while (1) {
// 按优先级顺序检查队列
if (xQueueReceive(dispatcher->high_priority_queue, &cmd, 0) == pdTRUE) {
// 立即执行高优先级命令
}
else if (xQueueReceive(dispatcher->normal_priority_queue, &cmd, 0) == pdTRUE) {
// 执行普通优先级命令
}
else if (xQueueReceive(dispatcher->low_priority_queue, &cmd, wait_time) == pdTRUE) {
// 执行低优先级命令
}
if (cmd != NULL && cmd->execute != NULL) {
cmd->execute(cmd);
if (cmd->cleanup != NULL) {
cmd->cleanup(cmd);
}
cmd = NULL;
}
wait_time = portMAX_DELAY;
}
}
总结
在嵌入式系统中,命令模式与FreeRTOS的任务通知等机制相结合,展现了强大的任务调度能力。该模式有效解耦了请求发送者与处理者,提供了灵活的任务调度策略和出色的系统扩展性。无论是处理用户交互、解析通信协议还是进行复杂的系统控制,命令模式都是构建响应迅速、架构清晰且可靠的任务管理系统的理想选择。