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);
设备树集成
-
查找设备树文件:项目设备树文件位于内核源码的
arch/arm64/boot/dts/amlogic/目录下 -
添加自定义设备节点:在对应板级DTS文件中添加:
armbian_led: armbian-led {
compatible = "armbian,led-demo";
gpios = <&gpio GPIOX_12 GPIO_ACTIVE_LOW>; // 根据实际硬件调整
status = "okay";
};
- 在模块中匹配设备树:
#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临时调整日志级别 |
高级调试技巧
- 使用动态调试:
# 启用模块动态调试
echo -n "module hello_armbian +p" > /sys/kernel/debug/dynamic_debug/control
dmesg -w # 实时查看调试信息
- 内核Oops分析:
# 安装调试工具
apt-get install ksymoops
# 分析Oops日志
ksymoops /var/log/kern.log
项目集成:使用编译脚本打包模块
修改内核编译配置
- 在
compile-kernel/tools/config/config-6.1中添加模块配置:
CONFIG_HELLO_ARMBIAN=m # 将模块编译为可加载模块
- 使用项目编译脚本重新生成内核:
./recompile -k 6.1.y -p true # -p true启用自定义补丁
创建模块补丁
- 在
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
- 将模块源码复制到内核对应目录,然后应用补丁并编译:
cp hello_armbian.c compile-kernel/kernel/linux-6.1.y/drivers/misc/
./recompile -k 6.1.y -p true
总结与进阶方向
通过本文,你已掌握:
- 内核模块的基本结构与编译方法
- 设备树与GPIO交互
- 项目集成与补丁制作
- 调试工具与问题排查
进阶学习路径
- 字符设备驱动:实现完整的read/write/ioctl接口
- 内核定时器:使用
setup_timer实现周期性任务 - 中断处理:通过
request_irq处理硬件中断 - DMA操作:优化大数据传输性能
参考资源
- 项目内核编译文档:
compile-kernel/README.md - Linux内核模块开发指南:kernel/doc/html/latest/kernel-hacking/index.html
- Amlogic官方文档:developer.amlogic
参与贡献
如果你开发了实用的内核模块,欢迎通过以下方式贡献到amlogic-s9xxx-armbian项目:
- 提交模块补丁到
compile-kernel/tools/patch/目录 - 在设备树中添加标准化硬件描述
- 更新
documents/目录下的驱动开发文档
【免费下载链接】amlogic-s9xxx-armbian amlogic-s9xxx-armbian: 该项目提供了为Amlogic、Rockchip和Allwinner盒子构建的Armbian系统镜像,支持多种设备,允许用户将安卓TV系统更换为功能强大的Armbian服务器系统。 项目地址: https://gitcode/GitHub_Trending/am/amlogic-s9xxx-armbian
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
版权声明:本文标题:amlogic-s9xxx-armbian内核模块开发:编写自定义驱动入门指南 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1763552026a3249272.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论