文章目录

  • 1 面向对象
  • 2 分层
  • 3 分离

1 面向对象

字符设备驱动程序抽象出一个 file_operations 结构体;

我们写的程序针对硬件部分抽象出led_operations 结构体。


2 分层

上下分层,比如我们前面写的 LED 驱动程序就分为 2 层:
① 上层实现硬件无关的操作,比如注册字符设备驱动:leddrv.c。
② 下层实现硬件相关的操作,比如 board_A.c 实现单板 A 的 LED 操作。


3 分离

还能不能改进?分离。
在 board_A.c 中,实现了一个led_operations,为 LED 引脚实现了初始化函数、控制函数:

static struct led_operations board_demo_led_opr = {.num = 1,
.init = board_demo_led_init,
.ctl = board_demo_led_ctl,
};

如果硬件上更换一个引脚来控制 LED 怎么办?你要去修改上面结构体中的 init、ctl 函数。
实际情况是,每一款芯片它的 GPIO 操作都是类似的。比如:GPIO1_3、GPIO5_4 这 2 个引脚接到 LED:

① GPIO1_3 属于第 1 组,即 GPIO1。
有方向寄存器 DIR、数据寄存器 DR 等,基础地址是 addr_base_addr_gpio1。
设置为 output 引脚:修改 GPIO1 的 DIR 寄存器的 bit3。
设置输出电平:修改 GPIO1 的 DR 寄存器的 bit3。

② GPIO5_4 属于第 5 组,即 GPIO5。
有方向寄存器 DIR、数据寄存器 DR 等,基础地址是 addr_base_addr_gpio5。
设置为 output 引脚:修改 GPIO5 的 DIR 寄存器的 bit4。
设置输出电平:修改 GPIO5 的 DR 寄存器的 bit4。

既然引脚操作那么有规律,并且这是跟主芯片相关的,那可以针对该芯片写出比较通用的硬件操作代码。

比如 board_A.c 使用芯片 chipY,那就可以写出:chipY_gpio.c,它实现芯片 Y 的 GPIO 操作,适用于
芯片 Y 的所有 GPIO 引脚。
使用时,我们只需要在 board_A_led.c 中指定使用哪一个引脚即可。

程序结构如下:

以面向对象的思想,在 board_A_led.c 中实现 led_resouce 结构体,它定义“资源”──要用哪一个引脚。

在 chipY_gpio.c 中仍是实现 led_operations 结构体,它要写得更完善,支持所有 GPIO。

代码实现:
程序仍分为上下结构:上层 leddrv.c 向内核注册 file_operations 结构体;下层 chip_demo_gpio.c 提
供 led_operations 结构体来操作硬件。

下层的代码分为 2 个:chip_demo_gpio.c 实现通用的 GPIO 操作,board_A_led.c 指定使用哪个 GPIO,
即“资源”。

led_resource.h 中定义了 led_resource 结构体,用来描述 GPIO:

#ifndef _LED_RESOURCE_H
#define _LED_RESOURCE_H/* GPIO3_0 */
/* bit[31:16] = group */
/* bit[15:0]  = which pin */
#define GROUP(x) (x>>16)
#define PIN(x)   (x&0xFFFF)
#define GROUP_PIN(g,p) ((g<<16) | (p))struct led_resource {int pin;
};struct led_resource *get_led_resouce(void);#endif

board_A_led.c 指定使用哪个 GPIO,它实现一个 led_resource 结构体,并提供访问函数:


#include "led_resource.h"static struct led_resource board_A_led = {.pin = GROUP_PIN(3,1),
};struct led_resource *get_led_resouce(void)
{return &board_A_led;
}

chip_demo_gpio.c 中,首先获得 board_A_led.c 实现的 led_resource 结构体,然后再进行其他操作:

#include <linux/module.h>#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"
#include "led_resource.h"static struct led_resource *led_rsc;
static int board_demo_led_init (int which) /* 初始化LED, which-哪个LED */
{   //printk("%s %s line %d, led %d\n", __FILE__, __FUNCTION__, __LINE__, which);if (!led_rsc){led_rsc = get_led_resouce();}printk("init gpio: group %d, pin %d\n", GROUP(led_rsc->pin), PIN(led_rsc->pin));switch(GROUP(led_rsc->pin)){case 0:{printk("init pin of group 0 ...\n");break;}case 1:{printk("init pin of group 1 ...\n");break;}case 2:{printk("init pin of group 2 ...\n");break;}case 3:{printk("init pin of group 3 ...\n");break;}}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");printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(led_rsc->pin), PIN(led_rsc->pin));switch(GROUP(led_rsc->pin)){case 0:{printk("set pin of group 0 ...\n");break;}case 1:{printk("set pin of group 1 ...\n");break;}case 2:{printk("set pin of group 2 ...\n");break;}case 3:{printk("set pin of group 3 ...\n");break;}}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;
}

