作者 | 将狼才鲸 |
---|---|
创建日期 | 2022-11-14 |
- Gitee源码和工程地址:才鲸嵌入式 / 开源安防摄像机(嵌入式软件)
- CSDN文章地址:项目介绍:开源安防摄像机(嵌入式软件)
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》
软件名 | 版本 | 作用 | 特点 |
---|---|---|---|
MSYS | MSYS,MSYS2 | Linux命令行终端:Shell,Bash | 没有在Windows下编译Linux程序的工具集,会自带已经被MinGW编译好的一些包;脱胎于Cygwin,但容量更小;MSYS2是因为MSYS常年不更新而新组的的一个项目;MSYS2安装完后的文件名为msys64,你可以将你安装好之后的msys64文件夹打包发给别人,这样别人无安装就可以用了,只是容量有点大,几十G |
MinGW | MinGW32,MinGW64 | 一组编译工具链 | 编译后生成的是纯粹的Windows程序;它自带的命令行终端很难用也不全,要和MSYS2终端配合使用;MinGW64是因为MinGW32常年不更新而新组的的一个项目 |
Cygwin | Cygwin | 编译工具+命令行 | 有模拟层,将Linux API转成Windows API再执行程序,效率低,容量大,速度慢,2010年左右在Windows下搭建交叉编译环境时还多用它;要运行纯粹的Linux程序时也用它 |
- 参考网址:
4.1 安装MSYS2
- 我当前下载的版本是msys2-x86_64-20221028.exe
- 网上的安装教程是使用msys2打造优雅的开发环境
- 在官网主页找到下载链接:github.com/msys2/msys2-installer/releases/download/2022-10-28/msys2-x86_64-20221028.exe ,85M左右,这只是一个安装器,不是全部的软件;这是GitHub的地址,有时候下载慢,有时候无法访问;这个可下载的软件是CICD自动生成的,国内的Gitee镜像中也没有这个下载包;但你也可以在网上其它的地方比如网盘之类的找到这个文件的下载。
- 我将软件安装在D盘根目录,软件会安装在d:\msys64中,安装目录不能有空格、中文。
- 安装完之后先不打开软件,先将国外镜像地址换成国内镜像地址,参考上方教程。
- 电脑配置环境变量,在PATH中增加一行D:\msys64\usr\bin
- 双击运行主目录下的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/repos 、 MSYS2 Base Packages 和 MSYS2 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交叉编译工具
-
一些工具介绍:
- 树莓派提供了在Linux下使用的交叉工具包的文件夹名为gcc-linaro-arm-linux-gnueabihf-raspbian-x64,使用的编译器名为arm-linux-gnueabihf-gcc,下载地址raspberrypi-tools/ arm-bcm2708。
- GNU官方提供了树莓派在Windows中使用的交叉工具包,默认的工具是使用Visual Studio + VisualGDB来进行编译的。
32位地址:Prebuilt Windows Toolchain for Raspberry Pi
64位地址:Prebuilt Windows Toolchain for Raspberry Pi (64-bit) - ARM在Windows下自带的交叉编译工具为gcc-arm-none-eabi-10.3-2021.10-win32.exe,网页路径在https://developer.arm.com/downloads/-/gnu-rm ,交叉编译工具名为arm-none-eabi-gcc,我们不使用树莓派自带的交叉编译工具,而直接使用ARM的;因为树莓派没有直接给出MinGW下的交叉编译工具,而我也不想在Cygwin环境使用树莓派的Linux交叉编译工具。
-
但也不在ARM官方下载,我们在MSYS2中同样也能找到:在https://packages.msys2.org/base 中能搜到mingw-w64-arm-none-eabi-gcc和mingw-w64-arm-none-eabi-gdb
- MSYS2下载命令 pacman -S mingw-w64-x86_64-arm-none-eabi-gcc,大小有1.24 GB,参考网址:Package: mingw-w64-x86_64-arm-none-eabi-gcc
- GDB调试工具下载的命令 pacman -S mingw-w64-x86_64-arm-none-eabi-gdb,大小有7.92 MB,参考网址:Package: mingw-w64-x86_64-arm-none-eabi-gdb
- 安装完成后的文件在msys64/mingw64/bin/arm-none-eabi-gcc.exe
- 如果你需要使用aarch64-elf-gcc编译64位的ARM程序,在新版的树莓派中运行,则MSYS2网站中没有,你要去Linaro软件中下载。
-
如果有需要,你也可以安装用于64位ARM的交叉编译工具。
- 软件名称:gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu.tar.xz ,大小364M
- 下载路径:https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/
- 下载完之后放到msys64/mingw32/bin/里面去,用Linux命令解压,然后设置环境变量,使用方法和32位gcc交叉编译工具一样
- 我msys64中的路径是msys64/mingw32/bin/gcc-linaro-7.5.0-2019.12-i686-mingw32_aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc.exe
- 在Linaro这里也能下到32位的GCC交叉编译工具:gcc-linaro-7.5.0-2019.12-i686-mingw32_arm-linux-gnueabihf.tar.xz
- https://www.linaro.org/ Linaro公司主要是做ARM的一些开源工具,树莓派也是直接使用的Linaro编译器。
-
MSYS2安装make
- pacman -S make
- Package: make
-
参考网址:
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模拟中运行
- 在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,确认已经生效
- 进入msys64 raspi3-tutorial源码目录,编译并运行
-
源码我已经拷贝到msys64中,并且已经改了Makefile,能直接编译和运行,同时修改过以后的源码我也会在本仓重上传
-
源码路径 ~/raspi3-tutorial/01_bareminimum,也就是/home/jim/raspi3-tutorial/01_bareminimum,也就是D:\msys64\home\jim\raspi3-tutorial\01_bareminimum,后面所有的示例路径我都采用第一种写法。
-
进入目录 cd ~/raspi3-tutorial/01_bareminimum
-
编译 make
-
运行 make run
-
make run能运行,是因为在Makefile里面写了命令 qemu-system-aarch64 -M raspi3b -kernel kernel8.img -d in_asm
-
01_bareminimum用例是一个空程序,所以QEMU里面什么都不会显示,其它用例的效果我会再后面展示。
-
参考网址:
-
树莓派有关裸机编程的教程很少,我只找到了几个英文教程和几篇中文博客:
-
参考网址:
4.6 有关树莓派裸机编程的介绍
-
树莓派里面有GPU和ARM CPU,GPU先上电运行,然后再引导ARM运行
-
树莓派的GPU底层固件(Bootloader)是闭源的,但可以在此基础上引导自己的U-Boot、Linux kernel,也可以不用U-Boot和Linux,直接引导裸机程序或者RTOS;这种引导方式和Xilinx ZYNQ类似,ARM和FPGA一个先启动一个后启动。
-
一些其它的树莓派嵌入式相关的开源仓库:
(1) 运行在 Raspberry Pi 上的小型嵌入式系统
- Xinu project (xinu-os/xinu)
- Ultibo project (ultibohub/Core)
(2) 一些在 Raspberry Pi 上可以嵌入在其他系统中的运行库
- USPi(rsta2/uspi), 一个小型的支持 USB 通讯的库
(3) 以及其他一些基于 Raspberry Pi 裸机开发例子:
- Bare Metal Programming on Raspberry Pi 3:(bztsrc/raspi3-tutorial)
- Raspberry Pi ARM based bare metal examples (dwelch67/raspberrypi)
- 参考网址:
五、raspi3-tutorial硬件测试用例
- 原始网址:mirrors_bztsrc / raspi3-tutorial
- 本仓库中的地址:根目录/raspi3-tutorial/
- msys64中的地址:家目录 ~/raspi3-tutorial/
- 硬件是raspi3,64位ARM芯片,但因为有现成的代码,可以先熟悉编译环境,之后再在32位ARM上跑。
用例名称 | 作用 | 备注 |
---|---|---|
00_crosscompiler | 文档,只是描述编译器相关的内容 | |
01_bareminimum | 空程序,在汇编中死循环,只是为了验证编译器和模拟器安装正确,能够编译和运行 | |
02_multicorec | 写汇编boot,并引导C语言main函数运行 | |
03_uart1 | 串口打印Hello world,从MSYS2控制台输出 | |
04_mailboxes | CPU和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_virtualmemory | MMU虚拟内存映射 | |
11_exceptions | 测试异常中断 | |
12_printf | 测试printf输出 | |
13_debugger | gdb调试输出 | |
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
>