历史上的今天
今天是:2025年04月19日(星期六)
2020年04月19日 | STM32 使用 Keil MDK 中的软件逻辑分析仪参与硬件调试
2020-04-19 来源:eefocus
这篇文章翻译自 ARM Keil Application Note 230 (1.2版)的前半部分。其中包括 STM32F4 处理器在 Keil MDK 中进行断点调试、变量实时观察,及逻辑分析仪参与硬件调试的实验。
原文使用的是 STM32F4-Discovery 开发板,我这里都改用 NUCLEO-F401RE 实现了。Discovery 板卡在新版本的 Pack Installer 中已没有 Blinky 例程支持,可以用 CMSIS-RTOS Blinky 来做,变量定义的位置等会有变化。
http://www.keil.com/appnotes/docs/apnt_261.asp。
Keil 网站上有 MDK 5 的 Legacy 支持软件,安装之后可以在 MDK 5 中使用 MDK 4 的工程,而不需要任何的 Software Pack。
我们建议使用 MDK 5.10 Software Pack,本文会持续跟进新的版本(译者注:并没有>_<,我在用5.17,如有区别会注明)。
Keil 针对各种 STM32 处理器有许多类似的实验手册,比如 CAN 的使用。详见www.keil.com/st。
这篇文档针对 MDK 5.10 及更新版本。
www.keil.com/mdk5/install 
将 MDK 安装到默认路径。安装到其他路径也是可以的,本教程会以默认路径为例:C:Keil_v5。
本教程使用C:MDK做为例程目录,建议同样使用这个默认路径。
如果 MDK 安装在其他路径,实验中需要做对应的路径修改。
(译者注:原文没有5,P.S. 上面这一段真贫)
Keil 网站上可以找到 DSP5 例程。
这个实验可以用评估版本(MDK-Lite)来完成,不需要购买授权。
不需要额外的调试器,只需准备 NUCLEO-F401RE 开发板、USB 线,以及在电脑上安装 MDK 5.10 就可以了(译者注:原文使用的是 STM32F4-Discovery 开发板)。
http://www.keil.com/appnotes/docs/apnt_230.asp。http://www.keil.com/mdk5/。http://www.keil.com/appnotes/docs/apnt_230.asp 上获得例程的 zip 文件。
http://www.keil.com/appnotes/docs/apnt_230.asp 上获得例程的 zip 文件。
解压缩到 C:MDKBoardsSTSTM32F4-Discovery。(译者注:这个程序是对 Discovery 开发板的。)
7) 测试 ST-Link V2 的连接
用 USB 线将 NUCLEO 开发板连接到电脑上。
如果 ST-Link USB 驱动程序安装正确,应该可以听到正常的 USB 设备连接的系统声音。否则需要根据下一章的指示,手动安装驱动程序。
两个红色 LED 应该点亮:LD1 (COM)和 LD3(PWR)。
启动 μVision
并选择 Project/Open Project。选择 Blinky 工程 C:MDKBoardsSTNUCLEO-F401REBlinkyBlinky.uvprojx。
在这个地方选择 STM32F401 Flash:
。点击 Target Options
或者按 ALT+F7,并选择 Debug 选项卡:
点击 Settings,会出现下面所示的窗口。如果显示出了 IDCODE 和 Device Name,说明 ST-Link 工作良好,可以继续下面的教程。点击两次 OK 返回 μVision 主界面。

