0 开发环境
1 完善被调试终端的KGDB
2 配置内核
2.1 构建开发环境
2.2设置内核选项
2.3 修改对应模块的优化等级
2.4 内核编译
3 代码修改记录总计
4 文件共享
5 串口复用
6 GDB优化
7 开发板配置
8 主机配置
参考博客
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 如下:
https://patchwork.kernel.org/patch/9741897/
注:至少我在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 debug-monitors.h>#include +#include ptrace.h>#include 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
出现如下问题,具体解决方案可以看,我就不在这里多费口舌了。
/usr/bin/ld: cannot find -lxxx的解决办法:https://www.cnblogs.com/zhming26/p/6164131.html
关于curses、ncurses、ncursesw区别及安装方法:https://blog.csdn.net/u013590407/article/details/79119377
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选项
![1a64ff7e43d49eff2dbbc5d2a0693d0f.png](https://i-blog.csdnimg.cn/blog_migrate/45ed76e65019835d4125df385bf650c9.png)
配置dwmac-imx编译为模块
注:这个是我用于调试的模块,其他模块类似的操作
![d1460843ea12104d75ef85a52ffe4f75.png](https://i-blog.csdnimg.cn/blog_migrate/a697fb7e77ba95248f9961735cb948ce.png)
2.3 修改对应模块的优化等级
stmac目录下的Makefile添加如下编译优化等级
![987bd53dacbac425a90ceece64db1c8b.png](https://i-blog.csdnimg.cn/blog_migrate/e99c295759f96aeda6bbd1bee41d08c9.png)
O1优化等级会出现如下小问题,不过还好,凑活着用
![2e8516ed54ff1a5bf9e64681da440582.png](https://i-blog.csdnimg.cn/blog_migrate/7891688849fcd3341a75be8fa59b73e5.png)
我想修改为O0,但是编译不成功,只能用O1了 注:这个地方因勉强可以用,就没有深究下去
![849ff643d2a171830fc015e6cefc1e28.png](https://i-blog.csdnimg.cn/blog_migrate/4a1ac3697894495739c3d2ad79abe2e8.png)
2.4 内核编译
make -j 8
3 代码修改记录总计
$git log --stat -p
commit 56e89cdadaac0ded943486912afc135b7dc46cf5 (HEAD -> imx_5.4.24_2.1.0)
Author: sazczmh
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
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
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 += -O2else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3KBUILD_CFLAGS += -O3else 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
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 #include
+#include
+
+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;
这个是截图,比较好看些
![734327dff561cef6cdf076bf24b665d1.png](https://i-blog.csdnimg.cn/blog_migrate/d6bc32168367e0e91c63f820a3b4dab7.png)
![1216ee7cb4896b26dc96632b84cc61f4.png](https://i-blog.csdnimg.cn/blog_migrate/af01b2b38e3d300c781b0f59caaaf09d.png)
4 文件共享
开发板与PC的文件传输是通过NFS,方便进行开发,具体可以参考
【Linux笔记】挂载网络文件系统:https://zhuanlan.zhihu.com/p/109222258
我的共享文件夹为~/imx8mp_evk_nfs/
,共享模块文件,使用如下命令即可,比较方便
cp ~/linux-imx/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.ko ~/imx8mp_evk_nfs/
注:文件夹挂载之前不要在这个文件夹,否则会没法刷新cd /;cd /mnt
即可解决。
注:我的配置环境是开发板与PC的网络是通过一个路由器进行通信的,网线直连会有所不同。
5 串口复用
为了调试方便使用agent-proxy即可,需要进行编译安装
https://git.kernel.org/pub/scm/utils/kernel/kgdb/agent-proxy.git
使用如下命令可以将ttyUSB2复用为两个端口,方便调试。
./agent-proxy 5550^5551 0 /dev/ttyUSB2,115200 -s003
其中一个可以用如下命令连接开发板,与板子进行通信
telnet localhost 5550
另一个端口用于KGDB调试使用
![2edf9d42996cce597a97e40f936c8846.png](https://i-blog.csdnimg.cn/blog_migrate/841a8329bc5de543f8837a932e0de980.png)
注:这个具体原理我没有深究,大概就是将串口的读取发送数据,通过localhost虚拟出来两个端口来进行使用,很容易上手。
注:这个/dev/ttyUSB2
需要具体情况具体设置,对于imx8mp来说是从USB插入开始,识别的第三个串口,具体可以用demsg
查看
6 GDB优化
Ubuntu18自带的GDB不太好使,调试不方便,需要gdb的界面增强版CGDB,增加了语法高亮等一系列小功能,可以提高调试效率。
使用如下命令即可进行安装
sudo apt install cgdb
下面是我cgdb的调试界面,相对于默认的gdb单色调试界面,这个语法高亮非常实用。
![a3c586e8dfeeb6de278e3475c8955e99.png](https://i-blog.csdnimg.cn/blog_migrate/78168852d580e69fe56cfc8161d92b3a.png)
注:我也尝试使用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 /mntecho ttymxc1 > /sys/module/kgdboc/parameters/kgdbocecho 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
开发板同时要加载模块,触发断点,就可以进行单步调试了。
参考博客
ARM64 的 Linux 内核 kgdb/kdb调试 :https://www.byteisland.com/arm64-%E7%9A%84-linux-%E5%86%85%E6%A0%B8-kgdb-kdb-%E8%B0%83%E8%AF%95/这个讲解的很全面具体,本文就是大部分是参考这个文章,然后根据个人需求进行魔改优化的。
GDB调试利器 :https://tutorial.linux.doc.embedfire.com/zh_CN/latest/linux_debug/gdb_use.html从火哥这个文章知道CGDB这个好东西,对于高效率调试非常有帮助,后面还会有关于它的文章。
注:个人能力有限,欢迎批评指正。
原创不易,严禁剽窃!
原创经验资料分享:包含但不仅限于FPGA、ARM、RISC-V、Linux、LabVIEW等软硬件开发,另外分享生活中的趣事以及感悟。目的是建立一个平台记录学习过的知识,并分享出来自认为有用的与感兴趣的道友相互交流进步。
![c52ebb51ef7db5ae8f4e391d096521c4.gif](https://i-blog.csdnimg.cn/blog_migrate/14f8466acf2dbac5ccd8de68861ef1bd.gif)
![7f7d49908635131f3ba5d95a81cb9e17.gif](https://i-blog.csdnimg.cn/blog_migrate/44f827630735bc3b558fe36f86e2fcc6.gif)
![7f7d49908635131f3ba5d95a81cb9e17.gif](https://i-blog.csdnimg.cn/blog_migrate/44f827630735bc3b558fe36f86e2fcc6.gif)
![575b148bdb008ecea5e7a7bba55baea2.gif](https://i-blog.csdnimg.cn/blog_migrate/401ad94695258086f0444bc4ccbbf4c8.gif)