STM32高级开发(11)-使用GDB调试你的工程

2019-07-19来源: eefocus关键字:STM32  高级开发  GDB调试  工程

在GNU编译器中,GDB无疑起着无足轻重的位置,常言有道:写工程3分靠写,7分靠调。GDB作为GNU编译器下的标准调试工具,在我们的项目编写即调试过程中会被平凡的使用到。而由于我们在IDE环境下娇生惯养出来的习惯,我们可能不太容易上手一个用命令行为主要操作和显示形式的调试器。所以在这篇中我们会为大家详细的讲解GDB工具的使用,来让大家快速的入门。


怎样启动arm-none-eabi-gdb

之前我们在安装和介绍调试器驱动的时候,曾举过例子,来使用指令开启一个操作接口,用以为gdb程序提供连接。这就是嵌入式GDB的工作方式,详细来说就是,使用调试器的驱动软件指令将调试器连接目标板,并将驱动软件的GDB指令接口开启在一个设定的计算机端口(此处的端口为计算机本地的网络端口)上,一般OpenOCD的默认端口是3333。在调试器驱动启动端口后,我们开启GDB软件连接本地的调试器端口,就可以开始调试了。了解了它的工作,我们下面就用一个具体的例子来讲解。


首先我们将调试器与目标板以及计算机之间的线连接好(此处默认调试器为st-link、对于其他调试器只要稍微更改OpenOCD的启动配置文件就可),并将st-link的接口设置到虚拟机上。随后我们通过OpenOCD指令连接调试器:


$ openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2.cfg -f /usr/local/share/openocd/scripts/target/stm32f4x_stlink.cfg

这里写图片描述

在执行完此条指令后该终端就会一直执行OpenOCD的程序了,不要关闭它,我们再打开一个终端界面,进入我们的工程目录,比如我这里进入的就是我的libopencm3样例工程下的blink子工程目录。


$ cd '/home/yangliu/workspace/libopencm3-my-example/blink'


然后我们使用指令输入调试文件并打开GDB程序。


$ arm-none-eabi-gdb blink.elf 


这里写图片描述

然后我们在GDB的指令界面中,输入连接指令,连接本地的3333端口。


(gdb)target remote localhost:3333


此时我们就将GDB与调试器接上了,运行OpenOCD的终端也会显示收到连接信息。


这里写图片描述


不过我们还没有完成所有的初始操作,此时我们需要输入指令来复位、停止MCU并加载elf文件:


(gdb)monitor reset

(gdb)monitor halt 

(gdb)load


这里 monitor意为这向连接的外部软件发送指令,此处即向OpenOCD发送指令,因为reset halt等指令不是GDB的内部指令,而是OpenOCD的指令。随后的load指令会将启动时输入GDB的elf文件加载入MCU,即下载到MCU的flash。


这里写图片描述


到这里我们的所有GDB连接的初始操作就完成了,当然我们不仅可以使用OpenOCD启动调试端口,st-link的驱动也也可以,使用指令:st-util就可以启动它,不过st-link驱动默认的端口是4242。


arm-none-eabi-gdb的调试指令

在我们将elf调试文件加载到MCU中后,我们就可以进行调试操作了。首先来介绍一下GDB调试的基本指令:


l,list指令的缩写,意为列出当前执行的源代码。同时输入指令后重复按回车等效于再次输入上次的指令。 

这里写图片描述


c ,continue的缩写,在嵌入式GDB中我们不能使用RUN指令来运行代码,相应的我们需要continue指令来运行。


b ,break缩写,用于在程序中打断点,使用方式有很多种


b 16,在当前低16行代码出加断点。


b i=1,当i等于1时停止,类似于这种条件式断点的方式也是GDB独有的一种强大功能。


b main,在main函数的入口打断点。


i b ,info break缩写,显示当前设置的断点信息。如下面这个查到了在main函数处有两个断点,序号分别为1 和 2。 


这里写图片描述

d break ,delet break 缩写,删除所有断点


d break 1 ,删除序号为1的断点


s,step缩写,会进入子函数的单步运行


n,next缩写,即会跳过子函数的单步运行


u,until缩写使用时后方加行号如: u 16 即运行到第16行


finish,完成并跳出当前的子函数


p,print缩写,使用时后面加变量名称如:p tmp ,用来显示变量数值


display ,使用时后面加变量名称如:display tmp ,用于跟踪变量数值,在每次执行停下时会自动显示变量数值。


bt,查看堆栈


q/Ctrl+d,使用q即quit指令或快捷键Ctrl+d来正常退出GDB


在GDB中其实还有很多的指令及指令特性我没有介绍到,但是我们常用的也就是这几条,更多的大家可以自己去百度或查看GDB的PDF说明文档来了解使用。


开启GDB的黑魔法

开启GDB的GUI调试

我们上面介绍了GDB的指令行操作模式,虽然在指令行下增加了强大的条件断点的功能,但是也显然的对代码调试我们不能实时的看到他的执行多少有些不便,那么下面我就来介绍开启GDB的GUI调试的隐藏模式吧~


在GDB的指令窗口我们输入


(gdb)-


对就是一个 减号,然后回车我们来见证奇迹的时刻~


这里写图片描述


刷新世界观有没有~,然后我们就愉快的调试吧~。


快速开启并配置GDB调试

上面我们介绍了GDB通过计算机本地端口链接调试器驱动软件的方式,无疑开启两个终端并输入一大堆的连接和加载指令是很不方便的,有没有什么会计的方式的,那答案必然是肯定的。


