您尚未登录。

#1 2021-02-23 11:20:42

qianfan
会员
注册时间: 2019-11-29
累计积分: 11

全志平台使用jlink调试vmlinux内核程序

硬件平台: 全志R40 + JLinkV9
软件工具: sunxi-tools, JLinkExe, JLinkGdbServer, arm-linux-gnueabihf-gcc, arm-linux-gnueabihf-gdb
程序源码:
2021.01-rc1-14752-gcdeb7b8f98-dirty 
Linux OrangePi_One 5.11.0-40525-g77cdf1d653ba-dirty


一. 使用sunxi-tools构建可从ram启动的系统

使用sunxi-tools将编译后的引导, 内核, dtb, 根文件系统通过usb下载至内存中, 等待u-boot启动之后, 按任意按键进入u-boot控制台, 之后输入bootz命令可以启动linux系统. 免去烧写镜像的过程. 使用的uInitrd可以从https://whycan.com/files/members/2542/uInitrd_20210223-1517.zip中下载.

#!/bin/bash

BOARD=r40
UBOOT=~/debug/port/github-os/u-boot-${BOARD}
LINUX=~/debug/port/github-os/linux-${BOARD}/arch/arm/boot
DTS=${LINUX}/dts/sun8i-r40-bananapi-m2-ultra.dtb

sunxi-fel -p uboot ${UBOOT}/u-boot-sunxi-with-spl.bin write 0x42000000 ${LINUX}/zImage write 0x43000000 ${DTS} write 0x43300000 ./ramdisk/uInitrd

echo "Input this command in u-boot shell to boot linux kernel:"
echo "bootz 42000000 43300000 43000000"
$ sudo ./start_r40_live.sh
[sudo] password for qianfan:
100% [================================================]  4688 kB,  352.0 kB/s
100% [================================================]    24 kB,  343.7 kB/s
100% [================================================]  5044 kB,  349.3 kB/s
Input this command in u-boot shell to boot linux kernel:
bootz 42000000 43300000 43000000

(测试发现, R40使用sunxi-fel下载镜像速度比H3慢很多. H3可以达到接近1M的速度)



二: 使用tf卡转接板从MMC0(PF0-PF5)接口上引出JTAG并连接至JLink. 按下RPI M2U的boot按键进入fel模式. 使用JLinkExe程序测试硬件连接.
正常的话可以读取到芯片的信息.

Type "connect" to establish a target connection, '?' for help
J-Link>connect
Please specify device / core. <Default>: CORTEX-A7
Type '?' for selection dialog
Device>
Please specify target interface:
  J) JTAG (Default)
  S) SWD
  T) cJTAG
TIF>
Device position in JTAG chain (IRPre,DRPre) <Default>: -1,-1 => Auto-detect
JTAGConf>
Specify target interface speed [kHz]. <Default>: 4000 kHz
Speed>
Device "CORTEX-A7" selected.


Connecting to target via JTAG
TotalIRLen = 4, IRPrint = 0x01
JTAG chain detection found 1 devices:
 #0 Id: 0x5BA00477, IRLen: 04, CoreSight JTAG-DP
DPv0 detected
Scanning AP map to find all available APs
AP[2]: Stopped AP scan as end of AP map has been reached
AP[0]: AHB-AP (IDR: 0x64770001)
AP[1]: APB-AP (IDR: 0x44770002)
Iterating through AP map to find APB-AP to use
AP[0]: Skipped. Not an APB-AP
AP[1]: APB-AP found
ROMTbl[0][0]: CompAddr: 80001000 CID: 00000000, PID: 00000000 ???
ROMTbl[0][1]: CompAddr: 80100000 CID: B105100D, PID: 000BB4A7 ROM Table
ROMTbl[1][0]: CompAddr: 80110000 CID: B105900D, PID: 005BBC07 Cortex-A7
Found Cortex-A7 r0p5
6 code breakpoints, 4 data breakpoints
Debug architecture ARMv7.1
Data endian: little
Main ID register: 0x410FC075
I-Cache L1: 32 KB, 512 Sets, 32 Bytes/Line, 2-Way
D-Cache L1: 32 KB, 128 Sets, 64 Bytes/Line, 4-Way
Unified-Cache L2: 512 KB, 1024 Sets, 64 Bytes/Line, 8-Way
System control register:
  Instruction endian: little
  Level-1 instruction cache disabled
  Level-1 data cache disabled
  MMU disabled
  Branch prediction enabled
