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

FreeRTOS学习笔记——总览

考虑到RTOS能够提升单片机开发能力,也是开发复杂任务的必经之路,还是有必要学习的。
FreeRTOS教程多,免费开源,是个不错的选择。后续可以考虑继续学习RT-Thread等。
参考1:FreeRTOS(教程非常详细)——作者:不秃也很强
参考2:部分内容由GPT生成,请注意核实。

一、FreeRTOS简介

FreeRTOS 是一个开源、实时操作系统 (RTOS),它提供了对多任务处理、资源管理和硬件抽象的支持。它主要用于嵌入式系统开发,特别适合资源受限的环境。以下是对 FreeRTOS 的简介,包括其特点、优缺点等内容:

FreeRTOS 简介

FreeRTOS 是一个功能强大的实时操作系统,广泛应用于嵌入式系统中。它轻量且高效,适用于对时间要求较高的应用场景,如自动化控制、工业设备、智能家居设备等。作为一个实时操作系统,FreeRTOS 支持多任务调度,并提供了诸如任务优先级、队列、信号量、互斥量等基本的同步机制。

特点

  1. 轻量级:
    FreeRTOS 内核非常小巧,适用于资源受限的嵌入式系统。它的内核代码可以精简到几 KB 的大小,适合存储空间有限的设备。

  2. 优先级调度:
    FreeRTOS 支持基于优先级的任务调度,用户可以为任务分配不同的优先级,并根据任务的优先级进行调度。

  3. 支持多种架构:
    FreeRTOS 支持多种微处理器架构,包括 ARM Cortex-M、AVR、PIC、RISC-V 等。可以在多种硬件平台上进行移植。

  4. 可配置性强:
    FreeRTOS 是高度可配置的,用户可以根据项目的需要定制调度策略、内存管理方案以及其他系统资源的管理方式。

  5. 广泛的社区支持:
    作为一个开源项目,FreeRTOS 拥有强大的社区支持,用户可以轻松获取文档、示例代码和开发者论坛的帮助。

  6. 实时性:
    FreeRTOS 是为实时应用设计的,支持精确的任务调度和时间管理,能够保证高优先级任务的及时响应。

  7. 集成丰富的同步机制:
    提供了信号量、队列、互斥量等同步机制,支持多任务之间的通信和协调。

  8. 低功耗支持:
    FreeRTOS 支持低功耗管理,适合电池供电的设备,能够根据任务需求调整处理器的工作状态。

优点

  1. 开源和免费:
    FreeRTOS 是完全开源的,可以自由使用并根据需要修改源代码,这使得它特别适合学术研究和商业产品开发。

  2. 高度可移植:
    支持多种硬件平台和编译器,开发者可以在不同的硬件上移植和使用 FreeRTOS。

  3. 灵活的任务管理:
    提供了丰富的任务调度功能,能够在多任务系统中灵活管理任务,包括任务创建、删除、挂起、恢复等。

  4. 实时性能:
    对实时任务的响应时间控制严格,适合需要严格时间约束的嵌入式系统。

  5. 广泛应用和成熟:
    已经被广泛应用于各类商业产品中,经过了大量实际应用的验证,具有很高的稳定性。

缺点

  1. 功能相对简单:
    虽然 FreeRTOS 提供了多任务管理和基本的同步机制,但其功能相较于一些更复杂的操作系统(如 Linux)较为简单,不支持复杂的进程管理、文件系统和网络协议栈。

  2. 调试较难:
    由于是嵌入式系统,调试 FreeRTOS 程序通常比较复杂。虽然有一些调试工具,但相比于标准操作系统,嵌入式开发环境的调试仍然面临一些挑战。

  3. 内存管理:
    FreeRTOS 的内存管理功能相对较为基础,缺乏先进的内存保护和虚拟内存管理,可能导致一些内存溢出等问题。

  4. 不适合复杂的任务管理:
    FreeRTOS 的多任务支持适合简单到中等复杂度的任务管理,对于需要大量进程、线程调度和高效资源管理的大规模应用可能不太适用。

总结

FreeRTOS 是一个非常适合嵌入式系统的小型实时操作系统,它提供了强大的多任务处理能力和良好的实时性支持,尤其适合资源有限、对时间要求严格的应用。它的开源特性和高可配置性使得它在嵌入式领域有着广泛的应用,但对于需要更复杂功能的系统,可能需要考虑其他更强大的 RTOS 或操作系统。

希望这个简介能够帮助你理解 FreeRTOS 的基本概念,后续可以在博客中进一步深入探讨具体的使用场景和移植过程。

二、函数名前缀和参数命名规范

在 FreeRTOS 中,函数名前缀和参数命名通常有一些约定,这些约定有助于区分不同类型的变量、函数或对象的作用。下面是一些常见的命名约定,解释了这些前缀的含义:

1. x 前缀

  • x 是 FreeRTOS 中非常常见的前缀,表示 “变量”。它用于标识一个 结构体、句柄、或其他对象,这些对象通常会存储状态信息或数据,并且可能会在多个任务间传递。
  • xTaskHandle:例如 xTaskHandle 是一个句柄类型,用于引用任务。
  • xQueueHandle:表示队列的句柄。
  • xSemaphoreHandle:表示信号量的句柄。
  • xEventGroupHandle:表示事件组的句柄。

