十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

嵌入式需求获取:挖出时序、硬件约束与异常边界中的隐性需求

嵌入式需求获取:挖出时序、硬件约束与异常边界中的隐性需求 做过嵌入式软件需求获取的人应该都有同感第一轮需求文档通常写得很“干净”系统要做什么、有哪些功能模块、大致交互流程全在纸面上说得过去。真正让人头疼的是等你把这份文档交给开发、画完框图、开始写驱动时才发现有一半的东西没人定义过——上电时外设初始化失败怎么办通信总线上出现非预期报文怎么处理极端温度下传感器读数漂了算不算故障当看门狗超时复位后系统应该回到什么状态这些问题恰恰是嵌入式系统需求获取过程中最容易被遗漏、却最能决定项目成败的部分。Part 1 聊过需求获取的总体流程、干系人识别、以及从“用户说什么”到“系统要什么”的基础方法。作为系列第二篇这篇不重复那些基础概念专门讲那些从正规文档里问不出来、必须靠特定手段逼出来的需求隐性需求、时序需求、硬件约束需求、异常边界需求和量化后的非功能需求。1. 为什么嵌入式系统的需求有一半是“看不见的”先说一个我实际经历过的场景。一个工业控制项目需求文档写到“设备启动后应能正常执行采集任务”评审时所有人都觉得没问题。结果样机做出来连续上电测试时发现如果断电后立刻重新上电外部看门狗芯片还在复位状态MCU已经跑起来了首次I2C通信直接超时整个采集流程卡死。开发团队改了一版又一版最后需求文档里补了一句“设备在上电后500ms内不允许访问外部看门狗寄存器”——就是这么一条谁都没在需求阶段想到的约束决定了整块逻辑的走向。嵌入式系统的需求之所以大量隐性根子在于它是软硬件深度耦合的系统而不是一个纯粹的“功能集合”。普通应用软件的需求来源相对单一用户界面、业务规则、数据流问一圈业务人员基本能覆盖七八成。嵌入式系统则不同它的行为由处理器、外设、通信总线、传感器、执行器、电源管理、操作系统调度共同决定每一层都隐含着对软件行为的要求。这些要求通常不会出现在用户写下的需求文档中因为它们对用户来说“理所当然”但对软件工程师来说却需要明确到每一毫秒、每一个错误码。我把嵌入式系统“看不见的需求”归纳为四个典型来源后面几节会逐一展开硬件行为产生的约束需求。芯片数据手册里的时序要求、电气特性、复位行为、中断行为都会转译成软件必须满足或必须容忍的规则。环境变化触发的边界需求。温度、湿度、振动、电磁干扰、电压波动正常环境外的东西往往没人写。异常路径中的故障行为需求。总线上出现乱码、传感器无响应、内存碎片化、任务超时这些都是“正常”之外的另一种常态。非功能目标的量化需求。“响应要快”“功耗要低”“运行要稳定”这类描述如果不翻译成可测量的数字等于没有需求。这里有一个反直觉的事实绝大多数隐形需求并不是“没人知道”而是“知道的人不觉得这需要写下来”。硬件工程师知道上电时序有要求但他默认软件应该懂算法工程师知道传感器数据有异常值但他默认驱动层会过滤测试工程师知道极端温度下会有误报但他默认需求已经定义过。需求获取的核心工作从某种程度上说就是把散落在这群人脑子里的默认假设一个个挖出来变成白纸黑字的条目。2. 时序需求从“系统能启动”到“启动的每一毫秒都有定义”嵌入式系统最典型、最容易出问题的需求盲区是时序。用户在需求文档里写的往往是功能性的语句“系统启动时初始化所有外设”“当检测到故障时进入安全状态”。但你问开发人员一个问题——“初始化失败怎么办”对方通常是愣了一下然后说“这要看情况”。这个“看情况”就是灾难的开始。2.1 用“时间线法”逼出启动时序需求我在做需求获取时有一个固定动作针对系统上电、复位、模式切换、关断这四个关键阶段和团队成员一起画时间线。时间线上面是硬件行为下面是软件行为逐段对齐。不要只用文字描述要画出来因为时间线一画冲突就当场显形。举个例子一个采集设备的上电启动。硬件侧要求电源稳定后MCU开始运行时钟芯片需要50ms完成起振外部E2PROM在上电后100ms内可访问通信PHY芯片需要30ms完成链路建立。软件侧呢如果代码一上电就去读E2PROM里的校准参数大概率会读失败。这条需求应该写成什么不能只写“初始化E2PROM”而要写成“MCU从上电复位释放算起等待至少100ms后开始首次E2PROM访问若首次访问超时需间隔20ms重试最多3次3次均失败则记录错误码并跳到出厂默认参数模式同时点亮告警LED”。这个过程不仅是为了补一条时序约束更重要的是它会触发一连串新问题重试多少次算放弃放弃之后走什么路径告警信息怎么上报这些问题的答案被记录成需求条目后开发阶段就不用再临时拍脑袋了。2.2 从复位源反推恢复路径需求时序需求里另一个高频盲区是复位。多数需求文档会对“系统启动”做描述但很少对“为什么启动”做分类。实际上嵌入式系统的复位来源五花八门上电复位、外部引脚复位、看门狗复位、低压检测复位、软件复位。同一次启动不同的复位源对应不同的期望行为。我用一个具体案例说明。一个车载控制器需求里写“系统启动后执行自检自检通过后进入正常运行”。后来在评审时我问了一句“看门狗复位也算启动吗”全场沉默。事实上看门狗复位通常是软件卡死导致的系统需要记录复位原因、保留现场数据、跳过部分耗时的自检流程、快速恢复到运行状态而上电复位则可以完整自检因为此时外部设备可能还没准备好慢一点反而安全。所以需求获取时应该把“系统启动”这个笼统条目拆成一张复位源对照表复位源软件应执行的行为关键差异点上电复位完整自检全速初始化等待外部设备稳定看门狗复位记录原因保留现场快速恢复跳过冗余自检保留故障前数据低压复位进入安全模式保护数据完整性禁止写入非易失存储器外部引脚复位按硬件设计意图执行确认外部设备联动行为这张表格从需求获取阶段就建立后续可以直接作为设计文档和测试用例的依据。不要小看这个动作它能把“系统启动”从一句话变成一个可验证的、多维度的需求集合。2.3 任务调度时序也是需求不只是设计实时操作系统环境下的系统任务调度往往是设计内容但调度产生的结果——任务响应时间、超时行为、优先级反转——本质上是需求。一个采集任务要求“在数据到达后10ms内完成处理”这条是需求一个通信任务“在收到报文后2ms内发送应答”这条也是需求。它们决定了你选什么操作系统、怎么分配优先级、怎么设计中断服务程序。需求获取阶段我会专门问一类问题如果两个任务同时就绪系统保证谁先执行如果一个高优先级任务长时间占用CPU低优先级任务会等多久如果通信任务和存储任务同时要访问共享缓冲区谁会让步这些问题的答案应该被记录下来作为“实时性需求”或“调度约束需求”而不是留给架构师临时决定。很多嵌入式系统后期出现的随机性卡顿、偶发丢包、系统复位追根溯源都是调度时序需求没有在需求阶段定义清楚。3. 从硬件文档里“挖”出来的软件需求嵌入式系统需求获取有一个独特渠道很多人没有意识到它的价值芯片数据手册、参考原理图、硬件设计说明和勘误表。一位有经验的嵌入式需求分析师有一半的需求条目来自这些硬件资料而不是用户访谈。3.1 数据手册里的每个时序参数都可能是一条需求芯片数据手册里的内容表面上看是给硬件工程师看的但里面充斥着对软件行为的隐含要求。比如一个传感器芯片的I2C接口数据手册写“上电后需至少等待5ms才能接受首次通信请求否则设备可能无响应”。这一条放在需求文档里就是“驱动初始化时必须包含上电延时5ms”。再比如一个以太网PHY芯片数据手册写“复位信号释放后MDIO接口在2ms后才可用”这意味着驱动的复位流程里必须有一个时延逻辑严格来说这条“等待2ms”就是软件需求。我的做法是需求获取阶段不要只坐在会议室里访谈要抽出时间通读关键芯片的数据手册把每个和软件行为相关的时序参数、初始化序列、故障状态寄存器标记出来。之后拿着这些标记和硬件工程师逐条确认“这里的数据手册要求会由软件处理吗”“这个初始化序列是由驱动完成还是由硬件自动完成”确认后的结果直接转写成需求条目编号归类纳入需求基线。这一步做扎实了后面写驱动时几乎不会出现“初始化时序不对”这种低级问题。有一个容易被忽视的点勘误表Errata也是需求来源。芯片厂商的勘误表里会写某个模块在某种条件下会触发异常行为需要软件规避。比如某款MCU的勘误表提到“当使用DMA且源地址和目的地址同时落在Flash区域内时可能产生总线错误需在软件中避免该配置”。这条一旦成立就应该作为设计约束需求写进需求文档否则换个不了解这片子的人来写驱动很容易踩坑。3.2 和硬件工程师一起“走原理图”需求获取阶段最有价值的活动之一是我称之为“走原理图”的评审。让硬件工程师拿着原理图从电源入口开始逐块讲解这里有一个电源监控芯片它的输出连接到MCU的复位引脚这意味着当电压跌到阈值以下时MCU会被复位这里有一个拨码开关配置地址软件需要在启动时读取这里有一个LED指示电路硬件上没有上拉电阻所以MCU引脚要配置成推挽输出。每讲一个硬件模块就问一句“这块硬件期望软件怎么配合它”。这个问题的答案通常就是需求条目的雏形。我统计过自己参与过的项目“走原理图”产出的需求条目数量往往比用户访谈产出的还多。原因很简单用户访谈解决的是“系统对外提供什么功能”而“走原理图”解决的是“软件和硬件如何协同工作”。后者是嵌入式系统特有的需求维度也是外包项目、团队交接项目中踩坑最多的地方。如果需求文档里只有功能描述、没有软硬件接口约定开发人员拿到之后一定会反复找硬件工程师确认效率极低。3.3 把硬件故障模式映射为软件需求硬件故障模式也是需求的重要来源。很多嵌入式系统要求“在传感器失效时系统仍能安全运行”这个“安全运行”怎么落地只有当你知道硬件失效时会发生什么才能定义软件该做什么。常规做法是列一张“硬件故障模式与软件响应”对照表逐项填写某个ADC通道读数为满量程通常意味着传感器断线或短路软件应该采取什么策略是丢弃数据取历史值还是进入安全模式某个通信节点持续无响应重试多少次后判定为永久故障是否需要降级运行某个电机的堵转电流触发硬件保护后软件如何感知、如何恢复这张对照表的产出需要硬件工程师参与因为只有他们知道每种故障模式下硬件引脚和总线的实际表现。但表格的主持人必须是需求工程师因为最终要的是软件行为定义而不是硬件设计说明。每次评审会后把新确认的映射关系追加进需求文档并要求测试团队后续针对每种故障模式设计验证用例形成一个闭环。4. 异常与边界用“故障注入式提问”撬开需求缺口异常路径需求缺失是嵌入式项目返工率最高的原因。用户描述系统需求时天然会把注意力放在正常流程上“按下按钮系统开始运行”“收到指令执行动作”“检测到信号上报数据”。这些统统是正常路径。而实际运行中系统有一大半时间在处理非正常情况指令校验失败、数据包长度不对、传感器数值超出量程、任务运行超时、内存分配失败、外设无响应。4.1 两种高效的异常需求挖掘提问法我在访谈和评审中常用两种方法来挖异常需求。第一种叫“每个输入都有非法值”法。系统里每一个输入信号、每一条通信报文、每一个用户操作依次追问如果这个值是无效的、超范围的、格式错误的话系统应该怎么反应注意这里不能停留在“系统应该提示错误”这种级别要往下追问提示什么记录什么是否阻断后续流程是否进入安全模式恢复条件是什么一连串追问下来一条看似简单的输入校验需求通常会裂变成五到八条详细需求。第二种叫“每个任务都有极限值”法。针对系统中的每一个功能任务追问当它的输入数据量达到上限时怎么处理当它处理不过来时是排队还是丢数据当它等待的资源长时间不可用时会不会超时超时后怎么办嵌入式系统因为是实时运行的处理不了的情况一定会出现与其等到压力测试暴露问题不如在需求阶段把策略定好。4.2 把“未知的未知”也纳入讨论比“已知的异常”更麻烦的是那些没人想到过的异常。业界常说需求分析里有“已知的已知”“已知的未知”“未知的未知”三层。前两种可以通过访谈和技术评审覆盖第三种“未知的未知”才是真正考验需求分析师的。我应对“未知的未知”的办法是引入一种类似故障注入的思维游戏。拿一张系统的拓扑图从电源、时钟、通信、存储、传感器、执行器、人机接口七个维度逐项假设“这个东西完全不工作了”然后问系统现在变成什么样哪个功能会受影响受影响的功能是否被需求文档覆盖比如假设通信总线完全断开采集功能还能继续吗数据存在哪恢复通信后数据怎么同步假设存储芯片损坏系统还能启动吗默认参数从哪来假设外部时钟源失效系统还能维持时间戳功能吗这个思维游戏的意义不在于每条假设最终都会成立而在于它迫使团队把所有关键资源的安全性都说一遍。很多隐性问题就在这种“故意刁难”中被暴露出来然后排进需求列表。做这个游戏时最好有测试人员在场因为他们天然带着“怎么把它弄坏”的思路能补充很多开发和硬件视角想不到的场景同时也为后续制定异常测试用例打下基础。4.3 边界条件要“数值化”不能停留在形容词异常需求挖掘到最后一定绕不开边界值。需求文档里出现“温度过高时系统应告警”这句话我基本会把它打回重写。什么叫过高多少度算过高是传感器读数达到某个阈值还是持续超过阈值一定时间告警之后自动恢复吗恢复的阈值和触发阈值之间有滞回吗这些都是必须数值化的问题。边界条件的数值化不能拍脑袋要基于实际硬件能力和业务场景来定。比如一个环境监测设备传感器精度正负0.5度业务要求温度在正负1度以内保持稳定那么“温度过高”的触发阈值可以设为业务要求的边界值而恢复阈值可以设置一个0.5度的滞回区间避免阈值附近反复触发。这些判断不能全交给开发人员在编码时自行决定应该在需求阶段由需求工程师、硬件工程师和业务方一起确认然后以清晰的参数表形式写进需求文档。这里给出一个边界需求的标准写法模板方便直接套用触发条件温度传感器读数大于等于85度且持续时间超过2秒触发动作点亮告警LED向上位机发送告警帧记录告警时间戳与数值恢复条件温度传感器读数小于等于82度且持续时间超过5秒恢复动作清除告警状态发送恢复帧保留历史告警记录特殊情况传感器读数异常如断线导致满量程时按“传感器故障”处理不触发温度告警看到没有这些需求如果不在获取阶段确认开发阶段只能靠猜猜错了就要改代码、改测试、改文档。与其事后返工不如在提问阶段多花半小时。5. 把“快一点”“稳定一点”翻译成可测量的数字嵌入式系统的非功能需求在很多需求文档里是重灾区。用户提需求时经常说“系统响应速度要快”“设备要低功耗”“运行要稳定”“通信要可靠”。技术团队也知道这些重要但往往因为不知道怎样获取更精确的需求就照单全收最后做出来的东西没法验收只能靠“感觉”判断达标与否。5.1 非功能需求不能问“要多快”要问“最慢能接受多慢”非功能需求获取的核心方法是把极端情形摆上台面。问用户“响应要快”没用因为每个人都希望快但这个“快”如果不能对应现实约束就等于没说。有效的问法是把代价和约束摆出来“如果响应时间从10ms变成100ms对系统影响是什么”“如果为了省电把采集频率从1Hz降到0.5Hz业务能接受吗”通过这种交换式提问才能得到真实的非功能需求边界。同时要锚定场景。同样的“通信可靠”在常温室内环境和在工厂电磁干扰环境下指标可以差一个数量级。所以我会追问“这个可靠性的数字是在什么条件下测得的”测试条件本身就是非功能需求的一部分必须写清楚比如“在工业现场环境温度-20到60度通信距离不超过50米带屏蔽双绞线条件下通信丢包率不超过千分之一”。没有测试条件的可靠性指标没有任何验收意义。5.2 从定性描述到定量指标的转换经过一轮轮提问最终的非功能需求应该能够落到一张量化表上。这里展示一张我从实践里总结的转换表供大家参考定性描述量化后的需求示例验证方式启动速度要快从上电到主界面出现不超过3秒上电计时测试功耗要低休眠电流不高于50uA工作平均电流不高于80mA专用功耗仪器测量通信可靠环境温度-20到60度下丢包率不高于0.1%长时间丢包统计测试系统稳定连续运行72小时无死机、无异常复位72小时老化测试数据精度高模拟量采集精度不低于12位误差不大于满量程的0.1%标准源比对测试抗干扰能力强通过IEC 61000-4-2静电放电测试接触放电正负4kV标准合规测试注意这张表里的每一个“量化后的需求”背后都必须有一轮针对业务场景的提问过程。如果只是凭经验拍一个数字填进去很容易出现需求不合理、后期根本无法实现的情况。我曾经在一个项目里看到需求写“系统响应时间不超过1ms”然而实际使用的通信总线光是一帧报文的传输时间就超过5ms这个需求在物理上就不成立。如果当时多问一句“这个1ms是从哪个事件开始、到哪个动作结束计的”就会发现在那个物理约束下合理的指标应该是50ms左右。5.3 可测试性是非功能需求的生命线与非功能需求配套的是每条需求都必须能被测试验证。如果一个需求写出来之后测试团队不知道用什么方法、什么仪器、什么条件去验证它是否满足那这条需求就不合格。我在需求评审时经常问测试负责人“如果这条需求实现了你怎么证明”回答不上来的需求条目必须当场重新讨论直到测试方法和需求描述同时清晰。比如“开机不自检保护”这类需求测试方法可以是故意让一个传感器断开上电后观察系统是否能忽略该传感器故障并进入待机模式期间不应有报警输出。有了这个验证思路需求描述就会变得更具体比如“上电后系统应在未完成传感器自检的情况下进入待机模式并显示传感器故障状态——注意是显示故障而不是执行保护动作”。反之如果一条需求在实际测试中完全无法构造相应的场景例如“卫星信号与地面信号同时异常时应保持系统稳定”而测试环境只有地面信号那这条需求就要降级为设计目标或者明确测试边界注明“该需求在仿真环境下通过注入故障方式验证”。非功能需求的生命线是可测试性可测试性决定了一条需求值不值得写进文档。6. 需求追踪矩阵让每一条需求都活到项目结束需求获取阶段产出的条目如果只躺在文档里那它和不存在没什么区别。嵌入式系统的开发周期长、变更频繁需求条目如果和设计、代码、测试没有关联后面任何一次需求变更都会变成一场灾难。解决这个问题的标准工具是需求追踪矩阵。6.1 从获取当天就开始建矩阵我习惯的做法是需求获取的第一天就建一个追踪矩阵的表格而不是等项目启动后再补。表格列可以这样设置需求编号需求描述来源干系人/文档优先级对应设计模块对应测试用例验证状态REQ-001上电后500ms内禁止访问看门狗寄存器硬件数据手册/硬件评审高驱动模块TC-ASM-007待验证REQ-002通信丢包率不高于0.1%产品经理确认中通信协议栈TC-COM-023待验证为什么一定要从获取当天开始维护因为在获取过程中需求条目是动态增长的今天访谈时确认的“启动等待500ms”可能在明天的硬件评审中变成“300ms”后天测试又发现300ms不够要改回500ms。如果一开始就没有追踪矩阵这种变更链条极容易断最后你根本分不清开发人员按哪个版本实现的。来源这一列很关键很多人不重视。有了来源后续需求变更时就能找到原始提出者让对方确认变更影响没有来源变更时就只能靠猜。我在实际项目里见过太多因为找不到需求来源最后硬生生把需求改回去然后又改回来的情况原因就是没有记录当时是谁在什么场景下提的这条需求。6.2 关键性等级决定需求描述的严谨程度嵌入式系统尤其涉及安全或可靠性要求的领域需求条目需要标记关键性等级。这个等级决定了需求描述需要细致到什么程度、需要哪些额外信息来支撑验证。关键性等级至少分三级。高等级是指失效会直接导致安全风险或系统不可恢复的需求这类需求必须写清触发条件、动作、恢复条件、超时时间、故障处理方法并且要有对应的高强度测试用例。中等等级是失效不导致安全风险但会严重影响功能完成的这类需要基本完整的状态定义和恢复路径。低等级是失效不影响核心功能、只影响体验的这类可以适当简化描述。同一系统内高等级需求不应该只有简洁的一句话必须按照“触发条件、触发动作、恢复条件、恢复动作”四要素写完整。这是需求获取阶段就建立的纪律不是后来补的。6.3 需求追踪矩阵要“前抓来源、后挂测试”需求追踪矩阵的价值最终体现在变更管理和测试覆盖上。每次需求变更矩阵能告诉我们哪些设计模块会受影响、哪些测试用例需要更新每次测试结束矩阵能回答“这条需求到底验证了没有、结论是什么”。有一次项目交付前客户突然提出要修改一个告警阈值。我打开追踪矩阵输入阈值参数对应的需求编号五分钟内列出了受影响的设计文档、驱动模块、通信协议字段和三条需要回归的测试用例。如果没有这个矩阵这种变更通常意味着全项目组开会对齐一折腾就是一天还经常漏掉某个被影响的模块。所以我的建议是需求获取不止是“问问题、记答案”的过程同时也是建立项目管理基础设施的过程。你拿到手的那些碎片化信息要经过编号、归类、关联、排优先级才能变成真正可用的需求文档。追踪矩阵就是把这些工作固化成体系的工具它不需要多复杂一张Excel表格就能用起来关键在于坚持维护。7. 一些不容易在教科书里看到的实操体会前面几节讲了不少方法论最后分享几条这几年在实际项目中反复验证过的体会算是给大家的一些补充。第一需求获取阶段一定要让测试人员全程参与。很多项目的测试团队是等开发得差不多了才介入这完全是浪费。测试人员在需求获取阶段的作用首先是“反着想”开发关注的是系统怎么工作测试关注的是系统怎么被弄坏——这种视角能在需求阶段补上大量的异常场景。其次测试人员提前介入能保证需求的可测试性他们知道哪些场景能构造、哪些不能这直接影响需求条目的写法。我发现以前请测试参与需求评审的项目后续的测试用例编写效率高得多返工也少。第二要习惯用“验收测试思维”倒推需求。在访谈中多问一句“如果我们做出了这个东西你怎样验收它”得到的答案往往比直接问“你需要什么”更具体。用户在对需求没有具象概念时很难说出准确的要求但他们对验收方式是有想法的。比如“设备要能长时间稳定工作”问验收方式用户会说“我们可能让它连续跑三天看看有没有复位”这一下子就得到了72小时无复位这个可测需求。第三需求文档里一定要写“非目标”和“明确不做的事”。嵌入式系统项目因为涉及软硬件边界、成本限制、市场策略经常出现“这个功能理论上可以做但当前版本不做”的情况。把这些不做的内容明确写出来可以防止后续需求蔓延。我在文档里专门有一节叫“明确不做什么”例如“本版本不支持远程固件升级”“本版本不要求数据加密传输”这些看似负面的描述实际上为开发节省了大量用来猜测的精力。最后需求获取永远不要追求“一次到位”。嵌入式系统需求这么多变一次性收集完整是不现实的。最好的做法是把需求获取作为一个持续的过程用上面提到的各类方法——时间线法、硬件文档扫描、走原理图、故障注入式提问、非功能需求量化——交叉迭代地进行每轮都能补上一些新条目同时澄清一些旧条目。项目越往后需求条目增长的曲线越平缓说明前期的工作基本做扎实了。如果你手头正好有一个嵌入式项目处在需求阶段可以试试这里的几个方法尤其是“走原理图”和“故障注入式提问”。这两个动作投入最少、见效最快很多需求缺口在讨论的过程中自己就浮出水面了。等项目运行到开发或测试阶段再回头对照你会发现当初补上的那些条目绝大多数都是真正省了钱的条目。
返回列表