购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.2 搭建树莓派实验环境

熟悉和掌握一个处理器体系结构最有效的方法是多做练习、多做实验。本书采用树莓派4B作为硬件实验平台。

本章需要准备的实验设备如图2.2所示。

●硬件开发平台:树莓派4B开发板。

●处理器体系结构:ARMv8体系结构。

●开发主机:Ubuntu Linux 20.04。

●MicroSD卡一张以及读卡器。

●USB转串口模块。

●杜邦线若干。

●Type-C USB线一根。

●J-Link EDU仿真器 ,如图2.3所示。J-Link EDU是针对高校教育的版本。

▲图2.2 硬件实验平台

▲图2.3 J-Link EDU仿真器

2.2.1 配置串口线

要在树莓派4B上运行实验代码,我们需要一根USB转串口线,这样在系统启动时便可通过串口输出信息来协助调试。读者可从网上商店购买USB转串口线,图2.4所示是某个厂商售卖的一款USB转串口线。串口一般有3根线。另外,串口还有一根额外的电源线(可选)。

▲图2.4 USB转串口线

●电源线(红色 ):5 V或3.3 V电源线(可选)。

●地线(黑色)。

●接收线(白色):串口的接收线RXD。

●发送线(绿色):串口的发送线TXD。

树莓派4B支持包含40个GPIO引脚的扩展接口,这些扩展接口的定义如图2.5所示。根据扩展接口的定义,我们需要把串口的三根线连接到扩展接口,如图 2.6所示。

●地线:连接到第6个引脚。

●RXD线:连接到第8个引脚。

●TXD线:连接到第10个引脚。

在Windows 10操作系统中需要在设备管理器中查看串口号,如图2.7所示。你还需要在Windows 10操作系统中安装用于USB转串口的驱动。

▲图2.5 树莓派扩展接口的定义

▲图2.6 将串口线连接到树莓派扩展接口

▲图2.7 在设备管理器中查看串口号

接上USB电源,在串口终端软件(如PuTTY或MobaXterm等)中查看是否有输出,如图2.8所示。即使没有插入MicroSD卡,串口也能输出信息,如果能看到串口输出信息,那么说明串口设备已经配置。这些信息是树莓派固件输出的。图 2.8 中的日志信息显示系统没有找到MicroSD卡。

▲图2.8 在串口终端软件中查看是否有输出

2.2.2 安装树莓派官方OS

树莓派的映像文件需要安装(烧录)到MicroSD卡里。第一次使用树莓派时,我们先给树莓派安装一个官方的OS——Raspberry Pi OS(简称树莓派OS),用来验证开发板是否正常工作。另外,要在树莓派上运行BenOS,也需要准备一张格式化好的MicroSD卡。格式化的要求如下。

●使用MBR分区表。

●格式化boot分区为FAT32文件系统。

下面是安装树莓派OS的步骤。

(1)到树莓派官方网站上下载ARM64版本的树莓派OS映像文件,例如2021-03-04-raspios-buster-arm64.img。

(2)为了将映像文件烧录到 MicroSD 卡中,将MicroSD卡插入 USB 读卡器。在 Windows 主机上,安装Win32DiskImager软件来进行烧录,如图 2.9 所示。而在Linux主机上通过简单地执行dd命令将映像文件烧录至MicroSD卡。

▲图2.9 烧录映像文件

#dd if= 2021-03-04-raspios-buster-arm64.img of=/dev/sdX status=progress

其中,/dev/sdX中的X需要修改为存储卡实际的映射值,可以通过“fdisk -l”命令来查看。

(3)把MicroSD卡重新插入主机,此时会看到有一个名为“boot”的分区。修改boot分区里面的config.txt配置文件,在这个文件中新增两行,目的是使能串口输出功能。

uart_2ndstage=1
enable_uart=1

(4)启动树莓派。把MicroSD卡插入树莓派中,通过USB线给树莓派供电。树莓派OS的用户名为pi,密码为raspberry。

(5)配置树莓派 4B 上的 Wi-Fi。使用树莓派上的配置工具来配置,在串口中输入如下命令。

$ sudo raspi-config

(6)选择System Options→S1 Wireless LAN,配置SSID和密码,如图2.10所示。

(7)更新系统,这样会自动更新树莓派4B上的固件。

sudo apt update
sudo apt full-upgrade
sudo reboot

▲图2.10 配置SSID和密码

