嵌入式系统可靠性设计

嵌入式系统可靠性设计

    • 硬件件可靠性设计
      • 1. 硬件设计原则
      • 2. 硬件设计注意问题
        • 2.1 引脚布局和走线
        • 2.2 元器件选择和布局
        • 2.3 电源和地线分离
        • 2.4 EMI/EMC设计
        • 2.5 系统可靠性
        • 2.6 资源利用和扩展性
    • 软件可靠性设计
      • 1. 设计原则
        • 1.1 模块化设计
        • 1.2 冗余设计
        • 1.3 容错设计
        • 1.4 实时性保障
        • 1.5 资源管理
      • 2. 开发流程
        • 2.1 需求分析
        • 2.2 架构设计
        • 2.3 编码规范
        • 2.4 代码审查
        • 2.5 版本管理
      • 3. 测试方法
        • 3.1 单元测试
        • 3.2 集成测试
        • 3.3 系统测试
        • 3.4 可靠性测试
        • 3.5 回归测试
      • 4. 可靠性设计技术
        • 4.1 看门狗定时器
        • 4.2 数据校验
        • 4.3 状态监控
        • 4.4 错误日志
        • 4.5 安全启动
      • 5. 文档与培训
        • 5.1 设计文档
        • 5.2 测试报告
        • 5.3 用户手册
        • 5.4 培训
      • 6. 工具支持
      • 总结
    • 测试可靠性方法
      • 静态分析法
      • 动态测试法
      • 综合测试法

在嵌入式系统领域,可靠性通常指的是系统在预定的时间和条件下,能够持续正确执行其功能的能力。一个可靠的嵌入式系统应当能够应对各种异常状况,如电源波动、温度变化、物理干扰,甚至软件缺陷。

硬件件可靠性设计

1、尽可能选择典型电路,并符合单片机常规用法。为硬件系统的标准化、模块化打下良好的基础。
2、系统扩展与外围设备的配置水平应充分满足应用系统的功能要求,并留有适当余地,以便进行二次开发。
3、硬件结构应结合应用软件方案一并考虑。硬件结构与软件方案会产生相互影响,考虑的原则是:软件能实现的功能尽可能由软件实现,以简化硬件结构。但必须注意,由软件实现的硬件功能,一般响应时间比硬件实现长,且占用CPU时间。
4、系统中的相关器件要尽可能做到性能匹配。 如选用CMOS芯片单片机构成低功耗系统时,系统中所有芯片都应尽可能选择低功耗产品。
5、可靠性及抗干扰设计是硬件设计必不可少的一部分,它包括芯片、器件选择、去耦滤波、印刷电路板布线、通道隔离等。
6、单片机外围电路较多时,必须考虑其驱动能力。驱动能力不足时,系统工作不可靠,可通过增设线驱动器增强驱动能力或减少芯片功耗来降低总线负载。
7、尽量朝“单片”方向设计硬件系统。系统器件越多,器件之间相互干扰也越强,功耗也增大,也不可避免地降低了系统的稳定性。随着单片机片内集成的功能越来越强,真正的片上系统SoC已经可以实现,如ST公司新近推出的μPSD32××系列产品在一块芯片上集成了80C32核、大容量FLASH存储器、SRAM、A/D、I/O、两个串口、看门狗、上电复位电路等等。

1. 硬件设计原则

常见硬件设计原则:

  • 适当的供电电源:选择稳定、可靠的电源供应方式,确保供电电压符合单片机的规格要求。同时,应考虑电源的过载和短路保护,以防止异常情况对单片机造成损害。
  • 良好的地线设计:布线时应注意地线的走向和接地方式。保持地线的短而粗,尽量减小回路的环路面积,以降低干扰和噪声的影响。
  • 合理的时钟电路:单片机通常需要外部时钟信号进行运行,因此需要设计相应的时钟电路。时钟电路应具备稳定性和频率准确性,并且要考虑到系统的抗干扰能力。
  • 合适的复位电路:复位电路用于单片机启动和初始化,必须正确设计以确保正常工作。复位电路应提供合适的复位脉冲宽度和延迟时间,并具备稳定的复位信号。
  • 合理选取外设接口:根据系统功能需求,选择合适的外设接口,如UART、SPI、I2C等。在进行接口设计时,需考虑电气特性匹配、信号线长度、阻抗匹配等因素,以保证可靠的通信。

