使用 arm-none-eabi-gcc 编译器为 RaspberryPI2 和 BeableBoneBlack 编译 sqrt 函数时出错

Errors compiling sqrt function for RaspberryPI2 and BeableBoneBlack with arm-none-eabi-gcc compiler

我是这种编码的新手,我正在尝试为 Cortex-A 处理器执行一些测试执行裸机软件。我有使用 Cortex-M MCU 的经验,我使用 IDE(如 ARM-Keil)和 Nordic 的 SDK 编译代码来完成一些 BLE 工作。现在我想尝试更好地了解 Cortex-A 的世界,我会以裸机方式学习编码,从我在网上找到的一些示例开始。我有一些使用 Cortex-M 的 freeRTOS 的经验,所以我在网上找到了一些来自一些好人的 git 存储库,它为 RaspberryPI 和 BeableBoneBlack 移植了 freeRTOS。从现在开始,我将只针对 BeableBoneBlack 解释我的问题,因为对于 RaspberryPI,它是相似的。

我在 linux,我安装了 gcc-arm-none-eabi 编译器,所以我从这个 link.[=32 克隆了带有 freeRTOS 存储库的 BeagleBone Black =]

我通常使用 VS Code 编写代码,所以在集成终端中,当我 运行 命令 make 一切正常时,我的 BBB 正确闪烁。 所以现在我想改进我的代码,为了做一些测试我想使用 rand() 函数,来自 stdlib.h。不幸的是,我发现有一些错误:undefined reference to rand。 最后几个月,在使用 BBB 进行测试之前,我找到了 RPi2 的其他存储库,并且我了解了一些关于 arm-none-eabi 编译器的 linker 的知识,它需要在中添加一些参数在此过程中订购 link 库文件。 从这个 repo 现在我有两个文件:makedefs_timakefile。打开 make 文件,我在第 26-27 行找到了生成文件 app 的部分,因此调用了 linker。在这一行中有对 LIB_GCCLIB_C 的引用,它们在 makedefs_ti 中定义。在第 49-50 行中有对编译器安装目录的引用(我将 4.7.3 更改为安装在我的 linux 电脑上的正确版本,即 9.2.1)。 在 makefile 中,在 -L$(LIB_C) 之后,如果我添加 -lc-lg 等 linker 参数并尝试重新编译,我会遇到 arm-none-eabi-ld: cannot find -lc 这样的错误。 通过对在线资源的一些了解,我修改了 makedefs_ti 如下:

# Toolchain/library path. LIB_PATH is an exported environmental variable which
# shall point to the installation of toolchain
#
#LIB_GCC=${LIB_PATH}/lib/gcc/arm-none-eabi/4.7.3/
#LIB_C=${LIB_PATH}/arm-none-eabi/lib/
LIB_GCC= /usr/lib/gcc/arm-none-eabi/9.2.1
LIB_C= /usr/lib/arm-none-eabi/lib

makefile :

$(LD) -o $@.out $< -T bbb.ld -Map bbb.map $(APP_LIB) $(LDFLAGS) $(RUNTIMELIB) -L $(LPATH) \
   -L $(LIB_GCC) -lgcc -L $(LIB_C) -lc -lg

这样我的 main.c 调用 rand() 函数的文件就可以正确编译。 在另一个测试中,我试图编译另一个代码。现在我写了一对 .c 和 .h 文件(我把它们放在 rtos 目录中,以便利用那里存在的同一个 makefile),它们包含在调用 sqrt() 的函数中。因此,调用 main() 中的函数并编译,即使我在所有地方都包含 <math.h> 我也有错误:

