【工具使用】Keil5软件使用-进阶调试篇

news2024/11/15 15:48:21

一、概述

    本文面向已经懂得软件基本操作的职业老手,如果是未使用过该软件的小鲜肉,请移步基础篇。这里以STM32芯片为例对工具进行讲解,其他品牌的芯片在调试方面上可能存在差异。

二、软件说明

    Keil提供了包括C编译器、宏汇编、链接器、库管理和一个功能强大的仿真调试器等在内的完整开发方案,通过一个集成开发环境(μVision)将这些部分组合在一起。
    目前软件对中文的支持不友好,不建议安装网上的一些汉化包之类的。另外建立的工程文件路径也尽量不要存在中文,否则可能会出现一些异常。
演示版本:5.24a

三、软件使用

3.1 基本调试操作

    首先点击"Debug->Start/Stop Debug Session"或下图2位置,进入调试。
在这里插入图片描述
    如果前面工程配置里选择了复位调试,则进入调试后,会停在main函数头部
在这里插入图片描述

    复位(Reset):对程序进行复位操作,根据烧录器不同的复位方式配置会触发不同的复位类型。
在这里插入图片描述

    全速运行(Run):使当前程序开始正常全速运行,直到程序遇到断点时停止。
在这里插入图片描述
    停止运行(Stop):当程序全速运行时,点击此按键可停止程序运行,停的是当前点击时的程序运行位置。
在这里插入图片描述

    单步调试(Step):根据当前调试的窗口的语言,执行单条语句。如果遇到函数,则会进入函数内部。如果是在反汇编窗口中,则只执行一条汇编指令。
在这里插入图片描述

    单步跳过调试(Step Over):如果是在C语言窗口中,则是按单条语句执行,与单步调试不同的是,遇到函数不会进入函数内部,而是直接全速运行函数,并跳到下一条语句。
在这里插入图片描述

    单步返回调试(Step Out):如果是在C语言窗口中,则是直接全速运行当前函数后面所有内容,直到函数返回上一级。
在这里插入图片描述

    插入/移除断点:如果当前光标所在行未有断点,则插入断点(前提是当前行可以插入,如果无法插入会显示一个感叹号),在有断点的情况下则是移除断点。插入断点后,当前行前面会有个红圆表示断点位置。也可以通过直接点击红圆位置进行插入/移除断点的操作。另一种断点方式,是通过指令来控制,当然也可以使用Keil提供的界面化操作,设置某个变量读或写时触发断点。不过目前貌似有部分芯片不支持这种操作。注:断点最多只能打7个。
在这里插入图片描述

    使能/禁止断点:开启或禁止当前光标所在行的断点。禁止后红圆变成白圆。
在这里插入图片描述

    禁止所有断点:禁止当前所有的断点。
在这里插入图片描述

    删除所有断点:删除所有断点。
在这里插入图片描述

3.1 调试窗口

  • 变量查看窗口——Watch1,Watch2

    通过"View->Watch Windows->Watch1、Watch2"可以选择打开Watch窗口,也可以在工具栏在这里插入图片描述这里打开。再点击一次则可以关闭。

在这里插入图片描述

    通过选中一个变量,右键添加入对应的Watch窗口,可以追踪查看当前变量的变化状态。注意,只有全局变量可以全程监视,临时变量只有在进入当前函数中才可监视到其数据,用static关键词修饰的变量无法监视。
在这里插入图片描述

    如果当前变量没有实时更新,则需要点击"View->Periodic Window Update"将其勾选上。
在这里插入图片描述
    在"Watch"窗口中,可以查看当前变量名称、值、数据类型,如果当前变量类型为结构体,则可以以对应的结构形式进行展开查看。
在这里插入图片描述

  • 内存查看窗口——Memory

    通过"View->Memory Windows->Memory1/2/3/4"打开Memory窗口,也可以通过工具栏Memory窗口