选择合适的处理器硬件是确保系统可靠性的第一步:
硬件的选型应基于项目需求、成本预算以及性能要求等多个因素进行综合考虑。

  • 性能需求:根据项目中对处理速度、内存大小、外设接口数量等性能指标的要求来选择合适的芯片。
  • 功耗要求:对于低功耗应用,选择低功耗的单片机,如使用ARM Cortex-M系列或FPGA等。
  • 成本因素:产品成本直接影响市场竞争力,合理选择芯片可降低成本。
  • 生态支持:选择具有良好开发社区和厂商支持的芯片,以便于开发和故障排查。

硬件的冗余设计:
为了增加系统的可靠性,设计中应考虑硬件的冗余设计:

  • 处理器冗余:使用双处理器或双核处理器,当一个处理器发生故障时,另一个可以接管其任务。
  • 电源冗余:设计双电源系统,一个为主电源,另一个为备用电源,防止单点故障导致系统瘫痪。

硬件设计的防错措施:
为了减少错误和故障的发生,单片机硬件设计中应采取一系列防错措施。

  • 电路的抗干扰设计
    电子系统运行的环境可能充满各种干扰,有效的抗干扰设计能够确保信号的稳定性和数据的准确性。常见的抗干扰措施包括:
    • 差分信号传输:使用差分信号而不是单端信号来提高抗噪声能力。
    • 滤波电路设计:在电源和信号输入端设计合适的滤波电路来过滤掉噪声。
    • 接地处理:正确设计接地回路,避免共模干扰。
  • 电源管理与保护
    电源管理的目的是保证单片机得到稳定而充足的电源供应。为了实现这一目标,可以采取以下措施:
    • 电源监控电路:监控电源电压,如电压低于正常值,则通过复位单片机或切断电源来保护系统。
    • 电源滤波:采用电容、电感和稳压器等元件对电源进行滤波,以稳定电压。
  • 接口电路的可靠性设计
    接口电路是单片机与外部世界连接的桥梁,其可靠性设计需特别注意:
    • 隔离措施:使用光耦合器等隔离器件,保护单片机免受外部高压或噪声影响。
    • ESD保护:设计时应考虑静电放电(ESD)保护措施,防止电气冲击损坏单片机。

硬件可靠性测试与验证:
硬件可靠性测试与验证是单片机硬件设计中不可或缺的环节,它能够确保设计符合预期的性能标准。

  • 硬件故障模式分析
    故障模式分析(FMEA)是一种系统性的分析方法,用于评估产品的潜在故障模式及其影响。在硬件设计阶段,通过FMEA可以识别潜在的故障点,并进行针对性的设计优化。
    • 故障树分析:通过故障树分析,可以了解系统故障发生的逻辑关系,找出薄弱环节。
    • 寿命测试:进行长期的寿命测试,确保硬件能在预期时间内稳定工作。
  • 环境测试和寿命测试
    环境测试包括温度、湿度、振动、冲击等环境因素对硬件的影响测试。寿命测试则用来评估硬件在长时间运行中的可靠性表现。通过这些测试,可以保证硬件在特定环境下能够达到预期的使用寿命。

2. 硬件设计注意问题

2.1 引脚布局和走线

合理的引脚布局和走线可以简化电路设计和布线过程。在布局时,应根据引脚的功能和连接要求,将相关引脚放置在相邻位置,以减少线路的长度和交叉。走线时应尽量避免平行走线和交叉走线,减少串扰和干扰。

2.2 元器件选择和布局

选择合适的元器件对于系统性能至关重要。在选择元器件时,应考虑其规格参数、工作温度范围、可靠性等因素。同时,在布局时应合理安排元器件的位置和间距,以保证良好的散热和信号完整性。

2.3 电源和地线分离

为了避免电源干扰,应将电源线和地线线路分开布置。尽量使用独立的电源地和信号地,并确保它们在一点处连接。这可以减少回路环流和共模噪声的影响。