undefined reference to `sqrt'

显然编译停止了。 从这里开始,我尝试向 linker 添加另一个参数,因此我修改了 makefile 如下:

$(LD) -o $@.out $< -T bbb.ld -Map bbb.map $(APP_LIB) $(LDFLAGS) $(RUNTIMELIB) -L $(LPATH) \
   -L $(LIB_GCC) -lgcc -L $(LIB_C) -lc -lg -lm

我遇到了其他无法以任何方式解决的错误:

arm-none-eabi-ld: /usr/lib/arm-none-eabi/lib/libm.a(lib_a-w_sqrt.o): in function `sqrt':
/build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/math/../../../../../newlib/libm/math/w_sqrt.c:62: undefined reference to `__aeabi_dcmpun'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/math/../../../../../newlib/libm/math/w_sqrt.c:63: undefined reference to `__aeabi_dcmplt'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/math/../../../../../newlib/libm/math/w_sqrt.c:64: undefined reference to `__errno'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/math/../../../../../newlib/libm/math/w_sqrt.c:65: undefined reference to `__aeabi_ddiv'
arm-none-eabi-ld: /usr/lib/arm-none-eabi/lib/libm.a(lib_a-e_sqrt.o): in function `__ieee754_sqrt':
/build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/machine/arm/../../../../../../newlib/libm/machine/arm/../../math/e_sqrt.c:110: undefined reference to `__aeabi_dmul'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/machine/arm/../../../../../../newlib/libm/machine/arm/../../math/e_sqrt.c:110: undefined reference to `__aeabi_dadd'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/machine/arm/../../../../../../newlib/libm/machine/arm/../../math/e_sqrt.c:117: undefined reference to `__aeabi_dsub'
arm-none-eabi-ld: /build/newlib-CVVEyx/newlib-3.3.0/build/arm-none-eabi/newlib/libm/machine/arm/../../../../../../newlib/libm/machine/arm/../../math/e_sqrt.c:117: undefined reference to `__aeabi_ddiv'
make: *** [makefile:26: app] Errore 1

我要说的是,调用 main 中的 sqrt() 可以正常工作,当我调用其他 .c 文件中的 sqrt() 时会出现问题。相反,.c 附加文件中的 rand() 函数可以正常工作。

我不知道如何解决这些错误,有人可以帮助我吗?

我改天尝试的是在 Code Composer Studio 项目中编写相同的代码并且它有效(具有在其他 .c 文件中调用 sqrt 和 rand 的相同函数。有什么区别?

如果解释很长,我很抱歉,但我没有找到其他方式来解释我的情况。

非常感谢。

齐发

start.s

.globl _start
_start:
    ;@ enable fpu
    mrc p15, 0, r0, c1, c0, 2
    orr r0,r0,#0x300000 ;@ single precision
    orr r0,r0,#0xC00000 ;@ double precision
    mcr p15, 0, r0, c1, c0, 2
    mov r0,#0x40000000
    fmxr fpexc,r0

    mov sp,#0x8000
    bl notmain
hang: b hang

notmain.c

double notmain ( double a, double b )
{
    return(a+b);
}

(不是真正的裸机应用程序,派生自一个)

为硬浮动构建

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mhard-float -mfpu=vfp -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

使用了硬件浮动

00008024 <notmain>:
    8024:   ee300b01    vadd.f64    d0, d0, d1
    8028:   e12fff1e    bx  lr

为软浮动构建

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf
arm-none-eabi-ld: notmain.o: in function `notmain':
notmain.c:(.text+0x4): undefined reference to `__aeabi_dadd'
Makefile:33: recipe for target 'notmain.elf' failed
make: *** [notmain.elf] Error 1

它需要 gcclib。

作为 linker 使用 gcc(我知道那是多么可怕的想法)。

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf -lgcc
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

...

00008024 <notmain>:
    8024:   e92d4010    push    {r4, lr}
    8028:   eb000003    bl  803c <__adddf3>
    802c:   e8bd8010    pop {r4, pc}

00008030 <__aeabi_drsub>:
    8030:   e2211102    eor r1, r1, #-2147483648    ; 0x80000000
    8034:   ea000000    b   803c <__adddf3>

00008038 <__aeabi_dsub>:
    8038:   e2233102    eor r3, r3, #-2147483648    ; 0x80000000

0000803c <__adddf3>:
    803c:   e92d4030    push    {r4, r5, lr}

gcc 将这些传递给 ld。

[0][/opt/gnuarm/lib/gcc/arm-none-eabi/10.2.0/../../../../arm-none-eabi/bin/ld]
[1][-plugin]
[2][/opt/gnuarm/libexec/gcc/arm-none-eabi/10.2.0/liblto_plugin.so]
[3][-plugin-opt=/opt/gnuarm/libexec/gcc/arm-none-eabi/10.2.0/lto-wrapper]
[4][-plugin-opt=-fresolution=/tmp/ccRiWZtk.res]
[5][-X]
[6][-o]
[7][notmain.elf]
[8][-L/opt/gnuarm/lib/gcc/arm-none-eabi/10.2.0]
[9][-L/opt/gnuarm/lib/gcc/arm-none-eabi/10.2.0/../../../../arm-none-eabi/lib]
[10][start.o]
[11][notmain.o]
[12][-lgcc]
[13][-T]
[14][memmap]

find | grep libgcc
./lib/gcc/arm-none-eabi/10.2.0/libgcc.a
./lib/gcc/arm-none-eabi/10.2.0/thumb/libgcc.a
./lib/gcc/arm-none-eabi/10.2.0/thumb/autofp/v7/fpu/libgcc.a
./lib/gcc/arm-none-eabi/10.2.0/arm/autofp/v5te/fpu/libgcc.a

所以要使用 ld 然后

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf -L/opt/gnuarm/lib/gcc/arm-none-eabi/10.2.0/ -lgcc
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

为什么现在要用addf3?不知道。

00008024 <notmain>:
    8024:   e92d4010    push    {r4, lr}
    8028:   eb000003    bl  803c <__adddf3>
    802c:   e8bd8010    pop {r4, pc}

00008030 <__aeabi_drsub>:
    8030:   e2211102    eor r1, r1, #-2147483648    ; 0x80000000
    8034:   ea000000    b   803c <__adddf3>

00008038 <__aeabi_dsub>:
    8038:   e2233102    eor r3, r3, #-2147483648    ; 0x80000000

0000803c <__adddf3>:
    803c:   e92d4030    push    {r4, r5, lr}
    8040:   e1a04081    lsl r4, r1, #1
    8044:   e1a05083    lsl r5, r3, #1

这就是你处理 aeabi 东西的方式,你需要使用硬浮点或包含 gcclib 的路径或将其添加到行

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /opt/gnuarm/lib/gcc/arm-none-eabi/10.2.0/libgcc.a
#arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf -lgcc
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

现在 sqrt() 是一个 C 库而不是 gcc 库,所以你需要一个 C 库(看起来你正在尝试使用 newlib)并且你需要构建 C 库来匹配 gcc 所以你需要为硬浮动或软浮动构建它,需要包含正确的库。我没有……好吧……

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /home/so/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1/libgcc.a
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

所以

double sqrt(double x);
double notmain ( double a )
{
    return(sqrt(a));
}

看起来很眼熟

arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /home/so/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1/libgcc.a /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/libm.a
arm-none-eabi-ld: /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/libm.a(lib_a-w_sqrt.o): in function `sqrt':
w_sqrt.c:(.text.sqrt+0x34): undefined reference to `__aeabi_dcmpun'
arm-none-eabi-ld: w_sqrt.c:(.text.sqrt+0x6c): undefined reference to `__aeabi_dcmplt'
arm-none-eabi-ld: w_sqrt.c:(.text.sqrt+0xc4): undefined reference to `__aeabi_ddiv'
arm-none-eabi-ld: w_sqrt.c:(.text.sqrt+0xd8): undefined reference to `__errno'
arm-none-eabi-ld: w_sqrt.c:(.text.sqrt+0x120): undefined reference to `__errno'
arm-none-eabi-ld: /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/libm.a(lib_a-e_sqrt.o): in function `__ieee754_sqrt':
e_sqrt.c:(.text.__ieee754_sqrt+0x200): undefined reference to `__aeabi_dmul'
arm-none-eabi-ld: e_sqrt.c:(.text.__ieee754_sqrt+0x20c): undefined reference to `__aeabi_dadd'
arm-none-eabi-ld: e_sqrt.c:(.text.__ieee754_sqrt+0x22c): undefined reference to `__aeabi_dsub'
arm-none-eabi-ld: e_sqrt.c:(.text.__ieee754_sqrt+0x238): undefined reference to `__aeabi_ddiv'
Makefile:33: recipe for target 'notmain.elf' failed
make: *** [notmain.elf] Error 1

