如何为 Raspberry pi 3 编译 ARMv8 代码
How to compile ARMv8 code for Raspberry pi 3
我一直在按照 here 上的教程为我的 raspberry pi 编写基本的 OS。我已经阅读了文档并更改了寄存器,以便它们应该 运行 但由于 raspberry pi 3 是 64 位,因此使用 ARMv8,lsl 超出范围。我正在使用 mac 所以我正在使用 YAGARTO 并且真的不知道如何或从哪里获得另一个 64 位编译器。
任何感兴趣的人的代码:
.section .init
.globl _start
_start:
ldr r0,=0x3f200000
mov r1,#1
lsl r1,#21
str r1,[r0,#16]
mov r1,#1
lsl r1,#47
str r1,[r0,#28]
loop$:
b loop$
我建议看一下 David Welch 的 RaspberryPi 3 的 aarch64 示例 here。为了方便起见,他的引导加载程序允许以 .hex 格式上传文件。
作为记录,您可以使用以下命令从已编译的可执行文件创建一个 .hex:
aarch64-none-objcopy program.elf -O ihex example.elf example.hex
关于工具链,据我所知Linaro和ARM只提供了Linux和mingw的工具链。但是您可以使用个人为 OSX 构建的工具链,例如 Sergio Benitez 提供的 this one。
更新: 一个方便的替代方法是根据 here.
中描述的出色过程在您的 SD 卡上安装 u-boot
假设您将 aarch64-none 工具链安装在 /opt 中,这样 aarch64-none-gcc 的路径将是:
/opt/aarch64-none/bin/aarch64-none-gcc
适合您需要的简化程序是:
正在您的 SD 卡上创建最小 config.txt,
enable_uart=1
arm_control=0x200
kernel=u-boot.bin
正在复制bootcode.bin, fixup.dat and start.elf到SD卡,
构建 u-boot,
wget ftp://ftp.denx.de/pub/u-boot/u-boot-2019.01.tar.bz2
tar Jxf u-boot-2019.01.tar.bz2
cd u-boot-2019.01
make CROSS_COMPILE=/opt/aarch64-none/bin/aarch64-none- ARCH=arm64 rpi_3_defconfig all
正在将 u-boot.bin 复制到 SD 卡 - 它现在应该包含以下文件:
2019-04-08 06:03 PM 108 config.txt
2019-04-08 04:11 PM 2,873,444 start.elf
2019-04-08 04:11 PM 52,296 bootcode.bin
2019-04-08 04:11 PM 6,701 fixup.dat
2019-04-08 04:08 PM 479,872 u-boot.bin
正在将 SD 卡安装到 Raspberry-pi3 中,
假设您安装了串口转 USB 加密狗,并且终端仿真器配置为使用具有以下设置的 USB 串口:
115200 bps, 8 data bits, 1 stop bit, no parity, no hardware flow control
您现在可以启动您的设备,并尽快按 CTRL+C
以中断启动过程:
U-Boot 2019.01 (Apr 08 2019 - 16:07:23 -0400)
DRAM: 948 MiB
RPI 3 Model B (0xa22082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT... *** Warning - bad CRC, using default environment
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB...
USB0: scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
U-Boot> <INTERRUPT>
bootdelay环境变量设置为2(秒),为了避免每次开机都使用CTRL+C
,需要设置为-1(无限):
U-Boot> printenv bootdelay
bootdelay=2
U-Boot> setenv bootdelay -1
U-Boot> saveenv
Saving Environment to FAT... OK
U-Boot>
如果你输入reset命令,pi会重启,但是u-boot会停止:
U-Boot> reset
resetting ...
U
‡t-Boot 2019.01 (Apr 08 2019 - 16:07:23 -0400)
DRAM: 948 MiB
RPI 3 Model B (0xa22082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT... OK
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB...
USB0: scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
U-Boot>
您现在可以对 examining/changing 内存和 loading/executing 程序使用所有可用的 u-boot 命令:
创建一个名为 hello-aarch64.s
的文件,内容如下:
.title "hello-aarch64.s"
.arch armv8-a
.equ AUX_MU_IO_REG, 0x3F215040
.equ AUX_MU_LSR_REG, 0x3F215054
.text
.section .text.startup,"ax"
.globl Reset_Handler
Reset_Handler: stp x29, x30, [sp, #-16]!
adr x19, msg
ldr x20,= AUX_MU_IO_REG
ldr x21,= AUX_MU_LSR_REG
loop: ldrb w0, [x19], 1
cbz w0, done
wait: ldrb w1, [x21]
tbz w1, #5, wait
strb w0, [x20]
b loop
done: ldp x29,x30, [sp], #16
ret
.balign 16
msg: .asciz "Hello, aarch64 bare-metal world!\r\n"
.end
因为我们将从 u-boot 调用程序并且不想让它崩溃,所以程序应该符合 ARM Procedure Call Standard for the ARM 64-bit Architecture - 这有点过分了,因为我们没有调用任何函数,不过没关系。
可以使用以下命令编译程序并创建 s-record 文件:
CROSS_COMPILE= /opt/aarch64-none/bin/aarch64-none-
AS=${CROSS_COMPILE}as
LD=${CROSS_COMPILE}ld
OBJCOPY=${CROSS_COMPILE}objcopy
OBJDUMP=${CROSS_COMPILE}objdump
${AS} -o hello-aarch64.o hello-aarch64.s
${LD} -e Reset_Handler --section-start .text=0x00200000 -Map=hello-aarch64.map -o hello-aarch64.elf hello-aarch64.o
${OBJCOPY} hello-aarch64.elf -O srec hello-aarch64.srec
现在可以上传并执行程序了:
在u-boot中输入以下命令:
U-Boot> loads
## Ready for S-Record download ...
从终端仿真器,将 hello-aarch64.srec
文件发送到 u-boot(没有 x-modem,没有 kermit,只是文件原样)。
## First Load Addr = 0x00200000
## Last Load Addr = 0x00200067
## Total Size = 0x00000068 = 104 Bytes
## Start Addr = 0x00200000
U-Boot>
使用 u-boot 的 go
命令来执行你的程序(go
命令实际上是一个 call
命令)。
U-Boot> go 0x00200000
## Starting application at 0x00200000 ...
Hello, aarch64 bare-metal world!
## Application terminated, rc = 0x0
U-Boot>
就是这样,你现在应该有一个很好的标准环境来学习 aarch64 汇编语言了。
抱歉说得冗长,但我们的目标是为需要的人提供一个简约但完整的程序。
我一直在按照 here 上的教程为我的 raspberry pi 编写基本的 OS。我已经阅读了文档并更改了寄存器,以便它们应该 运行 但由于 raspberry pi 3 是 64 位,因此使用 ARMv8,lsl 超出范围。我正在使用 mac 所以我正在使用 YAGARTO 并且真的不知道如何或从哪里获得另一个 64 位编译器。
任何感兴趣的人的代码:
.section .init
.globl _start
_start:
ldr r0,=0x3f200000
mov r1,#1
lsl r1,#21
str r1,[r0,#16]
mov r1,#1
lsl r1,#47
str r1,[r0,#28]
loop$:
b loop$
我建议看一下 David Welch 的 RaspberryPi 3 的 aarch64 示例 here。为了方便起见,他的引导加载程序允许以 .hex 格式上传文件。
作为记录,您可以使用以下命令从已编译的可执行文件创建一个 .hex:
aarch64-none-objcopy program.elf -O ihex example.elf example.hex
关于工具链,据我所知Linaro和ARM只提供了Linux和mingw的工具链。但是您可以使用个人为 OSX 构建的工具链,例如 Sergio Benitez 提供的 this one。
更新: 一个方便的替代方法是根据 here.
中描述的出色过程在您的 SD 卡上安装 u-boot假设您将 aarch64-none 工具链安装在 /opt 中,这样 aarch64-none-gcc 的路径将是:
/opt/aarch64-none/bin/aarch64-none-gcc
适合您需要的简化程序是:
正在您的 SD 卡上创建最小 config.txt,
enable_uart=1
arm_control=0x200
kernel=u-boot.bin
正在复制bootcode.bin, fixup.dat and start.elf到SD卡,
构建 u-boot,
wget ftp://ftp.denx.de/pub/u-boot/u-boot-2019.01.tar.bz2
tar Jxf u-boot-2019.01.tar.bz2
cd u-boot-2019.01
make CROSS_COMPILE=/opt/aarch64-none/bin/aarch64-none- ARCH=arm64 rpi_3_defconfig all
正在将 u-boot.bin 复制到 SD 卡 - 它现在应该包含以下文件:
2019-04-08 06:03 PM 108 config.txt
2019-04-08 04:11 PM 2,873,444 start.elf
2019-04-08 04:11 PM 52,296 bootcode.bin
2019-04-08 04:11 PM 6,701 fixup.dat
2019-04-08 04:08 PM 479,872 u-boot.bin
正在将 SD 卡安装到 Raspberry-pi3 中,
假设您安装了串口转 USB 加密狗,并且终端仿真器配置为使用具有以下设置的 USB 串口:
115200 bps, 8 data bits, 1 stop bit, no parity, no hardware flow control
您现在可以启动您的设备,并尽快按 CTRL+C
以中断启动过程:
U-Boot 2019.01 (Apr 08 2019 - 16:07:23 -0400)
DRAM: 948 MiB
RPI 3 Model B (0xa22082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT... *** Warning - bad CRC, using default environment
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB...
USB0: scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
Hit any key to stop autoboot: 0
U-Boot> <INTERRUPT>
bootdelay环境变量设置为2(秒),为了避免每次开机都使用CTRL+C
,需要设置为-1(无限):
U-Boot> printenv bootdelay
bootdelay=2
U-Boot> setenv bootdelay -1
U-Boot> saveenv
Saving Environment to FAT... OK
U-Boot>
如果你输入reset命令,pi会重启,但是u-boot会停止:
U-Boot> reset
resetting ...
U
‡t-Boot 2019.01 (Apr 08 2019 - 16:07:23 -0400)
DRAM: 948 MiB
RPI 3 Model B (0xa22082)
MMC: mmc@7e202000: 0, sdhci@7e300000: 1
Loading Environment from FAT... OK
In: serial
Out: vidconsole
Err: vidconsole
Net: No ethernet found.
starting USB...
USB0: scanning bus 0 for devices... 3 USB Device(s) found
scanning usb for storage devices... 0 Storage Device(s) found
U-Boot>
您现在可以对 examining/changing 内存和 loading/executing 程序使用所有可用的 u-boot 命令:
创建一个名为 hello-aarch64.s
的文件,内容如下:
.title "hello-aarch64.s"
.arch armv8-a
.equ AUX_MU_IO_REG, 0x3F215040
.equ AUX_MU_LSR_REG, 0x3F215054
.text
.section .text.startup,"ax"
.globl Reset_Handler
Reset_Handler: stp x29, x30, [sp, #-16]!
adr x19, msg
ldr x20,= AUX_MU_IO_REG
ldr x21,= AUX_MU_LSR_REG
loop: ldrb w0, [x19], 1
cbz w0, done
wait: ldrb w1, [x21]
tbz w1, #5, wait
strb w0, [x20]
b loop
done: ldp x29,x30, [sp], #16
ret
.balign 16
msg: .asciz "Hello, aarch64 bare-metal world!\r\n"
.end
因为我们将从 u-boot 调用程序并且不想让它崩溃,所以程序应该符合 ARM Procedure Call Standard for the ARM 64-bit Architecture - 这有点过分了,因为我们没有调用任何函数,不过没关系。
可以使用以下命令编译程序并创建 s-record 文件:
CROSS_COMPILE= /opt/aarch64-none/bin/aarch64-none-
AS=${CROSS_COMPILE}as
LD=${CROSS_COMPILE}ld
OBJCOPY=${CROSS_COMPILE}objcopy
OBJDUMP=${CROSS_COMPILE}objdump
${AS} -o hello-aarch64.o hello-aarch64.s
${LD} -e Reset_Handler --section-start .text=0x00200000 -Map=hello-aarch64.map -o hello-aarch64.elf hello-aarch64.o
${OBJCOPY} hello-aarch64.elf -O srec hello-aarch64.srec
现在可以上传并执行程序了: 在u-boot中输入以下命令:
U-Boot> loads
## Ready for S-Record download ...
从终端仿真器,将 hello-aarch64.srec
文件发送到 u-boot(没有 x-modem,没有 kermit,只是文件原样)。
## First Load Addr = 0x00200000
## Last Load Addr = 0x00200067
## Total Size = 0x00000068 = 104 Bytes
## Start Addr = 0x00200000
U-Boot>
使用 u-boot 的 go
命令来执行你的程序(go
命令实际上是一个 call
命令)。
U-Boot> go 0x00200000
## Starting application at 0x00200000 ...
Hello, aarch64 bare-metal world!
## Application terminated, rc = 0x0
U-Boot>
就是这样,你现在应该有一个很好的标准环境来学习 aarch64 汇编语言了。
抱歉说得冗长,但我们的目标是为需要的人提供一个简约但完整的程序。