这个图标打开。打开的状态下再按一次则可关闭。

在这里插入图片描述
    在Memory窗口中输入想要查看内存的起始地址,另外右上角的锁可以把当前界面锁定下来。
在这里插入图片描述
    另外如果查看的是Ram的地址,那其中的数据也可以直接通过此窗口进行修改。
在这里插入图片描述

  • 系统视窗——System Viewer Windows(这个根据不同芯片会有不同的展示)

    可以在"Peripherals"选项栏中选择"System Viewer"系统视窗中对应的外设,选择"Core Peripherals"则是内核调试窗口。另外系统视窗也可以通过工具栏中在这里插入图片描述这个位置可以打开。
    这个窗口用于查看当前单片机外设及内核寄存器的值,在调试外设底层时经常会使用到。
    在这个窗口中可以直接修改外设寄存器的值,当然部分只读寄存器是无法修改的,有些则是需要在特定条件下才可以设置生效,具体就得看对应的芯片手册里寄存器的说明了。
在这里插入图片描述

  • 调度关系窗口——Call Stack Window

    可以在"View->Call Stack Window"打开此窗口,也可以在工具栏在这里插入图片描述这个位置打开 。
在这里插入图片描述
    这个窗口用于查看当前程序调度关系,当出现有进入硬件错误异常调试时可以快速定位到是哪里触发的异常。这个窗口是的调度关系是从当前程序堆栈里获取的数据并将其图形化,所以如果当前堆栈数据被破坏,则此窗口也将无法查看调度关系。
    该窗口里显示的调度关系是从下至上调用的,最上面的表示当前程序所处的函数。展开对应的函数,可以查看各层调用函数跳转之前保存的一些临时变量等信息。
在这里插入图片描述

  • 寄存器窗口——Register Window

    该窗口可在"View->Registers Window"处打开,也可以在工具栏在这里插入图片描述这个位置打开。
在这里插入图片描述
    这个窗口用于查看当前内核的相关寄存器,如汇编里常说的15个通用寄存器。当然调试中比较常用的是其中的SP、LR、PC三个寄存器。SP为当前栈的地址位置,PC为当前程序地址,LR为函数跳转前的地址,即当前函数返回的地址。
在这里插入图片描述
    另外"Banked"中的MSP为当前程序系统主栈,PSP则为操作系统的任务栈,这两者的区别是,如果使用了操作系统,则当前任务中的所有调度关系使用的是任务栈,而类似中断这种内核的操作使用的是主栈;如果未使用操作系统,则只会使用主栈,不会使用任务栈。
在这里插入图片描述
    通过"Internal"可以查看当前是处在中断还是任务中,Mode为"Thread"表示是在线程/任务中,或者是函数中(非中断),为"Handle"表示是在中断中;Privilege为"Privelege"表示当前处于特权模式。Stack为"PSP"表示当前使用的是任务栈,为"MSP"则表示使用的是主栈。
在这里插入图片描述

  • 反汇编调试窗口——Disassembly Window

    该窗口在"View->Disassembly Window"中可以打开,也可以在工具栏中在这里插入图片描述这个位置打开。
在这里插入图片描述
    该窗口是通过bin文件反汇编出来的汇编文件(汇编跟二进制原本就是一一对应的关系)。当设置了优化等级后,部分C语言的调试会变得困难(汇编跟C语言不是一一对应,而程序运行又是完全根据汇编来走的),此时可能需要使用汇编窗口进行调试。

  • 命令窗口——Command Window

    该窗口在"View->Command Window"中可以打开,也可能在工具栏在这里插入图片描述这个位置打开。
在这里插入图片描述
    这个窗口可用来输入一些控制命令,比如保存输出当前内存地址等。在命令窗口中输入如下导出指令,按下回车即可导出数据

save filename startAddr,endAddr

