前言

前段时间有工程师分享了在 Keil MDK5 中 Breakpoints 断点设置窗口勾选 Write 功能以实现快速定位变量何时何处被修改,另外还提及到勾选 Read 、 Write 以及设置 Count 数值进行调试的方法。这实际上是给断点触发添加了一定的条件,减少程序不必要的中止。但仅仅设置 Read 、 Write 、 Coun 并不能完全满足我们日常开发调试的需求,下面将举例

引入

情景1

i==666 的时候触发断点

1
2
3
4
for(i=567; i<1234556; i++)
{
//...
}

情景2

i 为 int 类型,在 i>60 的时候均触发断点,但 i 的值在 0-100 之间无规律变化

情景3

i、j 为 int 类型,在第2次 i=1、j=10 的时候才触发断点

1
2
3
4
5
6
7
8
9
10
while(1)
{
for(i=0; i<100; i++)
{
for(j=0; j<100; j++)
{
//...
}
}
}

上述3种情景或许可以计算并设置 Count 值进行调试又或者每次进函数都查看 i、j 的值进行调试,但这样并没有效率。所以这里再补充一些 Breakpoints 断点设置窗口中的其他用法。我们先看看Breakpoints 窗口都有哪些内容

Breakpoints 窗口功能

窗口调出

Breakpoints 窗口调出有 3 种方式
方式一:在 Keil MDK 菜单栏中找到 Debug -> Breakpoints... 选择它
方式二:如图所示,该窗口快捷键为 Ctrl+B
方式三:在 Watch 窗口中对需要设置的变量右键,选择 Set Access Breakpoints at 'xxx'

![image-20240228005537408](./Keil Breakpoints 窗口功能的一些补充/image-20240228005537408.png)

![image-20240228005541962](./Keil Breakpoints 窗口功能的一些补充/image-20240228005541962.png)

窗口元素

![image-20240228005550851](./Keil Breakpoints 窗口功能的一些补充/image-20240228005550851.png)

① 当前已设置的断点

② “Expression”、“Count”、“Command” 功能设置

③ 访问方式设置

④ 功能操作:设置/保存断点、删除选择的断点、删除所有断点

对区域③(Access)的补充

Read

内存访问模式为读时触发

Write

内存访问模式为写时触发

Read 与 Write 可同时选择

Size 与 Bytes/Objects

  • 勾选为Bytes时有效Size:判断内存读/写的内存大小,字节为单位如目标地址为 0x200000D8Size 设置为 2 ,并且勾选BytesWrite则,地址0x200000D80x200000D9 其中一个位置以写模式访问时,触发断点
  • 勾选为Objects时,根据目标对象大小而确定Size ,无需再自行设置

对区域④的补充

Expression

程序运行期间的一个地址,或者是一个表达式

1
[\\ExecName][[\[Path/]Module][\Identifier]]

ExecName:以“\” 开头 + 工程名称 Path/Module:文件路径 + 文件名 Identifier:以“\” 开头 + 目标

ExecName:以“\” 开头 + 工程名称

Path/Module:文件路径 + 文件名

Identifier:以“\” 开头 + 目标

目标可以是:

  • 寄存器(如,R1==R2) 地址 (如,0x1234)
  • 运算符(&,&&,<,<=,>,>= ,==,!= 等)
  • 行号(如 “5”,表示第5行)
  • 常量
  • 变量
  • 函数

Count

满足断点条件的次数(Access以及Expression结果为TRUE)

Comand

触发断点时会执行此处命令,命令可以用户定义的函数或信号函数。Keil MDK 执行命令后继续运行目标
程序,若要暂停程序执行,需设置系统变量 _break_ 为非0

Command 为空时, break 默认非0

  1. 如下图所示设置 Command 后,Command 会打印出相关信息,但此时程序并没有暂停而是保持持续运行的状态
    1
    printf(\"Number:%d\n\",j);

![image-20240228010248315](./Keil Breakpoints 窗口功能的一些补充/image-20240228010248315.png)

![image-20240228010250536](./Keil Breakpoints 窗口功能的一些补充/image-20240228010250536.png)

  1. 设置系统变量_break_非0,每一次满足中断触发条件程序都会暂停
1
printf(\"Number:%d\n\",j); _break_=1;

![image-20240228010320454](./Keil Breakpoints 窗口功能的一些补充/image-20240228010320454.png)

示例

![image-20240228010323926](./Keil Breakpoints 窗口功能的一些补充/image-20240228010323926.png)

ExecName: \\DEMO\
Path/Module: ../User/main.c
Identifier: \11

![image-20240228010421763](./Keil Breakpoints 窗口功能的一些补充/image-20240228010421763.png)

触发条件:地址 0x200000D8(变量 i ) 被写 5 次时触发

断点触发的判定顺序

Access -> Expression -> Count

实践

情景1

在 i==666 的时候触发断点

1
2
3
4
for(i=567; i<1234556; i++)
{
//
}

Access :设置为 Write
Expression : 写 i==666 ,关键设置
Count: 默认 1 即可

![image-20240228010517136](./Keil Breakpoints 窗口功能的一些补充/image-20240228010517136.png)

情景2

i 为 int 类型,在 i>90 的时候均触发断点,但 i 的值在 0-100 之间无规律变化
Access:设置为 Write
Expression :写 i>60 ,关键设置
Count :默认 1 即可

![image-20240228010531837](./Keil Breakpoints 窗口功能的一些补充/image-20240228010531837.png)

情景3

i、j 为 int 类型,在第2次 i=1、j=10 的时候才触发断点
Access:设置为 Write
Expression :写 (i=1) && (j==10) ,关键设置
Count :设置为 2

![image-20240228010545128](./Keil Breakpoints 窗口功能的一些补充/image-20240228010545128.png)

资料

µVision User’s Guide - Break Set(arm.com)

µVision User’s Guide - Breakpoints Window(arm.com) µVision User’s Guide - System Variables(arm.com)