请有人帮帮我!我不知道答案是否一般,或者特定于我正在使用的电路板和软件版本。我离开了以前的区域,甚至不知道要问的正确问题。
在底部添加了编辑
我目前想要的是创建一个程序,它将在A20-OLinuXino-Micro-4GB板上运行独立(裸机;无操作系统),需要使用(至少)一些标准的数学库调用。最后,我想将它加载到NAND中,然后在上电时运行它,但是现在我试图从U-Boot手动加载它(loady)(github.com/linux-sunxi/u-boot-sunxi/ wiki)串口'控制台',从SD卡启动后。需要独立,因为一次使用多个位(端口组中的端口)时,Linux发行版级别对硬件GPIO端口的访问不是很灵活,而且非常慢。目标应用程序太慢了,我真的不想尝试修改/添加内核模块,只是为了看看它是否足够快。
是否需要一些标准的gcc / ld标志来创建裸机独立程序,并包含一些库例程?超越-ereestanding和-static?是否需要一些特殊的胶水代码?还有其他一些我甚至都没有想过的东西吗?
如果找到并查看Beagleboard裸机编程(stackoverflow.com/questions/6870712/beagleboard-bare-metal-programming)。答案有很好的信息,但是汇编程序,并没有引用任何库。 Application hangs when calling printf to uart with bare metal raspberry pi可能会显示问题的原因。 (当前)底部答案指出了VFP的问题,我已经遇到了软/硬浮点选项的问题。这显示了一些汇编程序代码,但我遗漏了有关如何添加包装器/粘合剂以与c代码组合的详细信息。我的汇编程序编码生锈了,但是会在hello_world的开头添加等效代码(至少在引用sin()函数之前(可能)会使事情正常工作吗?可能会将它添加到libstubs代码中。
我正在使用另一个A20主板作为主要开发环境。
$ gcc --version gcc (Debian 4.6.3-14) 4.6.3 Copyright (C) 2011 Free
Software Foundation, Inc. This is free software; see the source for
copying conditions. There is NO warranty; not even for
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ ld.bfd --version GNU ld (GNU Binutils for Debian) 2.22 Copyright
2011 Free Software Foundation, Inc. This program is free software; you
may redistribute it under the terms of the GNU General Public License
version 3 or (at your option) a later version. This program has
absolutely no warranty.
$ uname -a Linux a20-OLinuXino 3.4.67+ #6 SMP PREEMPT Fri Nov 1
17:32:40 EET 2013 armv7l GNU/Linux
我已经能够从repo为SD卡上的电路板创建可启动的U-Boot映像,可以直接从随板提供的linux-sunxi发行版构建,也可以从Fedora交叉编译21台机器。 U-boot示例中的独立hello_world程序也是如此,可以从U-Boot控制台加载和运行。
但是,将示例程序减少到最低限度,然后添加需要math.h,-lm和-lc的代码会因“软件中断”或“未定义操作”类型错误而失败(在各种迭代中)。原始示例程序与-lgcc链接,但稍微检查显示库中实际上没有包含任何内容。相同的二进制文件是在没有库的情况下创建的,所以问题可能是“使用裸机程序使用任何库需要什么?”
sun7i# go 0x48000000
## Starting application at 0x48000000 ...
Hello math World
undefined instruction
pc : [<48000010>] lr : [<4800000c>]
sp : 7fb66da0 ip : 7fb672c0 fp : 00000000
r10: 00000002 r9 : 7fb66f0c r8 : 7fb67778
r7 : 7ffbbaf8 r6 : 00000001 r5 : 7fb6777c r4 : 48000000
r3 : 00000083 r2 : 7ffbc7fc r1 : 0000000a r0 : 00000011
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
为了达到这个目的,我不得不调整构建选项,以指定硬件浮点,因为这就是基础库的编译方式。
以下是相应的源和构建脚本文件
hello_world.c
#include <common.h>
#include <math.h>
int hello_world (void)
{
double tst;
tst = 0.33333333333;
printf ("Hello math World\n");
tst = sin(0.5);
// printf ("sin test %d : %d\n", (int)tst, (int)(1000 * tst));
return (0);
}
构建脚本
#! /bin/bash
UBOOT="/home/olimex/u-boot-sunxi"
SRC="$UBOOT/examples/standalone"
#INCLS="-nostdinc -isystem /usr/lib/gcc/arm-linux-gnueabihf/4.6/include -I$UBOOT/include -I$UBOOT/arch/arm/include"
INCLS="-I$UBOOT/include -I$UBOOT/arch/arm/include"
#-v
GCCOPTS="\
-D__KERNEL__ -DCONFIG_SYS_TEXT_BASE=0x4a000000\
-Wall -Wstrict-prototypes -Wno-format-security\
-fno-builtin -ffreestanding -Os -fno-stack-protector\
-g -fstack-usage -Wno-format-nonliteral -fno-toplevel-reorder\
-DCONFIG_ARM -D__ARM__ -marm -mno-thumb-interwork\
-mabi=aapcs-linux -mword-relocations -march=armv7-a\
-ffunction-sections -fdata-sections -fno-common -ffixed-r9\
-mhard-float -pipe"
# -msoft-float -pipe
OBJS="hello_world.o libstubs.o"
LDOPTS="--verbose -g -Ttext 0x48000000"
#--verbose
#LIBS="-static -L/usr/lib/gcc/arm-linux-gnueabihf/4.6 -lm -lc"
LIBS="-static -lm -lc"
#-lgcc
gcc -Wp,-MD,stubs.o.d $INCLS $GCCOPTS -D"KBUILD_STR(s)=#s"\
-D"KBUILD_BASENAME=KBUILD_STR(stubs)"\
-D"KBUILD_MODNAME=KBUILD_STR(stubs)"\
-c -o stubs.o $SRC/stubs.c
ld.bfd -r -o libstubs.o stubs.o
gcc -Wp,-MD,hello_world.o.d $INCLS $GCCOPTS -D"KBUILD_STR(s)=#s"\
-D"KBUILD_BASENAME=KBUILD_STR(hello_world)"\
-D"KBUILD_MODNAME=KBUILD_STR(hello_world)"\
-c -o hello_world.o hello_world.c
ld.bfd $LDOPTS -o hello_world -e hello_world $OBJS $LIBS
objcopy -O binary hello_world hello_world.bin
EDITS补充道:
要成为其中一部分的应用程序需要一些相当高速的GPIO和一些数学函数。应该只需要sin()和sqrt()。我之前对GPIO的测试得到了单个引脚(端口组中的端口)的切换,最高可达8MHz。应用的限制需要在10μs(100Hhz)范围内获得完整的周期时间,包括从单个端口读取所有引脚,并在其他端口上写入几个引脚,与所连接的ADC芯片的时序限制同步( 3 ADC读取)。我有裸金属代码在大约2.1μs内进行(模拟)该过程。现在我需要添加数学来处理值,其输出将设置更多输出。未来计划的改进包括使用SIMD进行数学计算,并将第二个核心专用于数学,而第一个进行GPIO并“提供”计算。
所需的数学代码/逻辑已经使用非常标准的(c99)代码写入模拟程序。我只需要将它移植到裸机程序中。需要让'数学'先工作。
答案 0 :(得分:0)
首先,我建议阅读这篇关于使用ARM和GNU进行裸机编程的优秀论文http://rextester.com/LRMW38599。
然后,我会确保你避免任何系统调用Linux内核(你没有,你的编译器会尝试制作),例如避免返回void main()
中的值 - 无论如何都不应该返回。
最后,我要么使用newlib,要么如果你需要使用一小部分库提供的,编写自定义实现。
请记住,您使用的是Allinner SoC,这不是最好的裸机文档,但您可以在http://www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf找到TRM,因此我会检查库(如果您决定使用它们)或您的代码需要一些特殊的硅硬件进行初始化(某些互连结构,时钟和电源域等)。
我强烈建议,如果你只需要使用sin()和类似的东西,只需部署你自己的。