经过上面的步骤,我们得到格式化好的boot分区和最新版本的树莓派固件。boot分区主要包括如下几个文件。

●bootcode.bin:引导程序。树莓派复位上电时,CPU处于复位状态,由GPU负责启动系统。GPU首先会启动固化在芯片内部的固件(BootROM代码),读取MicroSD卡中的bootcode.bin文件,并装载和运行bootcode.bin中的引导程序。树莓派4B已经把bootcode.bin引导程序固化到BootROM里。

●start4.elf:树莓派4B上的GPU固件。bootcode.bin引导程序检索MicroSD卡中的GPU固件,加载固件并启动GPU。

●start.elf:树莓派3B上的GPU固件。

●config.txt:配置文件。GPU启动后读取config.txt配置文件,读取Linux内核映像(比如kernel8.img等)以及内核运行参数等,然后把内核映像加载到共享内存中并启动CPU,CPU结束复位状态后开始运行Linux内核。

2.2.3 实验2-1:输出“Welcome BenOS!”

1.实验目的

了解和熟悉如何在树莓派4B上运行最简单的BenOS程序。

2.实验详解

首先,在Linux主机中安装相关工具

$ sudo apt-get install apt-get install qemu-system-arm libncurses5-dev gcc-aarch64-linux-gnu build-essential git bison flex libssl-dev

然后,在Linux主机上使用make命令编译BenOS。

$ cd benos
$ make

编译完成之后会生成benos.bin可执行文件以及benos.elf文件。在把benos.bin可执行文件放到树莓派4B上之前,我们可以使用QEMU虚拟机来模拟树莓派运行,可直接输入“make run”命令。

$ make run
qemu-system-aarch64 -machine raspi4 -nographic -kernel benos.bin
Welcome BenOS!

把benos.bin文件复制到MicroSD卡的boot分区(可以通过USB的MicroSD读卡器进行复制),并且修改boot分区里面的config.txt文件。

<config.txt文件>

[pi4]
kernel=benos.bin
max_framebuffers=2

[pi3]
kernel=benos.bin

[all]
arm_64bit=1

enable_uart=1

kernel_old=1
disable_commandline_tags=1

插入MicroSD卡到树莓派,连接USB电源线,使用Windows端的串口软件可以看到输出,如图2.11所示。

▲图2.11 输出欢迎语句

2.2.4 实验2-2:使用GDB与QEMU虚拟机调试BenOS

我们可以使用GDB和QEMU虚拟机单步调试裸机程序。

本节以实验2-1为例,在终端启动QEMU虚拟机的gdbserver。

$ qemu-system-aarch64 -machine raspi4 -serial null -serial mon:stdio -nographic -kernel benos.bin -S -s

在另一个终端输入如下命令来启动GDB,可以使用aarch64-linux-gnu-gdb命令或者gdb-multiarch命令。

$ aarch64-linux-gnu-gdb --tui build/benos.elf

在GDB的命令行中输入如下命令。

(gdb) target remote localhost:1234
(gdb) b _start
Breakpoint 1 at 0x0: file src/boot.S, line 7.
(gdb) c

此时,可以使用GDB命令来进行单步调试,如图2.12所示。

▲图2.12 使用GDB调试裸机程序

2.2.5 实验2-3:使用J-Link EDU仿真器调试树莓派

调试BenOS是通过QEMU虚拟机中内置的gdbserver来实现的,但gdbserver只能调试在QEMU虚拟机上运行的程序。如果需要调试在硬件开发板上运行的程序,例如把BenOS放到树莓派上运行,那么GDB与QEMU虚拟机就无能为力了。如果我们编写的程序在QEMU虚拟机上能运行,而在实际的硬件开发板上无法运行,那就只能借助硬件仿真器来调试和定位问题。

硬件仿真器指的是使用仿真头完全取代目标板(例如树莓派4B开发板)上的CPU,通过完全仿真目标开发板上的芯片行为,提供更加深入的调试功能。目前流行的硬件仿真器是JTAG仿真器。JTAG(Joint Test Action Group)是一种国际标准测试协议,主要用于芯片内部测试。JTAG仿真器通过现有的JTAG边界扫描口与CPU进行通信,实现对CPU和外设的调试功能。

▲图2.13 J-Link仿真器的JTAG接口

