还没有学驱动时,大部分对驱动的言论,包括老师的介绍都说做驱动是嵌入式里最难的部分,涉及到底层硬件和内核的知识,心里因此增加了不少畏惧。自己开始学习的时候便开始看些驱动方面的书,希望能有个比较好的认识,可慢慢的发现几乎看不懂,看了韦东山老师的部分视频后果然豁然开朗,发现做LED驱动以及其它驱动时,最主要的是要明白应用程序、库、内核、驱动程序之间的关系,在视频里韦东山老师首先为我们一步一步构造出它们之间的关系,驱动属于底层硬件和上层应用程序之间的中间层,看完这部分视频后你会很清楚的知道驱动、应用程序的那些函数是如何工作的。 
    接下来就是编写驱动程序了,首先构造了open、read、write等函数,而这些只是一些简单的函数而已,如何发挥作用是通过一个结构体来定义,视频里给出的结构体如下: 
static struct file_operations first_drv_fops = { 
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ 
    .open    =   first_drv_open,      
    .read     =     first_drv _read,        
    .write    =     first_drv _write,        
}; 
 
然后再定义first_drv_init函数用来初始化设备等,实现方法如下: 
static int first_drv_init(void)   
{ 
    printk("MY DRIVER MODULE INIT\n"); 
    first_drv_major = register_chrdev(0,DEVICE_NAME, &first_drv_fops);  /*注册一设备*/ 
    if (first_drv_major < 0) 
    { 
        printk(DEVICE_NAME " can't register major number\n"); 
        return first_drv_major; 
    } 
    printk("register first_drv OK! Major = %d\n", first_drv_major); 
    firstdrv_class = class_create(THIS_MODULE, DEVICE_NAME);   /*创建一个类*/ 
    if(IS_ERR(firstdrv_class)) 
    { 
            printk("Err: failed in firstdrv_class. \n"); 
            return -1 ; 
    } 
    /*通过创建的类来创建一设备节点*/ 
firstdrv_class_dev=device_create(firstdrv_class, NULL, MKDEV(first_drv_major, 0), NULL, DEVICE_NAME); 
       if(unlikely(IS_ERR(firstdrv_class_dev))) 
            return PTR_ERR(firstdrv_class_dev); 
       printk(DEVICE_NAME " initialized\n"); 
    gpfcon = (volatile unsigned long *)ioremap(0x56000050, 16); /*把寄存器的地址映射成虚拟地址*/ 
    gpfdat = gpfcon + 1; 
          return 0; 
} 
 
创建了设备,在退出时就必须注销相关的设备和节点,实现函数如下: 
static void first_drv_exit(void) 
{ 
    printk("FIRST_DRV MODULE EXIT\n"); 
    unregister_chrdev(first_drv_major, DEVICE_NAME);    /*注销该设备*/ 
    device_destroy(firstdrv_class, MKDEV(first_drv_major, 0));  /*注销类创建的设备节点*/ 
    class_destroy(firstdrv_class);   /*注销类*/ 
    iounmap(gpfcon);  //取消地址映射 
    iounmap(gpfdat); 
} 
 
    编写完代码后再编写测试程序和makefile文件,拷贝相关文件到虚拟机下,执行make指令生成.ko文件,再编译测试程序,生成可执行程序,最后把.ko文件和测试程序的可执行文件拷到开发板的根文件系统下通过命令:insmod first_drv.ko动态加载驱动,再执行:./first_drv_test 0可以看到开发板上的灯全亮了,执行./first_drv_test 1时,灯全灭,说明驱动程序编写成功了。 
    在看到自己跟着视频里写好的代码烧到开发板上能正常运行时,心里是说不出的高兴,由于视频里的代码都是一条一条当场写出来的,讲解也非常清晰、易懂,让自己对驱动的编写有了更深入的了解,同时非常期望韦大神能尽早推出自己的后期3G无线上网,wifi等驱动视频!!!     |