例子:

xQueueHandle xQueue;  // 队列句柄
xTaskHandle xTask;    // 任务句柄

2. v 前缀

  • v 前缀通常表示 “void” 类型的函数,即不返回值的函数。许多 FreeRTOS 的 API 函数都是以 v 为前缀的,它们执行任务但不需要返回值。

例子:

void vTaskDelay( TickType_t xTicksToDelay );  // 延迟函数,不返回值
void vTaskStartScheduler(void);                // 启动调度器函数

3. px 前缀

  • px 前缀表示一个 指针,尤其是指向任务、队列、信号量等对象的指针。在 FreeRTOS 的许多数据结构中,使用了指针来管理和传递对象。

例子:

TaskHandle_t *pxTask;  // 任务指针
QueueHandle_t *pxQueue;  // 队列指针

4. ux 前缀

  • ux 前缀通常表示 无符号类型的变量,尤其是一些与计数、任务优先级、事件等有关的变量。

例子:

uxQueueMessagesWaiting( QueueHandle_t xQueue );  // 返回队列中消息的数量
uxTaskPriorityGet( TaskHandle_t xTask );  // 获取任务的优先级

5. pv 前缀

  • pv 前缀表示 指向 void 类型的指针。它通常用于指向无法预先确定类型的通用数据结构。

例子:

void *pvParameter = NULL;  // 无类型的参数

6. prv 前缀

  • prv 表示 “private”(私有的)。通常用于表示在文件内部或静态作用域中的私有函数。它表明这些函数不应该被外部调用,仅限于文件内部的使用。

例子:

static void prvTaskFunction(void *pvParameters);  // 私有任务函数

7. ux 和 x 的结合

  • uxx 在某些情况下会结合使用,用于表示 无符号普通 的参数或返回值。

8. 其他命名约定

  • TickType_t:表示 FreeRTOS 中时间计时单位的类型,通常是无符号整数。
  • BaseType_t:表示带符号的基础类型,常用于任务或事件标志返回的结果。
  • TickType_tBaseType_t:都是 FreeRTOS 内部时间和状态相关的标准数据类型。

总结:

这些命名约定为开发者提供了一定的 代码规范,便于理解和维护代码。在使用 FreeRTOS 时,熟悉这些命名规则能帮助你更快速地理解 API 的含义和功能,从而有效地进行开发。

三、开发规范

为了确保后续开发的规范性、可维护性和代码的统一性,命名约定是非常重要的。以下是一些通用的命名约定,适用于 FreeRTOS 或其他嵌入式开发项目。你可以根据具体项目的需求进行调整和扩展:

1. 函数命名

  • 动词+名词结构:函数名应该清晰表达其功能,通常使用动词+名词结构来描述。

  • 避免简写:使用完整的单词,避免使用不常见的缩写。

  • 动词使用

    • create: 创建任务、队列、信号量等(如 createTaskcreateQueue)。
    • init: 初始化操作(如 initSysteminitHardware)。
    • get: 获取某个值(如 getTaskPriority)。
    • set: 设置某个值(如 setTaskPriority)。
    • handle: 处理某个操作(如 handleInterrupt)。
    • start, stop: 启动和停止操作(如 startSchedulerstopTask)。
    • check: 检查状态(如 checkQueueEmpty)。

例子

void createTask(void);
void initSystem(void);
int getQueueLength(QueueHandle_t xQueue);
void startScheduler(void);
void stopTask(TaskHandle_t xTask);

2. 参数命名

  • 小写字母+驼峰法:使用小写字母,并遵循驼峰命名规则(第一个单词首字母小写,后续单词首字母大写)。
  • 描述性:参数命名要有描述性,能反映它在函数中的作用。
  • 避免缩写:尽量避免使用缩写,除非是众所周知的缩写(如 ptr 表示指针)。

例子

void setTaskPriority(TaskHandle_t taskHandle, UBaseType_t priority);
void initQueue(QueueHandle_t *queueHandle, size_t queueSize);

3. 结构体命名

  • 类型名称+结构体标识:结构体的名称应该能明确表示其用途和类型。通常以类型名称为基础,加上 Struct 后缀。
  • 驼峰命名法:使用大驼峰命名法(每个单词首字母大写)。
  • 结构体成员命名:结构体成员一般使用小写字母,并用下划线分隔(如果需要)。

例子

typedef struct TaskConfig {uint32_t taskId;uint32_t taskPriority;void (*taskFunction)(void *);
} TaskConfig_t;

4. 全局变量命名

  • 小写字母+下划线分隔:全局变量命名应简洁明了,使用小写字母和下划线分隔各个词。
  • 避免与局部变量冲突:确保全局变量的命名不会与函数中的局部变量冲突。

例子

uint32_t system_status;
TaskHandle_t scheduler_task;

