FreeRTOS的学习

📅 2026/8/18 14:17:24
FreeRTOS的学习
1、任务函数的一般写法//任务函数使用void类型的返回值但是有一个void*类型的参数 void vTask1void*pvParameters { //编程方式类似于main方法一般写一个无限循环 for { //使用vTaskDelay而不使用HAL_Delay()进行延迟 } //坚决不能写return vTaskDeleteNULL //一旦退出需要删除自身 }2、main方法的一般写法int main(void) { // 一些底层的初始化代码放这里 ........ //先创建任务 xTaskCreate(vTask1,Task1,......); //任务1 xTaskCreate(vTask2,Task2,......); //任务2 //再启动调度器 vTaskStartScheduler(); //无限循环 while1 { } }变量名的命名规则 变量名 类型前缀 实际名字函数名的命名规则宏定义命名规则FreeRTOS任务调度机制三种任务调度方式抢占式调度主要是针对优先级不同的任务每个任务都有一个优先级优先级高的任务可以抢占优先级低的任务时间片调度主要针对优先级相同的任务当多个任务的优先级相同时任务调度器都会在每一个系统时钟节拍到时候切换任务协程式调度当前执行任务将会一直运行同时高优先级任务不会在抢占低优先级任务当前任务主动放弃CPU才会执行下一个FreeRTOS现在虽然还支持但是官方表示不再更新协程式调度。四种任务状态Running 运行态 当任务处于实际运行状态被称之为运行态即 CPU 的使用权被这个任务占用。Ready 就绪态 处于就绪态的任务是指那些 能够运行没有被阻塞和挂起但是当前没有运行的任务因为同优先级或更高优先级的任务正在运行 。一个任务要能够运行前必须先进入就绪态。Blocked 阻塞态 由于等待信号量消息队列事件标志组等而处于阻塞的状态 被称之为阻塞态另外任务调用vTaskDelay() 延迟函数也会处于阻塞态。Suspended 挂起态 类似阻塞态通过手动调用函数 vTaskSuspend()对指定任务进行挂起挂起后这个任务不被执行只有手动调用函数 xTaskResume()才可以将这个任务从挂起态恢复。ldle 空闲任务优先级最低为 0 。空闲任务要么处于就绪态要么处于运行态永远不会阻塞。任务间的通信方式队列Queues核心作用队列是 FreeRTOS 中任务间传递数据的主要方式支持在任务与任务、中断与任务之间发送消息。工作原理队列本质上是一个线程安全的先进先出FIFO缓冲区。消息是通过复制的方式发送的即把数据本身或指向数据的指针拷贝到队列中。阻塞机制当任务尝试读取空队列或写入已满队列时可以指定一个阻塞时间。任务会进入“被阻止”状态直到有数据/空间可用或超时。处于该状态的任务不占用 CPU 时间。2. 信号量与互斥量Semaphores Mutexes核心作用主要用于任务间的同步和互斥访问保护共享资源。创建函数xSemaphoreCreatrBinary 二进制信号量初始 0xSemaphoreCreateCountinguxMaxCount, uxInitialCount ———计数信号量xSemaphoreCreateMutex ——互斥量操作xSemaphoreTask (xSemaphore, xTicksToWait) ——取portMax_DELAY 表示永久等待xSemaphoreGivexSemaphore ——释放xSemaphoreGiveFromISRxSemaphore, pxHigherPriorityTaskWoken ——ISR中使用二进制信号量Binary Semaphore只有 0 和 1 两个状态常用于任务与中断之间的同步或作为简单的信号机制。计数信号量Counting Semaphore具有大于 1 的计数值用于跟踪可用资源的数量或事件发生的次数允许多个任务共享一组资源。互斥量Mutex一种特殊的二元信号量内置了优先级继承机制。当高优先级任务等待低优先级任务持有的互斥量时低优先级任务的优先级会被临时提升从而最大程度减少“优先级翻转”问题。注意1、别用二进制信号量做互斥——它没有优先级继承可能出现严重的优先级反转。2、互斥量不能在 ISR 里用——ISR 没有任务优先级优先级继承无从谈起ISR 通知任务请用二进制信号量GiveFromISR。3、互斥量谁拿谁放——必须由取锁的同一个任务释放信号量则可以由任意任务/ISR 释放。3. 任务通知Task Notifications核心作用一种轻量级的事件通知机制允许任务直接与另一个任务或中断服务例程ISR同步。工作原理每个任务都有一个 32 位的通知值。发送方可以直接更新接收方的通知值并唤醒它无需创建额外的通信对象如队列或信号量。优势与限制相比于队列和信号量任务通知在执行速度上更快且 RAM 开销更小。但其局限性在于只能用于事件接收方是唯一的一个任务的场景。4. 事件组Event Groups核心作用允许一个任务同时等待多个事件组合条件的发生。工作原理事件组内部包含一组事件标志位Bits。当某个事件发生时对应的位被置 1。任务可以阻塞等待特定的位组合被置位从而一次性响应多个条件这比为每个事件单独创建信号量要节省内存且逻辑更清晰。5. 流缓冲区与消息缓冲区Stream Message Buffers核心作用主要用于传递字节流或离散的消息特别适合在中断和任务之间传递不定长的数据。工作原理支持一次写入或读取任意数量的字节。安全限制流缓冲区假定只有一个写入器和只有一个读取器写入器和读取器可以是不同的任务或中断但不能有多个写入器或多个读取器多对多读写是不安全的。在实际开发中传递具体数据使用队列Queue。保护共享资源使用互斥量Mutex。任务/中断间的简单同步使用二元信号量或更高效的任务通知。等待多个条件满足使用事件组。FreeRTOS 优先级反转高优先级的Task2 必须等待低优先级的Task1 放弃对互斥量的控制。这种高优先级任务被低优先级任务延迟的情况被称为“优先级反转”优先级的继承FreeRTOS的任务栈的大小栈①返回地址LR其他寄存器函数调用深度②局部变量③现场 16x464byte也就是栈用量 上下文现场 调用链上所有函数的局部变量 寄存器压栈。