1、课程导论与开发环境搭建:POS机行业现状、WiFi/BT模块选型、Linux驱动开发环境搭建

各位同学,大家好。我是你们这门课的主讲。说实话,在嵌入式这一行摸爬滚打了十几年,从最早的51单片机做到现在的四核ARM Linux,踩过的坑比走过的路还多。今天咱们开始第一讲,先把地基打牢。

做驱动开发,最怕什么?最怕你环境都没搭好,就开始撸代码。我见过太多新手,上来就git clone内核,然后make menuconfig,最后编译报错一脸懵。嗯,咱们今天就把这事儿捋清楚。

1.1 POS机行业现状:为什么我们要学这个?

先聊聊行业背景。你想想看,现在去超市、餐厅、便利店,哪个收银台没有POS机?而且这几年,传统的“大块头”POS机正在被智能POS取代。什么叫智能POS?说白了,就是一台带触摸屏、跑Linux或Android的嵌入式平板。

我去年帮一家支付公司做过方案选型。他们要求:机器要能连WiFi,要能扫蓝牙条码枪,还要支持NFC刷卡。你看,WiFi和蓝牙,这就是咱们这门课的核心。

目前行业里主流的方案有这些:

  • 全志/Rockchip方案:性价比高,适合中低端市场
  • 高通/MTK方案:性能强,但成本高,开发门槛也高
  • 瑞芯微RK33xx系列:我个人比较推荐,资料全,社区活跃

不管用哪家芯片,WiFi和蓝牙模块的驱动开发,都是绕不开的硬骨头。

核心观点:智能POS的本质,就是一台带支付外设的嵌入式Linux设备。WiFi负责联网通信,蓝牙负责连接外设(打印机、扫码枪、键盘)。这两块驱动搞不定,产品就出不了货。

1.2 WiFi/BT模块选型:别在硬件上栽跟头

做驱动开发,硬件选型你得懂一点。不然你辛辛苦苦把驱动写好了,结果发现模块不支持你的内核版本,那可就尴尬了。

我在项目中遇到过最坑的一次:客户选了一款很便宜的WiFi模块,结果连SDIO接口的时序都不标准。我调了整整两周,最后发现是硬件问题。嗯,从那以后,我选模块就特别谨慎。

目前市面上常见的WiFi/BT Combo模块:

模块型号 接口类型 WiFi标准 蓝牙版本 推荐场景
AP6255 SDIO+UART 802.11ac BT 4.2 中端POS机
RTL8822BS SDIO+UART 802.11ac BT 5.0 高性能POS机
ESP32-S3 SPI+UART 802.11b/g/n BT 5.0 低成本方案

选型时我建议你注意三点:

  • 内核支持度:Linux主线内核是否已经包含该模块的驱动?如果没有,你得自己移植,工作量不小。
  • 天线设计:POS机是金属外壳,天线位置很讲究。我见过因为天线匹配不好,WiFi信号差到连路由器都搜不到。
  • 蓝牙共存:WiFi和蓝牙共用天线时,要确认模块是否支持PTA(共存机制)。不然WiFi传数据时,蓝牙就断连,这谁受得了?

避坑指南:我曾经选了一款号称“完美兼容”的模块,结果发现它的蓝牙固件需要单独加载,而且加载时序有严格要求。如果上电顺序不对,蓝牙就起不来。所以,选型时一定要问清楚:固件怎么加载?有没有参考设计?

1.3 Linux驱动开发环境搭建:交叉编译链与内核源码树

好,到了动手环节。环境搭建这事儿,说简单也简单,说复杂也复杂。关键在于你要理解:我们是在PC上编译,在ARM板子上运行。这就叫交叉编译。

为什么不能直接在板子上编译?你想想看,POS机的CPU主频一般就1.2GHz,内存512MB,编译一个内核要几个小时。而你的PC,i7处理器,16GB内存,几分钟就搞定了。所以,交叉编译是嵌入式开发的标配。

