嵌入式软件中如何管理系统数据?

嵌入式大杂烩 2023-04-04 21:31

来源:狗哥嵌入式 https://zhuanlan.zhihu.com/p/604707040

软件架构这东西,众说纷纭,各有观点。在我看来,软件架构是软件系统的基本结构,包含其组件、组件之间的关系、组件设计与演进的规则,以及体现这些规则的基础设施。

软件架构,从来不是一件容易事,它贯穿在产品的整个生命周期,需要所有团队成员遵守并自律,才能将架构思想在软件中体现。

新手工程师,由于经历的项目太少,看不到项目全貌,很难从全局理解软件架构。但软件架构真的只是资深工程师的专利吗?这个也不见得。古人作文,讲究立意为先。

今天工程师做项目和产品,也应该先立意。这个意,就是指要有高度。工程师入门能从软件架构的高度出发,看待软件问题,相信对软件的理解,会更加深刻一些。因此,我总结了软件架构的六个步骤,供嵌入式工程师参考。

  • • 隔离硬件相关代码,建立抽象层

  • • 建立统一的软件基础设施

  • • 识别和管理系统数据

  • • 功能分层与分解

  • • 组件及其接口设计

  • • 测试、调试与跨平台开发的支持

今天,们将探讨设计嵌入式软件架构的第三步:识别和处理产品数据。当工作过程中,我发现嵌入式工程师们,在思考架构问题,有两种倾向:

首先,思考问题的出发点,大部分都是硬件。嵌入式工程师们总是会倾向于,把整个嵌入式程序,搞成一个时刻在与硬件交互的底层代码,没有有效隔离硬件,更没有合理分层,甚至一竿子从应用层捅到寄存器。

在《嵌入式软件架构的六个步骤(一)抽象层》中,我们对这一现象做过解释。这种做法,是由大部分嵌入式工程师的知识结构偏硬件决定的,可以理解,但绝不提倡。

因为这种写法,不符合软件发展的主流趋势,不符合层次化和复用性原则,无法支撑大规模的嵌入式软件开发。目前嵌入式开发产品的软件规模大了很多,硬件有关的部分所占的比例,已经降到了非常小的份额。在大多数嵌入式系统中,真正的价值在于应用层代码,即与硬件无关的部分。

一竿子捅到底的架构

其次,工程师总是喜欢围绕中断、任务、总线的原始数据等底层资源,展开对架构的思考。

这依然是面向硬件和面向底层的思维。在硬件资源紧张的年代里(15年前),任务的数量是有限制的(uC/OS-II只支持64个任务,而当前大多支持无限任务,只要RAM和ROM允许),而RAM也是非常紧张的,那时候的工程师,不得不将大量的精力,放在底层上,以便以最小的资源进行数据的处理。

而现在,当资源变得不那么稀缺甚至有些过剩时,我们要面向业务逻辑进行数据结构的设计。而业务逻辑体现到软件里,本质上就是数据抽象与数据结构的设计,其次才是程序的编写。

一旦团队完成了软件架构的第一步和第二步,对硬件相关代码进行了剥离,并建立了统一的软件基础设施(非必须步骤),设计嵌入式软件架构的第三步就是识别和管理产品数据。

数据包含任何类型,只要是系统内部,又利用其功能执行的任何数据,包括一些中间数据和临时数据,都算系统数据。拿我曾经做过的机器人控制器举例,嵌入式系统可能具有以下系统数据:

  • • IO口数据(含开关量输入口、开关量输出口、模拟量输入口、模拟量输入口)

  • • 通信口数据(含串口、CAN接口、RS485等)

  • • 传感器实时数据

  • • 电机实时数据

  • • 车体状态数据

  • • 地图数据

  • • 任务数据

  • • 指令数据

  • • 当前线路数据

  • • 当前位置数据

  • • 错误与报警历史

  • • LOG数据

  • • 配置参数

  • • 脚本数据

  • • 其他数据

这里面,有些数据,为一些功能独享,但也有很多的数据,由不同的器件产生,并被多个功能所共享。系统中数据越多,数据类型越多,数据共享越多时,系统架构就越复杂。当我们设计和构建一个实时嵌入式系统时,我们所做的核心是识别和管理数据。

嵌入式软件设计的第一原则

数据决定设计,是现代嵌入式软件设计的第一原则。Linux的创始人Linus Torvalds在一次演讲中也曾经说过说:"烂程序员关心的是代码,好程序员关心的是数据结构和它们之间的关系。"他在谈到Git时,也曾表达过类似的观点,“好程序员和烂程序员之间的差别,就在于他们认为是代码更重要还是数据结构更重要。”

我们上学时,就学过一个公式:程序 = 数据结构 + 算法。如果从嵌入式程序的宏观视角去理解这个公式:所谓的数据结构,就是数据结构与处理机制;而所谓的算法,就是代码逻辑。好的数据结构,总是会简化代码;而差的数据结构,会导致代码变的比较复杂。

