C 嵌入式系统设计模式 08:硬件代理模式

本书的原著为:《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》,讲解的是嵌入式系统设计模式,是一本不可多得的好书。

本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之一:硬件代理模式。

硬件代理模式 (Hardware Proxy Pattern) 是硬件抽象的典型模式。目的是封装细节。该模式通过创建软件模块来封装对特定硬件设备的操作,隐藏底层硬件的实现细节和复杂性,提供标准的接口给上层应用程序使用。

假设有一个嵌入式系统需要访问内存、传感器等硬件设备。如果每个应用都直接在程序中访问操作底层硬件,当更换了相同功能的不同硬件设备时,有可能硬件接口并不一致,而且对硬件的操作与控制方式也并不一样。这种情况下,就需要为每个硬件设备编写特定的访问代码,增加了软件开发的复杂性和工作量。

而采用硬件代理模式后,可以创建一个硬件代理来封装对内存、传感器等硬件设备的操作。应用程序通过调用硬件代理提供的标准接口来访问硬件设备,无需关心底层硬件的具体实现。当更换了相同功能的不同硬件设备时,只需要修改硬件代理的实现即可,无需修改客户程序的代码。这样就简化了软件与硬件的交互过程,提高了软件的可移植性和可维护性。

在这个过程中,最难的是定义一系列标准接口。标准接口是对硬件的抽象,而只要涉及到抽象,大都伴随艰难的脑力劳动。一个好的接口,能带来什么益处?答案是稳定。硬件可能随时会变,但好的接口通常不变,它比硬件要稳定。因此在接口之上的应用层,都不用变。这就将变化控制在硬件层这个狭小的范围内,从而让变更变得容易和可控。

抽象

硬件代理模式使用类或结构体来封装对硬件设备的所有访问,而不管其物理接口如何。硬件可以是内存、中断映射,也可以是通过总线、网络连接的设备。硬件代理提供一些服务,这些服务可以与硬件设备交互:初始化、配置、关闭、读写数据等。硬件代理为上层应用提供了一个与编码和连接无关的接口,因此如果硬件设备接口或者连接方式发生变化,则可以方便的修改现有代码。

问题

如果每个上层应用(书中称为“客户端” )都直接访问硬件设备,则由于硬件更改而导致的问题会加剧。比如数据编码方式、内存地址或连接方式发生变化,则必须跟踪并修改每一个上层应用。通过提供位于上层应用和硬件之间的代理,可以极大的减少硬件更改带来的影响。为了便于维护,高层应用不应该知道底层次代码的细节,包括数据编码方式、加密方式、压缩方式等。这些详细信息应由具有内部私有函数的硬件代理进行管理。

模式结构

模式结构见下图。
在这里插入图片描述

硬件代理客户端可能有多个,但是硬件设备只有 1 个硬件代理。硬件代理具有公共函数和私有的函数和数据。在 UML 图中,数据放在首部,比如 deviceAddr: void *,函数放在数据的下方,比如 initialize():void;公用函数和数据使用正常字体,私有函数和数据用带下划线的斜体。

模式详情

硬件设备

硬件设备 是一个具体的硬件实体,它本身无需编程即可运作。把它放到图中,只是为了便于理解模式结构。硬件代理硬件设备 之间的 关联 是通过硬件接口实现的,这些接口可以是一个寄存器地址或其他类似机制。关联关系使一个类知道另外一个类的属性和方法,这里硬件代理与硬件设备是双向关联,大家相互知道对方的细节。

硬件代理

硬件代理封装了针对特定硬件的数据和函数,为每种硬件设备提供了一套统一的接口。通常每个硬件都会有 initialize()configure()disable() 等基本操作函数,此外,硬件代理还提供了一组公共函数,用于对硬件进行读写访问。

尽管模式结构图中只标识出一个 access()mutate() 函数,但实际应用中通常有多个这样的函数,每个函数都针对特定的读写目标,具有明确的语义和用途。例如,accessMotorSpeed() 函数用于读取电机的速度,而 accessMotorDirection() 函数则用于读取电机的旋转方向。

