目录

1 实验环境概述

1.1 实验环境种类

1.2 树莓派4b简介

2 实验代码分析

2.1 实验代码结构

2.2 Makefile文件分析

2.3 linker.ld文件分析

2.4 程序流程分析

2.4.1 启动代码

2.4.2 kernel_main函数

3 基于qemu的实验环境搭建

3.1 使用qemu + gdb调试

3.1.1 启动qemu调试

3.1.2 启动gdb

3.1.3 连接gdb server

3.1.4 开始调试

3.2 使用qemu + eclipse调试

3.2.1 创建新工程

3.2.2 创建调试配置

3.2.3 开始调试

4 基于树莓派的实验环境搭建

4.1 调试工具概述

4.1.1 JLink

4.1.2 OpenOCD

4.2 烧写树莓派基础镜像

4.3 更新树莓派SPI BootRom

4.3.1 配置WiFi

4.3.2 更新系统软件包

4.4 树莓派4b启动流程

4.5 更新测试镜像

4.6 更新调试镜像

4.7 连接JLink

4.7.1 JLink升级

4.7.2 连接JLink和树莓派

4.7.3 JLink接入虚拟机

4.8 开始调试

4.8.1 启动OpenOCD

4.8.2 连接OpenOCD

4.8.3 暂停CPU

4.8.4 加载调试镜像到树莓派

4.8.5 设置CPU执行位置

4.8.5 连接gdb调试

5 实验验证

5.1 currentEL验证

5.2 SP指针验证


1 实验环境概述

1.1 实验环境种类

《奔跑吧Linux第3季》课程共提供2种实验环境

1. 使用qemu模拟树莓派4b的实验环境

2. 实际基于树莓派4b的实验环境

1.2 树莓派4b简介

我们的软硬件实验环境均基于树莓派4b,此处进行简要介绍

1. 使用BCM2711作为主芯片

2. 内置4核Cortex-A72

3. 内置GICv2中断控制器

4. 支持丰富的外设接口

说明:树莓派4b address map

介绍树莓派4b的address map主要是为了帮助理解下文种设置外设寄存器的操作

① BCM2711芯片手册中列出的外设地址是Legacy Master模式下的,Main peripherals的基地址为0x7c000000

以下文代码要设置GPFSEL寄存器为例,在BCM2711芯片手册中的地址为0x7e200000 + 0x04

② 树莓派4b启动后,根据config.txt中的设置,如果arm_peri_high为1,则使用High Peripheral模式,也就是图中的Full 35-bit Address Map模式

③ 如果不设置arm_peri_high,树莓派默认以Low Peripheral模式启动,我们的实验中就是这种情况,此时Main peripherals的基地址为0x0_fc000000

因此GPFSEL寄存器的地址就被映射到0xFC000000 + (0x7e200000 - 0x7c000000) + 0x04,即0xfc000000 + 0x02200000 + 0x04 = 0xfe200004

这与代码中的设置是一致的

2 实验代码分析

2.1 实验代码结构

2.2 Makefile文件分析

说明:启动qemu调试参数

可见与启动qemu运行相比,进行调试时增加了-S和-s参数

① -S:freeze CPU at startup,此时CPU会停在我们要调试程序的第1条指令处

② -s:shorthand for -gdb tcp::1234,此时qemu会启动内部的gdbServer,并等待gdb调试器通过网络连接,默认TCP端口号为1234

2.3 linker.ld文件分析

1. 链接起始地址为0x80000

之所以选择该地址,是因为在树莓派4b配置中,会将编译生成的镜像加载到0x80000处运行

2. 首先链接.text.boot段的内容,这也是镜像中最先执行的部分,我们对程序流程的分析也从这里开始

2.4 程序流程分析

2.4.1 启动代码

启动代码位于boot.S文件中

说明1:mpidr_el1寄存

对于CPU0(Primary CPU),该寄存器的bit[7:0]为0

说明2:cbz指令

CBZ指令当<Xt>寄存器值为0时,跳转到<label>处执行。在示例程序中,就是判断mpidr_el1的bit[7:0]为0时跳转到master label执行

说明3:清空BSS段

首先获取bss_begin & bss_end的地址,之后调用memzero函数对该区域清零。调用时,x0中存储的是BSS段起始地址,x1中存储的是BSS段大小