我们可以创建各种漂亮的架构,去开发项目,完成产品。但最有效的架构是围绕系统数据设计的架构。一个只有10个数据和1000个数据的处理方式,是完全不同的。无论工程师琢磨出多么漂亮和优雅的软件架构,只要这个架构不是有效的支撑数据的处理,都是无助于实际开发的。

当我们专注于数据进行架构设计时,需要工程师对数据本身以及数据的转换进行高度关注,关注到数据在软件内部转换的每一个关键环节。实际上,每一个软件(含承载它的硬件),都可以看做一个黑盒子,一端是输入数据,一端是输出数据,而黑盒子是对数据的处理和转换。

比如,我们开发一个恒温壶的项目,其原理大致为从一个热敏电阻获取温度,并经过ADC的采集、转换、滤波等操作,根据采集的温度,决定加热丝是否加热,以保持温度维持在恒定问题。原始温度数据,可以看做输入,加热丝的打开,可以看做输出。

架构可以变得高度关注它应该如何处理数据。事实上,数据的处理仅仅需要少量操作。首先,系统可以输入数据。例如,用户可以通过通信接口按下按钮或接收串行数据。其次,系统可以输出数据。例如,显示像素映射到显示器或驱动电机。第三,系统可以处理数据。

例如,串行数据可能以数据包格式进入系统,然后对其进行解码。进行处理以验证数据包,然后解压缩存储的数据。最后,系统可以将数据存储在易失性或非易失性存储器中。众所周知,在Linux和Unix系统中,五个操作就已经抽象所有的关于文件(可以认为数据的一种):

  • • open

  • • close

  • • read

  • • write

  • • control

识别系统数据,以及可对该数据执行的操作,可以极大地帮助团队设计其嵌入式软件体系结构。分析系统数据,能够很简单的明确设计中的架构需求。不幸的是,太多的团队忽略了数据,要不就是凭感觉和经验在编程,要么就是强行引入了并不适合但光鲜亮丽的架构方案。

在很多时候,合适的架构,都是朴素的。朴素到什么地步呢?当架构对软件质量提升没有帮助时,那就去他的架构!这就是为什么8位单片机和简单的嵌入式产品,不必讲究什么架构,就能完成设计和实现。

但当软件规模增大(个人观点是一万行代码以上)时,引入合理架构就变成了不得不做的事情,这时对系统的核心数据进行识别和分析,就势在必行。

那么什么是系统的核心数据?很多工程师在应用层里直接处理物理通信口(比如UART)来的数据,这依然是硬件思维。资源(RAM)紧张时,我们当然需要在底层,甚至在中断函数中,直接解析数据,以便节省资源。但从系统架构的角度来说,显然物理中断接收到原始数据,与业务层面,并没有直接关系。

在RAM资源允许的情况下,物理中断要经过几次转换,才会到应用层,这几次转换可能包含:外设框架缓冲区、协议栈、设备层、应用层。对于复杂系统,经过的环节可能会更多。

举例来说,我们假定主控制器使用UART(RS232)通过一个电机驱动器,间接控制一个电机,并获取电机实时数据,这在工业控制和机器人等行业是非常常见的场景。外设框架缓冲区,暂存收到的串口数据,然后协议栈解析数据,将有效的数据负载传递给应用层,应用层对数据进行合理转换(滤波、计算等),最后才得到电机的速度、电流、温度等数据。

