驱动设计的思想:面向对象/分层/分离
文章目录
- 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;
}
驱动设计的思想:面向对象/分层/分离相关推荐
- [Linux驱动之路] 驱动设计的思想_面向对象_分层_分离—程序扩展
韦东山老师的Linux驱动设计基础课程的p128 5_101 驱动设计的思想_面向对象_分层_分离这课在开发板上实作练习,可控制imx6ull_pro板子的LED开关. 基于韦老师代码的基础上,更改如 ...
- 【嵌入式Linux】嵌入式Linux驱动开发基础知识之驱动设计的思想:面向对象/分层/分离
文章目录 前言 1.分离设计 驱动程序分析---程序分层 通用驱动程序---面向对象 个性化驱动程序---分离 APP 程序分析 前言 韦东山嵌入式Linux驱动开发基础知识学习笔记 文章中大多内容来 ...
- 一、领域驱动设计核心思想与设计过程
一.软件发展的必然规律 1.软件是对真是世界的模拟,但真实世界软件十分复杂. 2.人在认识真实世界的时候总是有一个从简单到复杂的过程 3.软件需求的变更成为一种必然的事情,并且总是由简单向复杂转变 4 ...
- 何时使用领域驱动设计
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...
- 阿里文娱技术专家战獒: 领域驱动设计详解之What, Why, How?
战獒 阿里文娱技术专家 读完需要 8 分钟 速读仅需 3 分钟 阿里妹导读:什么是领域驱动设计?传统分层架构在实际开发中存在哪些问题?业务开发人员如何设计并搭建自己的领域模型?阿里文娱技术专家战獒将为 ...
- 解读《领域驱动设计 软件核心复杂性应对之道》(一)
最近学习了两遍<领域驱动设计 软件核心复杂性应对之道>.这本书是2000年出头由一个老外写的.然后经过了国人翻译. 2000年出头,技术架构还没有现在这么多好用的工具,也没有云原生的概念. ...
- 【转载】何时使用领域驱动设计
何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...
- 何时使用领域驱动设计(DDD)
何时使用领域驱动设计?其实当你的应用程序架构设计是面向业务的时候,你已经开始使用领域驱动设计了.领域驱动设计既不是架构风格(Architecture Style),也不是架构模式(Architectu ...
- 万字长文解析何时使用领域驱动设计
何时使用领域驱动设计 转载自:https://www.cnblogs.com/daxnet/p/15177443.html 何时使用领域驱动设计? 其实当你的应用程序架构设计是面向业务的时候,你已经开 ...
最新文章
- 浅谈Python Web的五大框架
- php web框架 symfony简介
- python【数据结构与算法】PriorityQueue and Huffuman树
- ITK:重新采样矢量图像
- Linux Centos7网络属性配置
- 使用 WRK 压力测试工具对 ASP.NET Core 的接口进行压力测试
- Linux start-kernel
- uni-app 实现微信授权登录
- android 小学课程,小学课堂(小学学习软件)
- 关于fork()父子进程返回值的问题
- 智能合约语言 Solidity 教程系列2 - 地址类型介绍
- nfc卡模式与标准模式_NFC是什么?有什么优势和劣势?
- 迷你世界显示服务器超时,迷你世界因出现不良信息下架 迷你世界下架原因
- Hypervisor小记
- Linux键盘输入读取
- AriaNG保存服务器信息,Aria2 AriaNg 安装配置教程
- Linxu命令(3)
- html5如何快速选择工具使用技巧,用PS快速选择工具抠图的方法
- 【UVA】【11021】麻球繁衍
- 今日简报 每日精选12条新闻简报 每天一分钟 知晓天下事 4月24日
热门文章
- cpout引脚是干什么的_电源IC欠压保护(Brown-out)功能介绍
- 【PC工具】图片压缩哪家强!tinyPNG图片压缩工具
- 从零开始的AI·吃透kNN算法,学完我悟了(附实例代码)
- 惊了!7 行代码优雅地实现 Excel 文件生成下载功能
- 阿里HBase的数据管道设施实践与演进
- java基础(一) 深入解析基本类型
- ubuntu 升级nodejs 和 npm
- python leetcode 1
- Android典型界面设计(8) ——ViewPager+PagerSlidingTabStrip实现双导航
- 排序和顺序统计学(2)——快速排序