FreeRTOS-任务管理

任务状态

在freertos里任务状态可大致分为四类:
运行态,就绪态,阻塞态,挂起态。
在这里插入图片描述
任务在创建完成并退出临界区后,各任务进入到就绪态①,最高优先级的首先运行进入到运行态开始运行②,其他任务仍为就绪态。当任务遇到延时,或者需要等待信号量,事件通知需要等待的时候,这时运行态的任务转到阻塞态④。次优先级高的任务接着运行进入到运行态②。当处于阻塞态的高优先级任务被唤醒(延时时间达到或有信号释放)进入到就绪态⑤,由于优先级比正在运行的任务要高,所以会立即抢占CPU进行运行,而被抢占的任务则回到就绪态③,等待高优先级任务被阻塞或挂起再继续运行。处在运行态的任务可以通过函数将自己和其他任务给挂起⑥⑦⑧,和退出挂起态的任务退出后处于就绪态。

就绪态:处在就绪态的任务具备运行的能力和条件,但还没挨到他运行。
(FreeRTOS属于伪并发的,是基于时间片轮转的并发模型,微观上还是同一时间只能运行一个任务,只是多个任务每运行一个时间片就进行来回的切换,宏观上看起来像是多个任务一块运行的。)
运行态:获得 CPU使用权,正在运行的任务。
阻塞态:正在运行的任务,因延时一段时间或等待外部事件发生,而处于阻塞的状态。
挂起态:通过函数 vTaskSuspend()和 vTaskResums()进入和退出挂起态与阻塞态一样,处于挂起态的任务也无法被运行。
任务优先级:FreeRTOS任务优先级和他的数值成正比。数值越大,对应的任务优先级也越高。

API函数

创建

动态创建:

BaseType_t xTaskCreate(
 TaskFunction_t pxTaskCode,
 const char * const pcName,
 const configSTACK_DEPTH_TYPE usStackDepth,
 void * const pvParameters,
 UBaseType_t uxPriority,
 TaskHandle_t * const pxCreatedTask);

参数一; 指向任务函数的指针(任务函数的名称)
参数二:任务名称
参数三:任务堆栈大小,单位:字
参数四:传给任务函数的参数。没有填NULL
参数五:任务优先级
参数六:任务句柄
通常在前面使用define进行定义如:

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		70  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);

删除

被删除的任务将被从就绪态任务列表、阻塞态任务列表、挂起态任务列表和事件列表中移除。(注:在任务被删除之前要把手动申请的内存给提前释放调,否则会导致内存泄漏。系统分配的内存则会由空闲任务自动释放)

void vTaskDelete(TaskHandle_t xTaskToDelete);

参数:要删除的任务句柄。NULL:删除自身。

挂起

被挂起的任务不再参与任务调度,不占用CPU资源。直到退出。
任务中:

void vTaskSuspend(xTaskToSuspend)

参数:要挂起的任务句柄。

中断中:

xTaskResumeFromISR(xTaskToSuspend) 

参数:要挂起的任务句柄。

恢复

不论一个任务被函数 vTaskSuspend()挂起多少次,只需要使用函数
vTakResumeFromISR()恢复一次,就可以继续运行。
任务中:

void vTaskResume(TaskHandle_t xTaskToResume)

参数:要恢复的任务句柄。
恢复全部任务:

void vTaskResumeAll(void)

中断中:

BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume)

参数:要恢复的任务句柄。
返回值:pdTRUE:恢复任务的优先级比正在运行的高或相等时。(需要进行上下文切换)
pdFALSE:恢复任务的优先级比正在运行的低时。(不需要进行上下文切换)

暂停

暂停任务调度器:

void vTaskSuspendAll(void)

执行完这句函数后,程序将关闭系统中的任务调度器不再进行任务间的调度,使程序一直运行在该任务中,保护共享资源。

退出暂停任务调度器:

void xTaskResumeAll(void)

可通过该函数来重新开启任务调度器,使任务可以正常的进行切换。

切换

void taskYLELD(void)

在同优先级使用时间片调度模式时,执行该函数可以使任务退出本次的CPU使用权,让给其他任务,进行任务间的切换。

延时

相对延时,延时时间受多种因素影响。可以理解为执行到这个函数时,任务进入到阻塞状态,经过xTicksToDelay 个节拍后任务退出阻塞,进入到就绪态,等待任务调度。如果此时有比他任务优先级高的任务在运行或等待,那么即使他延时时间到了也不会立即运行而是等待比他优先级高的任务都运行完才会继续运行。

void vTaskDelay( const TickType_t xTicksToDelay )

参数:延时时间
延时的时间单位为系统时钟节拍,系统时钟节拍的长短取决于FreeRTOSConfig.h 文 件 中 的 配 置 项configTICK_RATE_HZ 的大小,一般configTICK_RATE_HZ 为1000,换算一个时钟节拍等于1毫秒。

