FreeRTOS 第三课C 语言扩展 学习笔记嵌入式学习笔记 · FreeRTOS 第 3 课今天学习了 C 语言扩展变量的作用域和生命周期、变量在 SRAM 里的分布、堆和栈的概念、FreeRTOS 的任务栈以及 FreeRTOS 的代码规范整理成文方便复习。文章目录FreeRTOS 第三课C 语言扩展 学习笔记一、变量的作用域和生命周期1. C 语言的 5 类变量2. 完整代码例子二、变量在 SRAM 里的分布1. 单片机的 FLASH 和 SRAM2. 变量在 SRAM 的分布3. Minimum Heap Size 和 Minimum Stack Size三、堆的概念四、栈1. 栈的概念2. 调用栈Call Stack3. FreeRTOS 的任务栈五、FreeRTOS 的代码规范1. 三个常用数据类型2. 变量的命名规则前缀 实际名字3. 函数的命名规则返回类型 模块名 实际名字4. 宏定义的命名规则六、小结速查表一、变量的作用域和生命周期写 C 语言/嵌入式代码经常要回答两个问题这个变量在哪里能用—— 这就是作用域Scope这个变量什么时候创建、什么时候销毁—— 这就是生命周期Lifetime概念回答的问题通俗说法作用域变量在哪些代码里可见“这个变量管到哪一行”生命周期变量从生到死的过程“这个变量活多久”记忆作用域是空间范围生命周期是时间范围。1. C 语言的 5 类变量变量类型生命周期作用域典型用途全局变量程序开始 → 程序结束项目当中的所有文件需要跨文件共享的场合局部变量进入函数/代码块 → 退出函数/代码块定义它的函数/代码块函数内部存储临时数据静态全局变量程序开始 → 程序结束定义它的 .c 文件封装模块的内部数据静态局部变量首次进入函数 → 程序结束定义它的函数/代码块函数内需要保持的数据堆变量从 malloc() → 到 free()无固定作用域靠指针访问长度不定的数据注意堆变量没有固定作用域——它在堆上分配后靠指针在任意代码中访问指针传到哪就能在哪用。2. 完整代码例子下面这个例子把 5 类变量全部用上用户输入数字 n程序分配一个 n 个元素的 int 数组依次计算 1²、2²、3²……填入数组并打印。文件 1my_file.hintGetNextSquare();/* 获取下一个平方数 */文件 2my_file.c/* 静态全局变量仅展示用 */staticintstaticGlobalVar1100;/* 作用: 输入一个数, 计算它的平方 */staticintSquare(intinput)/* input函数参数 */{returninput*input;}/* 作用: 获取下一个平方数 */intGetNextSquare(){/* 静态局部变量存储当前底数的值 */staticintnum1;/* 计算 num 的平方 */intret;retSquare(num);/* 递增底数的值 */num;/* 返回结果 */returnret;}文件 3main.c#includestdio.h#includestdlib.h#includemy_file.hintglobalVar136;/* 全局变量1, 仅展示用 */intglobalVar2[100];/* 全局变量2, 仅展示用 */intmain(intargc,char*argv[]){intn;/* 局部变量 *//* #1. 要求用户输入数字n, n表示要产生的平方数的个数 */scanf(%d,n);/* #2. 使用malloc()分配一个长度为n的int型数组 */int*pBuffer(int*)malloc(sizeof(int)*n);/* 堆变量 *//* #3. 逐个计算平方数, 并填写到数组中 */for(inti0;in;i){pBuffer[i]GetNextSquare();}/* #4. 打印结果到控制台 */for(inti0;in;i){printf(%d, ,pBuffer[i]);}printf(\n);return0;}运行结果输入55 1, 4, 9, 16, 25,GetNextSquare() 每调用一次静态局部变量 num 自增 1返回 num²如果 num 是普通局部变量每次调用都会从 1 重新开始结果会变成 5 个 1。代码里各变量对照代码位置变量类型main.c 顶部globalVar1 / globalVar2全局变量main() 内n局部变量main() 内pBuffer堆变量my_file.c 顶部staticGlobalVar1静态全局变量Square() 参数input函数参数类似局部变量GetNextSquare() 内num静态局部变量GetNextSquare() 内ret局部变量二、变量在 SRAM 里的分布1. 单片机的 FLASH 和 SRAM对比项FLASHFlash 存储器SRAM静态随机存储器存什么程序代码、常量const变量全局/局部/堆栈掉电后数据不丢失数据丢失特点容量大、慢、只读运行中容量小、快、可读可写地址0x08000000 起0x20000000 起记忆程序住 FLASH变量住 SRAM。2. 变量在 SRAM 的分布SRAM 从上到下分为几段编译器把不同类型的变量放到不同段里┌───────────────────────────────┐ 高地址 │ .stack 段 │ 栈局部变量、函数参数等 │ 向下增长 │ 不包括静态局部变量 ├───────────────────────────────┤ │ 未分配区域 │ heap 和 stack 之间可扩展的空间 ├───────────────────────────────┤ │ .heap 段 │ 堆malloc() 分配的内存 │ 向上增长 │ ├───────────────────────────────┤ │ .bss 段 │ 无初值或零初值的全局变量/静态变量 ├───────────────────────────────┤ │ .data 段 │ 有初值的全局变量/静态变量 └───────────────────────────────┘ 低地址段存放内容说明.data 段有初值的全局变量或静态变量程序启动时从 FLASH 拷贝初值到 SRAM.bss 段无初值或者零初值的全局变量或静态变量启动时清零.heap 段堆malloc() 分配的内存从低地址向上增长.stack 段栈局部变量、参数等不包括静态局部变量从高地址向下增长未分配区域heap 与 stack 之间的剩余空间两边按需抢地盘要点静态局部变量不放在栈里它和全局变量一样放在 .data/.bss 段所以才能跨调用保持值。3. Minimum Heap Size 和 Minimum Stack Size在 Keil 工程里Options → Target有两个和 SRAM 分配相关的设置配置作用对应段Minimum Heap Size给 C 库 malloc/free 预留的最小堆大小.heap 段Minimum Stack Size给启动代码预留的最小栈大小.stack 段它们写在启动文件startup_xxx.s里Heap_Size EQU 0x00000200 Stack_Size EQU 0x00000400这是裸机/启动阶段的堆栈大小FreeRTOS 起来之后任务栈由 FreeRTOS 自己从 heap_x 分配互不干扰。三、堆的概念**堆Heap**是程序运行期间动态分配内存的区域特点说明分配方式malloc() / calloc() 动态申请释放方式free() 手动释放大小运行时才决定长度不定的数据管理由 C 库/内存管理器维护风险不 free 就内存泄漏多次分配释放会产生碎片int*p(int*)malloc(sizeof(int)*100);/* 申请 */if(p!NULL){/* 使用 */}free(p);/* 释放必须成对 */pNULL;在 FreeRTOS 里任务栈、队列等内核对象的内存由 FreeRTOS 自己的堆heap_1 ~ heap_5管理和 C 库的 malloc 是两套体系第二课讲过。四、栈1. 栈的概念**栈Stack**是一块后进先出LIFO的内存区域压栈Push数据从栈顶压入出栈Pop数据从栈顶弹出栈顶指针 SP 由 CPU 自动维护在 ARM 上栈从高地址向低地址增长。voidfuncA(void){inta1;funcB();}voidfuncB(void){intb2;}调用过程funcA 开始 → 压入 a1 funcA 调用 funcB → 压入返回地址 funcB 开始 → 压入 b2 funcB 返回 → 弹出 b、返回地址 funcA 返回 → 弹出 a2. 调用栈Call Stack函数调用时栈上依次保存内容说明返回地址函数结束后回到哪里函数参数传入的实参或寄存器保存局部变量函数内部定义的变量保存的寄存器调用前需要保留的 CPU 寄存器每调用一层函数栈就长高一层往下压递归太深或局部变量太大 →栈溢出Stack Overflow。3. FreeRTOS 的任务栈每个 FreeRTOS 任务都有一块独立的任务栈对比项裸机主栈FreeRTOS 任务栈数量只有 1 个每个任务 1 个分配方式启动文件预留xTaskCreate 时从堆分配大小Minimum Stack SizexTaskCreate 的 uxStackDepth 参数单位字内容主函数调用链任务的局部变量 任务切换时的上下文寄存器/* uxStackDepth 128表示 128 字 512 字节的任务栈 */xTaskCreate(Task_LED,LED,128,NULL,1,NULL);任务切换时FreeRTOS 把当前任务的寄存器压入它自己的栈再从下一个任务的栈里恢复互不干扰任务栈太小 → 栈溢出 → 程序跑飞可以开configCHECK_FOR_STACK_OVERFLOW检测。记忆裸机只有一个大栈RTOS 每个任务一个小栈。五、FreeRTOS 的代码规范FreeRTOS 源码有一套统一的命名规范看懂前缀就能猜出类型和作用。1. 三个常用数据类型类型作用说明TickType_t记录系统节拍的数据类型具体类型取决于 configTICK_TYPE_WIDTH_IN_BITS16/32 位BaseType_t基本数据类型表示成功/失败、是/否当前处理器架构下最有效率的类型STM32 int32_tUBaseType_tBaseType_t 的无符号版本非负数对 STM32F1 单片机为 uint32_tTickType_t xLastWakeTime;/* tick 计数 */BaseType_t xReturn;/* pdPASS / pdFAIL */UBaseType_t uxPriority;/* 优先级非负数 */2. 变量的命名规则前缀 实际名字前缀类型vvoidccharint8_tsshortint16_tllongint32_txBaseType_t、TickType_t或其它未知数据类型eenum枚举类型p指针uunsigned无符号数例子TickType_t xTicksToWait;/* x TickType_t */UBaseType_t uxPriority;/* u x unsigned BaseType_t */charcChar;/* c char */void*pvParameters;/* p v void 指针 */3. 函数的命名规则返回类型 模块名 实际名字函数名 返回类型前缀 所属模块名 动作名函数拆解含义vTaskDelayvvoid Task模块 Delay动作任务延时无返回值xTaskCreatexBaseType_t Task Create创建任务返回成功/失败xQueueSendx Queue Send发送到队列返回结果vSemaphoreGivev Semaphore Give释放信号量补充以prv开头的函数如 prvIdleTask表示模块内部私有函数static。4. 宏定义的命名规则宏定义全部大写 下划线分隔分类例子配置宏configUSE_PREEMPTION、configTICK_RATE_HZ返回值宏pdTRUE、pdFALSE、pdPASS、pdFAIL错误宏errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY移植宏portMAX_DELAY、portYIELD、portTICK_PERIOD_MS#defineconfigUSE_PREEMPTION1#definepdTRUE(1)#defineportMAX_DELAY(0xFFFFFFFFUL)六、小结速查表问题答案作用域变量在哪能用空间范围生命周期变量活多久时间范围5 类变量全局、局部、静态全局、静态局部、堆变量堆变量作用域无固定作用域靠指针访问程序代码/常量放哪FLASH变量放哪SRAM.data 段有初值的全局/静态变量.bss 段无初值/零初值的全局/静态变量堆malloc/free向上增长栈局部变量/参数向下增长LIFOFreeRTOS 任务栈每任务一个xTaskCreate 时从堆分配TickType_t记录系统节拍16/32 位BaseType_t / UBaseType_t有符号/无符号基本类型STM32 为 int32_t/uint32_t变量命名类型前缀 名字v/c/s/l/x/e/p/u函数命名返回类型前缀 模块名 动作名宏命名全大写 下划线记忆口诀作用域管空间生命周期管时间。程序住 FLASH变量住 SRAM.data 存有值、.bss 存清零、heap 向上、stack 向下。堆要手动 free栈自动生长RTOS 里每任务一个栈。x 是 BaseType_tu 是无符号p 是指针v 是 void函数名类型前缀模块动作。本文为 FreeRTOS 第三课学习笔记如有错误欢迎评论区指正。
企业数字化 ERP 产品动态
相关推荐
JX3Toy 剑网3宏脚本使用指南:PVE循环与日常操作的减负工具 JX3Toy 剑网3宏脚本使用指南:PVE循环与日常操作的减负工具 【免费下载链接】JX3Toy 全功能减负工具 项目地址: https://gitcode.com/GitHub_Trending/jx/JX3Toy
团队副本打BOSS时,技能循环要不断开,机制、减伤还得兼顾;日常… · 2026/11/5 3:40:16
OpCore-Simplify 一键生成 OpenCore EFI:四步菜单从硬件报告到可引导 U 盘 OpCore-Simplify 一键生成 OpenCore EFI:四步菜单从硬件报告到可引导 U 盘 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify
走完这篇&#… · 2026/11/5 3:40:16
10 分钟跑通 DBX:从装好到导出第一张 CSV 表 10 分钟跑通 DBX:从装好到导出第一张 CSV 表 【免费下载链接】dbx 25 MB lightweight cross-platform database client for 100 databases, including MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, SQL Server, and Dameng. Built-in AI, MCP Server, CLI, … · 2026/11/5 3:40:16
360度评估工具计费方式解析:四种口径、四个必问项与成本折算方法 更新时间:2026 年 10 月摘要
360度评估工具的计费方式可归纳为四种口径。选择哪种取决于企业用量的形状——被评人数、年度轮次与评价人构成三者共同决定成本结构。本文给出四种口径的适用边界、采购阶段必须确认的四项条款,以及用人力成本折算投入产出的… · 2026/11/5 5:31:08
稀土功能纤维的制备原理与功能特性 稀土在很多人印象中,是用于永磁电机、催化剂、激光晶体的工业原料。但近两年,稀土正在以一种更贴近生活的方式进入日常——功能纤维。稀土如何“织”进衣服里稀土功能纤维的制备,并不是简单地把稀土粉末混入纺丝液。以包头稀土研究院发布的“… · 2026/11/5 5:31:08
10-03-互操作-JobSystem与GC隔离 JobSystem 与 GC 隔离篇章:10-核心技术-托管互操作篇 | 阅读时间:约 35 分钟一、引言Unity Job System 要求 Job 中不能访问托管对象。这不是一个"推荐"规则,而是一条硬性约束——违反会导致运行时错误(InvalidOperatio… · 2026/11/5 5:31:08
从一家奶茶店讲透扫码登录:手机怎么让电脑登录 目录 一、扫码登录要解决的真问题 二、完整流程:从生成二维码到换取登录态 三、动手写一个能跑的扫码登录后端 四、为什么是长轮询,而不是 WebSocket 五、一次领取:三层保护缺一不可 六、状态机:pending 到 confirmed 到 con… · 2026/11/5 5:31:08
LInux | sudo 与 su 操作 sudo 与 su 操作手册
目录
sudoers 配置sudo 常用操作sudo 安全机制sudo 高级用法安全规范故障排查同类工具对比su、sudo 环境与 PATH 行为 1 sudoers 配置
sudo 的权限控制依托 /etc/sudoers,文件默认权限 440。
不直接使用 vi、vim 编辑,语法错误会… · 2026/11/5 5:31:08
焊接还是压接?USB、DC 线焊点虚焊的判定与工艺边界 焊点是冶金连接,压接是冷变形机械连接,失效模式不同:压接坏了是电阻慢慢爬、通电发热;焊点坏了常常一次震动就断,而静态通电还是通的。判焊点好坏,第一判据是润湿角,不是「亮不亮」。大电流、强… · 2026/11/5 5:30:08
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 3:16:49
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 6:59:29
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/4 7:02:38