资讯详情

资讯详情

FreeRTOS 命名规范|读懂内核源码,写出规范 RTOS 业务代码

学习参考铁头山羊 FreeRTOS 视频教程 P15《3.5 FreeRTOS 的代码规范》刚接触 FreeRTOS 的同学读内核源码一脸迷惑包括我为什么到处都是x、uc、ul、prv这类前缀这些不是随便起的名字是 FreeRTOS 一套完整、严格的编码命名规范同时遵循 MISRA‑C 编码规范目的是一眼从名字看出变量类型、函数属性提升代码可读性、可移植性便于团队协作。提示这套规范不是编译器强制要求但如果你阅读内核源码、写 RTOS 项目尽量对齐这套约定代码会和内核风格统一排错也更轻松。一、核心命名总公式视频重点变量名 类型前缀小写 真实变量名 函数名 返回值类型前缀小写 模块名 真实函数名 宏定义名 所在文件名的缩写小写 真实名字大写单词之间以下划线分割二、变量命名前缀表达数据类型核心规则前缀表达类型名字小写多单词下划线分隔指针增加p前缀表格前缀含义对应类型示例cchar 字符只存 ASCII 字符charcMessageCharucunsigned char 无符号字符uint8_tucLedStatususunsigned short 无符号短整型uint16_tusSensorValueulunsigned long 无符号长整型uint32_tulTimeoutMsxRTOS 自定义可移植有符号类型BaseType_t、TickType_t、各类句柄xReturnCode、xTicksToWait、xTaskHandleuxRTOS 自定义可移植无符号类型UBaseType_tuxPriority、uxStackDepthe枚举类型变量自定义 enumeTaskStatep指针叠加在原有类型前缀前面指针pcMsgBuf(char*)、pvDataBuffer(void*)、pusData(uint16_t*)✅ 重点BaseType_t/UBaseType_t/TickType_t详细讲解这三个是 FreeRTOS 最核心的可移植类型不是标准 C 原生类型会根据 MCU 架构、配置宏自动适配底层存储宽度保证内核跨平台运行。1. BaseType_t含义CPU 基础有符号整型是当前 CPU 架构下效率最高的有符号整数类型32 位 MCU底层等价int32_t16 位 MCUint16_t8 位 MCUint8_t用途函数返回状态、判断结果。绝大多数 FreeRTOS API 返回值都是这个类型例如xQueueSend、xSemaphoreTake命名前缀xBaseType_t xRet; // 正确x前缀⚠️坑不要直接用 int 接收它的返回值。换到 16 位平台int和BaseType_t位宽可能不一致产生移植 bug。2. UBaseType_t含义CPU 基础无符号整型对应BaseType_t的无符号版本32 位 MCU底层等价uint32_t16 位 MCUuint16_t8 位 MCUuint8_t用途任务优先级、栈深度、计数值代表非负数。典型 APIuxTaskGetStackHighWaterMark()命名前缀uxUBaseType_t uxTaskPriority; // 正确ux前缀3. TickType_t含义系统节拍计数器的类型用来保存 Tick 节拍数延时、等待超时✅新版 FreeRTOSV10位宽由configTICK_TYPE_WIDTH_IN_BITS宏控制#define configTICK_TYPE_WIDTH_IN_BITS TICK_TYPE_WIDTH_32_BITSTICK_TYPE_WIDTH_16_BITS→ TickType_t uint16_tTICK_TYPE_WIDTH_32_BITS→ TickType_t uint32_tTICK_TYPE_WIDTH_64_BITS→ TickType_t uint64_t旧版本 V9 及更早使用configUSE_16_BIT_TICKS宏来切换 16/32 位 tick新版本已经弃用该宏。用途存放超时等待节拍数如xTicksToWaitportMAX_DELAY就是这个类型的常量命名前缀x属于 FreeRTOS 自定义类型统一 x 前缀TickType_t xTicksToWait;⚠️坑不要直接强制写uint32_t来接收 TickType_t。如果改成 16bit Tick 配置时代码会出现溢出、类型不匹配问题。一句话区分三者BaseType_t有符号用于返回状态、结果判断可返回 pdPASS/pdFAIL前缀xUBaseType_t无符号CPU 原生无符号基础类型优先级、栈大小前缀uxTickType_t专门用于系统节拍 Tick 计数由configTICK_TYPE_WIDTH_IN_BITS配置 16/32 位前缀x实战示例BaseType_t xResult; // xBaseType_t 有符号基础类型 UBaseType_t uxStackSize; // uxUBaseType_t 无符号基础类型 TickType_t xTicksToWait; // xTickType_t 节拍计数类型 uint8_t ucButtonState; // ucuint8_t uint32_t ulDelayTicks; // uluint32_t char *pcUartBuffer; // pcchar*字符串指针 void *pvTransferBuf; // pvvoid*通用指针 TaskHandle_t xLedTaskHandle; // x开头任务句柄 QueueHandle_t xMsgQueue; // x开头队列句柄 SemaphoreHandle_t xSem; // x开头信号量句柄三、函数命名规则API 公共函数返回值类型作为函数名前缀返回void前缀v→vTaskDelay()、vQueueDelete()返回BaseType_t前缀x→xQueueSend()、xSemaphoreTake()返回UBaseType_t前缀ux→uxTaskGetStackHighWaterMark()返回TickType_t前缀x文件内私有静态函数前缀prvprivate 缩写内核源码大量使用仅本文件内部调用对外不可见static void prvInitialiseTaskLists( void ); static BaseType_t prvCheckTaskPriority( void );API 函数命名结构[返回前缀][模块名][动作]模块名对应源文件名tasks.c → Taskqueue.c → Queuetimers.c → Timer 例v(void 返回) Task(tasks.c 模块) Delete(动作) vTaskDelete()四、宏定义、配置项命名FreeRTOS 配置宏FreeRTOSConfig.h小写模块前缀_全部大写下划线分隔configUSE_PREEMPTION configMAX_PRIORITIES configTICK_TYPE_WIDTH_IN_BITS portMAX_DELAYconfig应用层配置项port移植层相关宏内核内部宏模块缩写前缀加大写例如tskIDLE_PRIORITY注意用户自己业务代码不要用config、port、tsk这类前缀避免和内核冲突。五、句柄类型HandleV8 版本之后统一使用xxxHandle_t类型变量依然使用x前缀TaskHandle_t xTaskHandle; QueueHandle_t xMyQueue; SemaphoreHandle_t xBinarySem; TimerHandle_t xSoftwareTimer;旧版本 V7 及更早写法xTaskHandle已经废弃新项目不要使用旧风格。六、重点避坑不要混淆标准 C 类型和 FreeRTOS 自定义类型不要拿int接收xQueueSend()返回值该 API 返回BaseType_t部分平台BaseType_t不等于 int。TickType_t不要直接使用uint32_t如果修改configTICK_TYPE_WIDTH_IN_BITS切换为 16bit tick 时代码会出错。指针前缀叠加顺序p放在最前面uint16_t*→pusValuechar*→pcStringvoid*→pvBuffer。命名要有语义拒绝简写天书 变量名尽量完整单词通用缩写可以接受不要写a、b、tmp1这种无意义名字。这是编码风格建议不是编译器强制语法。 你不按照写代码照样编译运行但读内核、团队协作强烈建议遵守这套约定。七、MISRA‑C 简单补充FreeRTOS 内核遵循char只用来存 ASCII 字符串不要拿来做无符号字节字节存储用uint8_t(uc)。内核源码尽量规避 C99 之后语法只使用stdint.h。内核源码层面禁止逗号运算符、三元运算符业务代码可以灵活使用。八、业务代码参考模板/* 任务句柄 */ TaskHandle_t xKeyScanTaskHandle; /* 队列句柄 */ QueueHandle_t xKeyEventQueue; /* 无符号8位按键状态 */ uint8_t ucKeyValue; /* TickType_t 等待节拍 */ TickType_t xTicksWait; /* BaseType_t 函数返回结果 */ BaseType_t xFuncRet; /* UBaseType_t 任务优先级 */ UBaseType_t uxKeyTaskPrio; /* 字符串指针 */ char *pcLogInfo; /* 私有静态函数 */ static void prvKeyFilterDeal(uint8_t ucKey); /* 任务函数 */ void vKeyScanTask(void *pvParameters);九、错误示范 ❌TaskHandle_t task1; // 缺少x前缀不符合规范 int ret xQueueSend(...); // 用int接收BaseType_t返回值移植风险 uint8_t *pData; // 规范应该写作pucData static void key_filter();// 静态私有内核风格建议加prv前缀 TickType_t ulTickCnt; // ❌错误TickType_t是x前缀不是ul UBaseType_t xPrio; // ❌错误UBaseType_t是ux前缀不是x课后习题视频原题6. 请简述 FreeRTOS 当中变量、函数和宏定义的命名规则。答题要点博客折叠参考答案details summary参考答案/summary变量命名变量名 类型前缀小写 真实变量名前缀标识变量类型指针类型在最前面叠加p前缀。BaseType_t、TickType_t、各类句柄前缀xUBaseType_t前缀ux函数命名函数名 返回值类型前缀小写 模块名 真实函数名静态私有函数使用prv前缀。宏定义命名宏名 所在文件名缩写小写 真实名字大写单词下划线分割例如tskIDLE_PRIORITY。扩展配置文件 FreeRTOSConfig.h 里的宏使用config前缀移植层宏使用port前缀。/details结尾总结这套命名本质是匈牙利命名法把类型信息写在变量名字的前缀。 好处扫一眼代码不用跳转看变量定义就知道变量是什么类型极大降低 FreeRTOS 源码阅读门槛。其中BaseType_t、UBaseType_t、TickType_t是 FreeRTOS 三大可移植类型是这套命名规范里最容易踩坑的知识点。如果你是 STM32 HAL 库 FreeRTOS 开发业务代码可以混合 HAL 库风格但是所有 RTOS 对象任务、队列、信号量、软件定时器尽量遵循这套规范。扩展阅读FreeRTOS 官方编码标准文档https://www.freertos.org/FreeRTOS‑Coding‑Standard‑and‑Style‑Guide.html
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →