刚学的现货,给自己做个小结。
想不出写什么啊 QAQ 。好吧,来随便编一点好了 =。=。
<1>module_init("驱动初始化函数"); \*o*/ module_exit("退出驱动函数"); 的申请。
{1.1 入口函数: 申请&自动生成 主设备号&设备节点
1.2 ioremap 我的理解是把实际的硬件地址告诉mmu向mmu申请虚拟的内存地址
volatile unsigned long
*gpfcon = (volatile unsigned long *)ioremap(0x56000050 /*gpfcon地址*/, 16 /*申请16字节长度*/);
volatile unsigned long
*gpfdat = gpfcon + 1; //通过基准地址得出地址
1.3 出口函数: 注销 设备&节点 取消映射
unregister_chrdev(major, "first_drv");
class_device_unregister(seconddrv_class_dev);
class_destroy(seconddrv_class);
iounmap(gpfcon);
iounmap(gpgcon);
}
<2> struct file_operations{ .open"中去申请中断".. };
{
2.1 申请中断
request_irq(IRQ_EINT0 /*这是中断号的一个宏*/,
buttons_irq /*自己写的中断处理函数的名字*/,
IRQT_BOTHEDGE /*这是啥玩意?*/,
"S2" /*好像是给中断在进程中取的名*/,
&pins_desc[0] /*想传入中断处理函数的参数,随便写 0.0*/
);
// 好吧,一共有五个参数了。
}
<3> IRQ handled 函数的编写
{
3.1 (传说中的)中断处理函数 的原型吧..
static irqreturn_t buttons_irq(int irq, void *dev_id){
*dev_id 就是传进来的参数了,这里用了结构体。
判断参数内容, 做出自己设计的动作。
irq 可能是中断号吧,这玩意没试过,可以打印看看、
}
3.2 唤醒进程么
把程序叫醒好来干活了
不过在程序里首先得申请static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
我现在也还不清楚它具体做啥的, button_waitq大概是进程号吧?
这样就能找到该叫醒的程序了么 0.0
wake_up_interruptible(&button_waitq);
}
<4> struct file_operations{ .read"返回键值".. };
{
4.1 驱动程序中主要 去和应用程序打交道的函数
ssize_t read/*名字随意取,用上面<4>那个结构体注册下就可以了*/(
struct file *file,/* 忘了 */
char __user *buf,/* 应用程序传进来的数据地址 */
size_t size, /* 数据的大小 */
loff_t *ppos) /* 还不知道 */
4.2 判断传进来的 size值是不是和你设想的一样,不是的话 return -EINVAL //-1
4.3 这里有个休眠,没有中断发生的话,程序就可去休息一会了。
wait_event_interruptible(button_waitq, ev_press);
ev_press 是自己设计的小机关,0去休眠 1就不睡
4.4 睡醒了就把中断已经处理好的key_val传给应用程序去啊
copy_to_user(buf, &key_val, 1);
"buf" 是应用程序说:你就放这里吧
好吧,那就copy key_val给它吧
而且是1个字节那么大
4.5 ev_press = 0; 打开接着睡的机关
}
<5> interrupt close 函数的编写
{
5.1 释放中断去
free_irq(IRQ_EINT0, &pins_desc[0]);
主要是IRQ_EINT0 这个中断好在起作用
pins_desc 是<2.1> 传给中断处理函数的参数,这里我现在没明白有啥用。
没准换个参数也行0。0 或不行 *-*
}
——2014/10/29 11:10