4. SDK与中间件:MCUXpresso SDK获取、安装与结构解析、FreeRTOS集成
好,咱们进入第四章。这一章我打算聊聊SDK和中间件。说实话,很多刚接触NXP MCU的朋友,第一步就卡在SDK上——要么不知道去哪下载,要么下载了不知道怎么用。我当年第一次用LPC系列的时候,也折腾了好一阵子。
这一章的核心就三件事:怎么拿到SDK、SDK里面到底装了啥、怎么把FreeRTOS跑起来。嗯,咱们一个一个来。
4.1 MCUXpresso SDK的获取方式
获取SDK的方式,我常用的有三种。你根据自己习惯选就行。
4.1.1 通过MCUXpresso IDE内置工具
如果你用的是MCUXpresso IDE,那最简单。IDE里自带了一个SDK管理工具。你打开IDE,点菜单栏的 Help → MCUXpresso SDK → Download SDK。然后选你的芯片型号,比如我常用的MIMXRT1062,点下载就行。
我个人习惯用这种方式。因为IDE会自动帮你解压、配置路径,省得手动折腾。不过要注意,IDE里下载的SDK版本可能不是最新的。如果你需要最新版,那就用第二种方式。
4.1.2 从NXP官网手动下载
去NXP官网的SDK构建页面(mcuxpresso.nxp.com),你可以自己定制SDK。选芯片、选中间件、选编译器,然后点生成。它会打包成一个压缩包发到你邮箱。
这种方式的好处是灵活。比如你只需要FreeRTOS和USB协议栈,其他用不到的中间件可以去掉,SDK体积能小不少。我在做量产项目时,经常这么干——只保留必要的组件,编译速度能快30%以上。
4.1.3 使用Git仓库
NXP的SDK也托管在GitHub上。你可以直接 git clone 下来。不过我不太推荐新手这么干。因为SDK的仓库很大,包含几十个芯片系列,下载一次可能要半小时。而且你还要自己处理依赖关系。
嗯,这种方式适合那些需要持续跟踪SDK更新的老手。我一般只在做芯片评估时用Git方式。
4.2 SDK安装与目录结构解析
下载完SDK,接下来就是安装。其实SDK不需要“安装”,解压就能用。但为了IDE能识别,你需要告诉IDE SDK的路径。
4.2.1 在IDE中导入SDK
打开MCUXpresso IDE,点 Window → Preferences → MCUXpresso SDK → Add SDK。然后选择你解压后的SDK文件夹。IDE会自动扫描并列出支持的芯片。
这里有个坑:SDK路径不要有中文和空格。我曾经因为路径里带了个“项目”两个字,结果编译报错,查了半天才发现是路径问题。
4.2.2 SDK目录结构
解压后的SDK,目录结构大概是这样的。我拿RT1060的SDK举个例子:
SDK_2.x_MIMXRT1062/
├── boards/ # 板级支持包
│ ├── evkmimxrt1060/ # 官方评估板
│ └── ...
├── devices/ # 芯片启动文件、链接脚本
│ └── MIMXRT1062/
├── docs/ # 文档
├── middleware/ # 中间件(FreeRTOS、USB、LWIP等)
├── rtos/ # 实时操作系统
├── source/ # 驱动层源码
└── tools/ # 工具脚本
你想想看,这个结构其实很清晰。最常用的是 boards 和 devices 这两个文件夹。
- boards:里面是各个评估板的例程。你如果用的是官方板,直接拿例程改就行。
- devices:芯片的启动文件、链接脚本、系统初始化代码。这部分一般不用动,但如果你要做低功耗优化,可能需要改改启动代码。
- middleware:各种中间件。咱们后面要集成的FreeRTOS就在这里面。
重点: 每个芯片系列都有一个 clock_config.c 文件,里面定义了系统时钟配置。我建议你拿到SDK后,先打开这个文件看看。很多外设不工作的原因,其实就是时钟没配对。
4.3 FreeRTOS集成
好,终于到重头戏了。FreeRTOS的集成,说白了就是把RTOS的源码加到你的工程里,然后配置好中断和时钟。NXP的SDK已经帮我们做好了大部分工作。
4.3.1 SDK中FreeRTOS的位置
在SDK的 middleware 目录下,有一个 freertos 文件夹。里面包含了FreeRTOS的源码、移植层、以及一些NXP特有的配置。
middleware/freertos/
├── FreeRTOS-Kernel/ # FreeRTOS内核源码
│ ├── include/
│ ├── portable/ # 移植层(针对不同MCU)
│ └── ...
├── freertos_application/ # 示例工程
└── ...
你注意看 portable 目录。里面有针对ARM Cortex-M系列的移植文件。NXP已经帮你写好了 port.c 和 portmacro.h。你基本不用改。
4.3.2 在工程中集成FreeRTOS
集成步骤其实就三步。我习惯这么干:
- 添加源码路径:把
FreeRTOS-Kernel文件夹加到工程的include路径里。 - 选择移植文件:根据你的芯片内核,选择对应的
port.c。比如Cortex-M7就用portable/GCC/ARM_CM7下的文件。 - 配置FreeRTOSConfig.h:这个文件是FreeRTOS的核心配置。里面定义了堆大小、任务优先级数量、时钟节拍频率等。
嗯,这里我要多说一句。FreeRTOSConfig.h 这个文件,你最好复制一份到你的工程目录下,不要直接改SDK里的原文件。为什么?因为如果你以后更新SDK,原文件会被覆盖,你的配置就丢了。
4.3.3 配置SysTick和PendSV中断
FreeRTOS需要两个中断:SysTick(系统节拍)和PendSV(任务切换)。在NXP的SDK里,这两个中断的优先级配置在 FreeRTOSConfig.h 中:
#define configKERNEL_INTERRUPT_PRIORITY 255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191
这里 configKERNEL_INTERRUPT_PRIORITY 是SysTick的优先级,一般设为最低(255)。configMAX_SYSCALL_INTERRUPT_PRIORITY 是允许调用FreeRTOS API的最高中断优先级。这个值要根据你的中断优先级设计来定。
我建议你把这两个值先保持默认。等系统跑起来了,再根据实际需求调整。一开始就调优先级,容易出问题。
4.3.4 一个简单的FreeRTOS示例
集成完成后,写个简单的任务测试一下:
#include "FreeRTOS.h"
#include "task.h"
void vTask1(void *pvParameters) {
while(1) {
// 任务代码
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
int main(void) {
// 硬件初始化
BOARD_InitHardware();
// 创建任务
xTaskCreate(vTask1, "Task1", 256, NULL, 1, NULL);
// 启动调度器
vTaskStartScheduler();
// 正常情况下不会执行到这里
while(1);
}
这个代码很简单。创建了一个任务,每1秒执行一次。你编译下载后,如果系统能正常运行,说明FreeRTOS集成成功了。
vTaskStartScheduler() 是否执行成功。可以在它后面加个 while(1) 和断点。如果执行到了 while(1),说明调度器启动失败了。常见原因是堆大小不够,或者中断优先级配置不对。
4.4 避坑指南
最后,我总结几个我在项目中踩过的坑,你遇到了可以少走弯路。
- 堆大小不够:FreeRTOS默认的堆大小是16KB。如果你创建的任务多,或者任务栈大,很容易堆溢出。我建议一开始就设成32KB或64KB。
- 中断优先级分组:NXP的MCU默认是4位优先级分组(16级)。FreeRTOS要求所有中断优先级必须可配置。如果你改了优先级分组,记得同步修改FreeRTOSConfig.h里的配置。
- 浮点寄存器保存:如果你用了Cortex-M4或M7的FPU,记得在FreeRTOSConfig.h里开启
configUSE_TASK_FPU_SUPPORT。否则任务切换时浮点寄存器没保存,计算结果会出错。
嗯,这一章的内容就这些。SDK的获取和安装其实不难,关键是理解它的结构。FreeRTOS的集成,NXP已经帮我们铺好了路,你只需要配置好 FreeRTOSConfig.h 就行。下一章咱们聊聊调试工具和技巧,到时候我会分享一些我常用的调试方法。