Keil MDK开发指南:从项目配置到调试
1. 项目启动与调试停止
当所有设置正确完成后,开发板上的LED灯应开始闪烁,这表明Cortex® - M项目运行正常。若示例项目已启动并运行,可通过以下方式停止调试会话:
- 使用下拉菜单 “Debug ! Start/Stop Debug Session”;
- 使用快捷键Ctrl - F5;
- 点击相应按钮。
需注意,这些停止调试的步骤与启动调试的步骤基本相同。
2. 项目选项概述
项目设置窗口的各个选项卡下有一系列项目选项,可在项目中定义多组项目选项,并在编译项目时在不同选项组之间切换。这对软件项目很有用,可设置以下两种选项组:
-
调试选项组
:用于调试软件,可将项目选项设置为较低的优化级别(便于调试),并在编译输出中启用调试符号的输出。
-
发布选项组
:用于发布版本,使用较高的优化级别,且不包含调试符号。
在Keil MDK中,每组选项称为一个目标。例如,项目窗口可能有 “Target 1”,目标名称可自定义,如 “Development” 或 “Release”。添加目标的操作步骤如下:
1. 右键单击目标名称;
2. 选择 “Manage Components”;
3. 点击 “New (Insert)” 目标按钮。
当项目中有多个目标时,可使用工具栏上的目标选择框在不同目标之间切换。
3. 各选项卡详细介绍
3.1 设备选项卡
该选项卡定义项目所使用的硬件设备/平台。安装特定设备的软件包(即CMSIS - Pack)后,可从该选项卡中选择所需设备。选择设备时,编译器标志、内存映射和闪存算法设置会针对该设备进行预配置。若所需设备未列出,可在Arm部分选择Cortex - M23或Cortex - M33处理器,然后手动设置配置选项。
3.2 目标选项卡
目标选项卡可用于定义以下内容:
|选项|说明|
|----|----|
|设备内存映射|可通过目标选项卡的设置生成内存布局,也可使用分散文件定义项目的内存映射,并通过链接器选项卡的选项将该文件传递给链接器。|
|编译器版本|对于Armv8 - M设备,应选择Arm编译器6;对于Armv6 - M或Armv7 - M设备,可选择Arm编译器5或Arm编译器6。|
|FPU功能使用|即使硬件平台具备FPU,若应用程序不需要浮点数据处理,可禁用FPU以节省功耗。|
|软件安全模式|可选择编译为非安全或安全软件。选择安全软件模型时,可使用一系列TrustZone功能;对于某些软件开发场景,应使用非安全软件模型。|
|C运行时库类型|可选择标准C运行时库(功能齐全,速度优化)或MicroLib(内存大小优化的C运行时库)。|
|内置RTX操作系统使用|可选择是否使用内置的RTX操作系统。|
|晶体频率|该设置供指令集模拟器和闪存编程算法使用,应设置为主晶体振荡器的频率,通常该振荡器位于设备外部。|
当选择不同的微控制器设备时,目标选项卡中的选项会自动更新。
3.3 输出选项卡
该选项卡允许选择项目是生成可执行映像还是库,还可指定生成文件的存储目录。例如,可在项目目录中创建子目录,并使用 “Select Folder for Objects” 对话框将输出目录设置为该位置,这有助于保持项目主目录的整洁。此外,输出选项卡还可生成批处理文件,用于批量模式回归测试,且该编译过程可在不使用Keil μVision IDE的情况下进行。
3.4 列表选项卡
此选项卡可启用/禁用汇编列表文件。默认情况下,C编译器列表文件处于关闭状态。调试软件问题时,启用生成C编译器列表的选项很有用,这样可以查看生成的汇编指令序列。与输出选项类似,可点击 “Select Folder for Listings” 定义输出列表文件的存储位置。另一种生成反汇编列表的方法是在链接阶段后添加用户命令,这在用户选项卡中有详细描述。
3.5 用户选项卡
用户选项卡允许指定在软件编译的每个阶段需要执行的额外命令。例如,可添加以下命令行以在编译阶段结束后生成完整程序映像的反汇编列表:
$K\Arm\Armclang\bin\fromelf -c -d -e -s #L --output list.txt –cpu=cortex-m33
此命令生成一个名为list.txt的文件,该文件是生成的程序映像的完整反汇编。其中,“$K” 是Keil开发工具的根文件夹,“#L” 是链接器输出文件。这些特殊关键字称为键序列,可用于将参数传递给外部用户程序。键序列代码列表可在Keil网站的此链接中找到:http://www.keil.com/support/man/docs/uv4/uv4_ut_keysequence.htm。
3.6 C/C++选项卡
该选项卡可定义优化选项、C预处理指令(定义)、“include - files” 的搜索路径以及其他编译开关。默认情况下,Keil MDK项目的文件搜索路径会自动包含一些包含文件目录。若要使用特定版本的CMSIS - CORE文件,需点击选项卡中的 “No Auto Includes” 框禁用自动包含路径功能。有关优化级别选项的详细概述,请参考Keil应用笔记AN298:http://www.keil.com/appnotes/files/apnt_298.pdf。
3.7 汇编器选项卡
汇编器选项卡可定义预处理指令、“include - paths”,并可根据需要设置额外的汇编器命令开关。
3.8 链接器选项卡
链接器选项卡可通过以下两种方式定义软件项目的内存映射:
1. 根据目标选项卡的设置生成内存布局,构建过程会根据内存布局细节自动生成配置文件(即分散文件),并将该文件传递给链接器。
2. 指定分散文件,该文件可由软件开发人员自定义创建,也可由微控制器供应商提供。使用此方法时,需取消选中 “Use Memory Layout from the Target Dialog” 选项,并在 “Scatter File” 选项框中添加分散文件的位置。
若使用较新的CMSIS - Pack的设备,启动代码很可能使用C语言编写,此时CMSIS - Pack可能会附带一个分散文件,可用于定义向量表、堆栈和堆内存的内存布局。在这种情况下,应在链接器选项中指定该分散文件,并取消选中 “Use Memory Layout from the Target Dialog” 选项。
3.9 调试选项卡
调试选项卡中的部分调试选项已有介绍,此外,该选项卡还允许选择在指令集模拟器中运行代码(图17.28左侧)或使用带有调试适配器的实际硬件(图17.28右侧),还可选择调试适配器的类型,并从子菜单中访问调试适配器的特定选项。可在调试选项卡中定义一个额外的脚本文件(即 “Initialization file”),该文件在每次调试会话开始前执行。调试适配器的子菜单中有以下几个不同的选项卡:
-
调试
-
跟踪
-
闪存下载
若计划使用跟踪功能(如使用Serial Wire Viewer显示printf消息),需在跟踪选项卡中设置时钟频率等配置。除时钟频率和跟踪端口协议设置外,还可选择启用 “Trace Events” 以获取额外的性能分析信息。
3.10 实用工具选项卡
实用工具选项卡可定义用于闪存编程的调试适配器。对于某些设备,在进行闪存编程之前需要执行硬件初始化序列,可通过在实用工具选项卡的 “Init File” 选项中添加硬件初始化脚本来实现。
4. 堆栈和堆大小的定义
4.1 确定所需的堆栈和堆大小
进行嵌入式软件项目时,确保为主要堆栈和堆分配足够的内存是一项重要任务。使用内存分配函数(如 “malloc()”)时需要堆内存,某些工具链在使用 “printf” 等函数时也可能使用堆内存。
使用Keil MDK时,软件编译结束后,“Objects” 目录中会有一个HTML文件,该文件显示函数调用树,并详细列出每个函数和调用树本身的最大堆栈大小。定义内存空间分配时,需要考虑异常堆栈帧所需的额外内存空间以及异常处理程序所需的堆栈空间。
例如,假设一个基于Cortex - M33的系统在非安全状态下运行裸机项目:
- 主线程最多使用1000字节的堆栈内存空间,且使用FPU进行处理;
- 使用两个中断优先级级别:
- 第一级使用200字节的堆栈空间,且使用FPU进行处理;
- 第二级使用300字节的堆栈空间(不使用FPU);
- 有一个HardFault异常处理程序,最多可使用100字节的堆栈空间。
假设该应用不使用不可屏蔽中断(NMI),则所需的最大堆栈内存大小如相应计算所示。在软件的每个执行级别,除非具有最高优先级,否则都需要为异常堆栈帧提供空间。堆栈帧所需的空间取决于代码中是否使用FPU。假设背景代码和处理程序代码均为非安全代码:
- 不使用FPU时,堆栈帧大小为8个字;
- 使用FPU时,堆栈帧大小为26个字。
在计算中,为每个异常堆栈帧包含了4字节的填充空间,因为异常堆栈帧需要对齐到双字地址边界,若异常发生时SP值未对齐到双字,则需要一个填充字。
使用RTOS时,每个线程的堆栈使用量为:
- 线程代码在调用树中使用的最大堆栈大小;
- 最大堆栈帧大小。
若RTOS使用线程堆栈存储 “其他数据”,则在计算所需堆栈空间时可能需要包含额外的空间。
确定堆内存大小需求时,若应用程序代码始终分配相同数量的堆空间,则较容易确定。但实际情况并非总是如此,有时需要采用试错法。为检测内存分配是否成功,需要检查内存分配函数的返回状态信息。使用OS提供的内存分配函数时,可能需要自定义OS的错误检测处理程序,以帮助检测OS线程是否使用了过多内存。
4.2 带有汇编启动代码的项目
在之前的示例项目中,初始堆栈和堆大小在汇编启动文件中定义。启动代码包含几个元数据块,可使用 “Configuration Wizard” 对启动代码进行配置。操作步骤如下:
1. 点击代码下方的 “Configuration Wizard” 选项卡;
2. 在用户界面中轻松编辑可配置设置。
点击用户界面底部的 “Text Editor” 选项卡可返回代码编辑器视图。
4.3 带有C启动代码的项目
使用带有C启动代码的项目时,可能会有一个分散文件,可用于定义初始堆和堆栈大小。该文件包含以下内容:
...
/*................... Stack / Heap Configuration .....................*/
#define __STACK_SIZE
0x00000400
#define __HEAP_SIZE
0x00000C00
...
可根据项目需求编辑这些值来定义堆栈和堆的大小。
5. 使用IDE和调试器
Keil μVision集成开发环境(IDE)通过工具栏提供了许多易于访问的功能。代码编辑时可使用IDE中的各种工具栏图标。调试器启动后,IDE显示会发生变化,呈现出对调试过程有用的信息和控件。从显示界面中,可查看和更改核心寄存器(左侧),还可查看源代码和反汇编窗口,工具栏上的图标也会相应改变。
调试操作可在指令级别或源代码级别进行:
- 若源代码窗口被高亮显示,调试操作过程(如单步执行、断点设置)会考虑C或汇编代码的每一行。
- 若反汇编窗口被高亮显示,调试操作基于指令级代码,即每个汇编指令都可单步执行,即使该指令是从C代码编译而来。
使用源代码或反汇编窗口时,可使用工具栏中靠近IDE窗口右上角的图标插入或删除断点,也可通过右键单击源代码/指令行并选择 “insert breakpoint” 来实现。当程序执行在断点处暂停时,断点会被高亮显示,此时可开始调试操作,例如使用 “single - stepping” 执行程序代码,并通过寄存器窗口检查结果。
“Run to main()” 调试选项会在 “main()” 的开头设置一个断点。设置此选项并启动调试器后,处理器从复位向量开始执行,到达 “main()” 时暂停。调试器有许多功能,更多使用Keil调试器功能与各种Cortex - M开发板的信息可在http://www.keil.com/appnotes/list/arm.htm 找到。
6. 项目配置流程总结
为了更清晰地展示项目配置的整体流程,下面通过一个mermaid流程图来呈现:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px
A([开始项目配置]):::startend --> B{选择硬件设备}:::decision
B -->|通过设备选项卡| C(安装CMSIS - Pack):::process
C --> D(选择目标设备):::process
D --> E(配置目标选项):::process
E --> F(设置输出选项):::process
F --> G(设置列表选项):::process
G --> H(设置用户选项):::process
H --> I(设置C/C++选项):::process
I --> J(设置汇编器选项):::process
J --> K(设置链接器选项):::process
K --> L(设置调试选项):::process
L --> M(设置实用工具选项):::process
M --> N{确定堆栈和堆大小}:::decision
N -->|汇编启动代码| O(在汇编启动文件定义):::process
N -->|C启动代码| P(在分散文件定义):::process
O --> Q(使用IDE和调试器进行开发调试):::process
P --> Q
Q --> R([完成项目配置]):::startend
从这个流程图可以看出,项目配置是一个逐步推进的过程,每个步骤都紧密相连。首先要确定硬件设备,然后依次对各个选项卡进行详细配置,接着确定堆栈和堆的大小,最后使用IDE和调试器进行开发和调试。
7. 常见问题及解决方法
7.1 设备未列出问题
在设备选项卡中,如果所需的设备未列出,可按以下步骤解决:
1. 检查CMSIS - Pack是否已正确安装。若未安装,需从官方渠道下载并安装相应的CMSIS - Pack。
2. 若设备确实不在列表中,可在Arm部分选择Cortex - M23或Cortex - M33处理器,然后手动设置配置选项。
7.2 堆栈溢出问题
当出现堆栈溢出问题时,可参考以下解决办法:
|问题表现|可能原因|解决方法|
|----|----|----|
|程序运行异常,出现HardFault等错误|堆栈空间不足|重新评估并增加堆栈大小。可根据函数调用树和异常处理程序所需的空间,结合之前介绍的计算方法,增大堆栈的分配。|
|性能下降|堆栈设置过大|检查函数调用树,合理减少堆栈空间的分配,避免不必要的内存浪费。|
7.3 调试适配器连接问题
如果在调试过程中遇到调试适配器连接问题,可按以下步骤排查:
1. 检查硬件连接是否牢固,确保调试适配器与开发板正确连接。
2. 在调试选项卡中,检查调试适配器的类型选择是否正确,并从子菜单中检查调试适配器的特定选项是否配置正确。
8. 优化建议
8.1 编译优化
在C/C++选项卡中,可以根据项目需求选择合适的优化级别。对于性能要求较高的项目,可参考Keil应用笔记AN298(http://www.keil.com/appnotes/files/apnt_298.pdf),选择较高的优化级别,但要注意可能会影响调试的便利性。若需要进行详细的调试,可选择较低的优化级别。
8.2 内存优化
- 选择合适的C运行时库 :在目标选项卡中,若项目对内存空间要求较高,可选择MicroLib,它是一种内存大小优化的C运行时库;若对功能完整性和速度要求较高,可选择标准C运行时库。
- 合理分配堆栈和堆大小 :根据项目的实际需求,准确计算并分配堆栈和堆的大小,避免内存的浪费或不足。
8.3 功耗优化
在目标选项卡中,若硬件平台具备FPU,但应用程序不需要浮点数据处理,可禁用FPU以节省功耗。
9. 总结
通过以上的介绍,我们详细了解了项目从启动到调试的整个过程,包括项目选项的配置、堆栈和堆大小的确定以及如何使用IDE和调试器进行开发。在实际开发中,要根据项目的具体需求,合理配置各个选项,确保项目的顺利进行。同时,遇到问题时要善于利用各种工具和方法进行排查和解决,不断优化项目的性能和资源利用效率。希望这些内容能对大家在使用Keil MDK进行开发时有所帮助。
在开发过程中,要养成良好的习惯,及时记录遇到的问题和解决方法,不断积累经验,提高自己的开发能力。相信通过不断的实践和学习,大家能够更加熟练地掌握Keil MDK的使用,开发出高质量的嵌入式软件项目。
超级会员免费看
6511

被折叠的 条评论
为什么被折叠?