找到

./arm-none-eabi/lib/libm.a
./arm-none-eabi/lib/thumb/v7e-m/nofp/libm.a
./arm-none-eabi/lib/thumb/v6-m/nofp/libm.a
./arm-none-eabi/lib/thumb/v8-m.base/nofp/libm.a
./arm-none-eabi/lib/thumb/v7/nofp/libm.a
./arm-none-eabi/lib/thumb/v8-m.main+dp/hard/libm.a
./arm-none-eabi/lib/thumb/v8-m.main+dp/softfp/libm.a
./arm-none-eabi/lib/thumb/v7e-m+dp/hard/libm.a
./arm-none-eabi/lib/thumb/v7e-m+dp/softfp/libm.a
./arm-none-eabi/lib/thumb/v7-r+fp.sp/hard/libm.a
./arm-none-eabi/lib/thumb/v7-r+fp.sp/softfp/libm.a
./arm-none-eabi/lib/thumb/v7e-m+fp/hard/libm.a
./arm-none-eabi/lib/thumb/v7e-m+fp/softfp/libm.a
./arm-none-eabi/lib/thumb/v8-m.main+fp/hard/libm.a
./arm-none-eabi/lib/thumb/v8-m.main+fp/softfp/libm.a
./arm-none-eabi/lib/thumb/v7-m/nofp/libm.a
./arm-none-eabi/lib/thumb/nofp/libm.a
./arm-none-eabi/lib/thumb/v7+fp/hard/libm.a
./arm-none-eabi/lib/thumb/v7+fp/softfp/libm.a
./arm-none-eabi/lib/thumb/v8-m.main/nofp/libm.a
./arm-none-eabi/lib/arm/v5te/hard/libm.a
./arm-none-eabi/lib/arm/v5te/softfp/libm.a

