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 | 低功耗蓝牙支持 |
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 依赖一些库,比如 glib、dbus、libudev。这些库也需要交叉编译,或者从你的 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 查看蓝牙控制器。
3.4 本章小结
这一章我们走完了从工具链到内核再到 BlueZ 的完整流程。你想想看,其实每一步都不复杂,但细节很多。尤其是库的依赖和路径问题,最容易出幺蛾子。
下一章,我们会真正开始调试蓝牙驱动。到时候,你会感谢今天认真搭建环境的自己。