嵌入式驱动开发之框架及调试技巧累积

本文详细介绍了Linux系统下驱动开发的基本框架,包括app如何调用驱动机制、字符设备驱动的编写步骤,以及通用GPIO驱动框架的理解。同时,文章探讨了在驱动开发过程中遇到的问题,如_IOW()函数的作用,并分享了嵌入式调试技巧,如利用gcc工具进行调试。
摘要由CSDN通过智能技术生成

知识储备。

基本的框架

在linux系统中,App无法操作硬件的,不具备相应的权限。在mmu(内存管理单元)作了划分的,应用层只能操作属于它的mmu部分。操作硬件只能是通过驱动程序。应用程序与驱动程序之间有严格的界限。驱动程序在内核中。

app如何调用驱动机制

如App使用open函数打开设备时,会先设置某个寄存器,会触发一个异常swi指令(此时由用户态切换到内核态才有更高的权限),此时会有中断服务程序被调用。然后根据先前设置的寄存器判断是什么操作;然后去读写硬件。

字符设备驱动编写步骤

1. 实现入口函数 XXX_init()和卸载函数 XXX_exit()

2. 申请设备号 register_chrdev_region(与内核相关)

静态分配设备号:在事先知道设备主设备号的情况下通过参数函数指定第一个设备号而向系统申请分配一定数目的设备号。
动态分配:alloc_chrdev_region():通过参数仅设置第一个次设备号(通常为0,事先不会知道主设备号)和要分配的设备数目而系统动态分配所需的设备号

3. 注册字符设备驱动 cdev_alloc / cdev_init /cdev_add(与内核相关)

4. 利用udev/mdev机制创建设备文件(节点)class_create,device_create(与内核相关)

5. 硬件部分初始化

io资源映射 ioremao,内核提供gpio库函数(与硬件相关)
注册中断(与硬件相关)
初始化等待队列(与内核相关)
初始化定时器(与内核相关)

6. 构建file_operation结构(与内核相关)

7. 实现硬件操作方法 XXX_open,XXX_read,XXX_write…(与硬件相关)

通用GPIO驱动框架的问题及理解

setup_timer()函数

原型:#define setup_timer(timer, fn, data) \ __setup_timer((timer), (fn), (data), 0)
第一个参数:是struct timer_list类型的变量,此变量用于存放动态定时器,是即将要被初始化的对象,其定义及详细解释参考
第二个参数是定时器到期时将要执行的函数,用于给定时器变量的function字段赋值。
第三个参数用于给定时器变量的data字段赋值

add_timer()函数

将定时器加入到定时器链表,并激活定时器

gpio_to_irq()函数或gpiod_to_irq()

int gpio_to_irq(unsigned int gpio);//返回值:gpio对应的中断号

request_irq()函数

原型:static inline int __must_check request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev) { return request_threaded_irq(irq, handler, NULL, flags, name, dev); }
irq:要申请的中断号。
handler:中断处理函数,当中断发生时,执行该函数。
flags:中断标志。
name:中断名字,设置后在/proc/interrupts目录下可以查看。
dev:如果flags设置为IRQF_SHARED,dev用来区分不同的中断,一般情况下,dev设置为设备结构体,它会传给中断处理函数irq_handler_t第二个参数,本例中置为NULL。

register_chrdev()

原型:int register_chrdev(unsigned int major, const char *name,struct file_operations *fops)
major:设备驱动程序向系统申请的主设备号,如果为0则系统为此驱动程序动态地分配一个主设备号
name:设备名
fops:对各个调用的入口点

class_create()函数

原型:#define class_create(owner, name) \ ({ \ static struct lock_class_key __key; \ __class_create(owner, name, &__key); \ })
owner:一个struct module结构体类型的指针,指向函数__class_create()即将创建的、“拥有”这个struct class的模块。一般赋值为THIS_MODULE,此结构体的详细定义见文件include/linux/module.h。
name:char类型的指针,代表即将创建的struct class变量的名字,用于给struct class的name字段赋值。通俗地说,就是指向struct class名称的字符串的指针。
效果:此函数的执行效果就是在/sys/class/目录下创建一个新的文件夹

device_create()函数

原型:struct device *device_create(struct class *cls, struct device *parent, dev_t devt, void *drvdata,const char *fmt, ...);
class:该设备依附的类
parent:父设备
devt:设备号(此处的设备号为主次设备号)
drvdata:私有数据
fmt:设备名。
device_create能自动创建设备文件是依赖于udev这个应用程序。udev是一种工具,它能够根据系统中的硬件设备的状态动态更新设备文件,包括设备文件的创建,删除等。设备文件通常放在/dev目录下。使用udev后,在/d

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

guangod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值