上图中 Serial Number 框里出现一串数字说明 ST-Link 调试器已经连接到了 μVision。
如果 SW Device 框中没有显示,或者显示 error,这个问题在继续本教程之前必须要解决。请参照下一节内容:安装 ST-Link USB 驱动程序。
如果已经显示正常,ST-Link USB 驱动程序安装良好。点击两次 OK 退出 Target Options 窗口并从第9章继续。
提示:在上图 Port 框中选择 JTAG,然后在选回 SW,可以刷新 SW Device 框的显示。也可以关闭再重新打开这个窗口。
提示:ST-Link V2 和 ST-Link 的主要区别是添加了 Serial Wire Viewer (SWV) 跟踪功能。
8) 安装 ST-Link USB 驱动程序
如果上面的测试没有问题,则不需要进行这一步。
安装 ST-Link USB 驱动程序:(当上面的测试没有通过时)
先断开 NUCLEO 开发板和电脑之间的 USB 连接。
需要手动运行 stlink_winusb_install.bat 来安装 USB 驱动,这个文件存放在 C:Keil_v5ARMSTLinkUSBDriver 中。找到这个文件并双击来安装驱动程序。
连接 NUCLEO 的 USB,USB 驱动程序应该会以正常的方式安装完毕。
重要提示:ST-Link V2 固件升级程序 ST-LinkUpgrade.exe 存放在 C:Keil_v5ARMSTLink。如果要更新 ST-Link 固件,找到并双击这个程序,操作还是比较简单的,程序会检查并报告当前的固件版本。请注意我们需要使用 V2.J16.S0 或更高的版本来支持 SWV 操作。另外不要使用 V2.J19.S0,这一版本与最新版驱动程序不兼容。
(译者注:V2.J19.S0 不兼容估计是个历史问题,我已经在用 MDK 5.17 和 V2.J24.M11 版本了。)
COM LED LD1 的含义:
LED 红色闪烁:电脑开始 USB 枚举,但还未完成。
LED 红色:电脑和 ST-LINK/V2 之间已经建立连接(枚举结束),但 μVision 还没有连接到 ST-Link (比如 Debug 模式)。
LED 绿色:μVision 以 Debug 模式连接到 ST-Link,上一个通信是成功的。
LED 红色、绿色间隔闪烁:μVision 和目标之间正在交换数据。
LED 熄灭,但当进入 Debug 模式或点击 RUN 时闪烁一下:μVision 的 SWV 跟踪已启动。
LED 熄灭:ST-LINK/V2 与目标 MCU 或 μVision 之间的连接失败,需要重新连接电源以重启开发板。
9) 使用 NUCLEO 开发板运行 Blinky 例程
我们将使用板载 ST-Link V2 调试器连接 Keil MDK 开发平台和真实的目标硬件。
点击桌面图标
启动 μVision,用 USB 线将 NUCLEO 开发板的 CN1 连接到电脑上。选择 Project/Open Project,打开文件 C:MDKBoardsSTNUCLEO-F401REBlinkyBlinky.uvprojx。
ST-Link 会默认被选择。第一次运行 μVision 和 NUCLEO 开发板的时候,可能需要安装 USB 驱动程序,详见上面章节。
点击 Rebuild 图标
编译源文件。也可以用旁边的 Build 图标
。点击 Load 图标
对 STM32 的 flash 进行编程。Output 窗口中会显示这个过程。点击 Debug 图标
进入 Debug 模式,如果出现 Evaluation Mode 对话框,点击 OK。
注意: 当下载到 flash 时才需要使用 Load 图标,如果选择的是 RAM 运行则不需要。点击 RUN 图标
。注意:点击 STOP 图标
可以停止程序运行。
NUCLEO 开发板上的绿色 LED 会开始闪烁。
按下开发板上蓝色的 USER 按键会暂停闪烁。
至此你已经了解如何编译工程、下载到 STM32 处理器的 flash 中、运行并停止程序!
注意: Blinky 程序已经永久的烧写到 flash 中了,开发板可以独立运行这个程序,直到下一次被烧写。
10) 硬件断点
STM32F4 共有六个硬件断点,可以在程序运行过程中随时设置或取消。
在 Blinky 程序运行过程中,打开 Blinky.c 文件,点击 main() 函数中 for 循环里的某一行左侧边缘深灰色区域。
会出现一个红色的圆形标志,程序会停止运行。
请注意断点同时显示在源代码窗口和反汇编窗口,如下图。

不论是反汇编窗口还是源代码窗口,左侧边缘显示深灰色方形的区域表示这些代码行存在汇编指令,可以在这里设置断点。
每次点击 RUN 图标
,程序会运行到下一次遇到断点。可以尝试点击 Single Step(Step In)
、Step Over
和 Step Out
。
提示: 如果单步调试(Step In)不工作,点击 Disassembly 窗口使它成为焦点,可能需要点击一行反汇编代码。这样操作表示想要汇编级别的单步运行,而不是 C 语言代码级别。
提示: ARM CoreSight 的断点是 no-skid 的,硬件断点发生在被设置断点的指令执行之前(译者注:有 skid 的断点的意思是,程序停止在断点设置的指令甚至后面几个指令执行之后)。另外 flash 中烧写的指令不会被替代或修改,这的特性对于高效率软件开发有重要意义。
完成这个实验后,再次点击这些断点以删除它们,为后面的实验做准备。
提示: 可以通过点击断点,或者选择 Debug/Breakpoints(或按 Ctrl+B)并选择 Kill All 来删除。
提示: 可以通过选择 Debug/Breakpoints 或按 Ctrl+B 来查看所有断点的设置。
11) Call Stack + Locals 窗口
局部变量
Call Stack + Locals 窗口被合并在一个集成窗口中,每当程序停止时会显示调用栈和当前函数的所有局部变量。
如果可能,局部变量的值会显示,否则显示 < not in scope >。菜单中的 View/Call Stack Window 用来切换 Call Stack + Locals 窗口显示或隐藏。
运行并停止 Blinky,点击 Call Stack + Locals 选项卡。
下图展示了Call Stack + Locals 窗口。