filename:导出数据的文件名,无论后缀是什么,导出的格式都是十六进制文件。没有输入路径时,文件自动保存在当前工程根目录下。
startAddr, endAddr:需要导出数据的起始地址和结束地址,也可以通过表达式写出来。

例如:

save ExportData.hex 0x08000000, 0x08000000+0x2000

  • 函数地址表——Symbols Window

    该窗口在"View->Symbols Window"中打开,也可能在工具栏在这里插入图片描述这个位置打开。
在这里插入图片描述

    可以查看当前所有程序的函数调用关系及其所在地址。

  • 串口调试窗口——Serial Windows

    该窗口在"View->Serial Windows"中打开,也可以在工具栏在这里插入图片描述这个位置打开。
在这里插入图片描述
暂未使用过,后续再添加。

  • 逻辑分析窗口——Analysis Windows

    该窗口在"View->Analysis Windows"中打开,也可以在工具栏在这里插入图片描述这个位置打开。
在这里插入图片描述
    这个貌似只能在软件模拟仿真中使用,如果使用硬件调试,需要硬件支持。

  • 跟踪窗口——Trace Windows

    该窗口可以在"View->Trace Windows"中打开,也可以在工具栏在这里插入图片描述这个位置打开。
暂时未使用过,后续再添加。

四、调试应用

  • HardFault(硬件错误)

    这个可以算是最常见的一个问题了,在开发过程中多多少少会遇到过程序死机的问题,而死机的大部分原因都是进入的HardFault中断,即常说的硬件错误中断。要想知道这个怎么调试,首先得清楚这是什么,怎么触发。
    触发原因:内存溢出,堆栈溢出,数组越界,中断错误,除0(在某些编译器下会有错误)等。前面三个,可以归结为都是内存异常操作导致,但因为其出现方式不一样,所以调试方式也不同。
    从现象反推,当出现这个错误时,第一时间查看函数的调度关系,看最后是死在哪个位置。如果不是堆栈溢出,一般来说是可以直接查到进入硬件错误前的最后执行的代码位置的。当然内存溢出跟数组越界也有可能导致无法查看调度关系,因为这个调度关系就是从程序运行栈里取出数据进行展示,所以当栈数据被破坏,则无法使用此方式进行调试。
    知道死机位置后(其实大概率就是因为某个异常指针的引用导致的问题),此时就去查找异常指针出现的原因。首先从逻辑层面看,异常指针是否是因为某个逻辑给指针赋了个错误值。
    其次是数据越界的角度来看,在Map文件中查找该指针的内存地址,查看其内存前后是否存在一些数组或结构体,然后去检查前后数组或结构体的操作是否存在下标溢出,指针偏移错误等问题。
    还有最后一种,就是直接从内存里获取数据作为指针地址进行引用,此类用法一般是在日志操作或GUI中比较常用,这种情况就要去内存数据来源是否存在问题。
    除以上三种可能性外,还有一种可能对一些人是涉及知识盲区的,就是引用地址没有地址对齐。这一部分是涉及内核的一些知识。这里简单讲下,对于M0内核,指针引用地址需要根据其引用的数据类型进行对齐。比如以下代码:

int main(void)
{
	uint32_t *p = 0x20000001;
	*p = 20;	/* 这句一执行就会导致异常 */
}

还有一种是操作指针本身的地址没有4字节对齐,也会出现问题。如下代码:

