07 树莓派裸机编程,并在Windows MSYS2 QEMU模拟器中运行

作者将狼才鲸
创建日期2022-11-14

4)完整的环境安装步骤

  • 写在前面,我会提供已经安装好各种工具的MSYS2环境,如果你没用过Linux,建议你直接下载本系统压缩包cj_msys64.zip,解压后使用,或者自行使用VMware Player虚拟机+Ubuntu安装开发环境,因为MSYS2中安装软件的教程很难快速找到,需要有一些使用Linux的经验才知道怎么安装特定软件;我的MSYS2环境添加了32位和64位的交叉编译工具,他们的来源不一样,后面会详述。

  • 下面是从头到尾的工具软件安装步骤:

    • 推荐使用MSYS2 + 已经用MinGW32或MinGW64编译好的程序,基本上开发过程中你能在Linux下实现的,也都能在这个环境下实现,只是有些教程没有Ubuntu下那么好找;在MSYS2中不能使用Linux的程序,必须用MinGW将源码重新编译过后才能使用,这一般是软件供应商已经做好的。
    • MSYS2的更多信息详见本仓库子文档《04_MSYS2简述.md》
表2 MSYS2、MinGW和Cygwin的关系
软件名版本作用特点
MSYSMSYS,MSYS2Linux命令行终端:Shell,Bash没有在Windows下编译Linux程序的工具集,会自带已经被MinGW编译好的一些包;脱胎于Cygwin,但容量更小;MSYS2是因为MSYS常年不更新而新组的的一个项目;MSYS2安装完后的文件名为msys64,你可以将你安装好之后的msys64文件夹打包发给别人,这样别人无安装就可以用了,只是容量有点大,几十G
MinGWMinGW32,MinGW64一组编译工具链编译后生成的是纯粹的Windows程序;它自带的命令行终端很难用也不全,要和MSYS2终端配合使用;MinGW64是因为MinGW32常年不更新而新组的的一个项目
CygwinCygwin编译工具+命令行有模拟层,将Linux API转成Windows API再执行程序,效率低,容量大,速度慢,2010年左右在Windows下搭建交叉编译环境时还多用它;要运行纯粹的Linux程序时也用它
4.1 安装MSYS2
  1. 我当前下载的版本是msys2-x86_64-20221028.exe
  1. 我将软件安装在D盘根目录,软件会安装在d:\msys64中,安装目录不能有空格、中文。
  2. 安装完之后先不打开软件,先将国外镜像地址换成国内镜像地址,参考上方教程。
  3. 电脑配置环境变量,在PATH中增加一行D:\msys64\usr\bin
  1. 双击运行主目录下的msys2.exe或者mingw64.exe都可以,其它的exe有些是32位的,有些是非gcc编译器对应的软件。
4.2 MSYS2中安装QEMU
  • 因为我已经有了MSYS2环境,可以在里面直接安装QEMU;你下载Windows版本的QEMU单独安装,也是走的MSYS2+MinGW这一套,只是和Git一样,它们都是在自己的软件安装包自带了精简版的MinGW环境。

  • 我们不需要用MinGW64或者MinGW32编译QEMU,我们只安装已经编译好的QEMU软件;网上没搜到MSYS2中安装QEMU的教程,但是我们知道MSYS2中的所有软件都在packages.msys2.org/reposMSYS2 Base PackagesMSYS2 Packages中有描述。

  • 在https://packages.msys2.org/base 中能找到mingw-w64-qemu;在https://packages.msys2.org/package/ 中能找到mingw-w64-x86_64-qemu;在https://packages.msys2.org/package/mingw-w64-x86_64-qemu?repo=mingw64 中能找到/mingw64/bin/qemu-system-aarch64.exe、/mingw64/bin/qemu-system-arm.exe,也能找到安装方法:pacman -S mingw-w64-x86_64-qemu;我当前使用的是Build Date: 2022-10-10 20:19:53,Installed Size: 768.72 MB,实际安装完后有2G。

  • 查看是否安装成功:进入cd /mingw64/bin/ 然后./qemu-system-arm.exe --version查看版本号;后续还需要设置环境变量,这里暂略。

  • 能看到输出信息:

