admin 管理员组

文章数量: 1184232

amlogic-s9xxx-armbian内核模块开发:编写自定义驱动入门指南

【免费下载链接】amlogic-s9xxx-armbian amlogic-s9xxx-armbian: 该项目提供了为Amlogic、Rockchip和Allwinner盒子构建的Armbian系统镜像,支持多种设备,允许用户将安卓TV系统更换为功能强大的Armbian服务器系统。 项目地址: https://gitcode/GitHub_Trending/am/amlogic-s9xxx-armbian

引言:为什么需要自定义内核模块?

你是否曾因Amlogic S9xxx设备缺少特定硬件驱动而困扰?是否希望为你的Armbian系统添加自定义功能却苦于没有入门指南?本文将带你从零开始,掌握在amlogic-s9xxx-armbian项目中开发内核模块的完整流程。通过本文,你将学会:

  • 搭建符合项目规范的内核模块开发环境
  • 编写支持热插拔的基础驱动程序
  • 集成设备树(Device Tree)配置
  • 使用项目编译系统打包和测试模块
  • 解决常见的模块加载冲突问题

开发环境准备

内核源码与工具链

amlogic-s9xxx-armbian项目提供了完整的内核编译脚本,位于compile-kernel/tools/script/armbian_compile_kernel_script.sh。开发模块前需确保内核源码和编译工具链就绪:

# 克隆项目仓库
git clone https://gitcode/GitHub_Trending/am/amlogic-s9xxx-armbian.git
cd amlogic-s9xxx-armbian

# 安装编译依赖
sudo apt-get install -y $(cat compile-kernel/tools/script/armbian-compile-kernel-depends)

# 下载特定版本内核源码(以6.1.y为例)
./recompile -k 6.1.y -a false

确认内核配置

项目配置文件(compile-kernel/tools/config/config-*)已默认启用模块支持:

CONFIG_MODULES=y                  # 启用模块支持
CONFIG_MODULES_TREE_LOOKUP=y      # 支持模块依赖解析
CONFIG_MODULES_USE_ELF_RELA=y     # 支持ELF重定位

通过以下命令验证当前内核配置:

# 查看已启用的模块相关配置
grep -E "CONFIG_MODULES|CONFIG_MODULE_UNLOAD" compile-kernel/kernel/linux-6.1.y/.config

第一个内核模块:Hello World

模块代码结构

创建hello_armbian.c文件,实现最基础的内核模块:

#include <linux/init.h>       // 模块初始化/退出函数
#include <linux/module.h>     // 模块核心宏定义
#include <linux/kernel.h>     // 内核API

// 模块元信息(必选)
MODULE_LICENSE("GPL");                      // 许可证声明
MODULE_AUTHOR("Your Name");                 // 作者信息
MODULE_DESCRIPTION("Amlogic S9xxx Demo Module"); // 模块描述
MODULE_VERSION("1.0");                      // 版本号

// 初始化函数(模块加载时执行)
static int __init hello_armbian_init(void) {
    printk(KERN_INFO "Hello amlogic-s9xxx-armbian! Module loaded\n");
    return 0; // 返回0表示加载成功
}

// 退出函数(模块卸载时执行)
static void __exit hello_armbian_exit(void) {
    printk(KERN_INFO "Goodbye amlogic-s9xxx-armbian! Module unloaded\n");
}

// 注册初始化和退出函数
module_init(hello_armbian_init);
module_exit(hello_armbian_exit);

Makefile编写

创建与源代码同级的Makefile

# 指定内核源码路径(根据实际编译路径调整)
KERNEL_DIR ?= $(CURDIR)/../compile-kernel/kernel/linux-6.1.y
PWD := $(shell pwd)

# 模块名称
MODULE_NAME := hello_armbian

obj-m += $(MODULE_NAME).o  # 声明要构建的模块

# 默认目标:编译模块
all:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) modules

# 清理编译产物
clean:
    $(MAKE) -C $(KERNEL_DIR) M=$(PWD) clean
    rm -f *.ko *.mod.c *.o Module.symvers modules.order

模块编译与测试

编译模块

# 使用项目工具链编译模块
make ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu-

# 查看编译产物
ls -l hello_armbian.ko  # 生成的内核模块文件

测试流程

# 复制模块到目标设备
scp hello_armbian.ko root@your_device_ip:/tmp

# 在目标设备上操作
ssh root@your_device_ip

# 加载模块
insmod /tmp/hello_armbian.ko

# 验证模块加载状态
lsmod | grep hello_armbian  # 查看模块是否加载
dmesg | tail -n 10          # 查看内核日志输出

# 卸载模块
rmmod hello_armbian

# 再次检查日志
dmesg | tail -n 1

进阶:硬件驱动开发基础

GPIO控制示例

以Amlogic S905X3的GPIO为例,编写控制LED的内核模块:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/gpio.h>       // GPIO控制API
#include <linux/delay.h>      // 延时函数

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("Amlogic GPIO Control Demo");

#define LED_GPIO 123  // 根据设备树定义的GPIO编号(需替换为实际值)

static int __init gpio_led_init(void) {
    int ret;
    
    // 申请GPIO资源
    ret = gpio_request(LED_GPIO, "armbian_led");
    if (ret) {
        printk(KERN_ERR "Failed to request GPIO %d\n", LED_GPIO);
        return ret;
    }
    
    // 设置GPIO为输出模式
    gpio_direction_output(LED_GPIO, 1);  // 初始化为高电平(LED熄灭)
    
    // 闪烁LED三次
    gpio_set_value(LED_GPIO, 0); msleep(500);  // 低电平点亮
    gpio_set_value(LED_GPIO, 1); msleep(500);
    gpio_set_value(LED_GPIO, 0); msleep(500);
    gpio_set_value(LED_GPIO, 1); msleep(500);
    gpio_set_value(LED_GPIO, 0); msleep(500);
    gpio_set_value(LED_GPIO, 1);
    
    printk(KERN_INFO "GPIO LED driver initialized\n");
    return 0;
}

