首页 > 技术文章 > FreeRTOS官方文档手记

eesaltedfish 2021-08-15 00:29 原文

Chapter 1 FreeRTOS 分布

1.1 引言

该章节帮助了解FreeRTOS ZIP的内容分布,方便读者能对FreeRTOS产生明确定位。

  • 提供FreeRTOS的顶层视图
  • 描述具体某个项目需要哪些文件
  • 介绍演示应用程序
  • 提供如何创建新项目的信息

1.2 理解FreeRTOS分布

  1. 定义:FreeRTOS端口

    FreeRTOS可以被20多种编译器构建

    可以在30多种处理器架构上运行

    编译器+处理器的组合即为一种端口

  2. 构建FreeRTOS

    FreeRTOS可被认为是一个库文件,为裸机提供多任务功能

    每个端口都配有配置例程,包含配置源文件与头文件。

  3. FreeRTOSConfig.h

    FreeRTOS的配置文件

    该文件属于正在构建的应用程序目录,不属于源文件(因为是需要配置的)。

  4. FreeRTOS官方发行版本

    通过一个zip压缩包发行,包含了所有的端口配置例程。

  5. FreeRTOS发行版的顶级目录

    • FreeRTOS
      • Source
      • Demo
    • FreeRTOS-Plus
      • Source
      • Demo
  6. FreeRTOS源文件适配所有端口

    • 核心FreeRTOS源代码仅包含在tasks.c和list.c中(FreeRTOS/Source)
    • Source文件中还包含有:
      • queue.c(提供队列和信号量服务)
      • timers.c(提供软件定时器功能)
      • event_groups.c(提供事件组功能)
      • croutine.c(共同例程功能,不重要)
  7. 特定于端口的FreeRTOS源文件

    包含在FreeRTOS/Source/portable目录(第二章详述)

    FreeRTOS将堆内存管理作为可移植层的一部分,提供了五个堆分配示例(heap_1到heap_5)

  8. 包含路径

    FreeRTOS要求编译器包含三个路径:

    • FreeRTOS/Source/include(始终包含,核心FreeRTOS头文件)
    • FreeRTOS/Source/portable/[compiler]/[architecture](正在使用端口的源文件)
    • FreeRTOSConfig.h
  9. 头文件

    • FreeRTOS.h
    • 调用的API任务的头文件:
      • task.h
      • queue.h
      • timer.h
      • event_groups.h

1.3 演示应用程序

演示应用程序目的:

  • 提供一个工作和预配置项目的示例(正确的文件和正确的编译器选项集)
  • 允许“开箱即用”的实验,只需最少的设置或事先了解。
  • 演示如何使用FreeRTOS API
  • 作为实际项目的基础

1.4 建立一个FreeRTOS项目

  1. 调整演示项目之一

    • 打开源文件

    • 删除main函数中除"prvSetupHardware()"和"vTaskStartScheduler()"的函数

    • 检查是否能够编译

  2. 从头开始创建新项目

    • 创建新项目(不含FreeRTOS)

    • 添加FreeRTOS源文件到项目中

    • 将FreeRTOSConfig.h头文件复制到项目目录中(从对应端口的演示项目中Copy)

    • 将以下目录添加到path

      • FreeRTOS/Source/include
      • FreeRTOS/Source/portable/[compiler]/[architecture]
      • 包含FreeRTOSConfig.h的目录
    • 从演示项目复制编译器设置

    • 安装FreeRTOS中断处理程序

    • 早版本的FreeRTOS还需要配置"heap_n.c"文件

1.5 数据类型与编码规范

  1. 数据类型

    每个端口都有独立的"portmacre.h"头文件

    该头文件包含了两个端口特定数据类型定义"TickType_t"、"BaseType_t"

    • TickType_t

      滴答周期中断,"tick period"用于计量FreeRTOS应用启动以来发生的滴答中断次数。

      TickType_t是用于保存tick period和时间的数据结构

    • BaseType_t

      BaseType_t只能接受非常有限的值范围的返回类型

  2. 变量名

    c——char

    s——int16_t

    l——int32_t

    x——BaseType_t

    u——unsigned

    p——pointer

  3. 函数名

    函数的前缀——返回类型/函数其中定义的文件

    • vTaskPrioritySet()——返回void,并在task.c中定义
    • xQueueReceive()——返回BaseType_t类型变量,并在queue.c中定义
    • pvTimerGetTimerID()——返回空指针(a pointer to void),并在timer.c中定义
  4. 格式

    一个Tab等于四个空格

  5. 宏命名

    大多数宏都是以小写字母为前缀的大写字母命名

    • port——portMAX_DELAY
    • task——taskENTER_CRITICAL
    • pd——configUSE_PREEMPTION
    • err——errQUEUE_FULL

    信号量API几乎都是作为宏编写,但却遵循函数命名约定。(不是宏命名约定)

  6. 强制转换的基本原理

    不同编译器希望以不同方式实现强制类型转换

    FreeRTOS源代码中包含更多的强制类型转换

Chapter 2 堆内存管理(heap)

2.1 引言

  1. 预备知识
  2. 动态内存分配与FreeRTOS的相关性
  3. 动态内存分配选项
  4. 总结

2.2 内存分配示例

  1. heap_1
  2. heap_2
  3. heap_3
  4. heap_4
  5. heap_5
  6. vPortDefineHeapRegions() API函数

2.3 与堆相关的函数

  1. xPortGetFreeHeapSize()
  2. xPortGetMinimumEverFreeHeapSize()
  3. Malloc失败的钩子函数

Chapter 3 任务管理

3.1 引言

总结