窗口中显示了当前活动函数的名称和局部变量列表。随同每个函数的名字会显示它被哪个函数或中断/异常调用。
当函数退出时,会从列表上移除。
最早调用的函数会出现在列表的底端。
这个列表只有在程序停止运行时有效。点击 Step In 图标
或按 F11 键。当单步运行到不同的函数时,观察它们在窗口上显示的变化。如果陷入到 Delay 函数的循环当中,可以用 Step Out
或 Ctrl+F11 键快速退出。点击几次 Step In,观察其他函数。
右键点击一个函数名,尝试 Show Callee Code 和 Show Caller Code 选项。

点击 Step Out 图标
退出所有函数,返回 main()。
提示: 如果单步调试(Step In)不工作,点击 Disassembly 窗口使它成为焦点,可能需要点击一行反汇编代码来执行汇编级别的单步运行。如果焦点在源代码窗口上,则是执行 C 语言代码级别的单步运行。
提示: 可以在程序停止运行时,通过 Call Stack + Locals 窗口来修改变量的值。
提示: 上述是标准的“Stop and Go”调试过程。ARM Coresight 调试技术还可以做很多更强大的事情,比如在程序运行中显示并实时更新全局或静态变量,而不需要修改程序。由于局部变量通常存储在 CPU 寄存器中,不能在程序运行时实时显示,需要转换成全局或静态变量使得作用域不会消失。
如果借助 ULINK pro 和 ETM 跟踪,可以记录所有指令的执行情况。Disassambly 和 Source 窗口是按编写的顺序显示代码的,而 ETM 跟踪可以按执行的顺序显示。另外 ETM 还提供 Code Coverage、Performance Analysis 及 Execution Profiling 等功能。
把局部变量转换成全局或静态变量通常意味着把它从 CPU 寄存器移动到 RAM 上,CoreSight 在程序运行中可以观察 RAM,但不能观察 CPU 寄存器。
调用栈
如上面可以看到的,当程序停止运行时,函数按栈的方式显示在列表中。当想要了解栈中有哪些函数被调用、存储的返回值是什么的时候,这个功能就很有用。
提示: 可以在程序停止运行时,通修改局部变量的值。
提示: 点击菜单 Debug/Breakpoints 或按 Ctrl+B 键可以查看 Hardware Breakpoint 列表,同时这也是配置 Watchpoint (观察点,也叫 Access Point)的地方。在这个列表里可以临时屏蔽某些项目。点击 Debug/Kill All Breakpoints 会删除断点,但不会删除观察点。
12) Watch 和 Memory 窗口及其使用方法
Watch 和 Memory 窗口实时显示变量的值,这是通过 ARM CoreSight 调试技术实现的,这项技术是包含在 Cortex-M 处理器中的一部分。同时,也可以在这些存储器地址上实时地“put”或插入数值。这两个窗口都可以通过拖拽变量名,或者手动输入来添加变量。
Watch 窗口
添加全局变量: 除非程序停止在局部变量所在的函数,否则 Watch 和 Memory 窗口不能观察局部变量。
停止运行处理器
并退出 Debug 模式
。在 Blinky.c 的第24行左右,声明一个全局变量(这里变量名叫做 value):unsigned int value = 0;。
在第104行左右添加语句 value++; 和 if (value > 0x10) value = 0;,如图:

选择菜单 File/Save All 或点击
。点击 Rebuild
,点击 Load
下载到 flash。进入 Debug 模式
,点击 RUN
,提示:可以在程序运行中设置 Watch 和 Memory 窗口。在 Blinky.c 中,右键点击变量 value 并选择 Add value to … 及 Watch 1,Watch 1 窗口会打开并显示 value 如下图。
value会实时增加到0x10。

提示: 也可以框选 value,单击并拖拽到 Watch 或 Memory 窗口。
提示: 请确认菜单 View/Periodic Window Update 在选中状态。也可以在 Name 下面区域双击或按 F2,再手动输入或复制粘贴变量名。或是打开菜单 View/Symbols Window 来输入变量。
提示: 如果要拖拽到一个非活动的选项卡,选中变量按住鼠标并移动至希望打开的选项卡名字上,等待其打开并拖拽鼠标到窗口内释放。
Memory 窗口
右键点击 value 并选择添加到 Memory 1,或手动添加 value 到 Memory 1。如果需要的话,选择菜单 View/Memory 来打开 Memory 1 窗口。
注意 value 被当作了一个指针,其值做为地址显示在了 Memory 1 上。这个操作在想要看一个指针指向的地址的时候很有用,但不是我们现在想看到的。
在变量名前面加一个“&”符号并按回车键,改为显示变量的物理地址(0x2000000C)。
右键点击 Memory 1 窗口并选择 Unsigned/Int。
value 的值现在以32位的形式显示了。
Watch 和 Memory 窗口都是实时更新的。
在 Memory 窗口中,鼠标移动到数据区域右键点击,选择 Modify Memory,可以修改对应地址的值。