这种设计方式使得上层应用程序(客户端)可以通过调用硬件代理提供的函数来与硬件进行交互,而无需关心底层硬件的具体实现细节。这不仅简化了软件与硬件之间的交互过程,还提高了软件的可移植性和可维护性。

硬件代理关键函数和数据为:

  1. initialize():在首次使用之前调用,初始化设备。
  2. configure():用于配置硬件设备。
  3. disable():关闭或禁用硬件设备。
  4. access_xxx():从硬件设备读取数据。但在实际编程中,更常见的做法是使用get_xxx()
  5. mutate_xxx():向硬件设备写入数据。但在实际编程中,更常见的做法是使用set_xxx()

在编程和软件设计中,函数名通常会给出关于函数功能的一些提示。accessmutate 这两个名字就很有代表性,它们分别暗示了读取(或访问)数据和修改(或变更)数据的操作。

  • access 函数通常用于读取或检索数据,但不修改它。例如,在数据库编程中,一个 access 函数可能是用来从数据库表中读取记录的。在对象导向编程中,access 方法(也称为 getter 方法)可能用于读取对象的某个属性值。
  • mutate 函数则用于修改或变更数据。在数据库编程中,这可能意味着更新数据库表中的记录。在对象导向编程中,mutate 方法(也称为 setter 方法)可能用于设置或修改对象的某个属性值。
  1. marshal():私有函数。将上层应用的数据格式转换成硬件可以理解的数据格式。可能需要加密、压缩或打包。这确保了硬件设备接口的特殊性对上层应用(客户端)是隐藏的。实际硬件设备所需格式的数据被称为“原生格式”数据。容易被软件操作的数据被称为“呈现格式”数据。由于原生格式对上层应用是隐藏的,因此上层应用无法访问此函数。

通过将数据处理和转换的逻辑封装在私有函数中,软件设计可以确保上层应用代码与硬件设备接口的复杂性隔离开来。这样,上层应用开发者只需要关心如何操作 呈现格式 的数据,而不需要了解如何将这些数据转换为硬件设备能理解的 原生格式。这简化了上层应用的开发工作,并提高了系统的可维护性。

  1. unmarshal():私有函数。将硬件数据转换成上层应用可以理解的数据格式。可能需要解密、解压缩或解包。也就是将原生格式数据转换成呈现格式数据。与 marshal() 函数一样,隐藏了硬件设备的细节,因此上层应用无法访问此函数。
  2. deviceAddr:私有变量。提供了对硬件的低层次直接访问。在代理模式中,它显示为 void* ,但它可能是一个整形( int* )或其它数据类型。如果使用了更复杂的方式来访问设备,如 RS232 串行端口或以太网连接,那么这个数据类型及其访问方法将更加复杂。无论如何,硬件代理提供的公共函数完全隐藏了代理如何连接到实际硬件设备的过程。上层应用无法直接访问这个变量。

代理客户端

也就是使用硬件代理的上层应用。上层应用知道硬件代理的公用函数和数据,然后调用这些服务来访问硬件设备。

结果

这种模式非常常见,它提供了封装硬件接口和编码细节的所有好处。它为实际的硬件接口提供了灵活性,使其可以在不改变上层应用代码的情况下变更硬件。这是因为硬件细节都封装在硬件代理中。这意味着上层应用通常不知道数据的原生格式,而只以呈现格式操作它们。

然而,这可能会对运行时性能产生负面影响。有时,让上层应用了解编码细节并以原生格式操作数据可能更高效。但是,这会降低系统的可维护性,因为如果硬件接口或编码发生变化,就需要修改上层应用。

实现策略

如第1章所述,在 C 语言中,类可以通过不同的方式实现,从简单的文件到使用结构体来存储类属性,再到使用支持真正多态性的虚函数表。所有这些方法都可以用来实现这个非常简单的模式。

