【内核编译、.ko驱动模块编译】- 未完结

首先,之前添加了ch9434.c,修改了Kconfig和Makefile,然后通过menuconfig启用了该驱动,选项前有星号。可能对内核配置符号(*、M、空格)的含义不太清楚,需要详细解释。

有时候在编译后发现没有生成.ko文件,或者在加载模块时遇到问题,所以想确认配置是否正确。我需要明确说明,选择<*>会将驱动编译进内核,而不是作为模块,因此不会生成.ko文件。如果他们希望生成模块,应该选择。

另外,可能混淆了内核镜像和模块的概念。需要解释不同配置选项的结果,以及如何验证驱动是否被正确编译进内核。还要指导他们如何检查内核的.config文件,确保配置正确生效。

此外,可能在之前的步骤中遇到了问题,比如没有生成.ko文件,所以需要检查配置是否正确,并解释为什么即使驱动被编译进内核,也不会产生.ko文件。可能需要建议如何调整配置以生成模块,或者确认驱动确实内建到了内核中。

一、内核编译区别

将【驱动编译进内核】与将【驱动编译成.ko驱动模块】的区别

1.make menuconfig 配置符号分析

符号含义编译结果
< >未选中不编译
<M>模块方式编译生成 .ko 文件
<*>内置到内核镜像直接编译进 Image

2 将驱动代码编译进内核镜像Image

2.1 例如下面是我当前的配置:

< * > SERIAL_CH9434 serial support前面是 * 号
配置了内核选项

①make menuconfig
②Device Drivers
  -> Character devices
    -> Serial drivers
      -> < * > SERIAL_CH9434 serial support
当前我的配置的影响(结果):
  1. 编译结果
    驱动代码:会被直接编译进内核镜像文件里面 arch/arm64/boot/Image
    模块文件不会生成 ch9434.ko 文件

  2. 运行时加载
    • 驱动会随内核启动自动加载,无需手动执行 modprobeinsmod进行加载驱动ch9434.ko 文件。


2.2 验证配置

步骤 1:检查 .config 文件
grep CONFIG_SERIAL_CH9434 .config

正确输出

CONFIG_SERIAL_CH9434=y
步骤 2:验证编译过程

重新编译内核后,检查驱动目标文件:

# 查看目标文件是否生成
ls drivers/tty/serial/ch9434.o

# 检查内核镜像是否包含驱动符号
nm arch/arm64/boot/Image | grep ch9434_probe

预期输出

ffffff8000123456 T ch9434_probe

3. 如果需要生成 .ko 文件

如果希望驱动以模块形式存在,需重新配置

步骤 1:修改配置为模块

配置了内核选项
通过menuconfig将 <*> 改为 < M > SERIAL_CH9434 serial support

①make menuconfig
②Device Drivers
  -> Character devices
    -> Serial drivers
      -> < M > SERIAL_CH9434 serial support
make menuconfig
步骤 2:验证配置
grep CONFIG_SERIAL_CH9434 .config

正确输出
在这里插入图片描述

CONFIG_SERIAL_CH9434=m
步骤 3:单独编译驱动模块

make -j 8 modules

hugo@hugo-virtual-machine:~/IMX8/Kernel/Linux-5.4.70$ make -j 8 modules

4. 关键差异对比及操作建议

特性内置到内核 (=y)编译为模块 (=m)
启动时加载自动需手动加载
修改驱动后需重新编译整个内核只需编译模块
内核镜像大小增大不变
适用场景核心关键驱动可选功能驱动

操作建议

  1. 硬件关键驱动(如SPI控制器)建议使用 <*> 内置到内核
  2. 外设扩展驱动(如CH9434)建议使用 <M> 模块方式
  3. 调试阶段优先使用模块,方便快速迭代

二、【实战】配置CH9434 SPI驱动

1、硬件配置阶段

做了什么

  1. 引脚复用:在设备树中把GPIO5_6到GPIO5_9配置成SPI信号线(SCLK/MOSI/MISO/CS0),GPIO4_27配置成中断引脚。
    通俗解释:就像给电脑插USB设备前要插对接口一样,这一步告诉芯片哪些针脚用来传SPI信号,哪个针脚用来通知中断。

2、把驱动编译进内核(关键步骤)

驱动代码放对位置

cd到 IMX8/Kernel/Linux-5.4.70/drivers/tty/serial

ch9434.c放到hugo@hugo-virtual-machine:~/IMX8/Kernel/Linux-5.4.70/drivers/tty/serial目录。

修改编译配置

vi Kconfig在/Kernel/Linux-5.4.70/drivers/tty/serial/Kconfig里加选项SERIAL_CH9434,让内核知道有9434这个驱动。

。。。。。。。
config SERIAL_ARC_NR_PORTS
        int "Number of ARC UART ports"
        depends on SERIAL_ARC
        range 1 3
        default "1"
        help
          Set this to the number of serial ports you want the driver
          to support.

