1:回顾字符设备驱动框架

        驱动层访问硬件外设寄存器依靠的是 ioremap 函数去映射到寄存器地址,然后开始控制寄存器。

1.2如何编写驱动程序

  1. 确定主设备号,也可以让内核分配
  2. 定义自己的 file_operations 结构体
  3. 实现对应的 drv_open/drv_read/drv_write 等函数,填入 file_operations 结构体
  4. 把 file_operations 结构体告诉内核:register_chrdev
  5. 谁来注册驱动程序啊?得有一个入口函数:安装驱动程序时,就会去调用这个入口函数
  6. 有入口函数就应该有出口函数:卸载驱动程序时,出口函数调用unregister_chrdev
  7. 其他完善:提供设备信息,自动创建设备节点:class_create,device_create

1.3:对于 LED 驱动,构建什么样的接口?

1.4LED 驱动能支持多个板子的基础:分层思想

1:把驱动拆分为通用的框架(leddrv.c)、具体的硬件操作(board_X.c)

2:以面向对象的思想,改进代码,抽象出一个结构体:

        每个单板相关的 board_X.c 实现自己的 led_operations 结构体,供上层 的 leddrv.c 调用

2:代码编写

        驱动程序分为上下两层:leddrv.cboard_demo.cleddrv.c 负责注册file_operations 结构体,它的 open/write 成员会调用 board_demo.c 中提供的硬件 led_opr 中的对应函数。

2.1:代码主体逻辑图

2.1.1:LED 的操作抽象出一个 led_operations 结构体

        首先看看 led_opr.h,它定义了一个 led_operations 结构体,把 LED 的操作抽象为这个结构体:

#ifndef _LED_OPR_H

#define _LED_OPR_H

struct led_operations {

    int (*init) (int which); /* 初始化LED, which-哪个LED */      

    int (*ctl) (int which, char status); /* 控制LED, which-哪个LED, status:1-亮,0-灭 */

};

struct led_operations *get_board_led_opr(void);
 

#endif

2.1.2 驱动程序的上层:file_operations 结构体

        上层是 leddrv.c,它的核心是 file_operations 结构体,
首先查看入口函数:
        向内核注册一个 file_operations 结构体。
        p_led_opr = get_board_led_opr();从底层硬件相关的代码 board_demo.c 中获得led_operaions 结 构体。

/* 4. 把file_operations结构体告诉内核:注册驱动程序                                */

/* 5. 谁来注册驱动程序啊?一个入口函数:安装驱动程序时,就会去调用这个入口函数 */

static int __init led_init(void)

{

    int err;

    int i;

   

    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    major = register_chrdev(0, "100ask_led", &led_drv);  /* /dev/led */
 

    led_class = class_create(THIS_MODULE, "100ask_led_class");

    err = PTR_ERR(led_class);

    if (IS_ERR(led_class)) {

        printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

        unregister_chrdev(major, "100ask_led");

        return -1;

    }

    for (i = 0; i < LED_NUM; i++)

        device_create(led_class, NULL, MKDEV(major, i), NULL, "100ask_led%d", i); /* /dev/100ask_led0,1,... */

    p_led_opr = get_board_led_opr();

   

    return 0;

}

查看file_operations 结构体的成员函数::

    p_led_opr->ctl(minor, status);    p_led_opr->init(minor); 调用 led_operations 结构体中对应的函数。

/* write(fd, &val, 1); */

static ssize_t led_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)

{

    int err;

    char status;

    struct inode *inode = file_inode(file);

    int minor = iminor(inode);

   

    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    err = copy_from_user(&status, buf, 1);

    /* 根据次设备号和status控制LED */

    p_led_opr->ctl(minor, status);   

    return 1;

}

static int led_drv_open (struct inode *node, struct file *file)

{

    int minor = iminor(node);

   

    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    /* 根据次设备号初始化LED */

    p_led_opr->init(minor);   

    return 0;

}

/* 2. 定义自己的file_operations结构体                                              */

static struct file_operations led_drv = {

    .owner   = THIS_MODULE,

    .open    = led_drv_open,

    .read    = led_drv_read,

    .write   = led_drv_write,

    .release = led_drv_close,

};

static int led_drv_close (struct inode *node, struct file *file)

{

    printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);

    return 0;

}

2.1.3:board_demo.c函数

static int board_demo_led_init (int which) /* 初始化LED, which-哪个LED */      

{

   

    printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);

    return 0;

}

static int board_demo_led_ctl (int which, char status) /* 控制LED, which-哪个LED, status:1-亮,0-灭 */

{

    printk("%s %s line %d, led %d, %s\n", __FILE__, __FUNCTION__, __LINE__, which, status ? "on" : "off");

    return 0;

}

static struct led_operations board_demo_led_opr = {

    .init = board_demo_led_init,

    .ctl  = board_demo_led_ctl,

};

struct led_operations *get_board_led_opr(void)

{

    return &board_demo_led_opr;

}

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