多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

[FreeRTOS]命名规范

[FreeRTOS]命名规范 目录为什么要学习 FreeRTOS 里面的命名规范数据类型命名标准类型TickType_tBaseType_tUBaseType_tStackType_tTaskHandle_tQueueHandle_tSemaphoreHandle_tTimerHandle_t自定义类型变量的命名规则代码示例变量的命名公式变量前缀总结变量修改示例函数的命名规则一、函数命名通用公式二、额外特殊规则三、案例解析BaseType_t xTaskCreate( ... );四、常用返回值前缀对照表五、典型函数举例对照宏定义命名规则一、宏命名公式二、前缀对应头文件示例本章结束为什么要学习 FreeRTOS 里面的命名规范刚开始接触 FreeRTOS 源码的时候很多人都会有一种感觉里面的函数名字为什么这么长比如xQueueGenericCreateStatic()、vTaskDelay()、uxTaskPriorityGet()看起来不像自己平时写代码时那种简单明了的函数名。甚至第一次打开源码会觉得这些命名方式增加了阅读难度。但是当真正开始学习 RTOS、阅读驱动代码甚至接触大型工程之后会慢慢发现命名规范并不是为了炫技而是为了让代码在越来越复杂的时候依然保持可读性和可维护性。在小项目中我们可能习惯给变量取一些简单的名字比如data、flag、temp几十行代码的时候没有问题但是当一个项目发展到几万行甚至几十万行时这种命名方式会让整个工程变得混乱。你可能几个月之后回头看自己的代码都不知道当初定义的data到底是什么数据flag到底表示什么状态。而优秀的工程代码会通过命名直接表达信息比如imu_data、motor_enable_flag、depth_target即使不用看注释也能够大概理解变量的作用。FreeRTOS 作为一个工业级实时操作系统里面有大量的任务、队列、信号量、定时器等对象如果没有严格的命名规则代码很快就会失去可读性。例如一个函数叫Create()你无法知道它创建的是任务、队列还是定时器也不知道它是动态创建还是静态创建。但是 FreeRTOS 中的xQueueCreateStatic()这个名字本身就包含了大量信息x表示函数有返回值Queue表示操作对象是队列Create表示创建Static表示使用静态内存方式创建。一个函数名就把它的功能、对象类型、创建方式表达出来了。再比如vTaskDelay()看到v就知道它没有返回值Task表示任务Delay表示延时所以不用查看源码也能知道这是一个任务延时函数。这些命名习惯实际上是在减少阅读代码时的大脑负担让程序员不需要频繁跳转到定义处查看变量含义。学习 FreeRTOS 命名规范更重要的意义是培养阅读大型工程代码的能力。现实的软件开发中很少有人每天都从零开始写一个完整系统更多时候是在阅读和维护别人已经写好的代码比如 STM32 HAL 库、Linux 驱动、机器人控制框架、各种开源项目。这些工程通常拥有几十万行代码如果没有良好的命名规范程序员很难快速理解系统结构。而掌握命名规则之后看到函数名就像阅读一种特殊语言可以快速判断它属于哪个模块、完成什么功能、返回什么类型。所以学习 FreeRTOS 的命名规范并不是为了记住几个固定的前缀而是在学习一种工程化思维。代码不仅是让计算机执行的指令也是程序员之间交流的语言。好的命名就像一张地图它告诉后来阅读代码的人这里是什么模块这个变量保存什么数据这个函数完成什么任务。当我们以后学习 STM32 底层驱动、机器人控制算法、Linux 系统或者更大型的软件框架时会发现很多优秀项目都有类似的思想。现在阅读 FreeRTOS 源码表面上是在学习几个函数和规则实际上是在训练自己阅读工业级代码的能力。真正优秀的工程师不一定能够背下所有 API但他能够通过代码结构和命名快速理解一个陌生系统这也是从“会写代码”走向“能够设计复杂系统”的重要一步。数据类型命名FreeRTOS 使用特定的前缀来标识数据类 型通常以port或config开头的类型是平台相关的。标准类型TickType_t用于表示系统滴答计数tick count的数据类型。核心作用存储系统 Tick 计数系统 Tick是周期性中断每触发一次计数加 1一般32位的单片机TickType_t的取值为uint32_tBaseType_t用于表示函数返回值和布尔值通常是 int 或 char。函数执行是否成功逻辑真假状态标志核心作用该架构下 “最高效的数据类型”CPU 处理该类型时速度最快if(xTaskCreate(vLED1Task, LED1,128, NULL,1,NULL)pdPASS) { //任务创建成功 } else { //任务创建失败 }UBaseType_t无符号版本的 BaseType_t。StackType_t用于表示任务堆栈的数据类型。TaskHandle_t任务句柄类型。QueueHandle_t队列句柄类型。SemaphoreHandle_t信号量句柄类型。TimerHandle_t软件定时器句柄类型。自定义类型plGlobalVar2下面练习左边是没修改的右边是修改以后的⚠️注意int plGlobalVar2[100];数组名本身等价于首元素指针因此数组变量使用指针前缀pl⚠️注意int plGlobalVar2[100];数组名本身等价于首元素指针因此数组变量使用指针前缀pl下面练习左边是没修改的右边是修改以后的用户自定义类型通常以_t结尾例如MyType_t。变量的命名规则代码示例void vLED1Task(void *pvParameters) { for(;;) // FreeRTOS任务无限循环任务主体 { HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_SET); vTaskDelay(pdMS_TO_TICKS(500)); // 延时500ms HAL_GPIO_WritePin(LED1_GPIO_Port, LED1_Pin, GPIO_PIN_RESET); vTaskDelay(pdMS_TO_TICKS(500)); // 延时500ms } vTaskDelete(NULL); vTaskDelay(pdMS_TO_TICKS(100)); // 延时100ms }变量的命名公式变量名 类型前缀 实际名字pvParameterspv类型前缀Parameters变量真实名称前缀含义图内示例pv pointer to void → 对应类型void *无类型指针变量前缀总结前缀含义C 类型vvoidvoid函数普遍以 v 开头pvpointer voidvoid *ucunsigned charuint8_tccharint8_tusunsigned shortuint16_tsshortint16_tulunsigned longuint32_tllongint32_tpxpointer to complex type结构体指针任务句柄、队列句柄等变量修改示例int lobalVar1 36; // int32_t int GlobalVar2[100];上面的变量应变成下面int lGlobalVar1 36; // int32_t int plGlobalVar2[100];lGlobalVar1l前缀 → long对应 int32_t /int32 位有符号长整型GlobalVar1语义名称代表全局变量 1pl前缀 → pointer to long代表int32_t *int 指针GlobalVar2语义名称函数的命名规则一、函数命名通用公式函数名 返回值类型前缀 模块名 实际名字二、额外特殊规则如果函数是 static 静态函数文件内私有函数前缀统一使用prvprivate三、案例解析BaseType_t xTaskCreate( ... );x返回值类型前缀代表返回类型BaseType_tTask模块名代表任务模块对应tasks.cCreate函数功能名称创建四、常用返回值前缀对照表前缀对应返回类型说明vvoid无返回值如 vTaskDelay()xBaseType_t基础长整型成功 / 失败、状态值uUBaseType_t无符号基础整型pvvoid *返回无类型指针px句柄指针如 TaskHandle_t *返回结构体对象指针五、典型函数举例对照void vTaskDelay()v→ 返回 voidTask→ 任务模块Delay→ 延时功能TaskHandle_t xTaskCreateStatic()x→ BaseType_tTask模块CreateStatic静态创建任务static void prvLedTask(void *pvParameters)prv静态私有函数仅当前.c 文件内可用宏定义命名规则一、宏命名公式宏定义名 文件名前缀小写 实际名字大写单词下划线分隔规则拆分前缀小写代表所属头文件主体名称全大写多个单词使用下划线_隔开二、前缀对应头文件示例前缀归属头文件典型宏pdprojdef.hpdTRUE、pdFALSE、pdPASS、pdFAILconfigFreeRTOSConfig.hconfigMAX_PRIORITIES、configTICK_RATE_HZportportmacro.hportMAX_DELAY、portYIELD本章结束
返回列表