5. 常量命名

  • 全大写+下划线分隔:常量(如宏、枚举等)使用全大写字母,单词之间使用下划线分隔。
  • 前缀标识:可以使用一些前缀来表示常量的作用或范围,例如 MAX_ 表示最大值,CONFIG_ 表示配置相关常量。

例子

#define MAX_TASK_PRIORITY 10
#define CONFIG_QUEUE_SIZE 128

6. 句柄命名

  • Handle 结尾:句柄一般是指向某个对象(如任务、队列等)的指针,命名时可以在名称的后面加上 Handle 后缀。

例子

TaskHandle_t taskHandle;
QueueHandle_t queueHandle;
SemaphoreHandle_t semaphoreHandle;

7. 类型定义

  • typedef 类型名+描述性后缀:如果需要为某些数据类型定义类型别名,可以使用描述性的名称,并以 _t 结尾。

例子

typedef uint32_t TickType_t;
typedef struct {int x;int y;
} Position_t;

8. 文件命名

  • 小写字母+下划线分隔:文件名应简洁明了,使用小写字母和下划线分隔,便于识别文件内容。
  • 与功能匹配:文件名应与文件中的功能或模块匹配。

例子

task_scheduler.c
queue_manager.c
system_init.c

9. 宏命名

  • 全大写字母:宏定义使用全大写字母,单词之间使用下划线分隔,便于区分常量和宏定义。

例子

#define TASK_STACK_SIZE 1024
#define QUEUE_TIMEOUT 100

10. 命名约定总结

  • 可读性优先:命名应具有描述性,能准确反映变量或函数的用途。
  • 统一性:保持项目中的命名风格一致,避免混用不同的命名方式。
  • 避免使用类似“temp”、“data”等没有实际意义的名称,除非是临时变量。
  • 避免过度缩写:缩写可以提高代码简洁性,但要确保其他开发者能理解这些缩写的含义。

总结

通过遵循这些命名约定,可以确保代码的清晰性和可维护性。为不同类型的参数、变量、函数等选择合适的命名规则,不仅可以提高开发效率,还能减少后期维护中的混淆和错误。在写博客时,你可以根据这些规则为开发项目提供清晰的命名标准,并帮助其他开发者更好地理解代码。


文章转载自:
http://bountifully.wsgyq.cn
http://chaplaincy.wsgyq.cn
http://arsonist.wsgyq.cn
http://accouchement.wsgyq.cn
http://calamary.wsgyq.cn
http://appellatively.wsgyq.cn
http://adela.wsgyq.cn
http://aroint.wsgyq.cn
http://barkhan.wsgyq.cn
http://brunhild.wsgyq.cn
http://agamemnon.wsgyq.cn
http://atonable.wsgyq.cn
http://beagle.wsgyq.cn
http://benzol.wsgyq.cn
http://applecart.wsgyq.cn
http://aeciospore.wsgyq.cn
http://borated.wsgyq.cn
http://autosum.wsgyq.cn
http://amr.wsgyq.cn
http://calque.wsgyq.cn
http://arrogancy.wsgyq.cn
http://cautioner.wsgyq.cn
http://baku.wsgyq.cn
http://agone.wsgyq.cn
http://adonis.wsgyq.cn
http://aeschylean.wsgyq.cn
http://alcoholism.wsgyq.cn
http://alienable.wsgyq.cn
http://beautifully.wsgyq.cn
http://atomic.wsgyq.cn
http://www.dtcms.com/a/280422.html

相关文章:

  • 【Docker基础】Dockerfile构建与运行流程完全指南:从原理到实践优化
  • CentOS 8-BClinux8.2更换为阿里云镜像源:保姆级教程
  • 【第二章自定义功能菜单_MenuItemAttribute_顶部菜单栏(本章进度1/7)】
  • Rust基础-part5-引用
  • 【jvm|基本原理】第四天
  • 游戏行业中的恶梦:不断升级的DDoS攻击
  • 深入理解C++11 std::iota:从原理到实践
  • UDP和TCP的主要区别是什么
  • 17. 什么是 webSocket ?
  • 力扣 hot100 Day45
  • ZYNQ千兆光通信实战:Tri Mode Ethernet MAC深度解析
  • Keepalived双机热备概述
  • 基于深度学习的LSTM、GRU对大数据交通流量分析与预测的研究
  • omniparser v2 本地部署及制作docker镜像(20250715)
  • 从浏览器到服务器:TCP 段的网络传输之旅
  • 设计模式二:策略模式 (Strategy Pattern)
  • 云计算如何提高企业的数据安全性和隐私保护
  • 我会秘书长杨添天带队赴杭州融量农业发展有限公司考察调研
  • NQTT-基础知识
  • CSS :root伪类详解:实现动态主题切换的关键所在
  • 7.15 Java基础|大小写转换、数组、ArrayList类
  • 基于Langchain4j开发AI编程助手
  • Python_1
  • 高等数学强化——导学
  • 【Python练习】044. 编写一个函数,实现快速排序算法
  • 第十三讲 | map和set的使用
  • JavaDemo——使用CGLIB动态代理
  • I3C通信驱动开发注意事项
  • 【雅思播客016】New Year Resolution 新年决心
  • docker搭建freeswitch实现点对点视频,多人视频