请注意, linux的应用层对字符设备都是采取文件读写的方式,所以说我们的驱动程序也是用的是文件的形式。

我们需要把所有的驱动程序封装到文件的读写形式里面。

1、 static int XXX_open(struct inode *inode, struct file *file)  //这个函数是挂载到struct file_operations  open里面的。

     此函数需要完成对各种引脚或者总线的硬件初始化,中断初始化 等等

2、static ssize_t XXX_write(struct file *file, const char __user *buf, size_t count, loff_t* ppos)   //这个函数是挂载到struct file_operations  write里面的。

在此函数中 我们可以给引脚赋值。

3. static struct file_operations XXX_XXX_fops = {

  

.owner = THIS_MODULE,
.open = first_drv_open,
.write = first_drv_write,

 

}

这个结构体是一个文件的结构我们把前面的读写函数都挂载到这里。

 

4、XXX_init //这个函数是注册在module_init 

     这个函数会给设备分配设备号,映射绝对地址给内核的虚拟地址。

    在此函数中我们会用到以下的函数:

     register_chrdev: Register a major number for character devices.

    

int register_chrdev ( unsigned int   major,
  const char *   name,
  const struct file_operations *   fops);

Arguments

major

major device number or 0 for dynamic allocation    //如果0的话将会自动的分配驱动设备号 如果写入别的数值则会按照数值去分配设备号

name

name of this range of devices                        //这个驱动设备的名字

fops

file operations associated with this devices  //这是存入上面的那个文件的结构体

 

class_create — create a struct class structure   //这个结构体只是给class_device_create 用的


class_create(struct module* owner, const char* name) //pointer to the module that is to “own” this struct class  (always THIS_MODULE), the name is the name of this range of devices.

ioremap(pysical address, length) : give the absolute address of pin address to kernel

 

 

class_device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz");   还不是太能理解这个函数 不过他能够自动的返回一个设备。我们可以知道这个设备的设备号。

5. module_init : 这是一个宏,会把XXX_init注册进入内核

6. module_exit: 这是一个宏,会调用XXX_Exit函数把设备从内核卸载。(rmmod 会调用这个函数。)

7.int first_drv_exit(void)  其中会用到的函数:

unregister_chrdev()取消函数的注册

class_device_unregister()卸载设备类型(想当于卸载了此设备)

iounmap()卸载了绝对地址和相对地址之间的关系。

 

//这个函数必须有 证书许可证

MODULE_LICENSE("GPL");   //MUST BE INCLUDED

 

关于中断的函数

1.request_irq

Synopsis

int request_irq ( unsigned int   irq,
  irq_handler_t   handler,
  unsigned long   irqflags,
  const char *   devname,
  void *   dev_id);

Arguments

irq

Interrupt line to allocate

handler

Function to be called when the IRQ occurs

irqflags

Interrupt type flags

devname

An ascii name for the claiming device

dev_id

A cookie passed back to the handler function

Description

This call allocates interrupt resources and enables the interrupt line and IRQ handling. From the point this call is made your handler function may be invoked. Since your handler function must clear any interrupt the board raises, you must take care both to initialise your hardware and to set up the interrupt handler in the right order.

Dev_id must be globally unique. Normally the address of the device data structure is used as the cookie. Since the handler receives this value it makes sense to use it.

If your interrupt is shared you must pass a non NULL dev_id as this is required when freeing the interrupt.

 

 

2. free_irq() normally write in XX_XXX_Close function

 

3. wait_event_interruptible(button_waitq, ev_press);

static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  //这个宏定义了一个事件,  从而从休眠中脱离,程序会直接跳到中断里面,然后执行中断,在中断中ev_press = 1. 当为1的时候XXX_read函数退出休眠可以执行后面的内容,然后请在执行之后ev_press 清0。

 

posted on 2020-06-18 05:51  闲云潭影  阅读(221)  评论(0编辑  收藏  举报