驱动设计的思想:面向对象/分层/分离相关推荐

  1. [Linux驱动之路] 驱动设计的思想_面向对象_分层_分离—程序扩展

    韦东山老师的Linux驱动设计基础课程的p128 5_101 驱动设计的思想_面向对象_分层_分离这课在开发板上实作练习,可控制imx6ull_pro板子的LED开关. 基于韦老师代码的基础上,更改如 ...

  2. 【嵌入式Linux】嵌入式Linux驱动开发基础知识之驱动设计的思想:面向对象/分层/分离

    文章目录 前言 1.分离设计 驱动程序分析---程序分层 通用驱动程序---面向对象 个性化驱动程序---分离 APP 程序分析 前言 韦东山嵌入式Linux驱动开发基础知识学习笔记 文章中大多内容来 ...

  3. 一、领域驱动设计核心思想与设计过程

    一.软件发展的必然规律 1.软件是对真是世界的模拟,但真实世界软件十分复杂. 2.人在认识真实世界的时候总是有一个从简单到复杂的过程 3.软件需求的变更成为一种必然的事情,并且总是由简单向复杂转变 4 ...

  4. 何时使用领域驱动设计

    何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...

  5. 阿里文娱技术专家战獒: 领域驱动设计详解之What, Why, How?

    战獒 阿里文娱技术专家 读完需要 8 分钟 速读仅需 3 分钟 阿里妹导读:什么是领域驱动设计?传统分层架构在实际开发中存在哪些问题?业务开发人员如何设计并搭建自己的领域模型?阿里文娱技术专家战獒将为 ...

  6. 解读《领域驱动设计 软件核心复杂性应对之道》(一)

    最近学习了两遍<领域驱动设计 软件核心复杂性应对之道>.这本书是2000年出头由一个老外写的.然后经过了国人翻译. 2000年出头,技术架构还没有现在这么多好用的工具,也没有云原生的概念. ...

  7. 【转载】何时使用领域驱动设计

    何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...

  8. 何时使用领域驱动设计(DDD)

    何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...

  9. 万字长文解析何时使用领域驱动设计

    何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...

最新文章

  1. 浅谈Python Web的五大框架
  2. php web框架 symfony简介
  3. python【数据结构与算法】PriorityQueue and Huffuman树
  4. ITK:重新采样矢量图像
  5. Linux Centos7网络属性配置
  6. 使用 WRK 压力测试工具对 ASP.NET Core 的接口进行压力测试
  7. Linux start-kernel
  8. uni-app 实现微信授权登录
  9. android 小学课程,小学课堂(小学学习软件)
  10. 关于fork()父子进程返回值的问题
  11. 智能合约语言 Solidity 教程系列2 - 地址类型介绍
  12. nfc卡模式与标准模式_NFC是什么?有什么优势和劣势?
  13. 迷你世界显示服务器超时,迷你世界因出现不良信息下架 迷你世界下架原因
  14. Hypervisor小记
  15. Linux键盘输入读取
  16. AriaNG保存服务器信息,Aria2 AriaNg 安装配置教程
  17. Linxu命令(3)
  18. html5如何快速选择工具使用技巧,用PS快速选择工具抠图的方法
  19. 【UVA】【11021】麻球繁衍
  20. 今日简报 每日精选12条新闻简报 每天一分钟 知晓天下事 4月24日

热门文章

  1. cpout引脚是干什么的_电源IC欠压保护(Brown-out)功能介绍
  2. 【PC工具】图片压缩哪家强!tinyPNG图片压缩工具
  3. 从零开始的AI·吃透kNN算法,学完我悟了(附实例代码)
  4. 惊了!7 行代码优雅地实现 Excel 文件生成下载功能
  5. 阿里HBase的数据管道设施实践与演进
  6. java基础(一) 深入解析基本类型
  7. ubuntu 升级nodejs 和 npm
  8. python leetcode 1
  9. Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航
  10. 排序和顺序统计学(2)——快速排序