3.2 任务函数

3.3 顶级任务状态

3.4 创建任务

3.5 任务优先级

3.6 时间测量与滴答中断

3.7 扩展“未运行”状态

  1. Blocked状态
  2. Suspended(挂起)状态
  3. Ready(就绪)状态
  4. 完成状态转换图
  5. vTaskDelayUntil() 函数

3.8 Idle(空闲)任务和空闲任务钩子

  1. 空闲任务钩子函数
  2. 对空闲任务钩子函数实现的限制

3.9 更改任务的优先级

  1. vTaskPrioritySet() 函数
  2. uxTaskPriorityGet() 函数

3.10 删除任务

  1. vTaskDelete() 函数

3.11 线程本地存储

3.12 调度算法

  1. 任务状态和事件的概述

  2. 配置调度算法

  3. 带时间切片的优先抢占式调度

  4. 优先抢占式调度(无时间切片)

  5. 合作调度

Chapter 4 队列管理

4.1 引言

总结

4.2 队列的特征

  1. 多任务访问
  2. 阻塞队列读取
  3. 阻塞队列写入
  4. 阻塞多个队列

4.3 使用一个队列

  1. xQueueCreate() 函数
  2. xQueueSendToBack() 和 xQueueSendToFront() 函数
  3. xQueueReceive() 函数
  4. uxQueueMessagesWaiting() 函数

4.4 从多个来源接收数据

4.5 处理大型/可变大小数据

  1. 队列指针
  2. 使用队列发送不同类型和长度的数据

4.6 从多个队列接收数据

  1. 队列集
  2. xQueueCreateSet() 函数
  3. xQueueAddToSet() 函数
  4. xQueueSelectFromSet() 函数
  5. 更多实际的队列集用例

4.7 使用队列创建邮箱

  1. xQueueOverwrite() 函数
  2. xQueuePeek() 函数

Chapter 5 软件定时器管理

5.1 引言

总结

5.2 软件定时器回调函数

5.3 软件定时器的属性和状态

  1. 软件定时器的周期
  2. 一次性和自动重加载定时器
  3. 软件定时器状态

5.4 软件定时器的上下文

  1. RTOS守护进程服务
  2. 定时器命令队列
  3. 守护进程任务调度

5.5 创建和启动任务定时器

  1. xTimerCreate() 函数
  2. xTimerStart() 函数

5.6 定时器ID

  1. vTimerSetTimerID() 函数
  2. pvTimerGetTimerID() 函数

5.7 更改定时器周期

  1. xTimerChangePeriod() 函数

5.8 重置软件定时器

  1. xTimerReset() 函数

Chapter 6 中断管理

6.1 引言

  1. 事件
  2. 总结

6.2 从ISR使用FreeRTOS API

  1. 中断安全API
  2. 使用单独的中断安全API的好处
  3. 使用单独的中断安全API的缺点
  4. xHigherPriorityTaskWoken 参数
  5. portYIELD_FROM_ISR() 和 portEND_SWITCHING_ISR()宏

6.3 延迟中断处理

6.4 用于同步的二进制信号量

  1. xSemaphoreCreateBinary() 函数
  2. xSemaphoreTask() 函数
  3. xSemaphoreGiveFromISR() 函数

6.5 计数信号量

  1. xSemaphoreCreateCounting() 函数

6.6 将工作推迟到RTOS守护进程任务

  1. xTimerPendFunctionCallFromISR() 函数

6.7 再中断服务例程中使用队列

  1. xQueueSendToFrontFromISR 和 xQueueSendToBackFromISR 函数
  2. 使用ISR队列的注意事项

6.8 中断嵌套

Chapter 7 资源管理

7.1 引言

  1. 进程互斥
  2. 总结

7.2 关键部分和挂起调度程序

  1. 基本临界截面
  2. 挂起(或锁定)调度
  3. xTaskSuspendAll() 函数
  4. xTaskResumeAll() 函数

7.3 互斥量(和二进制信号量)

  1. xSemaphoreCreateMutex() 函数
  2. 优先级反转
  3. 优先级继承
  4. 死锁(Deadlock)
  5. 递归互斥
  6. 互斥体和任务调度

7.4 守门员任务

Chapter 8 时间组

8.1 引言

总结

8.2 事件组的特征

  1. 事件组、事件标志和事件位
  2. "EventBits_t"数据类型
  3. 多任务访问
  4. 使用事件组的实际示例

8.3 使用事件组的事件管理

  1. xEventGroupCreate() 函数
  2. xEventGroupSetBits() 函数
  3. xEventGroupSetBitsFromISR() 函数
  4. xEventGroupWaitBits() 函数

8.4 使用事件组的任务同步

  1. xEventGroupSync() 函数

Chapter 9 任务通知

9.1 引言

  1. 通过中间对象进行通信
  2. 任务通知——直接与任务通信
  3. 总结

9.2 任务通知的优点与缺陷

  1. 任务通知的性能优势
  2. 任务通知的RAM占用优势
  3. 任务通知的限制

9.3 使用任务通知

  1. 任务通知API选项
  2. xTaskNotifyGive() 函数
  3. xTaskNotifyGiveFromISR() 函数
  4. ulTaskNotifyTake() 函数
  5. xTaskNotify() 和 xTaskNotifyFromISR() 函数
  6. xTaskNotifyWait() 函数
  7. 外围设备驱动程序使用任务通知——串口例子
  8. 外围设备驱动程序使用任务通知——ADC例子
  9. 直接在应用程序中使用的任务通知

Chapter 10 低功耗支持

Chapter 11 开发者支持

Chapter 12 故障排查

推荐阅读