/* 实际这样子定义编译器会报错(在Keil中编译),这里只是为了直观表示 */
uint32_t *p __attribute__((at(0x20000001)));
int main(void)
{
	p = 0x20000010;	/* 这句一执行就会导致异常 */
}
  • 复位

    复位有几种类型,一是看门狗复位,二是软件复位,三是硬件复位。复位类型可以通过芯片自带的复位寄存器进行查看。不过查看前需要手动清除所有复位标志,不然其复位标志会一直保留着。
    先讲下看门狗复位,当单片机开启看门狗后,很多问题都会变成复位问题,比如上面说的HardFault,因为HardFault也是一个中断,只是默认中断里是一个While(1)的死循环,所以当进入中断后,一段时间没有喂狗操作,就会触发复位。或者一些操作陷入死循环的,均是同理。这里我们把这一类问题都归为死循环问题。处理方式,先把看门狗关掉,然后调试看停在哪个死循环中,如果是HardFault,那就看上面硬件错误的处理方式。如果是其他死循环,那就看是什么条件触发的。死循环的问题相对来说比较好找。
    另外一种比较难处理的看门狗复位问题,莫过于某些操作时间过长,导致喂狗不及时。比如读写Flash时,通常会关闭中断,当大量读写时,其操作时间不可小靓,未开看门狗的情况下会有肉眼可见的程序卡顿,开了看门狗的情况下则通常会触发程序复位。这种类型的问题,通过关闭看门狗可能也无法定位到具体位置,因为程序还可以正常执行,只是在某些程序段会变得比较卡顿。对于这种问题,最好的方式是通过代码对比,通过对比原本没出问题的代码和出问题代码的差异性,锁定问题大体出现的位置,再通过程序执行时间进行估算。也可以借助一个独立的定时器,在一些时间操作较长的可疑之处计时。比如程序调用了某个底层未开源函数,那可以在调用前后打印定时器的计数,来计算函数运行的时间。当然也可以通过Keil自带的调试计数值来计算运行时间。
    软件复位就比较好找了,一般是需要人为调试内核的复位接口进行复位,所以只要查看是哪些位置触发的调用复位函数的条件就可以锁定问题点。
    硬件复位就只能从外围电路进行切入了,考虑干扰、连锡等问题。当然有些硬件复位是通过一个硬件看门狗进行复位的,如果是这种应用,那参考内部看门狗的问题排查方式。

  • 逻辑时序类调试

    时序类的用断点调试法就很难做到了,特别是那种时序要求很严格的。就比如Modbus通信,协议是规定了一帧数据中每两个字节间隔时间不能超过1.5字符。所以想要在一帧数据中,按一个字节一个字节断点调试从机是不可能的,主机不会给你休息的时间。这时候就必须得添加一些测试代码了,添加测试代码最重要的一个原则,是不能变更原本的功能。所以一般在数据流向的关键路径上添加一些监控变量,通过监控变量的变化来识别时序是否出现错误。
    另外也可以使用逻辑分析窗口,把对应的变量添加进窗口中,通过时间变化查看变量对应的变化关系,以此来判断逻辑时序是否正常。

  • 内存调试

    如果有涉及boot或日志记录功能的编写,那肯定会涉及大量内存的对比及调试,这时候可以利用上面提到的小技巧,在命令窗口那里输入save filename.hex StartAddr, EndAddr把对应的内存数据打印出来。

  • 底层外设调试

    这个打开对应外设的寄存器界面,对着芯片用户手册查看每个寄存器的功能进行调试,只有对寄存器功能熟悉了才有对应的调试手段。

五、注意事项

1、有时候在watch窗口中,变量值不会刷新,这时候就需要查看一下"View->Periodic Window Update"是否已勾选,如果没勾选,变量只有在第一次添加或停止调试时才会刷新。另外当窗口里一次性加载了一个很大的数组,当展开数组时,变量刷新也会变得很慢,并且软件会变卡顿。

2、当选择了非0级优化时,调试可能会变得困难,具体表现在断点调试。比如现在下面的代码,代码优化的关系,有可能把case0、1、2里的return 1都合并成一行,导致运行调试时,无论当前程序进入了哪个分支,使用断点时都只会进其中一个。所以当开启代码优化等级后,需要注意断点调试将变得不可信。另外优化编译后,有部分代码也将无法打断点(被优化的代码)。