Memory zones:
  Zone: Default Description: Default access mode
  Zone: AHB-AP (AP0) Description: DMA like acc. in AP0 addr. space
  Zone: APB-AP (AP1) Description: DMA like acc. in AP1 addr. space
Cortex-A7 identified.
J-Link>

三: 修改代码保留JTAG功能

u-boot及内核启动之后, 会配置MMC0的引脚, 复用为MMC功能. 需要禁用相关代码以保证JTAG功能呢可用.

u-boot:
禁用CONFIG_MMC和CONFIG_CMD_MMC
linux: 在dts中禁用mmc0

diff --git a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
index a7aa8112433a..68ffa2e48658 100644
--- a/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
+++ b/arch/arm/boot/dts/sun8i-r40-bananapi-m2-ultra.dts
@@ -175,21 +175,21 @@
 #include "axp22x.dtsi"

 &ir0 {
        status = "okay";
 };

 &mmc0 {
        vmmc-supply = <&reg_dcdc1>;
        bus-width = <4>;
        cd-gpios = <&pio 7 13 GPIO_ACTIVE_LOW>; /* PH13 */
-       status = "okay";
+       status = "disabled";
 };

 &mmc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pg_pins>;
        vmmc-supply = <&reg_dldo2>;
        vqmmc-supply = <&reg_dldo1>;
        mmc-pwrseq = <&wifi_pwrseq>;
        bus-width = <4>;
        non-removable;

四: 配置linux内核以增加调试信息

在menuconfig中勾上这些选项:
CONFIG_DEBUG_INFO=y
CONFIG_GDB_SCRIPTS=y
CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_VM=y

五: 启动系统并停留在u-boot控制台中.
(不要输入bootz命令, 仅停留在控制台中, 等待JLink连接. 参考步骤一)

六: 在u-boot停留在控制台中时, 使用JLinkGdbServer连接芯片

➜  ~ JLinkGDBServer -device CORTEX-A7 -if jtag -speed 2000
SEGGER J-Link GDB Server V6.92 Command Line Version

JLinkARM.dll V6.92 (DLL compiled Dec 18 2020 14:10:53)

Command line: -device CORTEX-A7 -if jtag -speed 2000
-----GDB Server start settings-----
GDBInit file:                  none
GDB Server Listening port:     2331
SWO raw output listening port: 2332
Terminal I/O port:             2333
Accept remote connection:      yes
Generate logfile:              off
Verify download:               off
Init regs on start:            off
Silent mode:                   off
Single run mode:               off
Target connection timeout:     0 ms
------J-Link related settings------
J-Link Host interface:         USB
J-Link script:                 none
J-Link settings file:          none
------Target related settings------
Target device:                 CORTEX-A7
Target interface:              JTAG
Target interface speed:        2000kHz
Target endian:                 little

Connecting to J-Link...
J-Link is connected.
Firmware: J-Link V9 compiled Dec 13 2019 11:14:50
Hardware: V9.30
S/N: 36310083
Feature(s): RDI, GDB, FlashDL, FlashBP, JFlash
Checking target voltage...
Target voltage: 3.31 V
Listening on TCP/IP port 2331
Connecting to target...

J-Link found 1 JTAG device, Total IRLen = 4
JTAG ID: 0x5BA00477 (Cortex-A7)
Connected to target
Waiting for GDB connection...

七: 启动arm gdb, 并连接到JLinkGdbServer的端口2331

➜  linux git:(sun8i-r40-usb-otg) ✗ arm-linux-gnueabihf-gdb vmlinux
GNU gdb (Linaro_GDB-2019.12) 8.3.1.20191204-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

连接成功之后, 使用target命令连接远程端口, 并在start_kernel上面打上断点. 此时CPU已经halt. 需要使用continue命令继续运行u-boot.

(gdb) tar extended-remote :2331
Remote debugging using :2331
0xbffa4740 in ?? ()
(gdb) b start_kernel
Breakpoint 1 at 0xc0b0093c: file init/main.c, line 850.
(gdb) c
Continuing.

八: 启动linux内核.

在u-boot控制台中输入bootz 42000000 43300000 43000000命令以启动内核. 启动之后gdb停在start_kernel函数中, 之后可以单步调试.