说明4:栈指针设置

① SECTION_SHIFT = PAGE_SHIFT + TABLE_SHIFT = 12 + 9 = 21

② SECTION_SIZE = 1 << SECTION_SHIFT = 1 << 21 = 2MB

③ LOW_MEMORY = 2 * SECTION_SIZE = 2 * 1MB = 4MB

可见此时栈设置在内存地址4MB处

2.4.2 kernel_main函数

kernel_main函数的主要流程如下,

1. 初始化串口

2. 向串口发送"Welcon BenOS!"字符串

3. 在循环中等待用户输入并回显

说明1:实验代码中的串口使用轮询方式工作

说明2:benos.elf文件符号表

① _start标号位于镜像文件起始处

② BBS段此时为空

3 基于qemu的实验环境搭建

3.1 使用qemu + gdb调试

3.1.1 启动qemu调试

在一个端口启动qemu调试,命令如下

# 在实验源码Makefile所在目录make debug

说明1:-machine raspi4参数

① -machine参数用于设置要模拟的设备

② 使用如下命令可以查看当前qemu支持的设备列表

qemu-system-aarch64 -machine help

说明2:-nographic参数

disable图像输出,将串口输入输出作为控制台(console)

说明3:-kernel benos.bin参数

将benos.bin作为内核镜像

3.1.2 启动gdb

在另一个端口启动gdb,命令如下

gdb-multiarch --tui build/benos.elf

说明1:--tui参数

① 使用终端界面(terminal user interface)

② 如果不加--tui参数,将不会有显示对应源码的窗口

说明2:gdb启动调试时,需要使用带有符号表的可执行文件,此处即为benos.elf

3.1.3 连接gdb server

在gdb命令行中输入如下命令,用于连接qemu调试时启动的gdb server

target remote localhost:1234

3.1.4 开始调试

1. 设置断点

使用如下命令将断点设置在_start标号处,也就是内核镜像的首条指令处

b _startc # 运行到断点处

2. 打开寄存器观察窗口

使用如下命令打开寄存器观察窗口

layout reg

3. 调试程序

之后便可以单步调试程序,观察程序运行状态

我们以获取bss_begin & bss_end为例,可见x0 & x1寄存器中正确获取了BSS段的起止地址

说明1:adr指令

adr指令用于获取标号相对于PC的地址(地址无关指令),此处获取的就是bss_begin & bss_end标号的地址,也就是BSS段的范围

需要注意的是,此时链接地址和运行地址是匹配的,所以使用地址无关操作获取的标号地址,与实际的运行地址是一致的

说明2:如果只是使用qemu运行内核镜像,则使用如下名

# 在实验源码Makefile所在目录make run

可见实验结果与之前的分析是一致的

说明3:此处调试的原理是使用了qemu内置的gdbserver

说明4:qemu不能100%模拟硬件行为

3.2 使用qemu + eclipse调试

在使用qemu + eclipse调试时,仍然是在一个端口启动qemu调试,之后启动eclipse进行如下配置

3.2.1 创建新工程

工程创建完成后,可见工程中包含了之前调试的源码

3.2.2 创建调试配置

配置完成Apply之后,就会生成新建的调试配置

3.2.3 开始调试

点击Debug之后便进入调试界面,可见模拟的树莓派4b中有4个CPU核

之后在Debugger Console中加载符号表

此处要注意ELF文件的路径

之后在Debugger Console中将断点设置在_start标号处,并运行到断点处,此时就会出现调试的源码界面,此时便可以进行单步调试,并观察处理器状态

此时可以查看Registers窗口,观察寄存器状态

4 基于树莓派的实验环境搭建

4.1 调试工具概述

4.1.1 JLink

1. 硬件仿真器使用仿真头完全取代目标板上的CPU,从而完全仿真目标板上的芯片行为,提供更加深入的调试功能

2. JTAG(Joint Test Action Group)是一种国际标准测试协议,主要用于芯片内部测试。JTAG仿真器通过边界扫描接口与CPU进行通信,实现对CPU和外设的调试功能

3. JLink是SEGGER公司开发的基于JTAG协议的仿真器,其V11版本支持树莓派4b主芯片的Cortex-A72调试

说明:JTAG 20pin接口

4.1.2 OpenOCD