2.4 EMI/EMC设计

电磁兼容性(EMC)是指电子设备在电磁环境中正常工作而不产生或受到其他设备的影响。在单片机硬件设计中,需要考虑并采取相应的措施来减小电磁干扰(EMI)和提高电磁兼容性。这包括合理的布线、使用合适的滤波器和屏蔽、地线规划等。

2.5 系统可靠性

在进行单片机硬件设计时,要注意系统的可靠性。这包括考虑温度、湿度等环境因素对硬件的影响,选择耐用可靠的元器件,进行合适的散热设计,以及进行合理的电路保护等。

2.6 资源利用和扩展性

在设计单片机硬件时,要充分考虑系统资源的利用和扩展性。合理利用IO口、存储器、外设等资源,确保系统具有足够的灵活性和可扩展性,以满足未来可能的功能扩展需求。

总之,单片机硬件设计需要遵循一些基本原则,如适当的供电、良好的地线设计、合理的时钟电路和复位电路等。同时,还需要特别关注引脚布局和走线、元器件选择和布局、电源和地线分离、EMI/EMC设计、系统可靠性以及资源利用和扩展性等问题。通过遵循这些设计原则和注意事项,可以有效提高单片机硬件设计的质量和稳定性,从而实现嵌入式系统的高效运行。

软件可靠性设计

嵌入式软件的可靠性设计规范是确保嵌入式系统在复杂环境中稳定运行的关键。

在软件开发过程中,代码结构的可维护性是一个值得关注的议题。为了保证代码的可维护性,开发人员需要遵循一定的架构原则和设计模式。下面是几个关键的设计原则:

  • 模块化: 将功能划分为独立的模块,每个模块完成一个具体的功能,有助于代码的复用性和模块间的解耦。
  • 抽象: 抽象层的使用可以减少不同模块之间的直接依赖,使得代码更加灵活和可维护。
  • 分层: 采用分层架构有助于管理复杂度,每一层只关心其直接相关的任务,从而提高系统的可维护性和可扩展性。

错误处理和异常管理是保证软件可靠性的关键。良好的错误处理机制应该能够检测、报告、并处理错误情况,以防止系统崩溃。以下是一些常用的错误处理和异常管理策略:

  • 错误检测: 通过断言、检查返回值等方式来及时发现潜在的错误。
  • 错误隔离: 将错误局限在最小的受影响范围内,防止错误影响到系统的其他部分。
  • 错误恢复: 尝试从错误状态恢复,继续执行或者提供优雅的降级服务。
  • 日志记录: 记录错误日志以便于后续分析,包括错误发生的上下文信息、错误类型和严重程度等。
    例如,在一个任务调度器中,对于任务执行中出现的异常,可以设计如下处理机制:

1. 设计原则

1.1 模块化设计

将软件划分为独立的模块,降低耦合度,提高可维护性和可测试性。
每个模块应具有明确的功能和接口。

1.2 冗余设计

对关键功能设计冗余机制,确保在部分模块失效时系统仍能正常运行。
例如:双机热备、数据校验等。

1.3 容错设计

设计异常处理机制,确保系统在出现错误时能够恢复或降级运行。
例如:看门狗定时器、状态监控等。常用容错处理如下:

  • 明确返回值的意义,使用错误码提高调试效率。
    C语言函数通常通过返回值来反馈操作的成功或失败。因此,为函数设计合理的返回值至关重要。如果函数可能失败,则最好返回一个整数值,其中0表示成功,使用非0值表示特定的错误代码。定义一组错误码,并为每个错误码提供描述性的错误消息。可读性更高的错误消息更有助于调试和记录错误,提高排查bug和修复bug的效率。
    调用现有函数时,如果不能保证一定执行成功,都必须判断返回值,不要纠结多那几行代码。

  • 使用断言(assert)
    断言是一种在开发过程中用于检测程序内部错误的方法。它们通常用于验证不应该发生的条件。如果断言失败,程序将终止执行,这有助于在开发阶段捕获逻辑错误。

  • 异常退出时清理已申请的资源
    当函数失败或发生异常时,确保释放已分配的资源非常重要。这包括动态分配的内存、打开的文件句柄、锁定的互斥量等。

  • 记录日志到文件中
    在程序运行时记录关键信息和错误有助于调试和监控程序的行为。可以将日志消息写入文件或使用专门的日志库。

  • 编写清晰的文档和注释
    编写清晰的文档和注释有助于其他程序员(包括未来的你)理解代码的预期行为和如何处理异常情况。确保为函数和变量提供描述性的名称,并使用注释来解释复杂或不寻常的代码段。它们能够帮助读者(包括未来的你自己)理解代码的功能、输入、输出以及可能的异常情况。

  • 用静态分析工具
    静态分析工具可以检查代码中的潜在问题,如内存泄漏、未初始化的变量、空指针解引用等。使用像Clang Static Analyzer、Cppcheck或Splint这样的工具可以帮助发现并修复代码中的错误。
    根据以往经验,一个大型项目,经过静态分析工具扫描后,可以提前发现30%的bug。