jim@DESKTOP-SVP3BEM MSYS /mingw64/bin
$ ./qemu-system-arm.exe --version
QEMU emulator version 7.1.0
Copyright (c) 2003-2022 Fabrice Bellard and the QEMU Project developers
4.3 MSYS2中安装32位和64位ARM交叉编译工具
4.4 用现成的程序从QEMU运行树莓派
  • 从以下网址https://gitee.com/mirrors_bztsrc/raspi3-tutorial/tree/master/0A_pcscreenfont 下载编译好的树莓派程序,我已下载好,存放在msys64家目录下的1_raspi/01_run文件夹中
  • 使用命令运行:/mingw64/bin/qemu-system-aarch64 -M raspi3b -kernel ~/1_raspi/01_run/kernel8.img -d in_asm
  • 能看到出现了QEMU窗口,并显示了hello world。
    效果如下:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbXCRLJO-1668607347474)(./picture/01_QEMU_RUN.png)]
4.5 交叉编译工具编译程序,并在树莓派QEMU模拟中运行
  1. mirrors_bztsrc/raspi3-tutorial下载一个国外的英文仓库,是演示64位ARM树莓派裸机编程的,我借鉴这里面的工程。
  • 这个工程已下载到当前仓库根目录下,我也会将这个目录拷贝到msys64的家目录下,我会将里面的Makefile和自动运行改成和msys64适配,保证一个make命令就能编译程序,一个make run就能在QEMU中运行刚刚编译的程序。
  • 输出qemu所在位置和aarch64编译器所在位置的环境变量,这样就不用每次都写完整的路径了。
  • 打开家目录也就是msys64/home/jim/下的.bashrc,在里面末尾加上
    export PATH= P A T H : / m i n g w 64 / b i n e x p o r t P A T H = PATH:/mingw64/bin export PATH= PATH:/mingw64/binexportPATH=PATH:/mingw32/bin/gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu/bin
  • 生效配置 source .bashrc
  • 查看环境变量 echo $PATH,确认已经生效
  1. 进入msys64 raspi3-tutorial源码目录,编译并运行
4.6 有关树莓派裸机编程的介绍
  • 树莓派里面有GPU和ARM CPU,GPU先上电运行,然后再引导ARM运行

  • 树莓派的GPU底层固件(Bootloader)是闭源的,但可以在此基础上引导自己的U-Boot、Linux kernel,也可以不用U-Boot和Linux,直接引导裸机程序或者RTOS;这种引导方式和Xilinx ZYNQ类似,ARM和FPGA一个先启动一个后启动。

  • 一些其它的树莓派嵌入式相关的开源仓库:
    (1) 运行在 Raspberry Pi 上的小型嵌入式系统

(2) 一些在 Raspberry Pi 上可以嵌入在其他系统中的运行库

  • USPi(rsta2/uspi), 一个小型的支持 USB 通讯的库

(3) 以及其他一些基于 Raspberry Pi 裸机开发例子:


五、raspi3-tutorial硬件测试用例

  • 原始网址:mirrors_bztsrc / raspi3-tutorial
  • 本仓库中的地址:根目录/raspi3-tutorial/
  • msys64中的地址:家目录 ~/raspi3-tutorial/
  • 硬件是raspi3,64位ARM芯片,但因为有现成的代码,可以先熟悉编译环境,之后再在32位ARM上跑。
表3 raspi3-tutorial各测试用例的描述
用例名称作用备注
00_crosscompiler文档,只是描述编译器相关的内容
01_bareminimum空程序,在汇编中死循环,只是为了验证编译器和模拟器安装正确,能够编译和运行
02_multicorec写汇编boot,并引导C语言main函数运行
03_uart1串口打印Hello world,从MSYS2控制台输出
04_mailboxesCPU和GPU邮箱通信,通信成功后打印串口号
05_uart0串口收发回环
06_random打印随机数
07_delays延时后打印
08_power关机与重启
09_framebuffer从屏幕显示未压缩的图片
0A_pcscreenfont从屏幕显示点阵字库文字
0B_readsector读SD卡扇区
0C_directory读SD卡文件夹
0D_readfile读SD卡文件
0E_initrd根文件系统
0F_executionlevel获取当前程序级别
10_virtualmemoryMMU虚拟内存映射
11_exceptions测试异常中断
12_printf测试printf输出
13_debuggergdb调试输出
14_raspbootin64一个简单的bootloader
15_writesector写SD卡

1)03_uart1

  • 作用:串口打印Hello world,从MSYS2控制台输出
  • 效果:
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/03_uart1
$ make
rm kernel8.elf *.o >/dev/null 2>/dev/null || true
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c start.S -o start.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c main.c -o main.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c uart.c -o uart.o
aarch64-linux-gnu-ld -nostdlib -nostartfiles start.o main.o uart.o -T link.ld -o kernel8.elf
aarch64-linux-gnu-objcopy -O binary kernel8.elf kernel8.img

jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/03_uart1
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio
Hello World!

2)04_mailboxes

  • 作用:CPU和GPU邮箱通信,通信成功后打印串口号
  • 效果:
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/04_mailboxes
$ make
rm kernel8.elf *.o >/dev/null 2>/dev/null || true
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c start.S -o start.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c main.c -o main.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c mbox.c -o mbox.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c uart.c -o uart.o
aarch64-linux-gnu-ld -nostdlib -nostartfiles start.o main.o mbox.o uart.o -T link.ld -o kernel8.elf
aarch64-linux-gnu-objcopy -O binary kernel8.elf kernel8.img

jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/04_mailboxes
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial null -serial stdio
My serial number is: 0000000000000000

3)05_uart0

  • 作用:串口收发回环(串口重定向到MSYS2命令行终端)
  • 效果:
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/05_uart0
$ make
rm kernel8.elf *.o >/dev/null 2>/dev/null || true
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c start.S -o start.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c main.c -o main.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c mbox.c -o mbox.o
aarch64-linux-gnu-gcc -Wall -O2 -ffreestanding -nostdinc -nostdlib -nostartfiles -c uart.c -o uart.o
aarch64-linux-gnu-ld -nostdlib -nostartfiles start.o main.o mbox.o uart.o -T link.ld -o kernel8.elf
aarch64-linux-gnu-objcopy -O binary kernel8.elf kernel8.img

jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/05_uart0
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
My serial number is: 0000000000000000
aaaaddddd
asdfasfsafsa

4)07_delays

  • 延时后打印
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/07_delays
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Waiting 1000000 CPU cycles (ARM CPU): OK
Waiting 1000000 microsec (ARM CPU): OK
Waiting 1000000 microsec (BCM System Timer): OK

5)08_power

  • 关机与重启
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/08_power
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
 1 - power off
 2 - reset
Choose one: 2

 1 - power off
 2 - reset
Choose one: 1

 1 - power off
 2 - reset
Choose one:
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/08_power

6)09_framebuffer

  • 从屏幕显示未压缩的图片

在这里插入图片描述

7)0A_pcscreenfont

  • 从屏幕显示点阵字库文字

在这里插入图片描述

8)0F_executionlevel

  • 获取当前程序级别
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/0F_executionlevel
$ jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/0F_executionlevel
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Current EL is: 00000001

9)11_exceptions

  • 测试异常中断
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/11_exceptions
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Synchronous: Data abort, same EL, Translation fault at level 2:
  ESR_EL1 0000000096000006 ELR_EL1 0000000000080CC4
 SPSR_EL1 00000000200003C4 FAR_EL1 FFFFFFFFFF000000

jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/11_exceptions

10)12_printf

  • 测试printf输出
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/12_printf
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Hello World!
This is character 'A', a hex number: 7FFF and in decimal: 32767
Padding test: '00007FFF', '    -123'

jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/12_printf

11)13_debugger

  • gdb调试输出
jim@DESKTOP-SVP3BEM MSYS ~/raspi3-tutorial/13_debugger
$ make run
qemu-system-aarch64 -M raspi3b -kernel kernel8.img -serial stdio
Synchronous: Breakpoint instruction
> run
 x0: 000000000008EF7C   x1: 0000000000000301   x2: 0000000000000070
 x3: 000000000000000B   x4: 0000000000024000   x5: 0000000000000000
 x6: 0000000000000000   x7: 0000000000000000   x8: 0000000000000000
 x9: 0000000000000000  x10: 0000000000000000  x11: 0000000000000000
x12: 0000000000000000  x13: 0000000000000000  x14: 0000000000000000
x15: 0000000000000000  x16: 0000000000000000  x17: 0000000000000000
x18: 0000000000000000  x19: 0000000000000000  x20: 0000000000000000
x21: 0000000000000000  x22: 0000000000000000  x23: 0000000000000000
x24: 0000000000000000  x25: 0000000000000000  x26: 0000000000000000
x27: 0000000000000000  x28: 0000000000000000  x29: 000000000007FFF0
x30: 000000000008EF7C  elr_el1: 8EF7C  spsr_el1: 600003C4
  esr_el1: F2000000  far_el1: 0
sctlr_el1: 30D00800  tcr_el1: 0
>
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值