Zephyr在第三方工具链下开启TLS

Creative Commons
本作品采用知识共享署名

本文说明如何在Zephyr下使用gcc-arm-none-eabi支持TLS.

Zephyr TLS线程本地存储的实现一文中说明了如何在Zephyr上使用TLS,在这种默认的情况下Zephyr的编译是使用的是Zephyr SDK提供的工具链。
而在一些特殊情况下我们希望使用重新配置编译第三方工具链来编译Zephyr,这就需要配置让第三方工具链支持TLS,并修改Zephyr的Kconifg加入第三方工具链支持TLS.

工具链编译

https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads下载要用的source code,例如我选择的是gcc-arm-none-eabi-9-2020-q2-update-src.tar.bz2
解压缩后有一个How-to-build-toolchain.pdf文档说明如何编译

安装依赖

我的环境是ubuntu 18.04,安装依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
sudo su

apt-get install software-properties-common
add-apt-repository universe
cat >/etc/apt/sources.list.d/xenial.list <<EOF
deb http://archive.ubuntu.com/ubuntu xenial main universe
deb-src http://archive.ubuntu.com/ubuntu xenial main universe
deb http://security.ubuntu.com/ubuntu xenial-security main
EOF

dpkg --add-architecture i386
apt-get update

apt-get install -y -t xenial \
gcc-mingw-w64-i686 g++-mingw-w64-i686 binutils-mingw-w64-i686

apt-get -f install -y \
build-essential \
autoconf \
autogen \
bison \
dejagnu \
flex \
flip \
gawk \
git \
gperf \
gzip \
nsis \
openssh-client \
p7zip-full \
perl \
python-dev \
libisl-dev \
scons \
tcl \
texinfo \
tofrodos \
wget \
zip \
texlive \
texlive-extra-utils \
libncurses5-dev

exit

修改编译配置项

  1. 不需要mingw32,配置为跳过加速编译

    1
    2
    skip_mingw32=yes
    skip_mingw32_gdb_with_python=yes
  2. --disable-tls修改为--enable-tls
    gcc-arm-none-eabi默认是关闭tls的,gcc编译代码后访问TLS时使用的是emulated tls,和Zephyr的实现不一致,需要改为--enable-tls

编译

执行下面命令进行编译

1
2
3
./install-sources.sh
./build-prerequisites.sh
./build-toolchain.sh

编译完成后的结果会被打包放在pkg/下, 例如我这里生成的就是gcc-arm-none-eabi-9-2021-q2-x86_64-linux.tar.bz2
在编译gdb的时候可能会提示python有问题,需要进行python版本切换gcc-arm-none-eabi-9-2020-q2使用python 2.7, 切换方法见Python2和3切换

第三方工具链配置TLS

使用第三方工具链

将gcc-arm-none-eabi-9-2021-q2-update-x86_64-linux.tar.bz2解压缩,根据解压缩的路径修改~/.zephyrrc如下,Zephyr就会使用第三方工具链进行编译

1
2
export ZEPHYR_TOOLCHAIN_VARIANT=gnuarmemb
export GNUARMEMB_TOOLCHAIN_PATH=/mnt/d/code/gcc-arm-none-eabi-9-2021-q2-update

修改Zephyr配置

当使用第三方工具链后即使配置了CONFIG_THREAD_LOCAL_STORAGE=y在编译的时候也会提示由于TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGEn而无法TLS, 但由于TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE是Zephyr的隐藏配置项因此无法在prj.conf中配置。
修改方式是在zephyr/kernel/Kconfig中为gnuarmemb添加默认支持TLS

1
2
3
config TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE
bool
default y if ("$(ZEPHYR_TOOLCHAIN_VARIANT)" = "zephyr" || "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "gnuarmemb")

通过以上修改,用第三方工具链gnuarmemb编译就可以支持Zephyr的TLS。

参考

https://docs.zephyrproject.org/latest/getting_started/toolchain_3rd_party_x_compilers.html