使用LLVM-embedded-toolchain-for-Arm-17.0.1开发STM32

电子说

1.2w人已加入

描述

LLVM-embedded-toolchain-for-Arm 是一个 ARM 公司开源的适用于 32 位ARM芯片的工具链,支持多种ARM指令集架构,包括最新的 CM85 内核。由于是基于 LLVM 和 picolibc构建出的工具链,因此在代码体积和执行效率上都很有竞争力,甚至可以和商用闭源的工具链进行 PK。

支持的架构
Armv6-M
Armv7-M
Armv7E-M
Armv8-M Mainline
Armv8.1-M Mainline
Armv4T (experimental)
Armv5TE (experimental)
Armv6 (experimental, using the Armv5TE library variant)
AArch64 armv8.0 (experimental)

这篇文章教大家,如何在 RT-Thread 上,使用最新发布的 LLVM-embedded-toolchain-for-Arm-17.0.1 版本开发stm32,以星火1号为例。

适配LLVM工具链

由于RT-Thread内核和构建工具已经支持了这款工具链,因此只需要修改我们当前使用的BSP即可。

主要工作就是修改rtconfig.py 添加llvm-arm的编译参数
由于目前RT-Thread主仓库已经有两个BSP支持了这个工具链,我们可以参考现有的。

打开星火1号对应的BSP,目录为:bsp/stm32/stm32f407-rt-spark。然后使用文本编辑工具(如:VSCode)打开rtconfig.py文件。

1.在CROSS_TOOL配置的地方添加 llvm-arm 相关信息:

cross_tool provides the cross compiler

EXEC_PATH is the compiler execute path, for example, CodeSourcery, Keil MDK, IAR

if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = r'C:UsersXXYYZZ'
elif CROSS_TOOL == 'keil':
PLATFORM = 'armcc'
EXEC_PATH = r'C:/Keil_v5'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iccarm'
EXEC_PATH = r'C:/Program Files (x86)/IAR Systems/Embedded Workbench 8.3'
elif CROSS_TOOL == 'llvm-arm': # 新添加的部分
PLATFORM = 'llvm-arm'
EXEC_PATH = r'D:ProgremLLVMEmbeddedToolchainForArm-17.0.1-Windows-x86_64bin'

2.完善具体的编译参数

if PLATFORM == 'gcc':

toolchains ...

elif PLATFORM == 'armcc':

toolchains ...

elif PLATFORM == 'armclang':

toolchains ...

elif PLATFORM == 'iccarm':

toolchains ...

elif PLATFORM == 'llvm-arm': # 新添加的部分

toolchains

PREFIX = 'llvm-'
CC = 'clang'
AS = 'clang'
AR = PREFIX + 'ar'
CXX = 'clang++'
LINK = 'clang'
TARGET_EXT = 'elf'
SIZE = PREFIX + 'size'
OBJDUMP = PREFIX + 'objdump'
OBJCPY = PREFIX + 'objcopy'
DEVICE = ' --target=arm-none-eabihf -mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16'
DEVICE += ' -ffunction-sections -fdata-sections -fno-exceptions -fno-rtti'
CFLAGS = DEVICE
AFLAGS = ' -c' + DEVICE + ' -Wa,-mimplicit-it=thumb ' ## -x assembler-with-cpp
LFLAGS = DEVICE + ' -Wl,--gc-sections,-Map=rt-thread.map,-u,Reset_Handler -lcrt0 -T board/linker_scripts/link.lds'
CPATH = ''
LPATH = ''
if BUILD == 'debug':
CFLAGS += ' -O0 -gdwarf-2 -g'
AFLAGS += ' -gdwarf-2'
else:
CFLAGS += ' -O2'
CXXFLAGS = CFLAGS
POST_ACTION = OBJCPY + ' -O binary **TARGET rtthread.binn' + SIZE + ' **TARGET n'

编译工程

使用 env 工具打开当前 bsp,设定要使用的工具链和对应的路径。

set RTT_CC=llvm-arm
set RTT_EXEC_PATH=D:ProgremLLVMEmbeddedToolchainForArm-17.0.1-Windows-x86_64bin

然后运行 scons 命令,执行编译

scons

发现编译报错了,看起来是原来的链接脚本不太规范,llvm检测比较严格。

gcc编译器

我们打开对应的文件,在 = 后面加一个空格,再次编译。

又出现了一个错误。

gcc编译器

这次是提示 .eh_frame 和 .data 两个段的地址发生了冲突。对比了下stm32l475-atk-pandora 和星火1号bsp的链接脚本文件。

发现星火1号的链接脚本缺少了.eh_frame 段的定义。

gcc编译器

我们添加是缺少的定义,继续编译。编译成功!

gcc编译器

然后拖入到星火1号的 U 盘,咦!没下载成功,提示下载失败了。。。

gcc编译器

然后,尝试了下使用gcc编译出来的bin文件,咦!下载成功了。这说明我们LLVM的工具链编译出来的文件缺少有问题!

使用比较工具,比较这两个bin文件,一打开就发现了不对劲的地方。LLVM编译出来的bin文件,前面缺少了一块。

gcc编译器

仔细一看,这不是前面的中断向量表吗,原来是LLVM编译的工具少了这一部分,这样就好办了,问题肯定出来启动文件这里。看了下控制启动文件是否参与编译的脚本,发现,确实缺少了针对llvm-arm这个工具链的处理。

gcc编译器

添加上之后,继续编译,成功了,果然固件大小也变大了很大,达到了和gcc一样的量级。

gcc编译器

这次下载成功了,而且程序也正常的运行起来了!

gcc编译器

代码优化对比

比较一下代码体积(text段大小)

gcc编译器

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分