目前市面上支持ARM芯片调试的仿真器主要有ARM公司的DSTREAM仿真器、德国Lauterbach公司的Trace32仿真器以及SEGGER公司的J-Link仿真器。J-Link EDU是SEGGER公司推出的面向高校和教育的版本,本章提到的J-Link仿真器指的是J-Link EDU版本。本节介绍如何使用J-Link仿真器 调试树莓派4B。

1.硬件连线

为了在树莓派4B上使用J-Link仿真器,首先需要把J-Link仿真器的JTAG接口连接到树莓派4B的扩展板。树莓派4B的扩展接口已经内置了JTAG接口。我们可以使用杜邦线来连接。

J-Link仿真器提供20引脚的JTAG接口,如图2.13所示。

JTAG接口引脚的说明如表2.2所示。

表2.2 JTAG接口引脚的说明

树莓派与J-Link仿真器的连接需要8根线,如表2.3所示。读者可以参考图2.5和图2.13来仔细连接线路。

表2.3 树莓派与J-Link仿真器的连接

2.复制树莓派固件到MicroSD卡

在实验2-1的基础上,复制loop.bin程序到MicroSD卡。另外,还需要修改config.txt配置文件,打开树莓派对JTAG接口的支持。

完整的config.txt文件如下。

# BenOS for JLINK debug

[pi4]
kernel=loop.bin

[pi3]
kernel=loop.bin

[all]
arm_64bit=1 
enable_uart=1 
uart_2ndstage=1 

enable_jtag_gpio=1
gpio=22-27=a4
init_uart_clock=48000000
init_uart_baud=115200

●uart_2ndstage=1:打开固件的调试日志。

●enable_jtag_gpio =1:使能JTAG接口。

●gpio=22-27=a4:表示GPIO22~GPIO27使用可选功能配置4。

●init_uart_clock=48000000:设置串口的时钟。

●init_uart_baud=115200:设置串口的波特率。

复制完之后,把MicroSD卡插入树莓派中,接上电源。

3.下载和安装OpenOCD软件

OpenOCD(Open On-Chip Debugger,开源片上调试器)是一款开源的调试软件。OpenOCD提供针对嵌入式设备的调试、系统编程和边界扫描功能。OpenOCD需要使用硬件仿真器来配合完成调试,例如J-Link仿真器等。OpenOCD内置了GDB server模块,可以通过GDB命令来调试硬件。

首先,通过git clone命令下载OpenOCD软件

然后,安装如下依赖包。

$ sudo apt install make libtool pkg-config autoconf automake texinfo

接下来,编译和安装。

$ cd openocd
$ ./ bootstrap
$ ./configure
$ make
$ sudo make install

另外,也可以从xPack OpenOCD项目中下载编译好的二进制文件。

4.连接J-Link仿真器

为了使用openocd命令连接J-Link仿真器,需要指定配置文件。OpenOCD的安装包里内置了jlink.cfg文件,该文件保存在/usr/local/share/openocd/scripts/interface/目录下。jlink.cfg配置文件比较简单,可通过“adapter”命令连接J-Link仿真器。

<jlink.conf配置文件>
# SEGGER J-Link

adapter driver jlink

下面通过openocd命令来连接J-Link仿真器,可使用“-f”选项来指定配置文件。

$ openocd -f jlink.cfg

Open On-Chip Debugger 0.10.0+dev-01266-gd8ac0086-dirty (2020-05-30-17:23)
Licensed under GNU GPL v2
For bug reports, read
     ****://openocd.***/doc/doxygen/bugs.html
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : J-Link V11 compiled Jan  7 2020 16:52:13
Info : Hardware version: 11.00
Info : VTarget = 3.341 V

从上述日志可以看到,OpenOCD已经检测到J-Link仿真器,版本为11。

5.连接树莓派

接下来,使用J-Link仿真器连接树莓派,这里需要描述树莓派的配置文件raspi4.cfg。树莓派的这个配置文件的主要内容如下。

<raspi4.cfg配置文件>
set _CHIPNAME bcm2711
set _DAP_TAPID 0x4ba00477

adapter speed 1000

transport select jtag
reset_config trst_and_srst

telnet_port 4444

# 创建 tap
jtag newtap auto0 tap -irlen 4 -expected-id $_DAP_TAPID

# 创建 dap
dap create auto0.dap -chain-position auto0.tap

set CTIBASE {0x80420000 0x80520000 0x80620000 0x80720000}
set DBGBASE {0x80410000 0x80510000 0x80610000 0x80710000}

set _cores 4