static void __exit gpio_led_exit(void) {
    // 释放GPIO资源
    gpio_set_value(LED_GPIO, 1);  // 确保LED熄灭
    gpio_free(LED_GPIO);
    printk(KERN_INFO "GPIO LED driver exited\n");
}

module_init(gpio_led_init);
module_exit(gpio_led_exit);

设备树集成

  1. 查找设备树文件:项目设备树文件位于内核源码的arch/arm64/boot/dts/amlogic/目录下

  2. 添加自定义设备节点:在对应板级DTS文件中添加:

armbian_led: armbian-led {
    compatible = "armbian,led-demo";
    gpios = <&gpio GPIOX_12 GPIO_ACTIVE_LOW>;  // 根据实际硬件调整
    status = "okay";
};
  1. 在模块中匹配设备树
#include <linux/of.h>            // 设备树操作
#include <linux/of_gpio.h>       // GPIO设备树解析

static struct device_node *led_node;

static int __init gpio_led_init(void) {
    int ret;
    unsigned int gpio;
    
    // 从设备树查找节点
    led_node = of_find_node_by_path("/armbian_led");
    if (!led_node) {
        printk(KERN_ERR "Failed to find device tree node\n");
        return -ENODEV;
    }
    
    // 从设备树获取GPIO编号
    gpio = of_get_named_gpio_flags(led_node, "gpios", 0, NULL);
    if (gpio_is_valid(gpio)) {
        // GPIO操作代码...
    }
    // ...
}

模块调试与问题排查

常见错误及解决方法

错误类型可能原因解决方案
编译错误:未定义符号内核版本不匹配确保使用项目编译的内核源码
insmod: invalid module format模块与内核版本不匹配重新编译模块,检查CONFIG_MODULES配置
gpio_request失败GPIO被占用或未定义检查设备树GPIO定义,使用free_gpio工具释放
dmesg无输出printk级别限制使用dmesg -n 7临时调整日志级别

高级调试技巧

  1. 使用动态调试
# 启用模块动态调试
echo -n "module hello_armbian +p" > /sys/kernel/debug/dynamic_debug/control
dmesg -w  # 实时查看调试信息
  1. 内核Oops分析
# 安装调试工具
apt-get install ksymoops

# 分析Oops日志
ksymoops /var/log/kern.log

项目集成:使用编译脚本打包模块

修改内核编译配置

  1. compile-kernel/tools/config/config-6.1中添加模块配置:
CONFIG_HELLO_ARMBIAN=m  # 将模块编译为可加载模块
  1. 使用项目编译脚本重新生成内核:
./recompile -k 6.1.y -p true  # -p true启用自定义补丁

创建模块补丁

  1. compile-kernel/tools/patch/common-kernel-patches/目录创建补丁文件:
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index xxxxxxx..xxxxxxx 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -xxx,6 +xxx,10 @@ config MISC_DEVICES
 	  If you have a device that doesn't fit into any other category,
 	  say Y here and look for your device in the following questions.
 
+config HELLO_ARMBIAN
+	tristate "Hello Armbian Demo Module"
+	help
+	  A simple demo module for amlogic-s9xxx-armbian project.
+
 endif # MISC_DEVICES
 
 config AD525X_DPOT
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index xxxxxxx..xxxxxxx 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -xxx,3 +xxx,4 @@ obj-$(CONFIG_SRAM)		+= sram.o
 obj-$(CONFIG_STAGING)		+= staging/
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-$(CONFIG_VIDEO_VIVID)	+= vivid/
+obj-$(CONFIG_HELLO_ARMBIAN)	+= hello_armbian.o
  1. 将模块源码复制到内核对应目录,然后应用补丁并编译:
cp hello_armbian.c compile-kernel/kernel/linux-6.1.y/drivers/misc/
./recompile -k 6.1.y -p true

总结与进阶方向

通过本文,你已掌握:

  • 内核模块的基本结构与编译方法
  • 设备树与GPIO交互
  • 项目集成与补丁制作
  • 调试工具与问题排查

进阶学习路径

  1. 字符设备驱动:实现完整的read/write/ioctl接口
  2. 内核定时器:使用setup_timer实现周期性任务
  3. 中断处理:通过request_irq处理硬件中断
  4. DMA操作:优化大数据传输性能

参考资源

  • 项目内核编译文档:compile-kernel/README.md
  • Linux内核模块开发指南:kernel/doc/html/latest/kernel-hacking/index.html
  • Amlogic官方文档:developer.amlogic

参与贡献

如果你开发了实用的内核模块,欢迎通过以下方式贡献到amlogic-s9xxx-armbian项目:

  1. 提交模块补丁到compile-kernel/tools/patch/目录
  2. 在设备树中添加标准化硬件描述
  3. 更新documents/目录下的驱动开发文档

【免费下载链接】amlogic-s9xxx-armbian amlogic-s9xxx-armbian: 该项目提供了为Amlogic、Rockchip和Allwinner盒子构建的Armbian系统镜像,支持多种设备,允许用户将安卓TV系统更换为功能强大的Armbian服务器系统。 项目地址: https://gitcode/GitHub_Trending/am/amlogic-s9xxx-armbian

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

本文标签: 自定义 内核 模块 入门 指南