config SERIAL_CH9434
        tristate "SERIAL_CH9434 serial support"
        depends on SPI
        select SERIAL_CORE
        help
        This selects support for ch9434 serial ports.

config SERIAL_RP2
        tristate "Comtrol RocketPort EXPRESS/INFINITY support"
。。。。。。。

/Kernel/Linux-5.4.70/drivers/tty/serial/Makefile里加一行obj-$(CONFIG_SERIAL_CH9434) += ch9434.o,告诉编译器要编译这个文件。

obj-$(CONFIG_SERIAL_MILBEAUT_USIO) += milbeaut_usio.o
obj-$(CONFIG_SERIAL_SIFIVE)	+= sifive.o
obj-$(CONFIG_SERIAL_CH9434) += ch9434.o

make menuconfig配置内核选项

/Kernel/Linux-5.4.70内核路径下用make menuconfig命令,找到Serial drivers,把SERIAL_CH9434标为<*>(直接编译进内核)。

①make menuconfig
②Device Drivers
  -> Character devices
    -> Serial drivers
      -> < * > SERIAL_CH9434 serial support

使能交叉编译工具链

/Kernel/Linux-5.4.70内核路径下source环境变量,使能交叉编译工具链,为下面make -j 8 Image进行编译内核镜像做准备

source /home/hugo/SDK/environment-setup-aarch64-poky-linux

⑤ **不用make distclean清除编译结果

(可选,如果清除了,就要再从新去步骤③make menucofig)**:
接下来是make distclean
如果之前编译过模块.ko,现在改为内置驱动,可能需要执行,在/Kernel/Linux-5.4.70路径下使用make distclean清理.ko文件来确保配置正确。

但make distclean会删除所有配置和中间文件,包括.config文件,这可能导致需要重新配置所有选项。
因此,建议不要使用make distclean,而是使用make clean来保留.config文件,避免重复配置。

不用make imx_v8_defconfig

然后是make imx_v8_defconfig。这会将内核配置重置为默认的内核配置,覆盖我们之前通过menuconfig所做的修改。
但是如果已经执行了⑤清理了配置,可以在在/Kernel/Linux-5.4.70路径下使用这个make imx_v8_defconfig来设置默认的配置,然后再这基础上再去③make menuconfig去设置9434的驱动

如果我们已经配置过内核,并且想保留这些配置,应该避免执行这一步。
正确的做法是备份当前的.config文件,或者在现有配置的基础上进行调整。

再次执行make menuconfig

如果做了步骤⑤⑥,就要再次运行make menuconfig来修改内核配置,确保驱动被选中为内置( * )

编译内核镜像Image

/Kernel/Linux-5.4.70路径下使用make -j 8 Image 。这里需要注意的是,当驱动被编译进内核时,编译整个Image是必要的,
但通常建议使用make all来编译所有必要的部分,包括设备树。
另外,-j8参数指定并行编译的线程数,根据用户机器的CPU核心数调整,这里没问题。

不用make modules,不用sudo make modules_install
是否需要编译模块(make modules)。由于驱动现在被编译进内核,不需要生成.ko文件,所以不需要编译模块。但如果有其他模块需要编译,就需要。

最后,不需要执行sudo make modules_install,因为驱动已经内置到Image中,没有生成.ko文件,不需要安装模块。

3、如果把驱动成.ko文件(关键步骤)

调整策略

改为模块编译:把配置从<*>改成<M>(生成.ko模块文件)。

sed -i 's/=y/=m/' .config  # 直接修改配置文件

重新编译模块

make modules -j8  # 只编译模块,速度更快

验证生成文件

ls drivers/tty/serial/ch9434.ko  # 看到这个文件说明成功

在这里插入图片描述

④ 驱动加载与验证

操作步骤

  1. 安装模块到开发板
    sudo cp ch9434.ko /lib/modules/$(uname -r)/  # 复制模块文件
    depmod -a  # 更新模块依赖
    
  2. 加载驱动
    modprobe ch9434  # 加载模块
    
  3. 检查加载结果
    dmesg | grep ch9434  # 看到"CH9434 initialized"表示成功
    ls /dev/ttyWCH*      # 出现4个串口设备节点(ttyWCH0~3)
    

发现问题
• 如果设备节点没出现:
• 检查设备树里的SPI总线地址是否正确(比如ecspi1节点)。
• 用示波器测量SCLK和CS引脚是否有信号。


4、调试技巧总结

  1. 模块 vs 内置
    • 模块(.ko)调试灵活,改代码后只需重新编译模块。
    • 内置驱动(直接进Image)适合最终产品,但调试麻烦。
  2. 验证三板斧
    看日志dmesg | grep ch9434
    查设备节点ls /dev/ttyWCH*
    测硬件信号:示波器量SCLK/CS是否有波形。
  3. 设备树是硬件字典
    • 驱动通过设备树知道硬件怎么连接,就像地图告诉司机路线。

5、最终成果

成功现象:加载驱动后,扩展的4个串口可直接用/dev/ttyWCH0~3操作,就像普通串口一样收发数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值