typedef struct motor_status_data
{
    float speed;                            /* RPM */
    float current;                          /* A */
    float temperature;                      /* °C */
motor_status_data_t;

void device_motor_get_status(device_motor_t *device, motor_status_data_t *data);

上述代码里,所表达的才是电机这个设备,在系统中的核心数据。它代表电机设备的核心特性。至于这个电机是串口驱动、SPI驱动还是CAN驱动,对应用层来说,并不重要,我们也不应该去关心他,我们将其屏蔽在设备层以下。在设备层里,我们只保留硬件无关的数据。这部分内容,我将在后续文章《设备抽象层》系列中进行详述。

以数据为中心的架构意味着什么?

对很多喜欢搞底层的工程师来说,“数据决定架构”的想法,显得很奇怪。在各种编程领域,面向对象的编程都是被重视的,因为它能将复杂的系统简化。而对象是什么?

本质上,对象就是各种彼此相关数据的集合,以及对该数据进行操作。而面向对象的编程理念已经出现几十年了,有很多人已经在讨论更加先进的编程范式了,但单片机上,面向对象还并未普及。实际上,以数据为核心的软件架构设计,在很多领域不仅是必要,而且是强制的。

在机器人领域,如果不使用数据驱动的架构设计原则,采集数据并脱机复现场景,是不可能实现的。以数据为中心的架构,有如下优势。

首先,可以完美的解决数据安全问题。不同类型的数据有着不同的安全等级。如果能以数据为中心进行软件架构,那么软件架构会和系统安全,完美融合。

工程师可以对数据的安全等级进行设置,不同的安全等级有着不同的保护措施,后续会在《防御式编程》系列文章中详细阐述这个问题。

其次,识别系统数据,可以帮助我们正确将系统拆分到模块这个粒度上。模块(组件),是工程师进行编程工作的最小任务。作为工程师,如果能严格遵循单一职责原则(SRP),每一组数据都会被单独封装在其模块内部,并执行相应的操作。如果模块切分的太粗,会导致很多无关的数据都放在了同一个模块进行处理。

在这种情况下,不符合模块设计的“单一职责原则”,从而导致内聚性差,复用性低。如果模块切分的太细,会导致关联密切的数据,被分到多个不同的模块进行处理。在这种情况下,模块之间会产生数据交换,从而导致耦合性太强,复用性也会降低。

第三,以数据为中心,进行系统架构,就意味着工程师是面对应用层进行系统和软件架构,而不是面向底层。在架构阶段上,工程师所关注到东西,是一组数据及其操作,如何达到简洁的状态,从来都不会关注获取这个数据,所需要的硬件资源是什么?一般而言,硬件机制、中断、缓冲区和DMA等底层细节,都会被直接屏蔽在驱动层以内(参考《嵌入式软件架构的六个步骤之抽象层》)。

那么,围绕数据进行的嵌入式软件架构的原则是什么?这就不得不提到老掉牙的一句话,那就是著名的“高内聚,低耦合”原则。

何为高内聚?将彼此联系紧密的数据,放进同一个模块进行处理;何为低耦合?让模块间的数据交互,尽可能的小。实际上,一旦一个软件模块符合了上述标准,其接口必然变得简洁。简洁的接口,才更有可能是合理的。

对于上述的AGV系统数据来说,我们可以大体分为如下几个域:

  1. 1. 外设与驱动:IO口数据、通信口数据 2. 设备与驱动:传感器实时数据、电机实时数据 3. 运动控制:车体状态数据 4. 业务逻辑:地图数据、任务数据、指令数据、当前线路数据、当前位置数据、错误与报警历史、LOG数据 5. 配置层:配置参数、脚本数据等

每一个域中,可能还会分为几个软件模块,软件模块包含自己的数据。具体的层次与模块分解,我们将在下一步骤中进行详述。

思维稍微脱离底层的工程师,可能会以任务作为架构设计的核心要素。对于多年之前的嵌入式软件设计,这是合适的。对从前资源紧张的MCU而言,任务是一个稀缺资源,每开一个任务,就意味着要耗费不少RAM的开销,这对于RAM资源紧张的MCU来说,不得不从全局上,由架构师小心规划任务的创建。

但在现在的嵌入式系统中,任务也成为了模块中的资源。面向过程式的开发,一般在任务里调用模块。而在合理的架构设计,要不要在模块中启动任务,一般在对模块进行实现的时候,才由负责模块实现的工程师决定。在项目开始时,合格的工程师,想好所有的细节;而优秀的工程师,则会预留最大的空间,推迟细节的决策,提高软件架构的灵活性。

结论

设计嵌入式软件架构的第三步是识别和管理系统数据。对于关注硬件的工程师来说,以数据为中心的软件架构,似乎很奇怪。帮助改变我们思维方式的一种方法是将嵌入式软件的定义修改为:“嵌入式软件,是设计和构建为确定性运行的代码,通畅具备实时性,通过各种形式的输入、处理、输出和存储来管理数据。”

数据体现的是嵌入式系统的本质,体现的是嵌入式系统的抽象特性,只有以数据为核心的嵌入式架构,才可能诞生最合理的软件架构。

识别数据,然后跟踪它如何与系统中的其他数据交互,可以帮助工程师了解架构是如何出现的。当工程师从数据的视角看待嵌入式系统时,一个抽象而非具象的视角已经形成;嵌入式系统架构的蓝图,也已经在他的脑中展开。我们就能进入嵌入式软件架构的第四个步骤,系统层次与模块分解。

本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

注意

由于微信公众号近期改变了推送规则,为了防止找不到,可以星标置顶,这样每次推送的文章才会出现在您的订阅列表里。

猜你喜欢:

分享一种日志滚动覆盖的方法

bug解决不了?使用日志法

关于嵌入式系统日志打印的一点建议

分享一份嵌入式软件工具清单!

易懂 | 手把手教你编写你的第一个上位机

实用 | 10分钟教你搭建一个嵌入式web服务器

嵌入式常用通信传输协议动图,收藏!

适用于嵌入式的差分升级通用库!

分享一种灵活性很高的协议格式(附代码例子)

分享几个实用的代码片段(第二弹)


在公众号聊天界面回复1024,可获取嵌入式资源;回复 ,可查看文章汇总

嵌入式大杂烩 专注于嵌入式技术,包括但不限于C/C++、嵌入式、物联网、Linux等编程学习笔记,同时,内包含大量的学习资源。欢迎关注,一同交流学习,共同进步!
评论
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 125浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 76浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 131浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 68浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 105浏览
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 167浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 82浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 187浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 221浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 202浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 162浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 201浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 530浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