Allwinner a64 - 通过热重置从 aarch32 切换到 aarch64
Allwinner a64 - switch from aarch32 to aarch64 by warm reset
我想在Pine64板上部署一个简单的裸机软件,托管Allwinner A64 SoC。配置如下:开机后,boot0启动u-boot,将我的hello.bin
加载到RAM(0x40000000
)并开始执行。问题是它处于aarch32执行状态,我想要aarch64。
我找到了一种方法,如 this patch. Some background also on the wiki 中所述。
我复制了代码和 objdump -d hello.o
returns 与 link:
相同的结果
.text 部分的反汇编:
00000000 <_reset>:
0: e59f0024 ldr r0, [pc, #36] ; 2c <_reset+0x2c>
4: e59f1024 ldr r1, [pc, #36] ; 30 <_reset+0x30>
8: e5801000 str r1, [r0]
c: f57ff04f dsb sy
10: f57ff06f isb sy
14: ee1c0f50 mrc 15, 0, r0, cr12, cr0, {2}
18: e3800003 orr r0, r0, #3
1c: ee0c0f50 mcr 15, 0, r0, cr12, cr0, {2}
20: f57ff06f isb sy
24: e320f003 wfi
28: eafffffe b 28 <_reset+0x28>
2c: 017000a0 .word 0x017000a0
30: 40008000 .word 0x40008000
它应该在 aarch64 执行状态下执行 热重置 并在 0x40008000
开始执行。但是当 运行 我收到 未定义指令 错误时,它会以相同的状态重新启动并从 0x0
开始。
## Starting application at 0x40000000 ...
undefined instruction
pc : [<40000018>] lr : [<7ff1d054>]
sp : 76eb8a90 ip : 00000030 fp : 7ff1d00c
r10: 00000002 r9 : 76ed0ea0 r8 : 7ffb5340
r7 : 77f1bd78 r6 : 40000000 r5 : 00000002 r4 : 77f1bd7c
r3 : 40000000 r2 : 77f1bd7c r1 : 40008000 r0 : 017000a0
Flags: nZCv IRQs on FIQs off Mode SVC_32
Resetting CPU ...
这是为什么?
编辑:
下面的@Frant 注意到了第一个问题,应该使用不同的 .text 部分地址 linked 的二进制文件,即从 0x40000000
开始而不是 0x0
.
u-boot加载也不行,就是在EL2中。为了写入 RMR,需要在 EL3 中。这可以通过 FEL 方法实现。
注意:
遇到这个问题后,我四处寻求帮助,显然我使用的是一种老式的烧写电路板的方法。由于一段时间以来 Pine64 得到了更好的支持,现在可以通过两种更方便的方式启动它:
* 带有 atf 的主线 u-boot,将直接生成一个二进制文件,可以闪存到 SD 卡,并将您放入 EL2,
* 使用 sunxi-fel
工具,如下所述,如果不想一直重新刷写 SD 卡,这将非常方便,让您进入 EL3(警告:sunxi wiki 在 sunxi-fel
命令参数,下面这些对我有用)。
我的回答是试图回答以下问题:您正在使用的 aarch32 状态切换代码是否有效?
好消息是您正在使用的代码可以正常工作。坏消息是,考虑到所有 Allwinner 开箱即用的 BSP 的糟糕状态,您的 environment.This 中的其他东西可能无法正常工作不会让我感到惊讶。
由于我不知道您使用的是哪个确切版本的 boot0 和 u-boot,我使用 Andre Przywara 的 FEL-capable SPL binaries for A64/H5 - see the FEL Booting section of the A64 entry for more details - and sunxi-fel 测试了您的代码:这确实删除了您用作潜在罪魁祸首的 boot0 和 u-boot。
我为测试您的代码而构建的 Minimal, Complete, and Verifiable example 需要:
- Pine64拔出SD卡,开机进入FEL模式,
- 一根公-A 转公-A USB 2.0 电缆,用于将您的 PC 连接到 Pine64 的 upper USB host receptacle。
一个 bash 脚本,build.sh
,用于构建 sunxi-tools,检索支持 FEL 的 SPL 二进制文件,
rmr_switch.S
,rmr_switch.S的一个版本减去注释加上一个设置起始地址需要预处理的符号,不用一直修改文件,
rmr_switch2.S
,上面提到的 rmr_switch.S 的一个版本,但使用 r0 和 r1 的方式与您引用的补丁中的使用方式相同。
uart-aarch32.s
,一个aarch32程序在UART0上显示*** Hello from aarch32! ***
,
uart-aarch64.s
,一个在 UART0 上显示 *** Hello from aarch64! ***
的 aarch64 程序。
以下是每个必需文件的内容:
build.sh:
#!/bin/bash
# usage:
# CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh
clear
CROSS_COMPILE_AARCH64=${CROSS_COMPILE_AARCH64:-/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf-}
CROSS_COMPILE_AARCH32=${CROSS_COMPILE_AARCH32:-/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi-}
SOC=${SOC:-a64}
#AARCH32_START_ADDRESS=0x42000000
#AARCH64_START_ADDRESS=0x42010000
AARCH32_START_ADDRESS=0x40000000
AARCH64_START_ADDRESS=0x40008000
SUNXI_FEL=sunxi-tools/sunxi-fel
install_sunxi_tools()
{
if [ ! -f ${SUNXI_FEL} ]
then
git clone --branch v1.4.2 https://github.com/linux-sunxi/sunxi-tools
pushd sunxi-tools
make
popd
fi
}
retrieve_spl_aarch32()
{
if [ ! -f sunxi-a64-spl32-ddr3.bin ]
then
wget https://github.com/apritzel/pine64/raw/master/binaries/sunxi-a64-spl32-ddr3.bin
fi
if [ ! -f sunxi-h5-spl32-ddr3.bin ]
then
wget https://github.com/apritzel/pine64/raw/master/binaries/sunxi-h5-spl32-ddr3.bin
fi
}
test_aarch32()
{
# testing aarch32 program
PROGRAM=uart-aarch32.s
BASE=${PROGRAM%%.*}
${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH64_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s
${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf
${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf
${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst
${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin
${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec
echo "------------------ test uart-aarch32 -----------------------------"
echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin
echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} uart-aarch32.bin
echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS}
echo "------------------------------------------------------------------"
}
test_aarch64()
{
# testing aarch64 program
PROGRAM=uart-aarch64.s
BASE=${PROGRAM%%.*}
${CROSS_COMPILE_AARCH64}gcc -O0 -nostdlib -nostartfiles -e ${AARCH64_START_ADDRESS} -Wl,-Ttext=${AARCH64_START_ADDRESS} -o ${BASE}.elf ${BASE}.s
${CROSS_COMPILE_AARCH64}objcopy --remove-section .note.gnu.build-id ${BASE}.elf
${CROSS_COMPILE_AARCH64}objcopy --remove-section .ARM.attributes ${BASE}.elf
${CROSS_COMPILE_AARCH64}objdump -D ${BASE}.elf > ${BASE}.lst
${CROSS_COMPILE_AARCH64}objcopy -O binary ${BASE}.elf ${BASE}.bin
${CROSS_COMPILE_AARCH64}objcopy ${BASE}.elf -O srec ${BASE}.srec
echo "------------------ test uart-aarch64 -----------------------------"
echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin
echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin
echo sudo ${SUNXI_FEL} reset64 ${AARCH64_START_ADDRESS}
echo "------------------------------------------------------------------"
}
test_rmr_switch()
{
# compiling rmr_switch.s
PROGRAM=rmr_switch.s
BASE=${PROGRAM%%.*}
rm -f ${BASE}.s
${CROSS_COMPILE_AARCH64}cpp -DAARCH64_START_ADDRESS=${AARCH64_START_ADDRESS} ${BASE}.S > ${BASE}.s
${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH32_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s
${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf
${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf
${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst
${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin
${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec
echo "------------------ test rmr_switch uart-aarch64 ------------------"
echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin
echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} rmr_switch.bin
echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin
echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS}
echo "------------------------------------------------------------------"
}
test_rmr_switch2()
{
# compiling rmr_switch2.s
PROGRAM=rmr_switch2.s
BASE=${PROGRAM%%.*}
rm -f ${BASE}.s
${CROSS_COMPILE_AARCH64}cpp -DAARCH64_START_ADDRESS=${AARCH64_START_ADDRESS} ${BASE}.S > ${BASE}.s
${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH32_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s
${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf
${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf
${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst
${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin
${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec
echo "------------------ test rmr_switch2 uart-aarch64 -----------------"
echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin
echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} rmr_switch2.bin
echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin
echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS}
echo "------------------------------------------------------------------"
}
# prerequisites
install_sunxi_tools
retrieve_spl_aarch32
# test
test_aarch32
test_aarch64
test_rmr_switch
test_rmr_switch2
rmr_switch.S:
.text
ldr r1, =0x017000a0 @ MMIO mapped RVBAR[0] register
ldr r0, =AARCH64_START_ADDRESS @ start address, to be replaced
str r0, [r1]
dsb sy
isb sy
mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register
orr r0, r0, #3 @ request reset in AArch64
mcr 15, 0, r0, cr12, cr0, 2 @ write RMR register
isb sy
1: wfi
b 1b
rmr_switch2.S:
.text
ldr r0, =0x017000a0 @ MMIO mapped RVBAR[0] register
ldr r1, =AARCH64_START_ADDRESS @ start address, to be replaced
str r1, [r0]
dsb sy
isb sy
mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register
orr r0, r0, #3 @ request reset in AArch64
mcr 15, 0, r0, cr12, cr0, 2 @ write RMR register
isb sy
1: wfi
b 1b
uart-aarch32.s:
.code 32
.text
ldr r1,=0x01C28000
ldr r2,=message
loop: ldrb r0, [r2]
add r2, r2, #1
cmp r0, #0
beq completed
strb r0, [r1]
b loop
completed: b .
.data
message:
.asciz "*** Hello from aarch32! ***"
.end
uart-aarch64.s:
.text
ldr x1,=0x01C28000
ldr x2,=message
loop: ldrb w0, [x2]
add x2, x2, #1
cmp w0, #0
beq completed
strb w0, [x1]
b loop
completed: b .
.data
message:
.asciz "*** Hello from aarch64! ***"
.end
一旦所有文件都在同一目录中,测试过程将是:
执行build.sh:可以指定你使用的SOC是A64(默认)还是H5,命令行中的aarch32/aarch64 toolchains:
CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh
输出应该是这样的,(我删除了无害的警告):
------------------ test uart-aarch32 -----------------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 uart-aarch32.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------ test uart-aarch64 -----------------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel reset64 0x40008000
------------------ test rmr_switch uart-aarch64 ------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 rmr_switch.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------ test rmr_switch2 uart-aarch64 -----------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 rmr_switch2.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------------------------------------------------------
现在,在输入四个测试中的每一个所需的 sunxi-fel
命令之前,您需要将 Pine64 从电源和它可能插入的任何 USB 主机插座上拔下(USB TTL uart,公-A 到公-USB 数据线)。将 Pine64 重新连接到电源,然后重新插入 USB 数据线。
lsusb
现在应该显示:
Bus 001 Device 016: ID 1f3a:efe8 Onda (unverified) V972 tablet in flashing mode
四个测试的串行控制台输出应该是:
测试 uart-aarch32(验证 aarch32 程序从 0x40000000 运行):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52)
DRAM: 512 MiB
Trying to boot from FEL
*** Hello from aarch32! ***
test uart-aarch64(验证 aarch64 程序从 0x40008000 运行):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52)
DRAM: 512 MiB
Trying to boot from FEL
*** Hello from aarch64! ***
test test rmr_switch uart-aarch64 (运行 rmr_switch from 0x40000000,会切换到aarch64状态,执行uart-aarch64 from 0x40008000):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52)
DRAM: 512 MiB
Trying to boot from FEL
*** Hello from aarch64! ***
test test rmr_switch2 uart-aarch64 (运行 rmr_switch2 from 0x40000000,会切换到aarch64状态,执行uart-aarch64 from 0x40008000) :
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52)
DRAM: 512 MiB
Trying to boot from FEL
*** Hello from aarch64! ***
值得一提的是,可以使用 Linaro mingw32 工具链、Windows 版本的 sunxi-fel 和 Zadig 执行这些测试on Windows。
最重要的是,您使用的代码似乎运行良好,我组装的 rmr_switch2.s 代码与您使用的代码相同(我猜):
rmr_switch2.elf: file format elf32-littlearm
Disassembly of section .text:
40000000 <.text>:
40000000: e59f0024 ldr r0, [pc, #36] ; 4000002c <.text+0x2c>
40000004: e59f1024 ldr r1, [pc, #36] ; 40000030 <.text+0x30>
40000008: e5801000 str r1, [r0]
4000000c: f57ff04f dsb sy
40000010: f57ff06f isb sy
40000014: ee1c0f50 mrc 15, 0, r0, cr12, cr0, {2}
40000018: e3800003 orr r0, r0, #3
4000001c: ee0c0f50 mcr 15, 0, r0, cr12, cr0, {2}
40000020: f57ff06f isb sy
40000024: e320f003 wfi
40000028: eafffffd b 40000024 <.text+0x24>
4000002c: 017000a0 cmneq r0, r0, lsr #1
40000030: 40008000 andmi r8, r0, r0
示例已在基于 H5 的 OrangePI PC2 上成功测试。 运行 build.sh 的命令行应该是:
SOC=h5 CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh
build.sh 的输出以及因此要执行的 sunxi-fel 命令将略有不同,因为必须使用不同的、特定于 H5、支持 FEL 的 SPL。
我注意到您使用的代码与 rmr_switch2 代码之间存在细微差别,但由于它出现在状态 switch/after wfi 之后,我想这应该无关紧要 - 我是假设您组装的代码本身略有不同:
你的 (.o):
28: eafffffe b 28 <_reset+0x28>
我的(.elf):
40000028: eafffffd b 40000024 <.text+0x24>
希望对您有所帮助。
我想在Pine64板上部署一个简单的裸机软件,托管Allwinner A64 SoC。配置如下:开机后,boot0启动u-boot,将我的hello.bin
加载到RAM(0x40000000
)并开始执行。问题是它处于aarch32执行状态,我想要aarch64。
我找到了一种方法,如 this patch. Some background also on the wiki 中所述。
我复制了代码和 objdump -d hello.o
returns 与 link:
.text 部分的反汇编:
00000000 <_reset>:
0: e59f0024 ldr r0, [pc, #36] ; 2c <_reset+0x2c>
4: e59f1024 ldr r1, [pc, #36] ; 30 <_reset+0x30>
8: e5801000 str r1, [r0]
c: f57ff04f dsb sy
10: f57ff06f isb sy
14: ee1c0f50 mrc 15, 0, r0, cr12, cr0, {2}
18: e3800003 orr r0, r0, #3
1c: ee0c0f50 mcr 15, 0, r0, cr12, cr0, {2}
20: f57ff06f isb sy
24: e320f003 wfi
28: eafffffe b 28 <_reset+0x28>
2c: 017000a0 .word 0x017000a0
30: 40008000 .word 0x40008000
它应该在 aarch64 执行状态下执行 热重置 并在 0x40008000
开始执行。但是当 运行 我收到 未定义指令 错误时,它会以相同的状态重新启动并从 0x0
开始。
## Starting application at 0x40000000 ...
undefined instruction
pc : [<40000018>] lr : [<7ff1d054>]
sp : 76eb8a90 ip : 00000030 fp : 7ff1d00c
r10: 00000002 r9 : 76ed0ea0 r8 : 7ffb5340
r7 : 77f1bd78 r6 : 40000000 r5 : 00000002 r4 : 77f1bd7c
r3 : 40000000 r2 : 77f1bd7c r1 : 40008000 r0 : 017000a0
Flags: nZCv IRQs on FIQs off Mode SVC_32
Resetting CPU ...
这是为什么?
编辑:
下面的@Frant 注意到了第一个问题,应该使用不同的 .text 部分地址 linked 的二进制文件,即从
0x40000000
开始而不是0x0
.u-boot加载也不行,就是在EL2中。为了写入 RMR,需要在 EL3 中。这可以通过 FEL 方法实现。
注意:
遇到这个问题后,我四处寻求帮助,显然我使用的是一种老式的烧写电路板的方法。由于一段时间以来 Pine64 得到了更好的支持,现在可以通过两种更方便的方式启动它:
* 带有 atf 的主线 u-boot,将直接生成一个二进制文件,可以闪存到 SD 卡,并将您放入 EL2,
* 使用 sunxi-fel
工具,如下所述,如果不想一直重新刷写 SD 卡,这将非常方便,让您进入 EL3(警告:sunxi wiki 在 sunxi-fel
命令参数,下面这些对我有用)。
我的回答是试图回答以下问题:您正在使用的 aarch32 状态切换代码是否有效?
好消息是您正在使用的代码可以正常工作。坏消息是,考虑到所有 Allwinner 开箱即用的 BSP 的糟糕状态,您的 environment.This 中的其他东西可能无法正常工作不会让我感到惊讶。
由于我不知道您使用的是哪个确切版本的 boot0 和 u-boot,我使用 Andre Przywara 的 FEL-capable SPL binaries for A64/H5 - see the FEL Booting section of the A64 entry for more details - and sunxi-fel 测试了您的代码:这确实删除了您用作潜在罪魁祸首的 boot0 和 u-boot。
我为测试您的代码而构建的 Minimal, Complete, and Verifiable example 需要:
- Pine64拔出SD卡,开机进入FEL模式,
- 一根公-A 转公-A USB 2.0 电缆,用于将您的 PC 连接到 Pine64 的 upper USB host receptacle。
一个 bash 脚本,
build.sh
,用于构建 sunxi-tools,检索支持 FEL 的 SPL 二进制文件,rmr_switch.S
,rmr_switch.S的一个版本减去注释加上一个设置起始地址需要预处理的符号,不用一直修改文件,rmr_switch2.S
,上面提到的 rmr_switch.S 的一个版本,但使用 r0 和 r1 的方式与您引用的补丁中的使用方式相同。uart-aarch32.s
,一个aarch32程序在UART0上显示*** Hello from aarch32! ***
,uart-aarch64.s
,一个在 UART0 上显示*** Hello from aarch64! ***
的 aarch64 程序。
以下是每个必需文件的内容:build.sh:
#!/bin/bash # usage: # CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh clear CROSS_COMPILE_AARCH64=${CROSS_COMPILE_AARCH64:-/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf-} CROSS_COMPILE_AARCH32=${CROSS_COMPILE_AARCH32:-/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi-} SOC=${SOC:-a64} #AARCH32_START_ADDRESS=0x42000000 #AARCH64_START_ADDRESS=0x42010000 AARCH32_START_ADDRESS=0x40000000 AARCH64_START_ADDRESS=0x40008000 SUNXI_FEL=sunxi-tools/sunxi-fel install_sunxi_tools() { if [ ! -f ${SUNXI_FEL} ] then git clone --branch v1.4.2 https://github.com/linux-sunxi/sunxi-tools pushd sunxi-tools make popd fi } retrieve_spl_aarch32() { if [ ! -f sunxi-a64-spl32-ddr3.bin ] then wget https://github.com/apritzel/pine64/raw/master/binaries/sunxi-a64-spl32-ddr3.bin fi if [ ! -f sunxi-h5-spl32-ddr3.bin ] then wget https://github.com/apritzel/pine64/raw/master/binaries/sunxi-h5-spl32-ddr3.bin fi } test_aarch32() { # testing aarch32 program PROGRAM=uart-aarch32.s BASE=${PROGRAM%%.*} ${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH64_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s ${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf ${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf ${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst ${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin ${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec echo "------------------ test uart-aarch32 -----------------------------" echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} uart-aarch32.bin echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS} echo "------------------------------------------------------------------" } test_aarch64() { # testing aarch64 program PROGRAM=uart-aarch64.s BASE=${PROGRAM%%.*} ${CROSS_COMPILE_AARCH64}gcc -O0 -nostdlib -nostartfiles -e ${AARCH64_START_ADDRESS} -Wl,-Ttext=${AARCH64_START_ADDRESS} -o ${BASE}.elf ${BASE}.s ${CROSS_COMPILE_AARCH64}objcopy --remove-section .note.gnu.build-id ${BASE}.elf ${CROSS_COMPILE_AARCH64}objcopy --remove-section .ARM.attributes ${BASE}.elf ${CROSS_COMPILE_AARCH64}objdump -D ${BASE}.elf > ${BASE}.lst ${CROSS_COMPILE_AARCH64}objcopy -O binary ${BASE}.elf ${BASE}.bin ${CROSS_COMPILE_AARCH64}objcopy ${BASE}.elf -O srec ${BASE}.srec echo "------------------ test uart-aarch64 -----------------------------" echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin echo sudo ${SUNXI_FEL} reset64 ${AARCH64_START_ADDRESS} echo "------------------------------------------------------------------" } test_rmr_switch() { # compiling rmr_switch.s PROGRAM=rmr_switch.s BASE=${PROGRAM%%.*} rm -f ${BASE}.s ${CROSS_COMPILE_AARCH64}cpp -DAARCH64_START_ADDRESS=${AARCH64_START_ADDRESS} ${BASE}.S > ${BASE}.s ${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH32_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s ${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf ${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf ${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst ${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin ${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec echo "------------------ test rmr_switch uart-aarch64 ------------------" echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} rmr_switch.bin echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS} echo "------------------------------------------------------------------" } test_rmr_switch2() { # compiling rmr_switch2.s PROGRAM=rmr_switch2.s BASE=${PROGRAM%%.*} rm -f ${BASE}.s ${CROSS_COMPILE_AARCH64}cpp -DAARCH64_START_ADDRESS=${AARCH64_START_ADDRESS} ${BASE}.S > ${BASE}.s ${CROSS_COMPILE_AARCH32}gcc -O0 -nostdlib -nostartfiles -e ${AARCH32_START_ADDRESS} -Wl,-Ttext=${AARCH32_START_ADDRESS} -o ${BASE}.elf ${BASE}.s ${CROSS_COMPILE_AARCH32}objcopy --remove-section .note.gnu.build-id ${BASE}.elf ${CROSS_COMPILE_AARCH32}objcopy --remove-section .ARM.attributes ${BASE}.elf ${CROSS_COMPILE_AARCH32}objdump -D ${BASE}.elf > ${BASE}.lst ${CROSS_COMPILE_AARCH32}objcopy -O binary ${BASE}.elf ${BASE}.bin ${CROSS_COMPILE_AARCH32}objcopy ${BASE}.elf -O srec ${BASE}.srec echo "------------------ test rmr_switch2 uart-aarch64 -----------------" echo sudo ${SUNXI_FEL} spl sunxi-${SOC}-spl32-ddr3.bin echo sudo ${SUNXI_FEL} write ${AARCH32_START_ADDRESS} rmr_switch2.bin echo sudo ${SUNXI_FEL} write ${AARCH64_START_ADDRESS} uart-aarch64.bin echo sudo ${SUNXI_FEL} exe ${AARCH32_START_ADDRESS} echo "------------------------------------------------------------------" } # prerequisites install_sunxi_tools retrieve_spl_aarch32 # test test_aarch32 test_aarch64 test_rmr_switch test_rmr_switch2
rmr_switch.S:
.text ldr r1, =0x017000a0 @ MMIO mapped RVBAR[0] register ldr r0, =AARCH64_START_ADDRESS @ start address, to be replaced str r0, [r1] dsb sy isb sy mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register orr r0, r0, #3 @ request reset in AArch64 mcr 15, 0, r0, cr12, cr0, 2 @ write RMR register isb sy 1: wfi b 1b
rmr_switch2.S:
.text ldr r0, =0x017000a0 @ MMIO mapped RVBAR[0] register ldr r1, =AARCH64_START_ADDRESS @ start address, to be replaced str r1, [r0] dsb sy isb sy mrc 15, 0, r0, cr12, cr0, 2 @ read RMR register orr r0, r0, #3 @ request reset in AArch64 mcr 15, 0, r0, cr12, cr0, 2 @ write RMR register isb sy 1: wfi b 1b
uart-aarch32.s:
.code 32 .text ldr r1,=0x01C28000 ldr r2,=message loop: ldrb r0, [r2] add r2, r2, #1 cmp r0, #0 beq completed strb r0, [r1] b loop completed: b . .data message: .asciz "*** Hello from aarch32! ***" .end
uart-aarch64.s:
.text ldr x1,=0x01C28000 ldr x2,=message loop: ldrb w0, [x2] add x2, x2, #1 cmp w0, #0 beq completed strb w0, [x1] b loop completed: b . .data message: .asciz "*** Hello from aarch64! ***" .end
一旦所有文件都在同一目录中,测试过程将是:
执行build.sh:可以指定你使用的SOC是A64(默认)还是H5,命令行中的aarch32/aarch64 toolchains:
CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh
输出应该是这样的,(我删除了无害的警告):
------------------ test uart-aarch32 -----------------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 uart-aarch32.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------ test uart-aarch64 -----------------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel reset64 0x40008000
------------------ test rmr_switch uart-aarch64 ------------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 rmr_switch.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------ test rmr_switch2 uart-aarch64 -----------------
sudo sunxi-tools/sunxi-fel spl sunxi-a64-spl32-ddr3.bin
sudo sunxi-tools/sunxi-fel write 0x40000000 rmr_switch2.bin
sudo sunxi-tools/sunxi-fel write 0x40008000 uart-aarch64.bin
sudo sunxi-tools/sunxi-fel exe 0x40000000
------------------------------------------------------------------
现在,在输入四个测试中的每一个所需的 sunxi-fel
命令之前,您需要将 Pine64 从电源和它可能插入的任何 USB 主机插座上拔下(USB TTL uart,公-A 到公-USB 数据线)。将 Pine64 重新连接到电源,然后重新插入 USB 数据线。
lsusb
现在应该显示:
Bus 001 Device 016: ID 1f3a:efe8 Onda (unverified) V972 tablet in flashing mode
四个测试的串行控制台输出应该是:
测试 uart-aarch32(验证 aarch32 程序从 0x40000000 运行):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52) DRAM: 512 MiB Trying to boot from FEL *** Hello from aarch32! ***
test uart-aarch64(验证 aarch64 程序从 0x40008000 运行):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52) DRAM: 512 MiB Trying to boot from FEL *** Hello from aarch64! ***
test test rmr_switch uart-aarch64 (运行 rmr_switch from 0x40000000,会切换到aarch64状态,执行uart-aarch64 from 0x40008000):
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52) DRAM: 512 MiB Trying to boot from FEL *** Hello from aarch64! ***
test test rmr_switch2 uart-aarch64 (运行 rmr_switch2 from 0x40000000,会切换到aarch64状态,执行uart-aarch64 from 0x40008000) :
U-Boot SPL 2018.01-00007-gdb0ecc9b42 (Feb 23 2018 - 00:50:52) DRAM: 512 MiB Trying to boot from FEL *** Hello from aarch64! ***
值得一提的是,可以使用 Linaro mingw32 工具链、Windows 版本的 sunxi-fel 和 Zadig 执行这些测试on Windows。
最重要的是,您使用的代码似乎运行良好,我组装的 rmr_switch2.s 代码与您使用的代码相同(我猜):
rmr_switch2.elf: file format elf32-littlearm
Disassembly of section .text:
40000000 <.text>:
40000000: e59f0024 ldr r0, [pc, #36] ; 4000002c <.text+0x2c>
40000004: e59f1024 ldr r1, [pc, #36] ; 40000030 <.text+0x30>
40000008: e5801000 str r1, [r0]
4000000c: f57ff04f dsb sy
40000010: f57ff06f isb sy
40000014: ee1c0f50 mrc 15, 0, r0, cr12, cr0, {2}
40000018: e3800003 orr r0, r0, #3
4000001c: ee0c0f50 mcr 15, 0, r0, cr12, cr0, {2}
40000020: f57ff06f isb sy
40000024: e320f003 wfi
40000028: eafffffd b 40000024 <.text+0x24>
4000002c: 017000a0 cmneq r0, r0, lsr #1
40000030: 40008000 andmi r8, r0, r0
示例已在基于 H5 的 OrangePI PC2 上成功测试。 运行 build.sh 的命令行应该是:
SOC=h5 CROSS_COMPILE_AARCH64=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_aarch64-elf/bin/aarch64-elf- CROSS_COMPILE_AARCH32=/opt/linaro/gcc-linaro-7.2.1-2017.11-x86_64_arm-eabi/bin/arm-eabi- ./build.sh
build.sh 的输出以及因此要执行的 sunxi-fel 命令将略有不同,因为必须使用不同的、特定于 H5、支持 FEL 的 SPL。
我注意到您使用的代码与 rmr_switch2 代码之间存在细微差别,但由于它出现在状态 switch/after wfi 之后,我想这应该无关紧要 - 我是假设您组装的代码本身略有不同:
你的 (.o):
28: eafffffe b 28 <_reset+0x28>
我的(.elf):
40000028: eafffffd b 40000024 <.text+0x24>
希望对您有所帮助。