armv5te 应该适用于 armv6

arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /home/so/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1/libgcc.a /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/arm/v5te/softfp/libm.a
arm-none-eabi-ld: /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/arm/v5te/softfp/libm.a(lib_a-w_sqrt.o): in function `sqrt':
w_sqrt.c:(.text.sqrt+0x94): undefined reference to `__errno'
arm-none-eabi-ld: w_sqrt.c:(.text.sqrt+0xdc): undefined reference to `__errno'
Makefile:33: recipe for target 'notmain.elf' failed
make: *** [notmain.elf] Error 1

errno 是一个全局变量。 C 库可能想将其用于软浮点数。

int __errno;
double sqrt(double x);
double notmain ( double a )
{
    return(sqrt(a));
}

现在这个工具很开心

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /home/so/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1/libgcc.a /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/arm/v5te/softfp/libm.a
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

但这是硬浮动而不是软浮动。

00008024 <notmain>:
    8024:   eaffffff    b   8028 <sqrt>

00008028 <sqrt>:
    8028:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
    802c:   ed2d8b02    vpush   {d8}
    8030:   e1a02000    mov r2, r0
    8034:   e1a03001    mov r3, r1
    8038:   e24dd02c    sub sp, sp, #44 ; 0x2c
    803c:   ec432b18    vmov    d8, r2, r3
    8040:   eb000038    bl  8128 <__ieee754_sqrt>
    8044:   e59f30d4    ldr r3, [pc, #212]  ; 8120 <sqrt+0xf8>
    8048:   eeb48b48    vcmp.f64    d8, d8
    804c:   e1d3c0d0    ldrsb   ip, [r3]
    8050:   eef1fa10    vmrs    APSR_nzcv, fpscr

你知道解决这个问题的方法是什么。你需要一个合适的 matched/built 库然后你需要 link 它。 Keil 和其他人只是在工具链中为您做这件事,根据项目匹配事物。 And/or 与工具链集成的 ​​C 库。

硬漂浮建筑

arm-none-eabi-as --warn --fatal-warnings -mcpu=arm1176jzf-s -march=armv6 -mfpu=vfp start.s -o start.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=arm1176jzf-s -mtune=arm1176jzf-s -mhard-float -mfpu=vfp -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles start.o notmain.o -T memmap -o notmain.elf /home/so/gcc-arm-none-eabi-9-2019-q4-major/lib/gcc/arm-none-eabi/9.2.1/libgcc.a /home/so/gcc-arm-none-eabi-9-2019-q4-major/arm-none-eabi/lib/arm/v5te/hard/libm.a
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy --srec-forceS3 notmain.elf -O srec notmain.srec
arm-none-eabi-objcopy notmain.elf -O binary kernel.img

工具很高兴。

00008024 <notmain>:
    8024:   eaffffff    b   8028 <sqrt>

00008028 <sqrt>:
    8028:   e52de004    push    {lr}        ; (str lr, [sp, #-4]!)
    802c:   ed2d8b02    vpush   {d8}
    8030:   eeb08b40    vmov.f64    d8, d0
    8034:   e24dd02c    sub sp, sp, #44 ; 0x2c
    8038:   eb000038    bl  8120 <__ieee754_sqrt>
    803c:   eeb48b48    vcmp.f64    d8, d8
    8040:   e59f30d0    ldr r3, [pc, #208]  ; 8118 <sqrt+0xf0>
    8044:   e1d310d0    ldrsb   

必须使它成为一个真正的应用程序,主要调用另一个在其中调用 sqrt 的函数。然后 运行 它在硬件上 and/or 检查这些指令。或者甚至更好地获取 sqrt 的 C 库实现并在项目中构建它,以便它与目标和指令集相匹配。 (根据需要调用 libgcc,测试它们或构建它们)。