通常,一个硬件代理支持特定设备的所有功能,并且每个独立的设备都使用一个不同的硬件代理,但这并不是一条绝对的规则。将设备分离成不同的部分意味着这些设备可以遵循独立的维护路径,因此对于未来来说非常灵活。

一般来说,最好将实际硬件的位编码、加密和数据压缩隐藏在上层应用之外。然而,也可以通过使原生格式对上层应用可见来实现该模式,在在这种情况下,无需使用 marshal()unmarshal() 函数。

实例

见原书。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/401076.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python 数据可视化之密度散点图 Density Scatter Plot

🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 密度散点图(Density Scatter Plot),也称为密度点图或核密度估计散点图,是一种数据可视化技术,主要用于展示大量数据点在二维平面上的分布情况…

解决MobaXterm网络错误连接超时问题

报错页面: 报错原因: ①网络断开了 ②网络端口,端口号改变 解决办法: ①重新连接网络按R ②固定端口号 第一步:编辑------>虚拟机网络编辑器(我的Linux在虚拟机里) 第二步:用…

MedicalGPT 训练医疗大模型,实现了包括增量预训练、有监督微调、RLHF(奖励建模、强化学习训练)和DPO(直接偏好优化)

MedicalGPT 训练医疗大模型,实现了包括增量预训练、有监督微调、RLHF(奖励建模、强化学习训练)和DPO(直接偏好优化)。 MedicalGPT: Training Your Own Medical GPT Model with ChatGPT Training Pipeline. 训练医疗大模型,实现了包括增量预训练、有监督微…

单调栈总结以及Leetcode案例解读与复盘

单调栈总结以及Leetcode案例解读与复盘 一、单调栈是什么? 单调栈(monotonous stack)是指栈的内部从栈底到栈顶满足单调性的栈结构。 二、如何维护单调性 新元素入栈时,会与栈顶元素进行比较,使得栈始终保持单调性…

Redis-内存管理

Redis是基于内存存储的,非关系型,键值对数据库。因此,对Redis来说,内存空间的管理至关重要。那Redis是如何内存管理的呢? 一、最大内存限制 Redis 提供了 maxmemory 参数允许用户设置 Redis 可以使用的最大内存大小。…

2023年12月CCF-GESP编程能力等级认证C++编程五级真题解析

一、单选题(每题 2 分,共 30 分) 第1题 下面C++代码用于求斐波那契数列,该数列第1、2项为1,以后各项均是前两项之和。下面有关说法错误的是( )。 A. fiboA( ) 用递归方式, fiboB() 循环方式 B. fiboA( ) 更加符合斐波那契数列的数学定义,直观易于理解,而 fiboB() 需…

Android TV遥控器探索,Android 桌面应用程序

Android TV 的遥控功能是通过红外遥控器或蓝牙遥控器来实现的。下面分别介绍这两种遥控器的工作原理: 红外遥控器: 红外遥控器是最常见的 Android TV 遥控器类型之一。 红外遥控器通过发送红外信号来控制电视或机顶盒。每个按键都有一个特定的红外编码&…

基于springboot+vue的课程答疑系统(前后端分离)