1. OpenOCD(Open On-Chip Debbugger,开源片上调试器)是一款开源软件,提供针对嵌入式设备的调试、系统编程和边界扫描功能

2. OpenOCD的功能在仿真器的辅助下完成,仿真器是必须的,因为调试主机(运行OpenOCD的PC)通常不具备调试电信号的解析能力

4.2 烧写树莓派基础镜像

首先使用一张SD卡烧写树莓派基础镜像

烧写工具:Win32DiskImager

镜像文件:2020-08-20-raspios-buster-arm64.img

注意:打开Win32DiskImager工具时,需要使用管理员权限

烧写完成后,SD卡中将自动生成FAT32格式的boot分区,其中的文件如下图所示

说明1:使能串口输出

修改boot分区中的config.txt配置文件,增加如下2行,用于使能串口输出

此时启动树莓派,可通过串口登录,其中树莓派镜像默认的用户名和密码如下

用户名:pi

密码:raspberry

说明2:使能串口配置项说明

① uart_2ndstage

设置该参数,可以使得树莓派从second-stage loader就开始打印调试信息

② enable_uart

设置该参数,可以配合cmdline.txt中的内核启动参数,使得内核创建控制台串口

4.3 更新树莓派SPI BootRom

通过WiFi更新树莓派4b全系统的软件包,这样会自动更新SPI BootRom固件

4.3.1 配置WiFi

使用如下命令配置WiFi

sudo raspi-config

我这里指令该命令时,会显示乱码,而不是配置界面

这是因为串口工具的编码方式需要修改,我们将编码方式选为UTF-8,重新执行上述命令,即可显示配置界面

WiFi配置流程如下,

此时可见wlan0 interface已经分配到IP地址,且可以ping通百度,这说明网络配置已经成功

说明:树莓派4b只能连接2.4GHz的WiFi网络

4.3.2 更新系统软件包

使用如下命令更新整个系统的软件包

sudo apt updatesudo apt full-upgrade

之后重启树莓派即可

4.4 树莓派4b启动流程

1. 当树莓派4b启动时,Cortex-A72处于standby状态,GPU将负责启动系统。GPU会加载片上ROM code并执行,ROM code的主要功能为初始化SD host controller,为后续读取SD卡上的文件做准备

2. SD host controller初始化完成后,ROM code会加载SD卡上的bootcode.bin文件并执行

3. bootcode.bin文件负责加载SD卡上的start.elf文件并执行

4. start.elf文件解析SD卡上的config.txt配置文件,加载SD卡上的kernel.img文件到内存指定地址,然后CPU结束standby状态开始执行内核

说明1:bootcode.bin和star.elf文件为树莓派官方提供,不开源

说明2:如何指定kernel文件并加载到内存指定地址

要完成这个目标,就需要用到config.txt配置文件中的2个参数

① kernel

kernel参数用于指定加载的内核镜像文件,如果不指定,对于树莓派4b,默认使用kernel7l.img文件

② kernel_old & kernel_address

这2个参数用于指定kernel文件的加载地址,如果这2个参数均不指定,则默认将64位kernel文件加载到0x200000地址处(但是根据树莓派4b上级验证情况,实际是加载到0x80000地址处)

4.5 更新测试镜像

在理解了树莓派4b的启动流程后,我们将课程提供的测试用的镜像拷贝到SD卡的boot分区

启动树莓派后,可见已经运行测试镜像

说明:测试镜像config.txt

此时启动使用的内核镜像为benos4.bin

4.6 更新调试镜像

下面我们更新调试镜像,该镜像是为了,也是将相关文件拷贝到SD卡的boot分区

同样分析一下调试镜像的config.txt配置文件

1. 启动的内核文件为loop.bin,我们查看该文件的二进制内容,对照ARMv8 AArch64指令集编码,该文件仅包含一条无条件跳转的B语句,用于实现无限循环,类似如下指令的效果

label:b label

这么做的目的,是让CPU处于循环状态,等待JLink获取CPU运行的控制权

2. enable_jtag_gpio=1

该选项用于设置JTAG相关的GPIO功能,同时在SoC内部建立相应连接

3. gpio=22-27=a4

将GPIO22 ~ GPIO27的功能设置为Alt4,该配置项与上面的enable_jtag_gpio=1功能一样

4. init_uart_clock=48000000

