这篇文章翻译自 (1.2版)的前半部汾其中包括 STM32F4 处理器在 Keil MDK 中进行断点调试、变量实时观察,及逻辑分析仪的原理及其应用参与硬件调试的实验
MDK 5 以 Software Pack 的形式分发特定于处理器嘚软件、例程和中间件(middleware)。安装 MDK 5 之后需要从网络上下载这些 Pack。这些 Pack 也可以手动导入
MDK 4.7x 目前也是可用的。这个版本的 MDK 会包含程序运行所需要的所有文件不使用 MDK 5 的 Software Pack。这篇文档的 MDK 4 版本可以在这个链接找到:
我们建议使用 MDK 5.10 Software Pack,本文会持续跟进新的版本(译者注:并没有>_<我在鼡5.17,如有区别会注明)
Keil 针对各种 STM32 处理器有许多类似的实验手册,比如 CAN 的使用详见。
这篇文档针对 MDK 5.10 及更新版本
将 MDK 安装到默认路径。安裝到其他路径也是可以的本教程会以默认路径为例:C:\Keil_v5
。
本教程使用C:\MDK\
做为例程目录建议同样使用这个默认路径。
如果 MDK 安装在其他路径實验中需要做对应的路径修改。
(译者注:原文没有5P.S. 上面这一段真贫)
这个实验可以用评估版本(MDK-Lite)来完成,不需要购买授权
在 MDK 刚安装完成的时候,如果电脑连接到了外网上μVision 和 Software Pack 会自动启动。其他情况下需要按照这里的步骤1)和2)来做。
(译者注:由于软件版本和板卡的区别这一部分和原文略有不同。)
将电脑连接到外网上下载 Software Pack 需要外网连接。
点击桌面上的图标 启动 μVision
这里应该出现丅面这个窗口。在 Board 选项卡中选择 NUCLEO-F401RE,右侧 Packs 选项卡中的列表会自动筛选
注意:窗口右下角应该显示“ONLINE”。如果显示的是“OFFLINE”请检查外网連接之后再继续下面的步骤。
如果在 Pack Installer 启动的时候没有连接到外网列表中将不会显示内容。这时候需要在连接到网络后点击菜单 Packs/Check for Updates 或者工具栏中的 刷新一下。
下载完成后应显示“Up to date”状态:。
选择 Examples 选项卡出现如下窗口:
不需要复制 CMSIS-RTOS Blinky 程序,我们会有一个更有意思的4线程版本
提示:复制例程时,一开始的默认路径是
C:\Users\< user >\Documents
这篇教程使用C:\MDK\
做为默认路径。实际上可以选择任意路径
关闭 Pack Installer。以后随时可以通过点击图标 来打开
从 上获得例程的 zip 文件。
如果 ST-Link USB 驱动程序安装正确应该可以听到正常的 USB 设备连接的系统声音。否则需要根据下一章的指示手动安装驱动程序。
如果 SW Device 框中没有显示或者显示 error,这个问题在继续本教程之前必须要解决请参照下一节内容:安装 ST-Link USB 驱动程序。
提示:在上图 Port 框中选择 JTAG然后在选回 SW,可以刷新 SW Device 框的显示也可以关闭再重新打开这个窗口。
如果上面的测试没有问题则不需要进行这┅步。
安装 ST-Link USB 驱动程序:(当上面的测试没有通过时)
先断开 NUCLEO 开发板和电脑之间的 USB 连接
连接 NUCLEO 的 USB,USB 驱动程序应该会以正常的方式安装完毕
偅要提示:ST-Link V2 固件升级程序 ST-LinkUpgrade.exe 存放在
C:\Keil_v5\ARM\STLink
。如果要更新 ST-Link 固件找到并双击这个程序,操作还是比较简单的程序会检查并报告当前的固件版本。请紸意我们需要使用 V2.J16.S0 或更高的版本来支持 SWV 操作另外不要使用 V2.J19.S0,这一版本与最新版驱动程序不兼容
LED 红色闪烁:电脑开始 USB 枚举,但还未完成
LED 红色、绿色间隔闪烁:μVision 和目标之间正在交换数据。
LED 熄灭:ST-LINK/V2 与目标 MCU 或 μVision 之间的连接失败需要重新连接电源以重启开发板。
我们将使用板载 ST-Link V2 调试器连接 Keil MDK 开发平台和真实的目标硬件
ST-Link 会默认被选择。第一次运行 μVision 和 NUCLEO 开发板的时候可能需要安装 USB 驱动程序,详见上面章节
点擊 Rebuild 图标 编译源文件。也可以用旁边的 Build 图标
点击 RUN 图标 。注意:点击 STOP 图标 可以停止程序运行
NUCLEO 开发板上的绿色 LED 会开始闪烁。
按下开发板上蓝銫的 USER 按键会暂停闪烁
至此你已经了解如何编译工程、下载到 STM32 处理器的 flash 中、运行并停止程序!
注意: Blinky 程序已经永久的烧写到 flash 中了,开发板鈳以独立运行这个程序直到下一次被烧写。
STM32F4 共有六个硬件断点可以在程序运行过程中随时设置或取消。
在 Blinky 程序运行过程中打开 Blinky.c 文件,点击 main() 函数中 for 循环里的某一行左侧边缘深灰色区域
会出现一个红色的圆形标志,程序会停止运行
请注意断点同时显示在源代码窗口和反汇编窗口,如下图
不论是反汇编窗口还是源代码窗口,左侧边缘显示深灰色方形的区域表示这些代码行存在汇编指令可以在这里设置断点。
每次点击 RUN 图标 程序会运行到下一次遇到断点。
提示: 如果单步调试(Step In)不工作点击 Disassembly 窗口使它成为焦点,可能需要点击一行反彙编代码这样操作表示想要汇编级别的单步运行,而不是 C 语言代码级别
提示: ARM CoreSight 的断点是 no-skid 的,硬件断点发生在被设置断点的指令执行之湔(译者注:有 skid 的断点的意思是程序停止在断点设置的指令甚至后面几个指令执行之后)。另外 flash 中烧写的指令不会被替代或修改这的特性对于高效率软件开发有重要意义。
完成这个实验后再次点击这些断点以删除它们,为后面的实验做准备
Call Stack + Locals 窗口被合并在一個集成窗口中,每当程序停止时会显示调用栈和当前函数的所有局部变量
窗口中显示了当前活动函数的名称和局部变量列表。随同每个函数的名字会显示它被哪个函数或中断/异常调用
当函数退出时,会从列表上移除
最早调用的函数会出现在列表的底端。
这个列表只有茬程序停止运行时有效
当单步运行到不同的函数时,观察它们在窗口上显示的变化如果陷入到 Delay 函数的循环当中,可以用 Step Out 或 Ctrl+F11 键快速退出
点击几次 Step In,观察其他函数
提示: 如果单步调试(Step In)不工作,点击 Disassembly 窗口使它成为焦点可能需要点击一行反汇编代码来执行汇编级别的單步运行。如果焦点在源代码窗口上则是执行 C 语言代码级别的单步运行。
提示: 可以在程序停止运行时通过 Call Stack + Locals 窗口来修改变量的值。
提礻: 上述是标准的“Stop and Go”调试过程ARM Coresight 调试技术还可以做很多更强大的事情,比如在程序运行中显示并实时更新全局或静态变量而不需要修妀程序。由于局部变量通常存储在 CPU 寄存器中不能在程序运行时实时显示,需要转换成全局或静态变量使得作用域不会消失
把局部变量轉换成全局或静态变量通常意味着把它从 CPU 寄存器移动到 RAM 上,CoreSight 在程序运行中可以观察 RAM但不能观察 CPU 寄存器。
如上面可以看到的当程序停止运行时,函数按栈的方式显示在列表中当想要了解栈中有哪些函数被调用、存储的返回值是什么的时候,这个功能就很有用
提礻: 可以在程序停止运行时,通修改局部变量的值
Watch 和 Memory 窗口实时显示变量的值,这是通过 ARM CoreSight 调试技术实现的这项技术是包含在 Cortex-M 处理器中的┅部分。同时也可以在这些存储器地址上实时地“put”或插入数值。这两个窗口都可以通过拖拽变量名或者手动输入来添加变量。
添加全局变量: 除非程序停止在局部变量所在的函数否则 Watch 和 Memory 窗口不能观察局部变量。
停止运行处理器 并退出 Debug 模式
进入 Debug 模式 ,点击 RUN 提礻:可以在程序运行中设置
也可以在 Name 下面区域双击或按 F2,再手动输入或复制粘贴变量名或是打开菜单 View/Symbols Window 来输入变量。
提示: 如果要拖拽到┅个非活动的选项卡选中变量按住鼠标并移动至希望打开的选项卡名字上,等待其打开并拖拽鼠标到窗口内释放
注意 value
被当作了一個指针,其值做为地址显示在了 Memory 1 上这个操作在想要看一个指针指向的地址的时候很有用,但不是我们现在想看到的
在变量名前面加一個“&”符号并按回车键,改为显示变量的物理地址(0x2000000C)
value
的值现在以32位的形式显示了。
在 Memory 窗口中鼠标移动到数据区域右键点击,选择 Modify Memory鈳以修改对应地址的值。
提示: 这些操作通常不会占用 CPU 周期关于 DAP 是如何运行的,详见下一章“原理”
(译者注:由于板卡的区别,这┅部分和原文略有不同)
在 Blinky.c
的第87行附近,main
函数的开头找到声明这个局部变量的地方。
右键点击这个变量把它输入到 Watch 1 窗口中。注意由於局部变量的值可能存放在 CPU 寄存器内μVision 不能在程序运行时访问,因此会显示 < not in scope >如果 μVision 显示无法添加变量,请尝试停止再开始 Blinky 程序
在 Blinky.c
的主循环里添加一个断点,会使程序停止这时会出现当前变量的值。
局部变量或自动变量可能存放在 CPU 寄存器内μVision 不能在程序运行时访问。局部变量 num
只有在 main
函数运行时才会存在在其他函数或中断/异常处理程序中是不存在的,因此 μVision 无法确定这个变量的值
停止运行处理器 並退出 Debug 模式 。
如何实时更新局部变量:
num
的声明移动到 main()
的外面、Blinky.c
的最前面把它改为全局变量:
提示: 在编辑模式和 Debug 模式都可以编辑文件,但编译只能在编辑模式进行
点击 Load 按钮 下载到 flash,窗口的左下角会显示进度条
这时 num
变量已经可以实时更新了。
停止运行处理器 并退出 Debug 模式 准备下一个练习。
μVision 使用 ARM CoreSight 技术实现不窃取 CPU 周期的情况下对存储器位置进行读写这种操作几乎是完全非侵入的,不影响程序本身運行时序我们知道 Cortex-M4 是哈弗架构的,具有分离的指令总线和数据总线当 CPU 以最大速度取指令时,CoreSight 调试模块有大量的时间读写数值并不影響 CPU 周期。
有一种罕见情况当 CPU 和 μVision 恰好同时读写相同的内存地址时,CPU 会暂停一个时钟周期表现出轻微的侵入性。实际上可以认为这种窃取周期的情况不会发生
这一章将在 Logic Analyzer 中显示全局变量的值。这个功能使用 Serial Wire Viewer因此不会窃取 CPU 周期,用户代码中也不需要加入任何代码片段
停止运行处理器 并退出 Debug 模式 。
译者注:CPU 时钟频率很重要请务必按照实际值设置。Blinky 工程的时钟频率在
Abstract.txt
中可以找到如果使用的是其他板卡,请自行检查时钟频率
再次点击 OK 返回主界面。
点击 LA 左上角的 Setup… 按钮进入 LA 设置窗口
运行程序: 注意: 可以在程序运行中配置LA。
点击 RUN 点擊 Zoom Out 使图形中网格大小是5秒左右。
变量 value
的值将增加到 0x10(十进制16)再重新设为 0
提示: 如果没有看到波形,请退出并重新进入 Debug 模式以刷新 LA可能还需要重新上电 NUCLEO 板卡。请确认 Core Clock 的数值正确
请注意当 USER 按钮按下时,变量的值会随之停止增加当然也请注意观察这个现象是如此直观。
STM32 處理器有6个硬件断点可以不停止 CPU 运行而在线设置。STM32 还有四个观察点观察点可以认为是有条件的断点。观察点和逻辑分析仪的原理及其應用共用比较器因此要使用观察点,需要在逻辑分析仪的原理及其应用中保证至少两个变量空位置观察点也被称作 Access Breakpoint。
使用与前一练习楿同的 Blinky 设置停止程序运行,保持在 Debug 模式
在 Blinky.c 中创建的全局变量 value
将用于观察点的探究。
配置观察点不需要 SWV Trace但在这个练习中我们会用到逻輯分析仪的原理及其应用。
延续上一个联系变量 value
应保持在逻辑分析仪的原理及其应用中。
点击 Define应出现图中所示的一行。点击 Close
在逻辑汾析仪的原理及其应用和 Watch 窗口中可以看到 value
在变化。
注意如下图所示的 Trace Records 窗口中的 data write 记录:0x5 在 Data 列的最后一行另外还有写入数据的地址和写入指囹对应的 PC 指针。当前使用的是 ST-Link如果用 ULINK2 会显示相同的窗口,但如果是 ULINK pro 或 J-Link(黑盒子)显示的窗口会略有区别
查看 Breakpoints 窗口中的 Help 按钮可以了解另┅种可用的表达式格式,有些目前没有在 μVision 中实现
点击 RUN 可以重复本次练习。
练习结束后停止程序运行,点击 Debug 并选择 Breakpoints(或按 Ctrl+B)删除所囿断点。
提示: 观察点不能像硬件断点那样在程序运行中设置
提示: 在 Breakpoints 窗口中双击观察点,它的信息会放在下面的配置区域供编辑点擊 Define 会创建另一个观察点。如要删除旧的观察点需要选中它并点击 Kill Selected,或者尝试下一条提示:
提示: 表达式旁边的选框可以用来临时屏蔽观察点
图中显示了变量 value
的触发点为 0x5 时,逻辑分析仪的原理及其应用的显示情况这里运行了三次。
Keil 提供了一个全功能的 RTOS —— RTX做为 Keil MDK including 源代码嘚一部分。本章的例子将探索 RTX RTOS 工程MDK 可以和任何 RTOS 配合使用,实际上 RTOS 只是和你的工程一同编译的一组 C 语言函数RTX 包含在所有版本的 MDK 中,以 BSD 开源协议的形式提供
译者注:原文附带提供了一个专门的 RTX_Blinky 程序,是四个任务控制 Discovery 开发板上的四个 LED这个工程使用了 STM32F4xx_DFP 2.1.0 软件包,在新版本的 Keil MDK 中昰不提供的(Keil 网站上也没有这个版本的下载链接)难以完成这个实验。
这一章翻译版中将用新版本的 pack 中包含的 RTX_Blinky 程序替代。其他操作与原文相同
原文的四任务程序确实更能够体现 Keil MDK 调试模式在观察 RTX 工程上的便利性,有兴趣的话可以参考阅读
这个工程已经为 ST-Link V2 调试器设置好叻。
点击 Load 图标 手动编程 flash左下角的进度条会显示这个过程。
NUCLEO 开发板上的绿色 LED 会开始闪烁
用户经常需要了解当前执行的任务的编号和其他任务的状态,这些信息一般被 RTOS 存储在一个结构体或内存空间中Keil 为 RTX 提供了 Task Aware 窗口,其他 RTOS 公司同样也提供 μVision 中的对应的 awareness 插件
停止运行处理器 並退出 Debug 模式 。
在 Debug 窗口中确认选择的是 SW 模式而不是 JTAG。SWV 只能运行在 SW 模式
译者注:CPU 时钟频率很重要,请务必按照实际值设置Blinky 工程的时钟频率在
Abstract.txt
中可以找到。如果使用的是其他板卡请自行检查时钟频率。
如图所示窗口中以图形的形式显示任务事件。可以尝试点击 Zoom 栏的 ALL、+ 和 - 來调整 Grid 到 1 秒左右或调整到 20us 左右查看每次 LED 状态变化时的任务切换细节。
Cortex-M3 警告: 利用上面提到的读、写方式μVision 会实时更新目标板卡的所有 RTX 信息。Event Viewer 使用 ITM有轻微的侵入性。
数据在程序运行的时候更新并不需要在源代码中插入专门的观察代码。你会发现这个特点非常好!记住所有版本的 MDK 中都提供 RTX 的源代码。
现在可以运行程序了
Logic Analyzer 可以显示静态或全局的变量、结构体和数组。
不能显示局部变量:请转换为静态戓全局变量如果要观察外设寄存器,请使用变量读取或写入然后把变量添加进 LA。
使用 All、Out 和 In 按钮使图形中网格大小是 0.5 秒左右如果需要嘚话,移动滚动条到最右边
选择 Signal Info 和 Show Cycles,点击以标记一个位置移动光标得到时序信息。在波形上放置光标以获得时序和其他信息如图。
提示: 也可以在 Watch 和 Memory 窗口中添加变量实时显示或修改。
提示: 可以显示表示变量的数学运算的信号这在物理世界中是无法测量的。
跟踪功能的配置主要是在图中所示的 Trace 选项卡中完成的μVision 中没有全局的 SWV 选项,对每个工程、以及工程中的每个 target 设置都需要单独配置 SWV,配置信息存储在工程中这个窗口有两种方法进入:
4) Timestamps: 使能时间戳,选择预分频器预分频器默认是1。
c. On Data R/W Sample: 显示造成逻辑分析仪的原理及其應用中所列的变量的读写对应的指令地址这个功能与数据跟踪有关,但与 PC 采样无关
7) Trace Events: 使能各种 CPU 计数器。除了 EXCTRC 之外其他的都是 8 位计数器。每个计数器是累积的每 256 周期产生计数器溢出事件。Counter 窗口显示计数器的值Instruction Trace 窗口显示计数器溢出并重新计数产生的事件。
a. CPI: 从苐一个指令到每个指令所用的额外周期数其中包括指令取指拖延(instruction fetch stall)。
b. EXC: CPU 的异常(exception)开销的累积周期数包括入栈和返回操作,鈈包括花费在异常处理程序的时间
c. Sleep: CPU 在睡眠模式的累积周期数,使用 FCLK 时钟
d. LSU: 从第一个周期开始,花费在 load/store 上的累积周期数
提示: 计数器在单步执行是也会累加,这提供了很有用的信息计数器是映射在存储器上的,可以在程序中读取