switch (xx)
{
	case 0:
	{
		do_something0();
		return 1;
	}
	case 1:
	{
		do_something1();
		return 1;
	}
	case 2:
	{
		do_something2();
		return 1;
	}
	default:
	{
		return 0;
	}
}

此时应该去看汇编的实现,其执行顺序与汇编一致。

3、目前发现有部分工程在一些电脑上调试时,打断点后在删除断点之前退出调试,会导致Keil崩溃,只能结束进程重启。

4、当开启内部看门狗并且未打开调试关看门狗功能时,停止运行一段时间后会复位。

5、在全速运行时,有时打断点会无效,取消断点也无效,貌似是Keil本身的问题。

六、相关知识

    Keil5软件使用-基础使用篇、Keil5软件使用-进阶工程配置篇、Keil软件包-知识宝藏库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/907863.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

内核日志过滤

本操作以centos为例。 1、不想把日志存入到 /var/log/messages中,转存到其他文件 >1.1、修改配置文件 /etc/rsyslog.conf vim /etc/rsyslog.conf# 添加以下代码if $programname kernel and ($msg contains hexdump or $msg contains shentong_data_file) then …

如祺出行递表,港交所迎来首位Robotaxi商业化观察对象

港交所近年来持续对新经济公司和科技创新类公司释放善意,接连优化上市条款,摆出“筑巢引凤”姿态。这也让外界对新兴领域的兴趣大大增加。 8月18日,出行科技与服务公司如祺出行正式递表港交所,其业务模式为Robotaxi和有人驾驶网约…

python AI绘图教程

前提 1.安装python 2.安装git 步骤 下载stable-diffusion-webui项目(链接:GitHub - AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI) git clone https://github.com/AUTOMATIC1111/stable-diffusion-webui.git 安装st…

git管理代码

理论上改代码前要pull一次,然后在push前在pull一次 改代码前pull一次是为了获取最新的同步,但是coding也是需要时间的,难保敲代码的这段时间没有人动远程仓库的东西,所以在改完代码要push的时候也应该再pull一下看有无冲突&#x…

《Zookeeper》源码分析(十七)之 LeaderZooKeeperServer

目录 LeaderZooKeeperServer类结构创建LeaderZooKeeperServer加载初始化数据loadData()启动LeaderZooKeeperServersetupRequestProcessors() LeaderZooKeeperServer 类结构 ZooKeeperServer主要是设置了一系列Processor处理器,对于不同的服务器角色有不同的实例类…

论文导读 | Operations Research近期文章精选

推文作者:张曦予 编者按 本期我们选取了七月后半月来自Operations Research的一篇文章以及来自Management Science的四篇文章以飨读者,内容涉及多个方面,我们选取的文章包含了各个方面对于管理以及运筹进行研究的文章,如研究疲劳对…

更新清华软件源时报错:Certificate verification failed: The certificate is NOT trusted.

场景: 在下载libapriltag-dev依赖时,Linux给报了一个错误:E: Unable to locate package libapriltag-dev 。这个错误经常会出现,无法在现有的软件源里找到该安装包或者该依赖,这个时候,首先我们就需要先检查…

服务运营 | MSOR文章精选:远程医疗服务中的统计与运筹(一)

推文作者:蔡君洋,Guo 编者按 《哈佛商业评论》在今年1月20日发表了《是时候巩固远程医疗在美国医疗保健中的地位了(It’s Time to Cement Telehealth’s Place in U.S. Health Care)》一文。文章指出,在COVID-19大流行…

4.SpringCloud 基本架构

1.SpringCloud概述 Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,…

设置前端项目站标 favicon.ico

1、首先我们需要准备一个小图标利用在线ico工具制作 .ico 的文件 在线工具favicon制作 - 在线工具favicon在线制作,icon制作,网站图标,网站图标制作,ico图标制作https://tool.lu/favicon/选择自己想要制作的小图标,然后选择48*48的下载就可以了 将下载的文件名改为f…