1.3.1 安装交叉编译链

我习惯用Linaro提供的GCC工具链,稳定,而且社区支持好。以ARM 32位为例:

# 下载ARM交叉编译链
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/

# 配置环境变量
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin

# 验证是否安装成功
arm-linux-gnueabihf-gcc --version

这里有个小细节:arm-linux-gnueabihf 中的 hf 代表硬浮点。如果你的POS机CPU支持硬件浮点运算,一定要用这个版本,性能差距很大。

个人经验:我建议你把交叉编译链的路径写到 ~/.bashrc 里,这样每次打开终端就不用重新 export 了。另外,不同内核版本可能依赖不同版本的GCC,比如Linux 4.19推荐用GCC 7.x,Linux 5.10推荐用GCC 9.x。别搞混了。

1.3.2 获取并配置内核源码树

内核源码树,说白了就是Linux内核的源代码。驱动开发时,你需要用它来编译驱动模块,以及生成头文件供应用程序调用。

获取内核源码有两种方式:

  • 从芯片厂商获取:比如Rockchip会提供BSP包,里面包含了适配好的内核源码。这是最推荐的方式,因为厂商已经帮你解决了很多硬件适配问题。
  • 从kernel.org下载主线内核:适合学习,但你需要自己打补丁。

以Rockchip RK3308为例,我一般这样操作:

# 解压BSP中的内核源码
tar -xvf rk3308_linux_sdk_v1.0.tar.gz
cd kernel/

# 配置内核,选择默认配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- rk3308_linux_defconfig

# 如果需要自定义配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

这里要注意:ARCH=arm 告诉编译器目标架构是ARM,CROSS_COMPILE 指定交叉编译链的前缀。这两个参数,每次编译都要带上,我建议你写成脚本,省得每次敲。

1.3.3 编译第一个驱动模块

环境搭好了,咱们来编译一个最简单的驱动模块,验证一下环境是否正常。

// hello.c
#include <linux/module.h>
#include <linux/kernel.h>

static int __init hello_init(void)
{
    printk(KERN_INFO "Hello, POS WiFi/BT Driver World!\n");
    return 0;
}

static void __exit hello_exit(void)
{
    printk(KERN_INFO "Goodbye, POS World!\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple test module for POS driver course");

对应的Makefile:

obj-m := hello.o

KERNEL_DIR := /path/to/your/kernel/source
CROSS_COMPILE := arm-linux-gnueabihf-
ARCH := arm

all:
    make -C $(KERNEL_DIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) modules

clean:
    make -C $(KERNEL_DIR) M=$(PWD) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) clean

编译命令:

make

如果一切顺利,你会看到生成了 hello.ko 文件。这就是编译好的内核模块。把它拷贝到POS机上,用 insmod hello.ko 加载,用 dmesg 查看内核日志,应该能看到我们打印的信息。

注意:编译内核模块时,KERNEL_DIR 必须指向你编译好的内核源码树。如果内核还没编译过,先执行 make 编译一遍内核,否则会报缺少 Module.symvers 的错误。我刚开始学的时候,就因为这个卡了整整一天。

1.4 本章小结

好了,第一讲的内容就到这里。咱们回顾一下:

  • POS机行业正在向智能化转型,WiFi和蓝牙是核心通信模块
  • 模块选型要关注内核支持、天线设计和蓝牙共存
  • 交叉编译环境搭建是驱动开发的第一步,别偷懒
  • 用一个小模块验证环境,确保工具链和内核源码树都正常工作

下一讲,咱们会深入WiFi驱动框架,从SDIO接口讲起,一步步把WiFi模块跑起来。到时候我会分享一个我当年调试AP6255时遇到的奇葩问题——模块能识别,但死活连不上AP。嗯,那个故事挺有意思的,下节课再说。

各位,先把环境搭好,有问题咱们群里交流。记住,驱动开发没有捷径,但有了正确的方法,可以少走很多弯路。