其实除了通过端口链接,GDB与调试器还可以通过系统标准管道链接,下面是一段我从上篇中提到的,我的libopencm3工程中rules.mk文件中截取的片段:


%.debug: %.elf

    @printf "  GDB DEBUG $

    $(Q)$(GDB) -iex 'target extended | $(OOCD) $(OOCDFLAGS) -c "gdb_port pipe"'

    -iex 'monitor reset halt' -ex 'load' -ex 'break main' -ex 'c' $(*).elf


在这里我们通过 -c gdb_port pipe来快速启动OpenOCD并与GDB连接,同时在main函数打断点并执行到main处。具体这里的参数输入的方式和意义大家可以查询GDB的说明书,这里就不做太多的解释了,大家想要改写为自己的应用时只需要将其中和工程相关的参数 elf 文件,的名称修改就可以了,(这里-iex 参数前缀是GDB的指令,意为在执行GDB本体调试程序前先执行-iex 后引号中的外部指令)。


总结

在这篇中我们介绍了GDB的使用方式,同时也解答了上篇中留下的问题,样例makefile中的 debug 功能是怎样实现的。


不过在调试中需要注意的是,如果我们不在程序中添加断点或在continue指令后的代码不存在断点,程序就会一直跑下去,而我们的GDB指令窗口也不会响应再输入的指令,此时我们就需要按动开发板上的reset复位按键才可以使得GDB再次响应操作。


如果我们没有使用指令或快捷键正常退出GDB窗口,可能会造成终端锁定socket端口,从而在这个终端被关闭以前,我们将无法再次链接调试器,此时我们只要关闭输错的终端,再重新打开一个就可以了。


关键字:STM32  高级开发  GDB调试  工程 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic468597.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32F4标准外设库模板工程建立与使用
下一篇:关于ST-Link的internal command error问题的解决方法

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32流水灯(基于库函数)
,GPIO_Pin_5);/ /PE.5 输出高}该代码里面就包含了一个函数 void LED_Init(void),该函数的功能就是用来实现配置 PB5和 PE5 为推挽输出。 这里需要注意的是: 在配置 STM32 外设的时候,任何时候都要先使能该外设的时钟。 GPIO 是挂载在 APB2 总线上的外设, 在固件库中对挂载在 APB2 总线上的外设时钟使能是通过函数 RCC_APB2PeriphClockCmd()来实现的。LED.h程序代码书写#ifndef __LED_H#define __LED_H#include "sys.h"//LED 端口定义#define LED0 PBout
发表于 2019-10-21
stm32入门——跑马灯(基于stm32f103zet6)
的驱动都要使能相应的时钟,首先看stm32系统的时钟框图经查阅资料可知,GPIO的时钟在APB2的外设时钟使能寄存器上,相关函数的定义在stm32f10x_rcc.h中 void   RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)其源代码为:void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState){  /* Check the parameters */ //检查值的有效性&nbs
发表于 2019-10-21
stm32入门——跑马灯(基于stm32f103zet6)
STM32流水灯的几种实现方法
#include “stm32f10x.h”void RCC_Configuration(void);//2void GPIO_Configuration(void);//GPIOvoid Delay(u32 count){u32 i=0;for(;i<count;i++);}int main(void){ RCC_Configuration();//3LED_Init();while(1){GPIO_SetBits(GPIOA,GPIO_Pin_0);//第一灯亮Delay(800000); //延时GPIO_ResetBits(GPIOA,GPIO_Pin_0); //第一灯灭Delay(800000); //延时
发表于 2019-10-21
STM32学习探究:流水灯的实现
流水灯的实现这里我们使用 stm32mini 开发板实现外接流水灯,这里我采用了三个灯(说明问题就可以了)。外接的引脚分别为PA2,PB8,PC13三个引脚,在连接的时候,采用灯的正极接GPIO引脚,负极接GND(这是一种合理的方式)。注意:虽然接VCC也可以发光,但是这样不是合理的连接方式,而且,发光的情况刚好与接GND的情况相反。参考的相关资料如下:时钟使能:端口配置:端口输出:具体实现的代码如下://led.h文件#ifndef __LED_H#define __LED_H  #include "sys.h"//LED端口定义#define LED0 PAout(2)#define LED1
发表于 2019-10-21
STM32学习探究:流水灯的实现
STM32学习探究:流水灯的实现
流水灯的实现这里我们使用 stm32mini 开发板实现外接流水灯,这里我采用了三个灯(说明问题就可以了)。外接的引脚分别为PA2,PB8,PC13三个引脚,在连接的时候,采用灯的正极接GPIO引脚,负极接GND(这是一种合理的方式)。注意:虽然接VCC也可以发光,但是这样不是合理的连接方式,而且,发光的情况刚好与接GND的情况相反。参考的相关资料如下:时钟使能:端口配置:端口输出:具体实现的代码如下://led.h文件#ifndef __LED_H#define __LED_H  #include "sys.h"//LED端口定义#define LED0 PAout(2) #define LED1
发表于 2019-10-21
STM32学习探究:流水灯的实现
STM32流水灯的几种实现方法
#include “stm32f10x.h”void RCC_Configuration(void);//2void GPIO_Configuration(void);//GPIOvoid Delay(u32 count){u32 i=0;for(;i<count;i++);}int main(void){ RCC_Configuration();//3LED_Init();while(1){GPIO_SetBits(GPIOA,GPIO_Pin_0);//第一灯亮 Delay(800000); //延时 GPIO_ResetBits(GPIOA,GPIO_Pin_0); //第一灯灭 Delay(800000); //延时
发表于 2019-10-21
小广播
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved