0 开发环境
- 笔记本:ubuntu18.04.5,内核版本为5.3
- 开发板:imx8mp-evk
- 内核版本:Linux5.4.24
- 交叉编译工具链:fsl-imx-xwayland-glibc-x86_64-imx-image-core-aarch64-imx8mpevk-toolchain-5.4-zeus.sh
注:下面的可能会遗漏部分细节,但主要的部分基本都写出来了,应该无大碍。
注:以下步骤虽然针对的imx8mp-evk,但只要是aarch64架构的芯片,大部分操作都通用的。
注:这是个人的踩坑记录,虽然可以解决问题,但估计不是最好的解决方案,欢迎评论区一起探讨。
1 完善被调试终端的KGDB
远端的 gdb 连上 linux 的 kgdb 之后,在断点处执行单步调式(step/next)的时候,调式器并不是执行断点处的语句,而是每次都陷入到下面的代码段:
arch/arm64/kernel/entry.S:356
el1_irq:
kernel_entry 1
enable_dbg
社区也有人碰到这个问题,并提交了如下 patch 来修复这个问题。这个问题并不是在所有的 arm64 平台上都会碰到,patch 还在讨论并没有合进 upstream,Patch 如下:
[v3,2/4] arm64: kgdb: disable interrupts while a software step is enabled
注:至少我在Linux5.4.24中发现并没有解决这个问题,更不用说大部分嵌入式板子还用的4.x的内核。
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index b9176b324e5a..fddbc6be3780 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -28,6 +28,7 @@
#include <asm/debug-monitors.h>
#include <asm/insn.h>
+#include <asm/ptrace.h>
#include <asm/traps.h>
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
@@ -111,6 +112,8 @@ struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
{ "fpcr", 4, -1 },
};
+static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
+
char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs)
{
if (regno >= DBG_MAX_REG_NUM || regno < 0)
@@ -200,6 +203,10 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
err = 0;
break;
case 's':
+ /* mask interrupts while single stepping */
+ __this_cpu_write(kgdb_pstate, linux_regs->pstate);
+ linux_regs->pstate |= PSR_I_BIT;
+
/*
* Update step address value with address passed
* with step packet.
@@ -242,11 +249,20 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
{
+ unsigned int pstate;
+
if (!kgdb_single_step)
return DBG_HOOK_ERROR;
kernel_disable_single_step();
+ /* restore interrupt mask status */
+ pstate = __this_cpu_read(kgdb_pstate);
+ if (pstate & PSR_I_BIT)
+ regs->pstate |= PSR_I_BIT;
+ else
+ regs->pstate &= ~PSR_I_BIT;
+
kgdb_handle_exception(1, SIGTRAP, 0, regs);
return 0;
}
2 配置内核
2.1 构建开发环境
source /opt/fsl-imx-xwayland/5.4-zeus/environment-setup-aarch64-poky-linux
make imx_v8_defconfig
make menuconfig
如果在make menuconfig
出现如下问题,具体解决方案可以看,我就不在这里多费口舌了。
HOSTLD scripts/kconfig/mconf
/usr/bin/ld: cannot find -lncursesw
collect2: error: ld returned 1 exit status
scripts/Makefile.host:116: recipe for target 'scripts/kconfig/mconf' failed
make[1]: *** [scripts/kconfig/mconf] Error 1
Makefile:567: recipe for target 'menuconfig' failed
make: *** [menuconfig] Error 2
注:source /opt/fsl-imx-xwayland/5.4-zeus/environment-setup-aarch64-poky-linux
为我yocto编译下载后的交叉编译工具链的安装位置
2.2设置内核选项
配置内核KGDB选项
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809104233327.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
配置dwmac-imx编译为模块
注:这个是我用于调试的模块,其他模块类似的操作
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020080910472922.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
2.3 修改对应模块的优化等级
stmac目录下的Makefile添加如下编译优化等级
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020080910494138.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
O1优化等级会出现如下小问题,不过还好,凑活着用
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809105057940.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
我想修改为O0,但是编译不成功,只能用O1了
注:这个地方因勉强可以用,就没有深究下去
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809105129453.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
2.4 内核编译
make -j 8
3 代码修改记录总计
<sazczmh 10:27:28@linux-imx>$git log --stat -p
commit 56e89cdadaac0ded943486912afc135b7dc46cf5 (HEAD -> imx_5.4.24_2.1.0)
Author: sazczmh <zmhzc@tju.edu.cn>
Date: Sat Aug 8 10:24:36 2020 +0800
Modify the dwmac module compilation aptimization level to O1
---
drivers/net/ethernet/stmicro/stmmac/Makefile | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 413d2104948d..91d55b92ce88 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
-# Modify the module compilation aptimization level to O0
-EXTRA_CFLAGS += -O0
+# Modify the module compilation aptimization level to O1
+EXTRA_CFLAGS += -O1
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
commit 550c7b51c425418b8122a834e5236592537a22f9
Author: sazczmh <zmhzc@tju.edu.cn>
Date: Sat Aug 8 09:43:29 2020 +0800
Modify the code warning!
---
arch/arm64/kernel/kgdb.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index dfe6ffcd71f6..52f5010c1166 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -269,7 +269,7 @@ static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
else
regs->pstate &= ~PSR_I_BIT;
- kgdb_handle_exception(1, SIGTRAP, 0, regs);
+ kgdb_handle_exception(1, SIGTRAP, 0, regs);
return DBG_HOOK_HANDLED;
}
NOKPROBE_SYMBOL(kgdb_step_brk_fn);
commit c92c9abd0aebdc70f9a97f670cfa61cc1fa8e96e
Author: sazczmh <zmhzc@tju.edu.cn>
Date: Sat Aug 8 09:35:38 2020 +0800
To reduce unnecessary compilation warnings, only module compilation optomization level is O0
---
Makefile | 2 +-
drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/Makefile b/Makefile
index 02191761c23f..c32c78cf2fe5 100644
--- a/Makefile
+++ b/Makefile
@@ -700,7 +700,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member)
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
-KBUILD_CFLAGS += -O1
+KBUILD_CFLAGS += -O2
else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3
KBUILD_CFLAGS += -O3
else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index ae223ec1b754..413d2104948d 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -1,4 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
+# Modify the module compilation aptimization level to O0
+EXTRA_CFLAGS += -O0
+
obj-$(CONFIG_STMMAC_ETH) += stmmac.o
stmmac-objs:= stmmac_main.o stmmac_ethtool.o stmmac_mdio.o ring_mode.o \
chain_mode.o dwmac_lib.o dwmac1000_core.o dwmac1000_dma.o \
commit 11eb493c15b271f00d982985dedca75e98145734
Author: sazczmh <zmhzc@tju.edu.cn>
Date: Sat Aug 8 09:21:53 2020 +0800
arm64, kgdb debug: Disable interrupts while a software step is enable
---
arch/arm64/kernel/kgdb.c | 23 ++++++++++++++++++++---
1 file changed, 20 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kernel/kgdb.c b/arch/arm64/kernel/kgdb.c
index 43119922341f..dfe6ffcd71f6 100644
--- a/arch/arm64/kernel/kgdb.c
+++ b/arch/arm64/kernel/kgdb.c
@@ -19,6 +19,11 @@
#include <asm/insn.h>
#include <asm/traps.h>
+#include <asm/ptrace.h>
+
+static DEFINE_PER_CPU(unsigned int, kgdb_pstate);
+
+
struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = {
{ "x0", 8, offsetof(struct pt_regs, regs[0])},
{ "x1", 8, offsetof(struct pt_regs, regs[1])},
@@ -206,7 +211,10 @@ int kgdb_arch_handle_exception(int exception_vector, int signo,
err = 0;
break;
case 's':
- /*
+
+ __this_cpu_write(kgdb_pstate, linux_regs->pstate);
+ linux_regs->pstate |= PSR_I_BIT;
+ /*
* Update step address value with address passed
* with step packet.
* On debug exception return PC is copied to ELR
@@ -249,8 +257,17 @@ NOKPROBE_SYMBOL(kgdb_compiled_brk_fn);
static int kgdb_step_brk_fn(struct pt_regs *regs, unsigned int esr)
{
- if (!kgdb_single_step)
- return DBG_HOOK_ERROR;
+ unsigned int pstate;
+
+ if (!kgdb_single_step)
+ return DBG_HOOK_ERROR;
+ kernel_disable_single_step();
+
+ pstate = __this_cpu_read(kgdb_pstate);
+ if (pstate & PSR_I_BIT)
+ regs->pstate |= PSR_I_BIT;
+ else
+ regs->pstate &= ~PSR_I_BIT;
kgdb_handle_exception(1, SIGTRAP, 0, regs);
return DBG_HOOK_HANDLED;
这个是截图,比较好看些
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809105836142.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809105819898.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
4 文件共享
开发板与PC的文件传输是通过NFS,方便进行开发,具体可以参考【Linux笔记】挂载网络文件系统
我的共享文件夹为~/imx8mp_evk_nfs/
,共享模块文件,使用如下命令即可,比较方便
cp ~/linux-imx/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.ko ~/imx8mp_evk_nfs/
注:文件夹挂载之前不要在这个文件夹,否则会没法刷新cd /;cd /mnt
即可解决。
注:我的配置环境是开发板与PC的网络是通过一个路由器进行通信的,网线直连会有所不同。
5 串口复用
为了调试方便使用agent-proxy即可,需要进行编译安装
使用如下命令可以将ttyUSB2复用为两个端口,方便调试。
./agent-proxy 5550^5551 0 /dev/ttyUSB2,115200 -s003
其中一个可以用如下命令连接开发板,与板子进行通信
telnet localhost 5550
另一个端口用于KGDB调试使用
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809112529385.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
注:这个具体原理我没有深究,大概就是将串口的读取发送数据,通过localhost虚拟出来两个端口来进行使用,很容易上手。
注:这个/dev/ttyUSB2
需要具体情况具体设置,对于imx8mp来说是从USB插入开始,识别的第三个串口,具体可以用demsg
查看
6 GDB优化
Ubuntu18自带的GDB不太好使,调试不方便,需要gdb的界面增强版CGDB,增加了语法高亮等一系列小功能,可以提高调试效率。
使用如下命令即可进行安装
sudo apt install cgdb
下面是我cgdb的调试界面,相对于默认的gdb单色调试界面,这个语法高亮非常实用。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200809112644253.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70)
注:我也尝试使用eclipse进行调试,可是存在着一些问题,因此就先不说那个了。
7 开发板配置
开发板的连接是通过如下命令进行的
./agent-proxy 5550^5551 0 /dev/ttyUSB2,115200 -s003
telnet localhost 5550
使用如下命令即可进入gdb命令行,然后再执行kgdb
即可等待主机的连接
mount -t nfs -o nolock,vers=4 192.168.3.5:/home/sazczmh/imx8mp_evk_nfs /mnt
echo ttymxc1 > /sys/module/kgdboc/parameters/kgdboc
echo g > /proc/sysrq-trigger
注:这个192.168.3.5:/home/sazczmh/imx8mp_evk_nfs
为我的主机共享文件夹,IP以及目录需要根据具体情况进行修改。
注:ttymxc1为imx8mp的调试串口,不同的把板子可能需要进行相应的修改。
8 主机配置
执行如下命令解析vmlinux,准备开始调试
cd ~/linux-imx
cgdb -d gdb-multiarch vmlinux
设置架构为aarch64,再加载被调试模块的信息
set architecture aarch64
add-symbol-file drivers/net/ethernet/stmicro/stmmac/dwmac-imx.ko 0xffff8000090a0000
注:set architecture aarch64
的目的是防止出现Remote ‘g’ packet reply is too long (expected 168 bytes, got 788 bytes)这个错误,也可以利用交叉编译工具链的gdb工具,就不会出现这个问题,后续文章会略有涉及。
注:0xffff8000090a0000这个可以提前通过insmod
加载对应模块,再通过cat /proc/modules
可以查看,查看之后注意要卸载rmmod。
现在要连接开发板,设置对应的断点,c
开始执行调试
target remote localhost:5551
b stmmac_dvr_probe
c
开发板同时要加载模块,触发断点,就可以进行单步调试了。
参考博客
注:个人能力有限,欢迎批评指正。
原创不易,严禁剽窃!
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190918110341834.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM1NzEyMTY5,size_16,color_FFFFFF,t_70#pic_center)
欢迎大家关注我创建的微信公众号——小白仓库
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。