该选项设置串口UART0的时钟为48MHz,也就是默认值

5. init_uart_baud=115200

该选项设置串口的波特率为115200,也是默认值

4.7 连接JLink

4.7.1 JLink升级

我们实验使用的JLink为V11版本,但是需要将固件更新到最新版本,才能支持Cortex-A72。可以使用J-Link Commander程序进行升级

如果当前固件版本不是最新,打开J-Link Commander程序后会自动提示升级,此时选择升级即可。当前使用的JLink固件版本已更新至2021年6月29日

4.7.2 连接JLink和树莓派

要在树莓派上使用JLink仿真器,需要将JLink仿真器的JTAG接口连接到树莓派的扩展板上。树莓派的扩展接口中已经内置了JTAG接口,可以使用杜邦线连接

树莓派与JLink仿真器的连接如下,

4.7.3 JLink接入虚拟机

1. 首先将JLink的连接接入虚拟机

2. 使用lsusb命令查看JLink是否已接入虚拟机

3. 使用如下命令,验证能否访问JLink

sudo openocd -f jlink.cfg # 在jlink.cfg文件所在目录执行

可见已经识别到JLink硬件版本为V11,且探测到目标CPU电压为3.244V,后续的错误是因为还没有指定要调试的设备信息

说明:jlink.cfg文件

可见该配置文件只是指定使用的调试接口类型为jlink(这里之所以要配置,是因为JLink硬件也可以使用SWD接口进行调试)

4.8 开始调试

4.8.1 启动OpenOCD

使用如下命令启动OpenOCD

sudo openocd -f jlink.cfg -f raspi4.cfg # 在配置文件所在目录执行

可见JLink已经识别到树莓派4b上的bcm2711芯片,且在3333端口启动了gdb server

说明:raspi4.cfg配置文件

4.8.2 连接OpenOCD

在另一个shell中使用telnet连接上一步中启动的OpenOCD,且根据raspi4.cfg配置文件,telnet的端口号为4444

telnet localhost 4444

可见telnet连接成功

4.8.3 暂停CPU

使用halt命令先让CPU暂停运行

可见bcm2711中的2个CPU核已因为JLink的debug请求暂停运行,且暂停前处于EL2异常等级,并使用SP_EL2栈指针

4.8.4 加载调试镜像到树莓派

使用如下命令加载要调试的进行到树莓派,,此处加载的是可运行的二进制文件

load_image /home/rlk/rlk/armv8_trainning/lab01/benos.elf 0x80000

4.8.5 设置CPU执行位置

使用如下指令让CPU执行流停止在指定位置,此处停止在可执行镜像的加载位置

step 0x80000

说明:根据上级验证,要想调试bin文件中的第1条指令,step应该将CPU执行位置设置在0x7FFFC

step 0x7FFFC

其实从上面的截图也可以看出,当使用step 0x80000命令时,CPU halt时的PC值为0x80004,也就是bin文件的第2条指令处,这与实际测试结果也是一致的

而使用step 0x7FFFC命令时,CPU halt时的PC值为0x80000,这是我们期望的结果

4.8.5 连接gdb调试

在另一个端口启动gdb,命令如下,此处加载的是带有符号表的ELF文件

gdb-multiarch --tui build/benos.elf# 在gdb命令行中target remote localhost:3333

此时便可以进行单步调试,可见在实际的树莓派4b中,寄存器值与qemu虚拟机不同

5 实验验证

5.1 currentEL验证

执行完mrs x0, CurrentEL指令后,X0的值为0x8

对照CurrentEL寄存器定义,此时异常等级为EL2

5.2 SP指针验证

1. SP寄存器值

在执行完mov sp, #LOW_MEMORY指令之后,可见SP指针被设置为0x400000,也就是4MB地址处

2. SPSel寄存器值

此时我们获取SPSel寄存器的值,该值为1,说明使用的是当前异常等级的栈指针,也就是SP_EL2

