3、开发环境搭建:交叉编译工具链、内核配置、BlueZ编译与安装

好,咱们进入第三章。这一章说白了,就是给你的开发板“配齐家伙事儿”。

我见过太多新手,代码写得挺溜,结果环境没搭对,一编译就报错,一跑就崩溃。嗯,这其实是最冤枉的浪费时间。所以这一章,咱们把交叉编译工具链、内核配置、BlueZ 编译安装这三件事,一次性捋清楚。

3.1 交叉编译工具链:为什么你不能用 gcc?

你想想看,你的 PC 是 x86 架构,你的开发板是 ARM 架构。你用 PC 上的 gcc 编译出来的程序,ARM 芯片根本看不懂。这就是为什么需要交叉编译工具链——它运行在 PC 上,但生成的是 ARM 能执行的机器码。

我个人习惯用 Linaro 提供的工具链,稳定且社区支持好。当然,你也可以用芯片厂商提供的 SDK,比如 Broadcom 或 TI 的包。

3.1.1 获取与安装

以 ARM Cortex-A 系列为例,我常用的版本是 gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf。下载后解压到 /opt 目录:

tar -xvf gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt/

然后配置环境变量。我个人习惯写到 ~/.bashrc 里:

export PATH=$PATH:/opt/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/bin
export CROSS_COMPILE=arm-none-linux-gnueabihf-
export ARCH=arm

记得 source ~/.bashrc 让它生效。

小提示: 验证是否安装成功,可以运行 arm-none-linux-gnueabihf-gcc --version。如果看到版本号,说明工具链已经就绪。

3.1.2 避坑指南:库的路径问题

我曾经在项目里遇到过,编译出来的蓝牙工具在开发板上运行时,报错“No such file or directory”。查了半天,发现是动态链接库的路径没对上。交叉编译时,链接器默认会找宿主机的库路径,而不是目标板的。

解决办法:编译时显式指定 --sysroot 参数,指向目标板的根文件系统。

arm-none-linux-gnueabihf-gcc --sysroot=/path/to/rootfs -o myapp myapp.c

3.2 内核配置:让 Linux 认识你的蓝牙芯片

工具链有了,接下来要让内核支持蓝牙。说白了,就是打开几个开关。

我建议你基于厂商提供的默认配置文件来改,比如 defconfig。然后运行 make menuconfig,进入图形化配置界面。

3.2.1 必须开启的选项

以下是我每次做蓝牙驱动调试时,一定会检查的内核选项:

配置项 路径 说明
CONFIG_BT Networking support → Bluetooth subsystem support 蓝牙协议栈总开关
CONFIG_BT_HCIUART Bluetooth subsystem support → HCI UART driver 串口 HCI 驱动,常用
CONFIG_BT_HCIBCM203X Bluetooth subsystem support → Broadcom HCI driver 如果你用 Broadcom 芯片
CONFIG_BT_HCIUSB Bluetooth subsystem support → HCI USB driver USB 蓝牙适配器
CONFIG_BT_LE Bluetooth subsystem support → Bluetooth Low Energy 低功耗蓝牙支持
注意: 如果你的蓝牙芯片是通过 SDIO 接口连接的,别忘了开启 CONFIG_MMC 和对应的 SDIO 驱动。我遇到过有人只开了蓝牙选项,忘了开 SDIO,结果内核根本枚举不到设备。

3.2.2 编译内核与模块

配置完成后,编译内核和模块:

make -j4 zImage
make -j4 modules
make modules_install INSTALL_MOD_PATH=/path/to/rootfs

把生成的 zImage.dtb 文件拷贝到开发板的启动分区。嗯,这一步别忘了。

3.3 BlueZ 编译与安装:蓝牙协议栈的灵魂

内核只是提供了底层驱动,真正让蓝牙跑起来的,是 BlueZ 协议栈。BlueZ 是 Linux 官方蓝牙协议栈,几乎所有蓝牙功能都依赖它。

3.3.1 下载与解压

我习惯从 http://www.bluez.org/ 下载最新稳定版。目前常用的是 5.xx 系列。

wget http://www.bluez.org/download/bluez-5.66.tar.xz
tar -xvf bluez-5.66.tar.xz
cd bluez-5.66

3.3.2 交叉编译配置

这里有个关键点:BlueZ 依赖一些库,比如 glibdbuslibudev。这些库也需要交叉编译,或者从你的 SDK 里获取。

配置命令如下:

./configure \
  --host=arm-none-linux-gnueabihf \
  --prefix=/usr \
  --sysconfdir=/etc \
  --localstatedir=/var \
  --enable-library \
  --with-dbusconfdir=/etc/dbus-1/system.d \
  --with-systemdsystemunitdir=/lib/systemd/system \
  --disable-systemd \
  --enable-test \
  --enable-tools \
  --enable-deprecated

我个人习惯加上 --enable-test,这样编译后会生成一些测试工具,方便调试。但生产环境建议去掉。

小提示: 如果编译过程中报错找不到 glib.h,说明你的交叉编译环境缺少 glib 的头文件。你需要先交叉编译 glib,或者从 SDK 中获取预编译的版本。

3.3.3 编译与安装

make -j4
make install DESTDIR=/path/to/rootfs

安装完成后,你的根文件系统里会有 /usr/bin/bluetoothd/usr/bin/hcitool/usr/bin/bluetoothctl 等工具。

3.3.4 验证安装

把根文件系统烧录到开发板,启动后运行:

bluetoothd --version

如果看到版本号,说明 BlueZ 安装成功。然后运行 bluetoothctl,进入交互界面,输入 list 查看蓝牙控制器。

核心要点: 交叉编译工具链是基础,内核配置是桥梁,BlueZ 是灵魂。这三者缺一不可。我建议你每完成一步,都做一次简单的验证,不要等到最后才发现问题。

3.4 本章小结

这一章我们走完了从工具链到内核再到 BlueZ 的完整流程。你想想看,其实每一步都不复杂,但细节很多。尤其是库的依赖和路径问题,最容易出幺蛾子。

下一章,我们会真正开始调试蓝牙驱动。到时候,你会感谢今天认真搭建环境的自己。