Breakpoint 1, start_kernel () at init/main.c:850
850     {
(gdb) n
854             set_task_stack_end_magic(&init_task);
(gdb)
850     {
(gdb)
854             set_task_stack_end_magic(&init_task);
(gdb)
855             smp_setup_processor_id();
(gdb)
858             cgroup_init_early();
(gdb)
860             local_irq_disable();
(gdb)

九: 部分函数设置断点无法进入

使用该方法调试内核时, 发现只能停在start_kernel中, 在驱动中打断点无法进入. 经过探索, 发现是多核引起的. 在menuconfig中关掉CONFIG_SMP并重新编译内核, 该问题得到解决.

例如: 在gpiolib_seq_show函数中打上断点.

(gdb) b gpiolib_seq_show
Breakpoint 2 at 0xc03ca5f8: file drivers/gpio/gpiolib.c, line 4321.
(gdb) c
Continuing.

在linux控制台中触发:
mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/gpio

断点被gdb捕捉到, 可进行单步调试:

(gdb) i b
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0xc0b0093c in start_kernel at init/main.c:850
        breakpoint already hit 1 time
2       breakpoint     keep y   0xc03ca5f8 in gpiolib_seq_show at drivers/gpio/gpiolib.c:4321
(gdb) c
Continuing.

Breakpoint 2, gpiolib_seq_show (s=0xc1bd3000, v=0xc1835800) at drivers/gpio/gpiolib.c:4321
4321    {
(gdb) n
4323            struct gpio_chip *gc = gdev->chip;
(gdb)
4321    {
(gdb)
4326            if (!gc) {
(gdb)
4334                       gdev->base, gdev->base + gdev->ngpio - 1);
(gdb)
4332            seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private,
(gdb)
4334                       gdev->base, gdev->base + gdev->ngpio - 1);
(gdb)
4332            seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private,
(gdb) p s
$1 = (struct seq_file *) 0xc1bd3000
(gdb) n
4334                       gdev->base, gdev->base + gdev->ngpio - 1);
(gdb)
4332            seq_printf(s, "%s%s: GPIOs %d-%d", (char *)s->private,
(gdb)
4335            parent = gc->parent;
(gdb) bt
#0  gpiolib_seq_show (s=0xc1bd3000, v=0xc1835800) at drivers/gpio/gpiolib.c:4335
#1  0xc02217fc in seq_read_iter (iocb=0xc1bf3e88, iocb@entry=0xc1bf3e80, iter=0xc0c043bc <totalreserve_pages>,
    iter@entry=0xc1bf3e68) at fs/seq_file.c:227
#2  0xc0221ce0 in seq_read (file=file@entry=0xc1bfe840,
    buf=buf@entry=0xbee4ec58 <error: Cannot access memory at address 0xbee4ec58>, size=size@entry=4096,
    ppos=ppos@entry=0xc1bf3f78) at fs/seq_file.c:159
#3  0xc03383b4 in full_proxy_read (filp=filp@entry=0xc1bfe840,
    buf=buf@entry=0xbee4ec58 <error: Cannot access memory at address 0xbee4ec58>, size=size@entry=4096,
    ppos=ppos@entry=0xc1bf3f78) at fs/debugfs/file.c:229
#4  0xc01fcf60 in vfs_read (file=0xc1bfe840, buf=0xbee4ec58 <error: Cannot access memory at address 0xbee4ec58>,
    count=<optimized out>, pos=0xc1bf3f78) at fs/read_write.c:494
#5  0xc01fd5d4 in ksys_read (fd=<optimized out>, buf=0xbee4ec58 <error: Cannot access memory at address 0xbee4ec58>,
    count=4096) at fs/read_write.c:634
#6  0xc0100060 in cpu_v7_reset () at arch/arm/mm/proc-v7.S:64
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)

最近编辑记录 qianfan (2021-02-23 15:20:01)

离线

#2 2021-02-24 09:34:43

dso_2019
会员
注册时间: 2019-10-13
累计积分: 32

Re: 全志平台使用jlink调试vmlinux内核程序

大神 能在IDE下进行调试吗

离线

页脚

工信部备案:粤ICP备20025096号 Powered by FluxBB

感谢为中文互联网持续输出优质内容的各位老铁们。 QQ: 516333132, 微信(wechat): whycan_cn (哇酷网/挖坑网/填坑网) service@whycan.cn