ARMv8体系结构基础02:搭建实验环境相关推荐

  1. ARMv8体系结构基础05:比较和跳转指令

    目录 1 比较与测试指令详解 1.1 CMP指令 1.1.1 概述 1.1.2 指令编码分析 1.2 CMN指令 1.2.1 概述 1.2.2 指令编码分析 1.3 TST指令 1.3.1 概述 1. ...

  2. 短信系统后台基础版本搭建服务器环境和功能说明

    短信系统基础版本数据库搭建和后台功能介绍 短信系统后台基础版本搭建服务器环境和功能 此版本为短信系统基础版本 一:服务器环境篇 1.1:服务器操作系统 使用windows2016 或者是windows ...

  3. ARMv8体系结构基础01:ARMv8体系结构简介

    目录 1 ARMv8体系结构特性 2 ARMv8体系结构基本概念 2.1 处理机(Processing Element, PE) 2.2 异常等级(Exception Level) 2.2.1 异常等 ...

  4. ARMv8体系结构基础03:加载和存储指令

    目录 1 A64指令集概述 1.1 A64指令集特征 1.1.1 指令定长 1.1.2 可使用64位指针 1.1.3 使用一致的编码结构(consistent encoding scheme) 1.1 ...

  5. 第一章:搭建实验环境_eve-ng模拟器

    工具:eve-ng的ova格式的虚拟机文件:vmware eve-ng是深度定制的Ubuntu操作系统 第一步:下载ova格式的eve-ng虚拟机文件,导入到vmware (软件已上传到百度网盘和我的 ...

  6. CCSA学习笔记 第二节 搭建实验环境

    搭建CCSA实验环境 一.个人电脑的要求 1.CPU支持虚拟化 2.win10注意关闭更新 3.内存大于等于16G 二.关于EVE的资源分配 1.内存大于等于8G 2.CPU分配2个,必须激活虚拟化( ...

  7. 快速搭建实验环境:使用 Terraform 部署 Proxmox 虚拟机

    作者 | Addo Zhang 来源 | 云原生指北 自从用上 m1 的电脑,本地开发环境偶尔会遇到兼容性的问题.比如之前尝试用 Colima 在虚拟机中运行容器运行时和 Kubernetes,其实际 ...

  8. 中谷教育02 搭建Python环境

    搭建python环境 Linux 环境 大多数都默认安装了python环境 命令行输入python可以启动python交互模式 推荐使用vim编辑 Windows环境 可以下载python 安装包(m ...

  9. 搭建实验环境时新路由器的常用配置命令

    修改主机名.设置特权模式密码.关闭DNS自动查找和设置登录和日期标志区: Router(config)#hostname *** Router(config)#enable secret *** Ro ...

最新文章

  1. [算法 笔记]字符串表达式计算(简易版)
  2. 回文字符串—回文子串—暴力破解法
  3. Android:VivoNex3S调试无法安装程序
  4. Java接口程序练习
  5. 关于simulink中参数传递到工作空间
  6. nginx cache配置
  7. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第3节 两种获取Stream流的方式_6_Stream流中的常用方法_count...
  8. OpenCV最简JAVA版范例
  9. 自回归模型AR(p)的python实现【案例】
  10. 小区同步、LTE的时间结构(FDD/TDD)
  11. 传说中的800句记7000词
  12. 若依前后端分离项目图片上传后访问404问题
  13. Flink 生产环境配置建议
  14. 时间管理-系统管理员
  15. 【嵌入式】如果用PS导出GIF图片
  16. Android开发之如何自定义垂直方向的SeekBar
  17. 操作系统调度算法--高响应比优先调度算法解析
  18. python爬取百度美女图片
  19. Oracle数据库提示密码过期,更改密码永不过期的一种方法。
  20. python从入门到精通pdf清华大学出版社-清华大学出版社-图书详情-《Python从入门到精通》...

热门文章

  1. 树莓派java 控制摄像头_在树莓派上使用动作进行网络摄像头流媒体问题
  2. php后台代码自动生成程序,Thinkphp自定义代码生成工具及用法说明(附下载地址)...
  3. 计算机三级之嵌入式系统学习笔记2
  4. Docker开启和关闭容器自启动
  5. css sprites原理,[css] 第17天 解释下 CSS sprites的原理和优缺点分别是什么?
  6. js ---- 数组操作
  7. html里面css什么意思,Web前端
  8. akka actor java_现代化的Java(三)——从Hello Akka说起
  9. c++已知2点求中垂线_呆哥数学函数合集——函数的概念【2】
  10. 鸿蒙引领着未来,华为智慧屏V65图赏:鸿蒙OS引领未来