当前位置:   article > 正文

S3C2440 字符设备驱动程序之LED驱动程序_编写编译(二)_编写一个led闪烁驱动程序led_boot3.s,s3c2440以400m主频工作,在bootram

编写一个led闪烁驱动程序led_boot3.s,s3c2440以400m主频工作,在bootram中执行,起
字符设备驱动程序之LED驱动程序_编写编译


app:    open  ,   read   ,   write

驱动: led_open,led_read,led_write



驱动框架:

一、写出:led_open,led_read

二、怎么告诉内核?

    a、定义一个file_operations

    b、把这个结构体告诉内核:

            register_chrdev(major,name,file_operations)

    c、谁来调用它 (register_chrdev)

        驱动的入口函数 first_drv_init

    d、修饰:module_init(first_drv_init) (怎么知道是哪个入口函数)

          module_init:(入口函数)定义了一个结构体,结构体有个函数指针,指向入口函数xxx_init。加载一个驱动的时候,内核就会找到这个结构体里面的函数指针,指向入口函数。

           加载一个驱动时,内核就会找到这个结构体里面的函数指针,指向入口函数。入口函数把file_operations告诉内核。



介绍一个内核里的数组chrdevs(字符设备的file_operations和major都包含在这个数组中):

  1. static struct char_device_struct {
  2. struct char_device_struct *next;
  3. unsigned int major;
  4. unsigned int baseminor;
  5. int minorct;
  6. char name[64];
  7. struct file_operations *fops;
  8. struct cdev *cdev; /* will die */
  9. } *chrdevs[CHRDEV_MAJOR_HASH_SIZE];



app:open("/dev/xxx")

       打开文件的属性:c _ _ _, _ _ _, _ _ _, major, minor

       设备类型,主设备号

       内核数组chrdevs:

12……………………major………………

★★VFS系统根据打开的这个文件的属性(设备类型:字符设备,主设备号major),就会找到注册进去的file_operations结构。

★★register_chrdev的实现:在一个内核数组chrdevs里,以major为索引,找到一项,在这一项里把file_operations填充进去,挂进去。



总结:

怎么根据打开的设备(open),找到驱动程序具体的实现(led_open)?

在内核定义了一个chrdevs数组,在这个数组里面,根据主设备号,找到了那一项的file_operations,这个file_operations结构是驱动程序里面实现的。


驱动程序:1、定义了led_open、led_write、led_read

                2、定义了file_operations结构体,.open=led_open,.write=led_write

                3、入口函数里,用register_chrdev(major,name,file_operations)把这个结构体放到内核数组chrdevs,对应的主设备号里面。


入口函数(注册):把file_operations结构体挂到chrdevs数组对应的设备号那一项

出口函数(卸载):把file_operations结构体从对应的设备号那一项拖出来。



第一个驱动程序 first_drv.c:

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/fs.h>
  4. #include <linux/init.h>
  5. #include <linux/delay.h>
  6. #include <asm/uaccess.h>
  7. #include <asm/irq.h>
  8. #include <asm/io.h>
  9. #include <asm/arch/regs-gpio.h>
  10. #include <asm/hardware.h>
  11. static int first_drv_open(struct inode *inode, struct file *file)
  12. {
  13. printk("first_drv_open\n");
  14. return 0;
  15. }
  16. static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  17. {
  18. printk("first_drv_write\n");
  19. return 0;
  20. }
  21. static struct file_operations first_drv_fops = {
  22. .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
  23. .open = first_drv_open,
  24. .write = first_drv_write,
  25. };
  26. int first_drv_init(void)
  27. {
  28. register_chrdev(111, "first_drv", &first_drv_fops); //注册驱动程序,告诉内核
  29. return 0;
  30. }
  31. void first_drv_exit(void)
  32. {
  33. unregister_chrdev(111, "first_drv"); //卸载驱动
  34. }
  35. module_init(first_drv_init);
  36. module_exit(first_drv_exit);


Makefile文件:

KERN_DIR = /work/system/linux-2.6.22.6
 
all:
	make -C $(KERN_DIR) M=`pwd` modules

clean:
     make -C $(KERN_DIR) M=`pwd` modules clean
     rm -rf modules.order

 obj-m   += first_drv.o

KERN_DIR表示内核的目录,编一个驱动程序,依赖于内核。

-C:转到这个KERN_DIR这个目录去,用这个目录的Makefile来进行编译。

M=:当前目录是什么。modules:目标。



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/76002
推荐阅读
  

闽ICP备14008679号