当前位置: 首页 > news >正文

FreeRTOS在MCU开发中常用应用

除了队列,FreeRTOS 还有很多其他实用功能。我来详细说明几个在MCU开发中经常使用的应用:

1. 任务通知(Task Notifications)

高性能任务同步

// 任务通知比二进制信号量快45%,比事件组快很多TaskHandle_t xSensorTaskHandle;
TaskHandle_t xDisplayTaskHandle;// 传感器任务 - 使用通知等待数据就绪
void vSensorTask(void *pvParameters) {uint32_t ulNotificationValue;BaseType_t xResult;while(1) {// 等待通知(替代信号量)xResult = xTaskNotifyWait(0x00,              // 不清除任何位ULONG_MAX,         // 清除所有位&ulNotificationValue, pdMS_TO_TICKS(1000));if(xResult == pdPASS) {// 根据通知值执行不同操作if(ulNotificationValue & 0x01) {// 开始测量start_measurement();}if(ulNotificationValue & 0x02) {// 停止测量stop_measurement();}if(ulNotificationValue & 0x04) {// 校准传感器calibrate_sensor();}} else {// 超时处理sensor_timeout_handler();}}
}// 命令处理任务 - 发送通知
void vCommandTask(void *pvParameters) {while(1) {if(receive_command()) {// 发送通知给传感器任务(设置位0)xTaskNotify(xSensorTaskHandle, 0x01, eSetBits);}if(calibration_requested()) {// 发送校准通知(设置位2)xTaskNotify(xSensorTaskHandle, 0x04, eSetBits);}vTaskDelay(pdMS_TO_TICKS(10));}
}// 中断中使用任务通知
void ADC_ConversionComplete_ISR(void) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;// 通知显示任务数据就绪vTaskNotifyGiveFromISR(xDisplayTaskHandle, &xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

2. 事件组(Event Groups)

多事件同步

// 创建事件组
EventGroupHandle_t xSystemEvents;// 定义事件位
#define EVENT_NETWORK_CONNECTED    (1 << 0)
#define EVENT_DATA_READY           (1 << 1) 
#define EVENT_USER_INPUT           (1 << 2)
#define EVENT_SYSTEM_ERROR         (1 << 3)
#define EVENT_ALL_EVENTS           (EVENT_NETWORK_CONNECTED | EVENT_DATA_READY | EVENT_USER_INPUT)void vNetworkTask(void *pvParameters) {while(1) {if(network_connect()) {// 设置网络连接事件xEventGroupSetBits(xSystemEvents, EVENT_NETWORK_CONNECTED);}vTaskDelay(pdMS_TO_TICKS(1000));}
}void vDataAcquisitionTask(void *pvParameters) {while(1) {if(data_available()) {// 设置数据就绪事件xEventGroupSetBits(xSystemEvents, EVENT_DATA_READY);}vTaskDelay(pdMS_TO_TICKS(500));}
}void vMainControlTask(void *pvParameters) {EventBits_t uxEvents;while(1) {// 等待多个事件发生(所有事件都需要,自动清除)uxEvents = xEventGroupWaitBits(xSystemEvents,          // 事件组句柄EVENT_ALL_EVENTS,       // 等待的事件位pdTRUE,                 // 退出时清除这些位pdTRUE,                 // 需要所有位都设置portMAX_DELAY           // 无限等待);// 处理事件if((uxEvents & EVENT_ALL_EVENTS) == EVENT_ALL_EVENTS) {// 所有必要事件都已发生,执行主逻辑execute_main_logic();}if(uxEvents & EVENT_SYSTEM_ERROR) {// 处理系统错误handle_system_error();}}
}// 中断中设置事件
void UART_ISR(void) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;if(uart_rx_error()) {xEventGroupSetBitsFromISR(xSystemEvents, EVENT_SYSTEM_ERROR, &xHigherPriorityTaskWoken);}portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

3. 软件定时器(Software Timers)

周期性和单次定时器

// 定时器句柄
TimerHandle_t xSensorTimer;
TimerHandle_t xTimeoutTimer;
TimerHandle_t xWatchdogTimer;// 传感器采样定时器回调
void vSensorTimerCallback(TimerHandle_t xTimer) {// 读取传感器数据read_all_sensors();// 发送数据到处理队列sensor_data_t data = collect_sensor_data();xQueueSend(xSensorQueue, &data, 0);
}// 通信超时定时器回调
void vTimeoutTimerCallback(TimerHandle_t xTimer) {// 通信超时处理printf("Communication timeout!\n");reset_communication();
}// 看门狗定时器回调
void vWatchdogTimerCallback(TimerHandle_t xTimer) {// 检查系统状态if(!system_healthy()) {system_recovery();}
}void init_system_timers(void) {// 创建周期性定时器 - 每100ms采样一次xSensorTimer = xTimerCreate("SensorTimer",              // 定时器名称pdMS_TO_TICKS(100),         // 周期 100mspdTRUE,                     // 自动重载(void *)0,                  // 定时器IDvSensorTimerCallback        // 回调函数);// 创建单次定时器 - 通信超时5秒xTimeoutTimer = xTimerCreate("TimeoutTimer",pdMS_TO_TICKS(5000),pdFALSE,                    // 单次定时器(void *)1,vTimeoutTimerCallback);// 创建看门狗定时器 - 每1秒检查一次xWatchdogTimer = xTimerCreate("WatchdogTimer",pdMS_TO_TICKS(1000),pdTRUE,(void *)2,vWatchdogTimerCallback);// 启动定时器if(xSensorTimer != NULL) {xTimerStart(xSensorTimer, 0);}if(xWatchdogTimer != NULL) {xTimerStart(xWatchdogTimer, 0);}
}// 在通信开始时启动超时定时器
void start_communication(void) {send_request();xTimerStart(xTimeoutTimer, 0);  // 启动5秒超时定时器
}// 收到响应后停止超时定时器
void handle_response(void) {xTimerStop(xTimeoutTimer, 0);   // 停止超时定时器process_response();
}

4. 流缓冲区和消息缓冲区

数据流处理

// 流缓冲区用于字节流数据
StreamBufferHandle_t xUartStreamBuffer;
#define STREAM_BUFFER_SIZE 256
#define TRIGGER_LEVEL 32// 消息缓冲区用于离散消息
MessageBufferHandle_t xCommandMessageBuffer;
#define MESSAGE_BUFFER_SIZE 128void init_buffers(void) {// 创建流缓冲区(UART数据)xUartStreamBuffer = xStreamBufferCreate(STREAM_BUFFER_SIZE,TRIGGER_LEVEL);// 创建消息缓冲区(命令数据)xCommandMessageBuffer = xMessageBufferCreate(MESSAGE_BUFFER_SIZE);
}// UART接收中断 - 写入流缓冲区
void UART_RX_ISR(void) {BaseType_t xHigherPriorityTaskWoken = pdFALSE;uint8_t rx_data;rx_data = USART1->RDR;  // 读取接收数据寄存器// 写入流缓冲区xStreamBufferSendFromISR(xUartStreamBuffer,&rx_data,sizeof(rx_data),&xHigherPriorityTaskWoken);portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}// 数据处理任务 - 从流缓冲区读取
void vDataProcessTask(void *pvParameters) {uint8_t data_buffer[64];size_t xReceivedBytes;while(1) {// 等待流缓冲区中有足够数据xReceivedBytes = xStreamBufferReceive(xUartStreamBuffer,data_buffer,sizeof(data_buffer),pdMS_TO_TICKS(1000));if(xReceivedBytes > 0) {// 处理接收到的数据process_uart_data(data_buffer, xReceivedBytes);}}
}// 发送命令到消息缓冲区
void send_command(const char *command, size_t length) {xMessageBufferSend(xCommandMessageBuffer,command,length,pdMS_TO_TICKS(100));
}// 从消息缓冲区接收命令
void vCommandTask(void *pvParameters) {char command_buffer[64];size_t xReceivedBytes;while(1) {xReceivedBytes = xMessageBufferReceive(xCommandMessageBuffer,command_buffer,sizeof(command_buffer),portMAX_DELAY);if(xReceivedBytes > 0) {execute_command(command_buffer, xReceivedBytes);}}
}

5. 互斥量(Mutex)和递归互斥量

资源保护

// 共享资源保护
SemaphoreHandle_t xI2CMutex;
SemaphoreHandle_t xDisplayMutex;
SemaphoreHandle_t xConfigMutex;// 共享资源
typedef struct {uint32_t setting1;uint16_t setting2;uint8_t  setting3;
} system_config_t;system_config_t system_config;void init_mutexes(void) {// 创建互斥量xI2CMutex = xSemaphoreCreateMutex();xDisplayMutex = xSemaphoreCreateMutex();xConfigMutex = xSemaphoreCreateMutex();
}// I2C总线访问保护
bool i2c_read_register(uint8_t dev_addr, uint8_t reg_addr, uint8_t *data) {if(xSemaphoreTake(xI2CMutex, pdMS_TO_TICKS(100)) == pdTRUE) {// 获取到互斥量,访问I2C总线bool result = i2c_read(dev_addr, reg_addr, data);// 释放互斥量xSemaphoreGive(xI2CMutex);return result;}return false; // 获取互斥量超时
}// 配置数据保护
void update_system_config(system_config_t *new_config) {if(xSemaphoreTake(xConfigMutex, portMAX_DELAY) == pdTRUE) {// 临界区 - 安全地更新配置memcpy(&system_config, new_config, sizeof(system_config_t));// 验证配置if(validate_config(&system_config)) {save_config_to_flash(&system_config);}xSemaphoreGive(xConfigMutex);}
}// 递归互斥量使用 - 可重入函数
SemaphoreHandle_t xRecursiveMutex;void init_recursive_mutex(void) {xRecursiveMutex = xSemaphoreCreateRecursiveMutex();
}void low_level_function(void) {if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {// 访问共享资源access_shared_resource();xSemaphoreGiveRecursive(xRecursiveMutex);}
}void high_level_function(void) {if(xSemaphoreTakeRecursive(xRecursiveMutex, portMAX_DELAY) == pdTRUE) {// 调用低层函数(可重入)low_level_function();// 其他操作other_operations();xSemaphoreGiveRecursive(xRecursiveMutex);}
}

6. 任务挂起和恢复

动态任务管理

TaskHandle_t xDataLoggerHandle;
TaskHandle_t xCommunicationHandle;void vSystemManagerTask(void *pvParameters) {while(1) {// 检查系统状态if(battery_low()) {// 挂起非关键任务节省电量printf("Battery low, suspending non-critical tasks...\n");vTaskSuspend(xDataLoggerHandle);}if(battery_normal()) {// 恢复挂起的任务printf("Battery normal, resuming tasks...\n");vTaskResume(xDataLoggerHandle);}if(network_available()) {// 恢复通信任务vTaskResume(xCommunicationHandle);} else {// 挂起通信任务vTaskSuspend(xCommunicationHandle);}vTaskDelay(pdMS_TO_TICKS(5000));}
}// 任务自挂起示例
void vDataLoggerTask(void *pvParameters) {while(1) {if(should_log_data()) {// 执行数据记录log_sensor_data();vTaskDelay(pdMS_TO_TICKS(1000));} else {// 没有数据要记录,自挂起节省CPUprintf("No data to log, suspending myself...\n");vTaskSuspend(NULL); // 挂起自己}}
}// 外部恢复数据记录任务
void trigger_data_logging(void) {vTaskResume(xDataLoggerHandle);
}

7. 优先级继承和死锁预防

实时系统最佳实践

// 优先级继承互斥量
SemaphoreHandle_t xHighPriorityMutex;void init_priority_inheritance(void) {// 创建具有优先级继承的互斥量xHighPriorityMutex = xSemaphoreCreateMutex();#if (configUSE_MUTEXES == 1)// 确保启用互斥量#endif
}void vHighPriorityTask(void *pvParameters) {while(1) {if(xSemaphoreTake(xHighPriorityMutex, pdMS_TO_TICKS(10)) == pdTRUE) {// 高优先级任务获取互斥量critical_operation();xSemaphoreGive(xHighPriorityMutex);}vTaskDelay(pdMS_TO_TICKS(1));}
}void vLowPriorityTask(void *pvParameters) {while(1) {if(xSemaphoreTake(xHighPriorityMutex, portMAX_DELAY) == pdTRUE) {// 低优先级任务获取互斥量时,优先级会临时提升// 防止优先级反转lengthy_operation();xSemaphoreGive(xHighPriorityMutex);}vTaskDelay(pdMS_TO_TICKS(100));}
}// 死锁预防 - 固定顺序获取锁
void safe_resource_access(void) {// 按照固定顺序获取锁(先A后B)xSemaphoreTake(xMutexA, portMAX_DELAY);xSemaphoreTake(xMutexB, portMAX_DELAY);// 访问资源A和Baccess_both_resources();// 释放顺序无所谓,但通常反向释放xSemaphoreGive(xMutexB);xSemaphoreGive(xMutexA);
}

8. 调试和监控功能

系统状态监控

void print_system_status(void) {// 获取任务状态TaskStatus_t *pxTaskStatusArray;UBaseType_t uxArraySize, x;uint32_t ulTotalRunTime;uxArraySize = uxTaskGetNumberOfTasks();pxTaskStatusArray = pvPortMalloc(uxArraySize * sizeof(TaskStatus_t));if(pxTaskStatusArray != NULL) {uxArraySize = uxTaskGetSystemState(pxTaskStatusArray,uxArraySize,&ulTotalRunTime);printf("Task Name\tState\tPriority\tStack\tCPU%%\n");for(x = 0; x < uxArraySize; x++) {printf("%s\t\t%d\t%d\t\t%u\t%lu\n",pxTaskStatusArray[x].pcTaskName,pxTaskStatusArray[x].eCurrentState,pxTaskStatusArray[x].uxCurrentPriority,pxTaskStatusArray[x].usStackHighWaterMark,pxTaskStatusArray[x].ulRunTimeCounter);}vPortFree(pxTaskStatusArray);}// 获取堆内存信息HeapStats_t xHeapStats;vPortGetHeapStats(&xHeapStats);printf("Heap: Free %u, Min Ever Free %u, Allocations %u, Frees %u\n",xHeapStats.xAvailableHeapSpaceInBytes,xHeapStats.xMinimumEverFreeBytesRemaining,xHeapStats.xNumberOfSuccessfulAllocations,xHeapStats.xNumberOfSuccessfulFrees);
}// 运行时堆栈检查
void check_task_stacks(void) {printf("IDLE Task Stack Watermark: %u\n", uxTaskGetStackHighWaterMark(xTaskGetIdleTaskHandle()));// 检查所有任务的堆栈使用// 如果水位线太低,可能需要增加堆栈大小
}

这些应用涵盖了FreeRTOS在MCU开发中的主要实用场景,从基本的任务同步到复杂的系统监控,都是实际项目中验证过的可靠方案。

http://www.dtcms.com/a/528708.html

相关文章:

  • AIGC视频生成之Deepseek、百度妙笔组合实战小案例
  • wordpress 付费剧集网站免费建立网站有必要吗
  • ES数据聚合及其java实现
  • 二、模型训练与参数高效微调范式
  • 美的公司网站建设的目的网站设计注意因素
  • 手机环境光自动亮度调节系统完整实现详解
  • 记录一次海思Hi3798MV200-android7.0平台开机卡在第一张图无法进入系统问题分析解决过程
  • 【设计模式笔记03】:里氏代换原则和依赖倒置原则
  • 网站运行环境建设方案南京做网站南京乐识赞
  • [sam2图像分割] 图像编码器 | Hiera FPN Neck
  • 基于 Dify 的 Excel 测试用例自动化脚本生成工作流开发
  • Photoshop - Photoshop 工具栏(16)画笔工具
  • 深圳网站建设信科便宜设计欣赏网
  • CSS简介(本文为个人学习笔记,内容整理自哔哩哔哩UP主【非学者勿扰】的公开课程。 > 所有知识点归属原作者,仅作非商业用途分享)
  • css之box-sizing属性
  • 【设计模式笔记02】:面向对象设计原则-开闭原则
  • 用于电动汽车的永磁同步电机调速系统建模与仿真(论文+)
  • 校区网站建设网站建设区别
  • 网站建设是什么科目注册企业邮箱免费
  • 长短期记忆网络(LSTM)与门控循环单元(GRU)详解
  • 研究报告:系统排列(Systemic Constellations)的原理、理论体系及文献综述
  • 尚庭公寓学习笔记
  • Unity单例模式基类全解析
  • 餐饮行业做网站的数据ctoc网站有哪些
  • 深圳建设局网站投诉电话淄博网站建设优化公司
  • 久治县网站建设公司东莞人才网最新招聘信息
  • MySQL OCP认证、Oracle OCP认证
  • 深入探讨HarmonyOS中ListItem的滑动操作:从基础实现到高级分布式交互
  • Eclipse Uninstall Software
  • 广东南方通信建设有限公司官方网站合肥网站建设的价格