博主主页:猫头鹰源码 博主简介:Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战,欢迎高校老师\讲师\同行交流合作 ​主要内容:毕业设计(Javaweb项目|小程序|Pyt…

【算法 - 动态规划】最长回文子序列

上篇文章中,我们学习一个新的模型: 样本对应模型,该模型的套路就是:以结尾位置为出发点,思考两个样本的结尾都会产生哪些可能性 。 而前篇文章中的 纸牌博弈问题 属于 [L , R]上范围尝试模型。该模型给定一个范围&…

【洛谷 P8780】[蓝桥杯 2022 省 B] 刷题统计 题解(二分查找+数学)

[蓝桥杯 2022 省 B] 刷题统计 题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a a a 道题目,周六和周日每天做 b b b 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n n n 题? 输入格式 输入一…

Android14 InputManager-InputReader的处理

IMS启动时会调用InputReader.start()方法 InputReader.cpp status_t InputReader::start() {if (mThread) {return ALREADY_EXISTS;}mThread std::make_unique<InputThread>("InputReader", [this]() { loopOnce(); }, [this]() { mEventHub->wake(); });…

Nignx的搭建与核心配置

目录 一、Nginx是什么&#xff1f; 1、Nginx概述 2、Nginx模块与作用 3、Nginx三大作用&#xff1a;反向代理&#xff0c;负载均衡&#xff0c;动静分离 nginx七层负载均衡调度算法&#xff08;六种&#xff09; 1、轮询&#xff08;默认调度算法&#xff09; 2、加权轮…

雨量水位在线监测站

TH-SW2随着科技的不断进步&#xff0c;雨量水位在线监测站在防汛、水资源管理、环境保护等领域发挥着越来越重要的作用。传统的雨量水位监测方法往往存在精度不高、实时性不强等问题&#xff0c;而雷达式测量技术的出现&#xff0c;则为这一领域带来了革命性的变化。 一、雨量水…

【踩坑专栏】主机ping虚拟机失败

我出现的问题finalshell连接超时&#xff0c;ping了一下发现ping都ping不通&#xff0c;于是发现问题所在。 最开始我是把虚拟机的网络设置改为桥接模式&#xff0c;问题解决了&#xff0c;但是这种模式的问题就是每次开机&#xff0c;ip都会改变&#xff0c;因此非常麻烦&…

零到大师:嵌入式Linux学习书单分享

大家好&#xff0c;我是知微&#xff01; 上一篇推荐的书单嵌入式软件必读10本书_单片机篇&#xff0c;收到反响很好。再推荐一篇嵌入式Linux相关的书单。 《鸟哥的Linux私房菜》 鸟哥的Linux系列适合零基础小伙伴&#xff0c;从电脑基础到文件系统、shell脚本等等&#xff…

【PX4学习笔记】04.QGC地面站的使用

目录 文章目录 目录PX4代码烧入PX4固件代码的烧入方式1PX4固件代码的烧入方式2 QGC地面站的基础使用连接地面站的方式查看关键的硬件信息 QGC地面站的Application Settings模块Application Settings模块-常规界面单位其他设置数据持久化飞机中的数传日志飞行视图计划视图自动连…

Unity Shader ASE基础效果思路与代码(一):遮罩、硬边溶解、光边溶解、UV扰动

Unity Shader ASE基础效果思路与代码(一)&#xff1a;遮罩、硬边溶解、光边溶解、UV扰动 文章目录 Unity Shader ASE基础效果思路与代码(一)&#xff1a;遮罩、硬边溶解、光边溶解、UV扰动遮罩效果硬边溶解光边溶解UV扰动 遮罩效果 效果展示&#xff1a; 思路与代码&#xff1…

SQL注入:堆叠注入-强网杯[随便注]

目录 什么是堆叠注入&#xff1f; 强网杯-随便注 rename && alter绕过 prepare绕过 Handle绕过 靶机&#xff1a;BUUCTF在线评测 什么是堆叠注入&#xff1f; 在一些场景中&#xff0c;应用程序支持一次执行多条SQL语句&#xff0c;我们称为堆叠查询&#xff0c;…

HTML5-CSS3

一、HTML5的新特性 HTML5 的新增特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题&#xff0c;基本是 **IE9 以上版本的浏览器**才支持&#xff0c;如果不考虑兼容性问题&#xff0c;可以大量使用这些新特性…

前端是做什么的?

前端很多时候代表从事前端开发的工程师&#xff0c;定义上来说&#xff0c;他们负责规划、设计、构建和运行网站、软件程序和基于 Web 的应用程序的用户界面系统。通俗点来说&#xff0c;我们看到的网站、点击网站所有的按钮以及和网站的交互都是前端所进行的工作。 概述 前端…