我正在寻找有关裸机编程的一些信息。 我正在研究不同的powerpc平台,目前正试图证明某些测试不会受到linux内核的影响。这些测试非常基本,加载和存储在asm volatile,一些基准测试(Coremark,Dhrystone等)。这些测试在Linux上完美运行,但我现在必须在裸机中测试它们,这是一个我真的没有经验的环境。 我的所有平台都安装了u-boot,我想知道是否有这样的应用程序可以让我运行我的测试powerpc-eabi交叉编译?例如,u-boot启动的gdbserver是否能够通过串口或以太网进行通信?是否可以使用U-boot调用的busybox?
答案 0 :(得分:3)
Uboot是一个引导加载程序......使用它。你可能有一个xmodem下载程序或ymodem下载程序与uboot,如果push推到你可以把你的程序变成一系列写入单词到内存然后分支到那。
uboot已经设置了ram和串口,无论如何你都在和uboot交谈,所以你不必做所有这些。您不需要配置串行端口,但是您需要了解如何写入字符,这意味着将发送器寄存器的状态寄存器轮询为空,然后将一个字符写入发送寄存器。对字符串中的每个字符重复或重复打印。
C程序的引导程序(假设它是C)通常只涉及设置堆栈指针(btw uboot正在运行,因此堆栈已经设置,只要你加载你的程序你就可以不这样做这样它就不会与uboot正在做的事情发生冲突)然后分支到你的C入口点。
根据您编写高级语言程序的方式(我假设为C),您可能必须将.bss区域归零并设置.data区域,使用引导加载程序将程序复制到ram并且只是运行它是你通常不必做任何这个,你下载和运行的二进制文件已经将bss归零和.data放在正确的位置。所以它回来设置堆栈和分支或简单分支,因为你甚至可能不需要设置堆栈。
构建裸机程序是一项真正的挑战,因为您没有系统来进行系统调用,这是一个很难放弃和/或模拟的事情。例如,newlib使生活变得更容易,因为它有一个非常容易替换的系统后端,所以你可以将printfs留在dhrystone中(除了删除它们并找到一种不同的方式来根据需要输出字符串或输出结果。 / p>
编译到C文件的对象很容易,组装程序很容易,你应该可以用powerpc-eabi gcc交叉编译器来完成,接下来的挑战是链接,告诉链接器哪里有东西。因为这可能是一个扁平的ram块,你可能会做类似-Ttext 0x123450000的事情,其中数字是你想要使用的ram的基地址。如果你有任何乘法或除法或任何浮点数或任何其他gcc库函数(替换你的处理器可能做或不做的事情或需要包装器正确执行它们),或任何libc调用,那么它将尝试链接它们理想情况下,gcc库很容易,但依赖于交叉编译器,它们可能是一个挑战,最糟糕的情况是采用gcc源代码并自己构建这些函数,或者获取或构建具有不同目标选项的不同gcc交叉编译器(通常很容易做)。
我强烈建议您反汇编二进制文件,并确保您的引导程序的入口点没有其他任何内容位于二进制文件的开头。使用objcopy制作二进制文件powerpc -...- objcopy myprog.elf -O binary myprog.bin。然后在uboot提示符下使用xmodem或ymodem来复制该程序并运行它。
备份。当您查找uart并找出基本地址时,从部件的数据表中,您应首先使用uboot提示写入uart传输寄存器的地址,例如将0x30写入该地址,如果您有正确的地址然后在你的命令之后它再次打印uboot提示之前它应该有一个额外的零' 0' 0在输出中。如果你不能通过uboot命令行中的一次写操作来做到这一点,你就不会让它在任何类型的程序中工作,你有错误的地址或者你做错了什么。
然后用汇编语言编写一个非常小的程序,通过写入该地址向uart输出一个字符,然后根据处理器的速度计算一些大数字。如果你以100Mhz运行然后计数到1亿或更多(或从几亿减少到零)然后分支到开头并重复,输出,等待输出,等待。构建并链接这个小程序,然后使用xmodem或其他任何内容下载并分支到它。如果你不能每隔几秒就输出一个角色,那么你将无法进入更复杂的角色。
接下来的小程序,轮询状态寄存器,等待tx缓冲区为空,然后将0x30写入tx寄存器。将保持0x30的寄存器递增到0x31,将寄存器递增到0x37。分支到等待tx为空并输出新值0x31,使其成为无限循环。如果一旦你开始跑步,你就不会看到01234567012345670 ...永远重复,没有数字被破坏,他们必须是0-7并重复,那么你将无法进展到更复杂的东西。
使用分支到C入口点的小型引导程序重复C中的最后两个程序,如果你不能使那些工作,你将无法继续前进。
从你认为你不能没有的任何库调用(例如printf)开始,如果你不能制作一个简单的printf(" Hello World \ n");使用所有链接和系统后端等,然后你将无法运行Dhrystone并留在系统调用。
编译器可能会将某些Dhrystone转换为你必须实现的memcpy或memset调用,这些调用最有可能是手动调整的汇编版本,你的Dhrystone性能数字可以并且将会受到类似函数实现的巨大影响这些,所以你不能简单地这样做
void memset ( unsigned char *d unsigned char c, unsigned int len)
{
while(len--) *(d++)=c;
}
并期待任何表现。你可以抓住这些的gcc lib或gnu libc版本,或者只是从其中一个测试的linux版本中窃取它们(反汇编并抓住asm),这样你就可以学到苹果了......
基准测试通常比实际更虚假,在同一环境(在Linux或裸机等)上使用相同的编译器很容易采用相同的基准测试源,并通过做各种简单的事情显示出截然不同的结果,不同的编译器选项,重新安排功能,在引导程序中添加几个nop等。任何要么构建不同的代码或利用或受到cahce等的伤害。如果你想显示裸机比运行更快系统,如果没有一点工作,它可能不会发生。你将需要获得i和d缓存d缓存可能需要你获得mmu等等。这些都可以是研究项目。然后你需要知道如何控制你的编译器构建,确保开启优化,如上所述在你的引导程序中添加或删除nops以改变代码中紧密循环与高速缓存行的对齐。在一个操作系统上有中断和事情发生,可能你是多任务处理所以使用裸机你应该能够得到像测试一样的dhrystone以比linux更快或更快的速度运行,如果你不能因为linux更快这是因为你在裸机实施中没有做正确的事情。
是的,您可以使用gdb与uboot交谈并加载程序,不确定我从不使用gdb,我更喜欢使用哑终端和x或y调制解调器或使用jtag与openocd终端(telnet到openocd而不是gdb)在)。
答案 1 :(得分:0)
您可以尝试与u-boot一起编译基准测试。因此,在u-boot完成加载后,它会加载您的程序。我知道这对ARM平台来说是可能的。 我不知道powerpc裸机开发是否存在工具链
答案 2 :(得分:0)
在https://cirosantilli.com/linux-kernel-module-cheat/#dhrystone的this commit中,我提供了一个可运行的Dhrystone裸机示例,该示例具有在QEMU和gem5上运行的ARM上的Newlib。从这个起点出发,将其移植到PowerPC或其他ISA和实际平台上应该不难。
在该设置中,Newlib实现了除系统调用本身以外的所有功能,如https://electronics.stackexchange.com/questions/223929/c-standard-libraries-on-bare-metal/400077#400077中所述,这使得使用C标准库的较大子集更加容易。
然后我通过crosstool-NG构建的工具链使用newlib。
该设置中的一些关键文件:
完整的make命令,显示使用的某些标志:
make \
-j 8 \
-C /home/ciro/bak/git/linux-kernel-module-cheat/submodules/dhrystone \
CC=/home/ciro/bak/git/linux-kernel-module-cheat/out/crosstool-ng/build/default/install/aarch64/bin/aarch64-unknown-elf-gcc \
'CFLAGS_EXTRA=-nostartfiles -O0' \
'LDFLAGS_EXTRA=-Wl,--section-start=.text=0x40000000 -T /home/ciro/bak/git/linux-kernel-module-cheat/baremetal/link.ld' \
'EXTRA_OBJS=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/bootloader.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/lkmc.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls_asm.o /home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/lib/syscalls.o' \
OUT_DIR=/home/ciro/bak/git/linux-kernel-module-cheat/out/baremetal/aarch64/qemu/virt/submodules/dhrystone \
-B \
;