<think>好的,用户现在想在FreeRTOS-plus-TCP上实现轻量级MQTT客户端。我需要结合之前的对话和提供的引用内容来给出合适的建议。首先,回顾用户之前的提问,他们提到了三个轻量级MQTT客户端的实现方案:MQTT-C、coreMQTT和OneNET实现。现在用户的具体环境是FreeRTOS-plus-TCP,这是一个针对FreeRTOS的网络协议栈,适合嵌入式设备。用户提供的引用内容中,引用[3]提到系统后端使用SpringBoot,前端Vue3,消息服务器用EMQX5.0,设备端支持FreeRTOS等。这可能意味着用户的项目是物联网相关的,需要设备端通过FreeRTOS连接到MQTT服务器,比如EMQX。接下来,我需要考虑如何在FreeRTOS-plus-TCP上实现MQTT客户端。根据之前的推荐,coreMQTT是内存优化最好的,而且支持TLS,可能更适合资源受限的环境。而FreeRTOS-plus-TCP已经处理了TCP/IP层,所以需要将MQTT库移植到这个协议栈上。步骤方面,首先需要确认FreeRTOS-plus-TCP的网络接口如何与MQTT客户端库适配。例如,coreMQTT需要实现网络传输层的发送和接收函数,这里可能需要调用FreeRTOS的socketAPI。另外,内存管理也很重要,要确保动态内存分配适合FreeRTOS的环境,可能需要使用静态内存分配或堆管理。然后,用户可能需要配置MQTT的连接参数,比如客户端ID、服务器地址、端口等。由于是轻量级,需要确保代码尽可能精简,避免不必要的功能。QoS的选择也很重要,QoS0最轻量,但可靠性低,QoS1需要消息确认,会增加一些开销。另外,引用[2]提到需要前端和移动端开发,但用户当前的问题是关于设备端的,所以可能暂时不需要涉及前端部分,但可以提醒用户如果需要与前端交互,可能需要考虑消息格式和协议的一致性。在代码示例部分,需要展示如何在FreeRTOS任务中初始化网络,连接MQTT服务器,并发布消息。可能需要使用FreeRTOS任务、队列等机制来处理网络通信和消息处理,避免阻塞。最后,相关问题需要围绕FreeRTOS和MQTT的集成,比如内存优化、网络适配、QoS处理、掉线重连等,这些都是实际开发中常见的问题。同时,TLS集成也是一个重点,因为安全通信在物联网中很重要,但会增加资源消耗,需要权衡。</think>### 在FreeRTOS-plus-TCP上实现轻量级MQTT客户端的步骤解析 #### 一、架构设计要点 1. **协议栈适配** - 基于FreeRTOS-plus-TCP的`socket()`接口实现网络传输层[^3] - 使用单任务模型处理MQTT报文收发与心跳维护 - 内存占用控制在$20KB$以内(不含TLS) 2. **代码结构示例**: ``` mqtt_freertos/ ├── mqtt_client.c // MQTT协议核心实现 ├── mqtt_freertos.c // FreeRTOS适配层 └── mqtt_config.h // QoS/心跳等参数配置 ``` #### 二、关键实现步骤 1. **网络接口适配** ```c // FreeRTOS_connect()封装示例 int mqtt_net_connect(const char* host, uint16_t port) { Socket_t xSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM, FREERTOS_IPPROTO_TCP); FreeRTOS_connect(xSocket, &xAddress, sizeof(xAddress)); return xSocket; } ``` 2. **MQTT任务实现** ```c void vMQTTTask(void *pvParameters) { MQTTClient_t xClient; NetworkContext_t xNetworkContext; // 初始化网络连接 xNetworkContext.socket = mqtt_net_connect("broker.emqx.io", 1883); // MQTT协议握手 MQTT_Init(&xClient, &xNetworkContext, get_current_time, message_handler_cb); for(;;) { // 处理报文接收与心跳 MQTT_ProcessLoop(&xClient, 500); vTaskDelay(pdMS_TO_TICKS(100)); } } ``` 3. **内存优化配置**(mqtt_config.h): ```c #define MQTT_RX_BUFFER_SIZE 512 // 接收缓冲区 #define MQTT_TX_PAYLOAD_MAX 128 // 最大消息负载 #define MQTT_KEEP_ALIVE 60 // 心跳间隔(秒) ``` #### 三、性能优化策略 1. **动态内存控制** - 使用FreeRTOS静态内存分配器: ```c void* mqtt_malloc(size_t size) { return pvPortMalloc(size); // 使用FreeRTOS内存管理 } ``` 2. **QoS分级实现** - QoS 0: 直接发送不等待ACK[^3] - QoS 1: 使用消息ID映射表记录发送状态 ```c typedef struct { uint16_t packet_id; uint32_t send_timestamp; } QoS1PendingList_t; ``` 3. **网络异常处理** - 实现自动重连机制: ```c if(FreeRTOS_recv(xSocket, ...) < 0) { vReconnectNetwork(&xClient); // 包含指数退避算法 } ``` #### 四、测试验证方法 1. **EMQX服务器验证** ```bash $ mosquitto_sub -h broker.emqx.io -t "freertos/status" ``` 2. **内存占用统计** ```c printf("Heap free: %d", xPortGetFreeHeapSize()); ``` ### 实现方案对比 | 功能模块 | 传统实现 | FreeRTOS优化方案 | |---------------|---------------|-----------------| | 网络IO | 阻塞式read/write | 非阻塞式事件驱动 | | 内存管理 | 动态分配 | 静态缓冲区池 | | 心跳机制 | 独立定时线程 | 主循环轮询 | ### 开发建议 1. 优先实现QoS 0级别保证基础通信 2. 使用Wireshark抓包验证协议合规性[^3] 3. 通过`uxTaskGetStackHighWaterMark()`监控任务栈使用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值