嵌入式Linux驱动开发基础知识(一)
·
嵌入式Linux驱动开发基础知识点精要
一、开发环境搭建
- 交叉编译工具链
- 安装:
arm-linux-gnueabihf-gcc - 验证:
arm-linux-gnueabihf-gcc -v
- 安装:
- 内核编译与设备树
- 编译内核:
make Image dtbs - 设备树文件:
.dts(源码) →.dtb(二进制) - 关键配置:屏幕分辨率(
display-timings节点)
- 编译内核:
二、驱动开发核心基础
-
内核模块开发
- 模块入口/出口函数:
module_init(drv_init); module_exit(drv_exit); - 字符设备注册流程:
- 分配设备号:
alloc_chrdev_region - 初始化
cdev结构体 - 关联文件操作集:
cdev_init(&cdev, &fops) - 添加设备到内核:
cdev_add
- 分配设备号:
- 模块入口/出口函数:
-
用户态交互
- 文件操作接口:
struct file_operations { .owner = THIS_MODULE, .open = drv_open, .read = drv_read, .write = drv_write, .release = drv_release }; - 测试APP:通过
open/read/write系统调用与驱动交互
- 文件操作接口:
三、设备树(DTS)核心操作
-
设备树解析函数
- 查找节点:
of_find_node_by_path("/soc/gpio@ff260000") - 获取属性:
of_get_property(node, "compatible", NULL) - 地址转换:
of_iomap(自动映射物理地址到虚拟地址)
- 查找节点:
-
资源管理
- 定义资源结构体:
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - 手动映射寄存器:
void __iomem *reg = ioremap(res->start, resource_size(res));
- 定义资源结构体:
四、并发与竞争控制
| 机制 | 适用场景 | 核心API |
|---|---|---|
| 原子操作 | 单个变量的简单保护 | atomic_read(), atomic_set() |
| 自旋锁 | 短时临界区,不可睡眠 | spin_lock(), spin_unlock() |
| 信号量 | 允许休眠的长时任务 | down(), up() |
| 互斥体 | 替代信号量,支持优先级继承 | mutex_lock(), mutex_unlock() |
| 读写锁 | 读多写少场景 | read_lock(), write_lock() |
五、中断处理
- 注册中断
request_irq(irq_num, handler, IRQF_TRIGGER_RISING, "key_irq", dev); - 顶半部与底半部
- 顶半部:快速响应(清除中断标志)
- 底半部:
- Tasklet:不可睡眠,轻量级
DECLARE_TASKLET(my_tasklet, tasklet_func, data); - 工作队列:可睡眠,处理复杂逻辑
INIT_WORK(&work, work_func); schedule_work(&work);
- Tasklet:不可睡眠,轻量级
六、内核定时器
- 定时器使用
struct timer_list my_timer; timer_setup(&my_timer, timer_callback, 0); mod_timer(&my_timer, jiffies + msecs_to_jiffies(1000)); - 延时函数
- 毫秒级:
mdelay(10) - 纳秒级:
ndelay(100)
- 毫秒级:
七、阻塞与非阻塞IO
- 等待队列
DECLARE_WAIT_QUEUE_HEAD(wq); wait_event_interruptible(wq, condition); wake_up_interruptible(&wq); - 应用场景
- 按键防抖:定时器延时处理中断
- 数据等待:进程休眠直到数据就绪
基础学习路径
- 环境搭建:交叉编译器 + 内核编译
- 第一个驱动:字符设备控制虚拟LED
- 设备树实战:修改GPIO引脚定义并验证
- 并发实验:用自旋锁保护共享计数器
- 中断实验:按键触发LED状态切换
- 综合练习:按键防抖 + 定时器呼吸灯
常见面试考点
- 设备号管理:主/次设备号分配机制
- 内存映射:
ioremap与mmap的区别 - 中断上下文:为什么顶半部不能休眠?
- 自旋锁 vs 信号量:使用场景对比
- 设备树作用:为什么取代了板级文件?
核心文档参考:
- 《Linux设备驱动开发详解》第5章(字符设备)
- 《Linux内核设计与实现》第10章(中断处理)
- 内核源码:
drivers/char(简单驱动参考)
掌握以上知识点后,可尝试实现一个多按键LED控制系统(含防抖、并发控制、sysfs调试接口),作为面试展示项目。
更多推荐
所有评论(0)