提示: 这些操作通常不会占用 CPU 周期。关于 DAP 是如何运行的,详见下一章“原理”。
提示: 在 Debug 模式中选择菜单 View/Symbol Window,可以打开 Symbol 窗口查看变量和各自的位置。
上面展示的 Memory 和 Watch 窗口的操作并不需要配置 Serial Wire Viewer (SWV),这些机制使用的是 SWV 之外的另一个 CoreSight 特性。CoreSight Debug Access Port (DAP)通过 Serial Wire Debug (SWD)或 JTAG 连接来处理读写操作,从而实现实时在线的存储器访问。
13) 如何在 Watch 和 Memory 窗口中观察局部变量
(译者注:由于板卡的区别,这一部分和原文略有不同。)
运行 Blinky.c 程序。我们将使用 main() 中的局部变量 num。
在 Blinky.c 的第87行附近,main 函数的开头,找到声明这个局部变量的地方。
右键点击这个变量,把它输入到 Watch 1 窗口中。注意由于局部变量的值可能存放在 CPU 寄存器内,μVision 不能在程序运行时访问,因此会显示 < not in scope >。如果 μVision 显示无法添加变量,请尝试停止再开始 Blinky 程序。

在 Blinky.c 的主循环里添加一个断点,会使程序停止,这时会出现当前变量的值。
删除这个断点。
局部变量或自动变量可能存放在 CPU 寄存器内,μVision 不能在程序运行时访问。局部变量 num 只有在 main 函数运行时才会存在,在其他函数或中断/异常处理程序中是不存在的,因此 μVision 无法确定这个变量的值。
停止运行处理器
并退出 Debug 模式
。
如何实时更新局部变量:
只需把 num 改为全局变量定义在 Blinky.c 中。
把 num 的声明移动到 main() 的外面、Blinky.c 的最前面,把它改为全局变量:
unsigned int value = 0; int32_t num = 0;12
提示: 也可以定义成静态变量,如: static int32_t num = 0; 。
提示: 在编辑模式和 Debug 模式都可以编辑文件,但编译只能在编辑模式进行。
上一篇:STM32之FreeRTOS
下一篇:STM32简单任务调度的总结
史海拾趣
|
供应麦肯MDT单片机,PIC单片机,Freescale传感器,单片机,单片机开发 广州远景微电子有限公司从1999年至今专业从事麦肯MDT单片机,十速TENX单片机,美国MEAS传感器,Freescale单片机、传感器,自产IC的销售及产品方案单片机开发设计。公司技术力量雄厚,拥有专业的工程师队伍,专业承接各类单片机的开发与设计,坚持以 ...… 查看全部问答> |
|
我用的是CE6.0 。 系统定制时编译出现一个错误,只能找到最后说 ; Build for Windows CE (Release 601) (Built on Aug 17 2006 15:18:52) File names: Build.log Build.wrn Build.err Build.dat CEBUILD: Running sysgen -p script preproc St ...… 查看全部问答> |
|
三星6410/Wince6.0 环境下,Directshow显示 三星6410/Wince6.0 环境下,Directshow 的范例一般在什么目录下? 我想用Directshow 显示 Byte *pBuf(pBuf 是一个指向RGB数据 的指针) 中的数据应可以吧?… 查看全部问答> |
|
我现在在学C++,想设计代码通过电脑远程控制电机的转动,可是脑子里连个概念都没有,希望各位大虾能详细指教一下该怎么实现,不是求代码,是想求得一个详细可行的方法以及实现的过程,我现在就是个程序设计初学者,对于串口之类还没有认识,希望您 ...… 查看全部问答> |
|
各位老大好,今天用PSPICE仿真一个RC震荡电路。有个问题没有想明白,请教各位高手,有劳指点一下。电路很简单,就是一个RC振荡电路。输入是一个1V的正弦波,输入是下面图中最右边的电容。见下。我首先是进行AC扫描,频率从80k到150k,得到的输出如 ...… 查看全部问答> |
|
急救!!!!哪位大大帮看看我的HS9148红外解码程序哪儿除了问题? 这是源代码。//使用12M晶振 适用于HS9148芯片#include<reg52.h>#include<stdio.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit led=P1^1;sbit in=P3^2;//红外接口标志uchar const tab[]={0x3f,0x06,0 ...… 查看全部问答> |