1.4 实时性保障

确保关键任务能够按时完成,避免因任务阻塞导致系统失效。
使用实时操作系统(RTOS)或合理设计任务调度机制。

1.5 资源管理

合理管理内存、CPU、外设等资源,避免资源泄漏或竞争。
例如:动态内存分配限制、使用静态分配为主。

2. 开发流程

2.1 需求分析

明确软件的功能需求、性能需求和非功能需求(如可靠性、安全性)。
编写详细的需求文档,并进行评审。

2.2 架构设计

设计软件的总体架构,包括模块划分、数据流、控制流等。
确保架构满足可靠性要求。

2.3 编码规范

遵循统一的编码规范,提高代码的可读性和可维护性。
例如:使用MISRA C规范、避免全局变量、限制函数复杂度等。

2.4 代码审查

定期进行代码审查,发现潜在的错误和隐患。
使用静态代码分析工具辅助审查。

2.5 版本管理

使用版本控制系统(如Git)管理代码,确保代码的可追溯性。
对每次版本更新进行记录和评审。

3. 测试方法

3.1 单元测试

对每个模块进行独立测试,确保其功能正确。
使用自动化测试工具(如Ceedling、Unity)提高测试效率。

3.2 集成测试

测试模块之间的接口和交互,确保整体功能正常。
重点关注数据流、控制流和异常处理。

3.3 系统测试

测试整个嵌入式系统在真实环境中的表现。
包括功能测试、性能测试、压力测试等。

3.4 可靠性测试

模拟极端条件(如高低温、电压波动、电磁干扰)测试系统的稳定性。
使用故障注入技术验证系统的容错能力。

3.5 回归测试

在每次代码更新后,重新运行测试用例,确保新代码未引入新的问题。

4. 可靠性设计技术

4.1 看门狗定时器

使用硬件或软件看门狗监控系统运行状态,防止系统死锁。

4.2 数据校验

对关键数据进行校验(如CRC、校验和),确保数据的完整性。

4.3 状态监控

实时监控系统状态(如任务运行时间、资源使用情况),及时发现异常。

4.4 错误日志

记录系统运行中的错误信息,便于故障分析和修复。

4.5 安全启动

设计安全启动机制,确保系统在异常断电或崩溃后能够恢复正常。

5. 文档与培训

5.1 设计文档

编写详细的设计文档,包括需求文档、架构文档、接口文档等。

5.2 测试报告

记录测试过程、测试结果和问题分析,形成完整的测试报告。

5.3 用户手册

提供用户手册,说明系统的使用方法、注意事项和维护建议。

5.4 培训

对开发人员和维护人员进行培训,确保其掌握系统的设计原理和操作方法。

6. 工具支持

静态代码分析工具:如PC-Lint、Coverity、CppCheck。
单元测试工具:如Ceedling、Unity。
版本控制工具:如Git、SVN。
仿真工具:如QEMU、Keil Simulator。

总结

嵌入式软件可靠性设计规范是确保系统稳定运行的基础。通过模块化设计、冗余设计、容错设计等技术手段,结合严格的开发流程和测试方法,可以有效提高嵌入式软件的可靠性。同时,完善的文档和工具支持也是不可或缺的。

测试可靠性方法

