Linux 转到u-boot命令提示符。您可以从那里使用u-boot命令检查内存,查看程序是否按预期工作,或者使用其他命令
但如果您想再次使用Linux 转到u-boot命令提示符。您可以从那里使用u-boot命令检查内存,查看程序是否按预期工作,或者使用其他命令,linux,xilinx,u-boot,Linux,Xilinx,U Boot,但如果您想再次使用go,则必须重新启动u-boot。 从这里开始,如果您想在Allwinner平台上使用go,您可以修改回实现,以便u-boot在执行程序之前不会切换到EL1,并在您的系统上安装修改后的版本: unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc, char *const argv[]) { int ret = 0; if (current_el(
go
,则必须重新启动u-boot。
从这里开始,如果您想在Allwinner平台上使用go
,您可以修改回实现,以便u-boot在执行程序之前不会切换到EL1
,并在您的系统上安装修改后的版本:
unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
char *const argv[])
{
int ret = 0;
if (current_el() > 1) {
smp_kick_all_cpus();
dcache_disable();
ret = entry(argc, argv);
} else {
printf("FAIL: current EL is not above or equal to EL1\n");
ret = EINVAL;
}
return ret;
}
另一种方法是添加一个新的go2
命令,该命令将使用上述实现
b) hello_world程序的启动代码不会根据ARM调用约定保留寄存器,更重要的是,它会按照一些ARM应用程序注释中的建议清除所有寄存器:
Disassembly of section .text:
0000000000000000 <_vector_table>:
0: 1400024e b 938 <_boot>
...
200: 14000061 b 384 <SynchronousInterruptHandler>
...
280: 14000082 b 488 <IRQInterruptHandler>
...
300: 140000a1 b 584 <FIQInterruptHandler>
...
380: 14000099 b 5e4 <SErrorInterruptHandler>
0000000000000938 <_boot>:
938: d2800000 mov x0, #0x0 // #0
93c: d2800001 mov x1, #0x0 // #0
940: d2800002 mov x2, #0x0 // #0
944: d2800003 mov x3, #0x0 // #0
948: d2800004 mov x4, #0x0 // #0
94c: d2800005 mov x5, #0x0 // #0
950: d2800006 mov x6, #0x0 // #0
954: d2800007 mov x7, #0x0 // #0
958: d2800008 mov x8, #0x0 // #0
95c: d2800009 mov x9, #0x0 // #0
960: d280000a mov x10, #0x0 // #0
964: d280000b mov x11, #0x0 // #0
968: d280000c mov x12, #0x0 // #0
96c: d280000d mov x13, #0x0 // #0
970: d280000e mov x14, #0x0 // #0
974: d280000f mov x15, #0x0 // #0
978: d2800010 mov x16, #0x0 // #0
97c: d2800011 mov x17, #0x0 // #0
980: d2800012 mov x18, #0x0 // #0
984: d2800013 mov x19, #0x0 // #0
988: d2800014 mov x20, #0x0 // #0
98c: d2800015 mov x21, #0x0 // #0
990: d2800016 mov x22, #0x0 // #0
994: d2800017 mov x23, #0x0 // #0
998: d2800018 mov x24, #0x0 // #0
99c: d2800019 mov x25, #0x0 // #0
9a0: d280001a mov x26, #0x0 // #0
9a4: d280001b mov x27, #0x0 // #0
9a8: d280001c mov x28, #0x0 // #0
9ac: d280001d mov x29, #0x0 // #0
9b0: d280001e mov x30, #0x0 // #0
节的反汇编。文本:
0000000000000000 :
0:1400024e b 938
...
200:14000061 b 384
...
280:14000082B488
...
300:140000a1 b 584
...
380:14000099 b 5e4
0000000000000938 :
938:d2800000 mov x0,#0x0/#0
93c:d2800001 mov x1,#0x0/#0
940:d2800002 mov x2,#0x0/#0
944:d2800003 mov x3,#0x0/#0
948:d2800004 mov x4,#0x0/#0
94c:D280005MOVx5,#0x0/#0
950:D280006 mov x6,#0x0/#0
954:d2800007 mov x7,#0x0/#0
958:d2800008 mov x8,#0x0/#0
95c:d2800009 mov x9,#0x0/#0
960:D28000A mov x10,#0x0/#0
964:d280000b mov x11,#0x0/#0
968:D28000C mov x12,#0x0/#0
96c:d280000d mov x13,#0x0/#0
970:d280000e mov x14,#0x0/#0
974:d280000f mov x15,#0x0/#0
978:d2800010 mov x16,#0x0/#0
97c:d2800011 mov x17,#0x0/#0
980:d2800012 mov x18,#0x0/#0
984:d2800013 mov x19,#0x0/#0
988:d2800014 mov x20,#0x0/#0
98c:d2800015 mov x21,#0x0/#0
990:d2800016 mov x22,#0x0/#0
994:d2800017 mov x23,#0x0/#0
998:d2800018 mov x24,#0x0/#0
99c:d2800019 mov x25,#0x0/#0
9a0:d280001a mov x26,#0x0/#0
9a4:d280001b mov x27,#0x0/#0
9a8:d280001c mov x28,#0x0/#0
9ac:d280001d mov x29,#0x0/#0
9b0:d280001e mov x30,#0x0/#0
当然,这确实使得优雅地返回u-boot变得不可能,即使这是一种很好的方法,如果您不必返回被调用方
c) u-boot执行的程序应该返回到调用代码,但演示程序的启动代码实际上进入了一个无休止的循环,这通常很好,但在您的用例中不是这样:
00000000000014c0 <_exit>:
14c0: 14000000 b 14c0 <_exit>
00000000000014c0:
14c0:14000000B 14c0
解决当前行为需要修改Vitis提供的启动代码,或使用您自己的修改版本,以便:
- u-boot使用的寄存器将被保存/恢复
- 程序将返回,而不是进入无休止的循环
go
命令的行为,这样程序就不会在EL1
上执行:这对于安全和生产系统来说是完美的,但对于学习来说确实是有害的。我个人在学习Armv8-a
体系结构时,正在使用运行于EL3
的u-boot
这将需要更多的工作/测试,可能值得,也可能不值得,这取决于您计划做什么。我删除了我的原始答案,因为我忽略了您能够执行
add.bin
,只有第二次尝试失败,因为程序在切换到EL1
后返回。我最终能够下载。使用Vitis,并分解hello_world程序。第二个版本应该正确地回答您的原始问题。更具体地说,它确实解释了为什么您的程序永远不会返回u-boot命令提示符。@Prasanna Kotrappa这是否回答了您最初的问题,还是需要改进?谢谢
#include <stdint.h>
int main(int argc, char** argv) {
register uint64_t __regCurrentEL;
__asm volatile ("mrs %0, CurrentEL" : "=r" (__regCurrentEL));
return __regCurrentEL >> 2;
}
CROSS_COMPILE=/opt/arm/10/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-
${CROSS_COMPILE}gcc -O0 -nostdlib -nostartfiles -e main -Wl,-Ttext=0x0000000042000000 -o el.elf el.c
${CROSS_COMPILE}objdump -D el.elf > el.lst
${CROSS_COMPILE}objcopy el.elf -O srec el.srec
=> loads
## Ready for S-Record download ...
## First Load Addr = 0x42000000
## Last Load Addr = 0x42000023
## Total Size = 0x00000024 = 36 Bytes
## Start Addr = 0x42000000 => go 0x42000000
## Starting application at 0x42000000 ...
## Application terminated, rc = 0x2
=>
fatload mmc 1 0x42000000 el.bin
int main(int argc, char** argv) {
int rc = 0;
for (int i = 1; i < argc; i++) {
rc += *argv[i] - '0';
}
return rc;
}
CROSS_COMPILE=/opt/arm/10/gcc-arm-10.2-2020.11-x86_64-aarch64-none-elf/bin/aarch64-none-elf-
${CROSS_COMPILE}gcc -O0 -nostdlib -nostartfiles -e main -Wl,-Ttext=0x0000000042000000 -o add.elf add.c
${CROSS_COMPILE}objdump -D add.elf > adl.lst
${CROSS_COMPILE}objcopy add.elf -O srec add.srec
loads
## Ready for S-Record download ...
## First Load Addr = 0x42000000
## Last Load Addr = 0x4200006B
## Total Size = 0x0000006C = 108 Bytes
## Start Addr = 0x42000000
=> go 0x42000000
## Starting application at 0x42000000 ...
## Application terminated, rc = 0x0
=> go 0x42000000 1
## Starting application at 0x42000000 ...
## Application terminated, rc = 0x1
=> go 0x42000000 1 3 5
## Starting application at 0x42000000 ...
## Application terminated, rc = 0x9
=>
fatload mmc 1 0x6000000 add.bin
108 bytes read in 9 ms (11.7 KiB/s)
$ go 0x6000000
## Starting application at 0x06000000...
## Application terminated, rc = 0x0
go 0x6000000 1
## Starting application at 0x06000000 ...
FAIL: current EL is not above EL1
## Application terminated, rc = 0x16
unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
char *const argv[])
{
int ret = 0;
if (current_el() > 1) {
smp_kick_all_cpus();
dcache_disable();
armv8_switch_to_el1(0x0, 0, 0, 0, (unsigned long)entry,
ES_TO_AARCH64);
} else {
printf("FAIL: current EL is not above EL1\n");
ret = EINVAL;
}
return ret;
}
unsigned long do_go_exec(ulong (*entry)(int, char * const []), int argc,
char *const argv[])
{
int ret = 0;
if (current_el() > 1) {
smp_kick_all_cpus();
dcache_disable();
ret = entry(argc, argv);
} else {
printf("FAIL: current EL is not above or equal to EL1\n");
ret = EINVAL;
}
return ret;
}
Disassembly of section .text:
0000000000000000 <_vector_table>:
0: 1400024e b 938 <_boot>
...
200: 14000061 b 384 <SynchronousInterruptHandler>
...
280: 14000082 b 488 <IRQInterruptHandler>
...
300: 140000a1 b 584 <FIQInterruptHandler>
...
380: 14000099 b 5e4 <SErrorInterruptHandler>
0000000000000938 <_boot>:
938: d2800000 mov x0, #0x0 // #0
93c: d2800001 mov x1, #0x0 // #0
940: d2800002 mov x2, #0x0 // #0
944: d2800003 mov x3, #0x0 // #0
948: d2800004 mov x4, #0x0 // #0
94c: d2800005 mov x5, #0x0 // #0
950: d2800006 mov x6, #0x0 // #0
954: d2800007 mov x7, #0x0 // #0
958: d2800008 mov x8, #0x0 // #0
95c: d2800009 mov x9, #0x0 // #0
960: d280000a mov x10, #0x0 // #0
964: d280000b mov x11, #0x0 // #0
968: d280000c mov x12, #0x0 // #0
96c: d280000d mov x13, #0x0 // #0
970: d280000e mov x14, #0x0 // #0
974: d280000f mov x15, #0x0 // #0
978: d2800010 mov x16, #0x0 // #0
97c: d2800011 mov x17, #0x0 // #0
980: d2800012 mov x18, #0x0 // #0
984: d2800013 mov x19, #0x0 // #0
988: d2800014 mov x20, #0x0 // #0
98c: d2800015 mov x21, #0x0 // #0
990: d2800016 mov x22, #0x0 // #0
994: d2800017 mov x23, #0x0 // #0
998: d2800018 mov x24, #0x0 // #0
99c: d2800019 mov x25, #0x0 // #0
9a0: d280001a mov x26, #0x0 // #0
9a4: d280001b mov x27, #0x0 // #0
9a8: d280001c mov x28, #0x0 // #0
9ac: d280001d mov x29, #0x0 // #0
9b0: d280001e mov x30, #0x0 // #0
00000000000014c0 <_exit>:
14c0: 14000000 b 14c0 <_exit>