Linux LED驱动源码简析

驱动的加载与卸载函数

驱动加载服务函数

int major;
static int first_drv_init(void)
{
    major = register_chrdev(0, "first_drv", 
    &first_drv_fops); 
    // 注册驱动,其中第一个参数为0,则表示采用系统动态分配的主设备号
    //第二个参数是其注册的设备名
    //第三个很重要的参数,就是我们配置驱动函数的结构
    //(具体见上一篇对该函数的解析)

    firstdrv_class = class_create(THIS_MODULE, 
    "firstdrv");
    //创建一个驱动类
    firstdrv_class_dev = 
    class_device_create(firstdrv_class, NULL, 
    MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
    //用于自动的在系统的目录下创建一个字符设备的节点
    gpfcon = (volatile unsigned long 
    *)ioremap(0x56000050, 16);
    //通过内存映射到真实地址
    gpfdat = gpfcon + 1;
    //配置GPIO为输出

    return 0;

}

驱动卸载服务函数

static void first_drv_exit(void)
{
    unregister_chrdev(major, "first_drv");
    //告诉内核,卸载该驱动
    //major是程序的主设备号
    class_device_unregister(firstdrv_class_dev);
    class_destroy(firstdrv_class);
    //这两句用于删除在文件系统中创建的节点

    iounmap(gpfcon);
    //取消GPIO的映射
}

最后别忘了,把这两个函数注册进去

module_init(first_drv_init);
module_exit(first_drv_exit);

重要的结构体

static struct file_operations first_drv_fops = {
    .owner  =   THIS_MODULE,    
    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    //说是与神秘高级特性有关,不懂,先这么写       
    .open   =   first_drv_open,     
    .ioctl  =   first_drv_ioctl,       
};

用来存储驱动内核模块提供的对设备进行各种操作的函数的指针。该结构体的每个域都对应着驱动内核模块用来处理某个被请求的事务的函数的地址

驱动函数

open()函数

static int first_drv_open(struct inode *inode, struct 
file *file)
{
    printk("first_drv_open\n");
    /* 配置GPF4,5,6为输出 */
    ......
    return 0;
}

ioctl()函数

这个函数比较重要,用于应用程序到驱动程序的参数传递

int ioctl(int fd, ind cmd, …);
//最多可以传递三个参数 

static int first_dev_ioctl(struct inode *inode, 
struct file *file, int cmd, int arg)
{
    printk("first_drv_ioctl\n");
    ......
}

证书

因为Linux遵循GNU/GPL ,所以要在内核做出声明
(要不,内核会傲娇…)

MODULE_LICENSE("GPL");

就此,一个简单的led的驱动程序就是分析完了,下面开始说说,驱动是如何被使用的。

在应用层,和硬件层之间的中间层,就是驱动所在的位置那么我们的驱动程序,一定是要通过应用程序调用的

驱动测试程序

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    int fd;

    fd = open("/dev/xyz", O_RDWR);
    if (fd < 0) {
        printf("can't open!\n");
    }
    ...
    ioctl(fd, strtol(argv[2]));
    return 0;
}

一套驱动就算完成了,
长路漫漫,这这只是最简单的第一步

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值