静态分析法

  • 代码质量分析:采用静态的方法对软件质量进行分析与评估。

  • 代码规范性检测:这种方法目前流行于很多知名企业,制定或执行一定的编码规范,在软件开发过程中,可以避免错误陷阱和代码误解。

  • 代码缺陷分析:对被测代码进行静态扫描,查出可能存在的运行出现时错误的代码段,这种分析可以检测出动态测试状态下难以捕捉到的错误。

动态测试法

白盒测试又称为结构测试,是指在了解被测装置内部结构和软件实现细节的基础上进行的软件测试,根据测试需要可以打开被测装置,重点关注软件内部的实现细节。
黑盒测试又被称为功能测试,是指再不打开被测装置、不考虑其内部逻辑结构的情况下,通过功能测试项目来检测每个功能是否符合测试要求。
灰盒测试是介于白盒测试与黑盒测试之间的测试方法,该测试方法是建立在可以打开被测装置内部结构但不关注软件实现细节的基础上进行的关键信息点测试,这种测试方法只是通过一些表征性的现象、事件、标志来判读内部的运行状态,而不像白盒测试中那么详细。

综合测试法

很多嵌入式软件的可靠性评价都会采用静态分析与动态测试相结合的综合性测试法。

参考:
高可靠性嵌入式主板设计:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

cJSON在STM32单片机上使用遇到解析数据失败问题

我们在单片机上解析JSON格式时(比如在用云平台物联网开发时),可以直接使用cJson库来完成自己的操作,而不需要单独实现,具体使用方法可以搜一下。 cJson:一个基于 C 语言的 Json 库,它是一个开源…

python3基础语法梳理(三)

接上一篇博客 🎮 猜数字小游戏 - Python版 🧠 游戏规则: 系统随机生成一个 1 到 10 的整数玩家输入猜测的数字使用 if 语句判断玩家猜得是否正确提示“猜对了”或“太大/太小了” import randomsecret_number random.randint(1, 10) att…

【docker】将已有mysql脚本导入镜像内使用

准备SQL脚本将SQL脚本(如init.sql)放在宿主机目录下,例如:/path/to/sql-scripts/init.sql启动MySQL容器并挂载脚本使用 -v 参数将SQL脚本挂载到容器的初始化目录:docker run --name mysql-container \-e MYSQL_ROOT_PA…

【机器学习深度学习】LLamaFactory微调效果与vllm部署效果不一致如何解决

目录 前言 一、问题本质 1.1 问题说明 1.2 问题本质示意 二、常见原因 LLaMAFactory对话模板规则定义 模型对话模板定义规则 三、解决方法 提取代码myset.py 创建jinja文件 安装VLLM 运行VLLM 安装运行open webui流程 四、流程梳理 前言 本文主要讲述的主要内容…

Python入门构建网页

用纯 Python 构建 Web 应用 本教程将带你从零开始,构建一个交互式的待办事项清单。 fasthtml 的核心哲学是“回归初心,大道至简”。在当今复杂的前后端分离技术栈中 ,它提供了一条返璞归真的路径,旨在让你能用纯粹的 Python 构建从…

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。 相关链接: 开源 Arkts …

Go的defer和recover

在 Go 语言中,defer 和 recover 是两个紧密相关的关键字,主要用于错误处理和资源清理。它们通常一起使用,特别是在处理panic(运行时崩溃)时,确保程序不会直接崩溃,而是能够优雅地恢复并继续执行…

Spring Boot 配置文件常用配置属性详解(application.properties / application.yml)

前言 Spring Boot 的一大优势就是通过简单的配置文件即可快速定制应用行为,而无需编写大量 XML 配置或 Java 代码。Spring Boot 使用 application.properties 或 application.yml 作为核心配置文件,支持丰富的配置属性。 本文将详细介绍 Spring Boot 常用…

uni-appDay02

1.首页-通用轮播组件 轮播图组件需要再首页和分类页使用&#xff0c;封装成通用组件 准备组件自动导入组件 <script setup lang"ts"> import XtxSwiper from /components/XtxSwiper.vue import CustomNavbar from ./components/CustomNavbar.vue </scrip…

FastAPI入门:请求体、查询参数和字符串校验、路径参数和数值校验