set _TARGETNAME $_CHIPNAME.a72
set _CTINAME $_CHIPNAME.cti
set _smp_command ""

for {set _core 0} {$_core < $_cores} { incr _core} {
   cti create $_CTINAME.$_core -dap auto0.dap -ap-num 0 -ctibase [lindex $CTIBASE $_core]

   set _command "target create ${_TARGETNAME}.$_core aarch64 \
                -dap auto0.dap  -dbgbase [lindex $DBGBASE $_core] \
                -coreid $_core -cti $_CTINAME.$_core"
   if {$_core != 0} {
      set _smp_command "$_smp_command $_TARGETNAME.$_core"
   } else {
      set _smp_command "target smp $_TARGETNAME.$_core"
   }

   eval $_command
}

eval $_smp_command
targets $_TARGETNAME.0

使用如下命令连接树莓派,结果如图2.14所示。

$ openocd -f jlink.cfg -f raspi4.cfg

如图2.14所示,OpenOCD已经成功连接J-Link仿真器,并且找到了树莓派的主芯片BCM2711。OpenOCD开启了几个服务,其中Telnet服务的端口号为4444,GDB服务的端口号为3333。

▲图2.14 使用J-Link仿真器连接树莓派

6.登录Telnet服务

在Linux主机中新建终端,输入如下命令以登录OpenOCD的Telnet服务。

$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
>

在Telnet服务的提示符下输入“halt”命令以暂停树莓派的CPU,等待调试请求。

> halt
bcm2711.a72.0 cluster 0 core 0 multi core
bcm2711.a72.1 cluster 0 core 1 multi core
target halted in AArch64 state due to debug-request, current mode: EL2H
cpsr: 0x000003c9 pc: 0x78
MMU: disabled, D-Cache: disabled, I-Cache: disabled
bcm2711.a72.2 cluster 0 core 2 multi core
target halted in AArch64 state due to debug-request, current mode: EL2H
cpsr: 0x000003c9 pc: 0x78
MMU: disabled, D-Cache: disabled, I-Cache: disabled
bcm2711.a72.3 cluster 0 core 3 multi core
target halted in AArch64 state due to debug-request, current mode: EL2H
cpsr: 0x000003c9 pc: 0x78
MMU: disabled, D-Cache: disabled, I-Cache: disabled
target halted in AArch64 state due to debug-request, current mode: EL2H
cpsr: 0x000003c9 pc: 0x80000
MMU: disabled, D-Cache: disabled, I-Cache: disabled
>

接下来,使用load_image命令加载BenOS可执行程序,这里把benos.bin加载到内存的0x80000地址处,因为在链接脚本中设置的链接地址为0x80000。

> load_image /home/rlk/rlk/lab01/benos.bin 0x80000
936 bytes written at address 0x80000
downloaded 936 bytes in 0.101610s (8.996 KiB/s)

下面使用step命令让树莓派的CPU停在链接地址(此时的链接地址为0x80000)处,等待用户输入命令。

> step 0x80000
target halted in AArch64 state due to single-step, current mode: EL2H
cpsr: 0x000003c9 pc: 0x4
MMU: disabled, D-Cache: disabled, I-Cache: disabled

7.使用GDB进行调试

现在可以使用GDB调试代码了。首先使用aarch64-linux-gnu-gdb命令(或者gdb-multiarch命令)启动GDB,并且使用端口号3333连接OpenOCD的GDB服务。

$ aarch64-linux-gnu-gdb --tui build/benos.elf

(gdb) target remote localhost:3333  <=连接OpenOCD的GDB服务

当连接成功之后,我们可以看到GDB停在BenOS程序的入口点(_start),如图2.15所示。

▲图2.15 连接OpenOCD的GDB服务

此时,我们可以使用GDB的“step”命令单步调试程序,也可以使用“info reg”命令查看树莓派上的CPU寄存器的值。

使用“layout reg”命令打开GDB的寄存器窗口,这样就可以很方便地查看寄存器的值。如图2.16所示,当单步执行完第16行的“adr x0, bss_begin”汇编语句后,寄存器窗口中马上显示了X0寄存器的值。

▲图2.16 单步调试和查看寄存器的值 33DTFxQAp9f8xbwtESkDrGlL5N3TJ6CZxIWSU5zUWlretEUgkfRAabDmLA+2wJ49

点击中间区域
呼出菜单
上一章
目录
下一章
×