leetcode 123. 买卖股票的最佳时机 III

2023.8.21 本题限制了买卖次数:最多买卖两次。 与之前的股票问题相比,dp数组的第二个维度需要设置四个状态: 第一次持有股票第一次不持有股票第二次持有股票第二次不持有股票 ps:持有股票不等于购买股票!&#xff01…

【Git版本控制工具使用---讲解一】

Git版本控制工具使用 安装设置用户名签名和邮箱Git常用的命令 初始化本地库查看本地状态Git 命令添加暂存区提交本地库查看版本信息修改文件版本穿梭 安装 首先根据自身电脑的配置选择性的安装是32位的还是64位的Git版本控制工具 我这边安装的是64位的 以下是我安装的时候的过…

jmeter HTTP信息头管理器

首先,打开JMeter并创建一个新的测试计划。右键单击测试计划,选择"添加" > “线程组”,然后在线程组上右键单击,选择"添加" > “Sampler” > “HTTP请求”。 在HTTP请求中填写服务器的URL和其他必要…

深入浅出带你玩转栈与队列——【数据结构】

W...Y的主页 😊 代码仓库分享 💕 目录 1.栈 1.1栈的概念及结构 1.2栈的结构特征图 ​编辑 1.3栈的实现 1.3.1栈的初始化 1.3.2进栈 1.3.3出栈 1.3.4销毁内存 1.3.5判断栈是否为空 1.3.5栈底元素的读取 1.3.6栈中大小 1.4栈实现所有接口 2…

时序预测 | MATLAB实现SO-CNN-BiLSTM蛇群算法优化卷积双向长短期记忆神经网络时间序列预测

时序预测 | MATLAB实现SO-CNN-BiLSTM蛇群算法优化卷积双向长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现SO-CNN-BiLSTM蛇群算法优化卷积双向长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 时序预测 | MATLAB实现SO-CNN-BiL…

增强数字风险防护管理,天际友盟牵头正式发布GDN·全球数字风险阻断网络

随着数字化进程的加快,企业对于数字风险防护管理的需求与日俱增,其数字足迹、数字资产,甚至高管的个人形象都可能成为不法分子的攻击目标。保护关键数字资产与数据免受外部威胁,提升在线业务运营稳健性的价值毋庸置疑。 8月18日&a…

QQ音乐刷时长和音响力工具-无需密码

QQ音乐刷等级是一款安卓端的QQ音乐刷时长和音响力工具,使用时无需密码登录,直接输入qq号码即可,支持微信账号,每提交一次可以刷99分钟的听歌时长,实时到账,刷的听歌时长可以增加听歌排行榜跟音响力(就是QQ音…

辅助笔记-安装Ubantu20.04.1虚拟机

安装Ubantu20.04.1虚拟机 文章目录 安装Ubantu20.04.1虚拟机步骤一:检查BIOS虚拟化支持步骤二:VMware17安装虚拟机步骤1:新建虚拟机步骤2:验证虚拟机能否上网 步骤三:设置Ubantu语言为中文步骤四:软件仓库镜…

江西景德镇陶瓷三维扫描工艺品瓷器数字化3D打印-CASAIM中科广电

江西景德镇陶瓷是中国著名的传统陶瓷产地,其瓷器作为文化遗产具有重要的历史和艺术价值。对于陶瓷工艺品瓷器的三维扫描和数字化,利用三维激光扫描和3D打印相结合的方式助力文物数字化及复原领域是目前主流的发展趋势。 1. 三维激光扫描操作:…

编织梦想:SpringBoot AOP 教程与自定义日志切面完整实战

什么是 AOP AOP 是指通过预编译方式和运行期动态代理的方式,在不修改源代码的情况下对程序进行功能增强的一种技术。AOP 不是面向对象编程(OOP)的替代品,而是 OOP 的补充和扩展。它是一个新的维度,用来表达横切问题&a…