请求体 FastAPI 使用请求体从客户端&#xff08;例如浏览器&#xff09;向 API 发送数据。请求体是客户端发送给 API 的数据。响应体是 API 发送给客户端的数据。 使用 Pydantic 模型声明请求体&#xff0c;能充分利用它的功能和优点 from fastapi import FastAPI from pydanti…

Docker的docker-compose类比Spring的ApplicationContext

总一句话是&#xff1a;Docker Compose&#xff1a;集中化管理多个容器及其依赖的资源环境&#xff1b;ApplicationContext&#xff1a;集中化管理 多个Bean 及其运行所需的资源和依赖关系。 1. 整体概念 Docker Compose&#xff1a;用于定义和运行多容器 Docker 应用程序&…

Reason-before-Retrieve(CVPR 2025)

研究方向&#xff1a;Image Captioning论文全名&#xff1a;《Reason-before-Retrieve: One-Stage Reflective Chain-of-Thoughts for Training-Free Zero-Shot Composed Image Retrieval》1. 论文介绍组合图像检索&#xff08;CIR&#xff09;旨在检索与参考图像密切相似的目标…

Idefics2:构建视觉-语言模型时,什么是重要的

温馨提示&#xff1a; 本篇文章已同步至"AI专题精讲" Idefics2&#xff1a;构建视觉-语言模型时&#xff0c;什么是重要的 摘要 随着large language models和vision transformers的进步&#xff0c;视觉-语言模型&#xff08;VLMs&#xff09;受到了越来越多的关注…

再谈fpga开发(fpga调试方法)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】我们之前在学校学习c、c的时候&#xff0c;其实学校漏掉了很重要的一个教学环节&#xff0c;那就是调试、测试。很多时候我们代码写出来了&#xff…

C语言中的数据结构--栈和队列(1)

前言本届开始我们将对数据结构中栈的内容进行讲解,那么废话不多说,我们正式进入今天的学习栈栈是一种很特殊的线性表&#xff0c;它只能在固定的一端进行插入和删除操作&#xff0c;进行数据的插入和删除的一端叫做栈顶&#xff0c;另外一端叫做栈底&#xff0c;栈中的元素遵守…

字符串是数据结构还是数据类型?

比较纠结的一个问题&#xff0c;以下是在网上查到后总结的&#xff0c;不知道对不对&#xff0c;欢迎讨论。这是个触及计算机科学核心概念的精妙问题&#xff01;字符串既可以被视为一种数据类型&#xff0c;也可以被视为一种数据结构&#xff0c;这取决于你观察的视角和讨论的…

Cline与Cursor深度实战指南:AI编程助手的革命性应用

引言 在AI编程工具快速发展的今天&#xff0c;Cline和Cursor作为两款备受瞩目的AI编程助手&#xff0c;正在重新定义开发者的工作方式。作为一名深度使用这两款工具的开发者&#xff0c;我在过去一年的实践中积累了丰富的经验和独到的见解。本文将从技术角度深入分析Cline和Cur…

根本是什么

根本是什么 根本没有了&#xff0c;枝叶还在么&#xff1f; 没有了内涵&#xff0c;外延还有么&#xff1f; 丢弃了根本&#xff0c;再嗨也是无意义&#xff0c;无根据空虚之乐罢了。 人之所行所言所思所想所念皆欲念、历程感怀&#xff0c;情思。所谓得失过往&#xff0c;时空…

springboot基于Java的人力资源管理系统设计与实现

管理员&#xff1a;登录&#xff0c;个人中心&#xff0c;部门管理&#xff0c;员工管理&#xff0c;培训信息管理&#xff0c;员工奖励管理&#xff0c;员工惩罚管理员工考核管理&#xff0c;调薪信息管理&#xff0c;员工调动管理&#xff0c;员工工资管理员工&#xff1a;注…

金字塔降低采样

文章目录image_scale.hppimage_scale.cppmainimage_scale.hpp #ifndef IMAGE_SCALE_HPP #define IMAGE_SCALE_HPP#include <vector> #include <cstdint> #include <utility> // for std::pair #include <algorithm> #include <string> enum cl…