embedded式系统最差的做法
在开发embedded式系统时,你会认为什么是“最差的做法”?
我不想做的一些想法是:
我确信有很多好的想法,不要做什么,让我们听听他们!
- 未初始化的exception向量(您知道,那些“永远不会到达”的向量)
- 跟我说:全局variables。 特别是在ISR和任务(或前台循环)之间共享而没有保护。
- 未能在必要时使用“易失性”。
- 有例程DisableInterrupts(),然后EnableInterrupts()配对。 了解? 不RestoreInterrupts() ,但启用 。 是的,嵌套。
- testing时无GPIO切换。
- 船上没有testing点。
- 没有LED或串行端口用于查看运行系统状态。
- 没有测量CPU的忙/闲情况。
- 除最严重的情况外,对所有内联程序集使用内联程序集。 写一个快速的标注。
- 使用for(i = 0; i <1000; i ++){}来“延迟一点”。 是的,这不会以一百种不同的方式咬你
- 不要在任何地方使用const来保存RAM并减less启动时间(不要复制/初始化variables)
我还有更多,但应该让我们开始….
在我伤害自己之前,有人阻止我。
顺便说一下,我意识到并不是所有这些都严格专门针对embedded式开发,但我相信他们每个人在embedded式世界中至less与现实世界一样重要。
-
在制定时间表时,请继续并假设所有事情都是第一次。
-
在没有示波器和/或逻辑分析仪的情况下接近电路板。 ESP。 范围,这是没有用的。
-
devise时不要考虑电源。 诸如热量,效率,ADC读数和系统行为上的纹波效应,EMF辐射,启动时间等问题并不重要。
-
无论你做什么,都不要使用复位控制器(5美分IC型),只需使用一个RC电路(希望有一个有很多高频交stream噪声的电路)
-
拥抱大爆炸! 不要逐步开发小块,经常整合,愚蠢的傻瓜! 只需要代码数个月,与同事一起工作,然后在大型展会演示前一个晚上把它放在一起!
-
不要用debugging/跟踪语句来编写代码。 可见性不好。
-
在你的ISR中做很多东西。 泡泡sorting,数据库查询等…嘿,没准会打断你的,你有发言权,喜欢它的伙伴!
-
忽略devise中的电路板布局。 让自动布线器走到镇上,find那些匹配的阻抗迹线以及大电stream,高频率的电源。 嘿,你有更重要的事情要担心,伙伴!
-
使用全新的,testing版,未发布的早期采用芯片,特别是如果它对安全至关重要(航空,医疗)或高容量(这是很有趣的召回100万单位)。 为什么在4核300MHz 7级stream水线芯片上有新的硅取样时去维加斯?
好的,第2轮….再多几个:
-
不要使用看门狗定时器(尤其是内置的定时器!)
-
使用浮点types和例程时,缩放整数math就足够了
-
不保证时使用RTOS
-
如果真的有意义,不要使用RTOS
-
永远不要看生成的汇编代码来了解底层的情况
-
编写固件,使其不能在现场更新
-
不要logging你正在做的任何假设
-
如果你在testing/debugging时看到一些奇怪的东西,只要忽略它,直到它再次发生。 它可能不是什么重要的事情,像是一个电力不足,一个中断,一个堆栈腐败的迹象,或其他一些短暂和间歇性的问题
-
在select堆栈的时候,最好的理念是“从小处着手,不断增加,直到程序停止崩溃,那么我们可能就OK”
-
不要利用像Micrium的uC / Probe这样的运行时分析工具(我确信还有其他的)
-
在运行主应用程序之前,不要包含硬件的开机自检 – 嘿,启动代码正在运行,有什么可能无法正常工作?
-
在POST(上面)中肯定不包括RAMtesting,你不打算实现
-
如果目标处理器有一个MMU,所有这些都是神圣的,不要使用那个可怕的MMU! 特别是不要让它保护你从写入代码空间,执行数据空间等…
-
如果您一直在testing,debugging和集成一些编译器选项(例如无/低优化),请确保在最终版本构build之前开启全面优化! 但是只有在你不打算testing的时候才打开优化。 我的意思是,你已经testing了好几个月了 – 可能会出错?!
初始化后的dynamic内存分配。 系统启动并运行后,内存池应保持静态。
- 在伐木设备上滑行。 embedded式系统很难debugging,你需要大量的日志logging。
- 没有能力允许日志级别。 其中的一个系统会出现奇怪的行为,您需要将该系统日志logging的debugging级别设置为更详细的行为。
- 不允许某种输出端口允许logging到例如控制台。
- 没有能力“执行”代码。
- 没有能力分析代码,所以你可以看到哪些位需要优化,例如汇编器。
- 不开发某种“健康testing”,所以你可以快速检查设备工作一旦加载,并在出货前。
- 基于一些“本土”操作系统的devise
尝试开发而无法访问正在开发的实际硬件。
在您的解决scheme中使用多个处理器,并确保它们具有相反的字节顺序。 然后确保它们之间的接口是其中一个可以直接访问另一个的内存。
是的,我之前编写过这个架构。
假设永恒将永远是一样的。
(将其扩展到寄存器的大小以及有关硬件规格的任何内容)
(在评论中的案例解释)。
没有定义“embedded式编程”,就不可能说出好坏的做法。
例如,许多你用来编程一个8位微的技术,在一个非常规的“C”非方言方言中,在CE或XPe平台上完全不合适。
在很多情况下,抽象是一种(过度)昂贵的奢侈品,所以“避免它”可能是好的而不是坏的。
这里有几个:
-
不要devise一个易于解释的架构,开发人员,pipe理人员和客户都能理解。
-
embedded式系统几乎总是一个成本敏感的平台。 不要计划硬件越来越慢(更便宜),也不打算在关键数据path中使用新function。
-
大多数embedded式系统是“无头的”(没有键盘或鼠标或任何其他HID)。 不要在您的日程安排中编写debugging工具。 而且不要至less有一个开发人员来维护它们。
-
一定要低估得到提示需要多长时间。 这是需要多长时间才能让核心CPU可以与您和您谈谈的地步。
-
始终假设硬件子系统是开箱即用的,如内存,时钟和电源。
别:
-
留下未使用的中断向量指向无处(毕竟,他们永远不会被触发,所以在那里的伤害…),而不是让他们跳转到一个默认的未使用的中断处理程序,做一些有用的事情。
-
不熟悉你正在使用的处理器的细节,尤其是如果你正在编写任何低级驱动程序。
-
select闪存数量最less的处理器系列版本,理由是您可以随时“升级”,除非成本无法避免。
- 假设数据表做的是数据表所说的/不做数据表所承诺的。
- 将看门狗服务程序置于一个高优先级的定时中断中,以防止发生任何其他事件,看门狗将永远不会失败。
- 使用互联网上看到的任何代码,尤其是来自Arduino / Pic网站的代码。
- 假设从一个组件到下一个组件有任何标准定义,例如Tx / Rx(我们有一个Sony单元,其中有2个通信端口,其中一个Tx / Rx相对于另一个反向)。
- 想象一下,顾客会费事去检查/testing任何东西,直到他们卖出至less100个单位
- 假设这个领域的其他参与者真的知道他们在做什么(我们有一个标准文件,里面写着“我们认为这是我们的旧协议所做的事情,但没有人真的记得”)
embedded式系统中一个重要的事情是独立于应用程序,对软件(编译器,库,操作系统)和硬件(芯片组)进行评估。 避免使用这些testing床是非常危险的。 应该购买评估套件或build立自己的testing床。
-
写你的FW模块是完全通用的接受每个可能的参数作为一个variables,即使你上面的层总是会调用相同的参数。
-
即使在系统中有一个DMA引擎,为什么还要在代码中使用memcpy (为什么要打扰HW)。
-
devise复杂的分层FW体系结构,然后让模块直接访问高层模块拥有的全局variables。
-
select一个实时操作系统,但不打扰testing其实际性能(我们不能相信供应商给出的数字?)
printf的。
如果你的跟踪工具需要一个上下文切换和/或中断,你将永远无法debugging任何东西,甚至模糊的时间相关。
写入一个内存缓冲区(memcpy'ing枚举的奖励分数,而不是s(n)printf),并在另一个时间读取它。
这可能更多的是硬件方面的答案 – 但是为了从头开始新的项目,低估资源需求是一个大问题,特别是在处理小型自包含微控制器时,没有简单的方法来扩展代码/存储容量。
这不仅仅是embedded式系统,而是花费所有的时间去寻找错误(debugging),而不是像例如代码评论那样避免错误,这绝对是一个最常见的应用。
另一个是让一个巨大的处理器做所有的工作,而不是把问题分解成小的问题,比如用更less的处理器。 记得COCOMO?
这很大程度上取决于您正在编程的控制器的types。 有时候,成本是最重要的,而且你正在努力尽可能less的。 这是我通常使用的船。以下是我使用过的最糟糕的做法:
- 不要专注于改善你的stream程。 下次再努力一点。 后来当我们不忙于发布新产品的时候,在支持这个领域的所有这些bug的时候,我们可以担心这些东西。
- 避免devise一个工程工具来使你的生活更轻松,如果你build立一个工程工具,不要让它发送无效的input到设备
- 不要质疑优化。 这是魔法。 编译器知道它在做什么。 永远不会有编译器的bug,特别是不适合你的客户的7位PIC微控制器。 太多的人会注意到吗?
- 分而治之,就像你正在运行一个物理引擎,不要担心溢出,精度损失,四舍五入到零。
- 如果你的时间似乎工作,不要检查你是否是1或者随着时间的推移漂移。 你在高中打了打击乐器,你会注意到720万个时钟周期和7200001之间的差别。
- 依赖对您的固件不了解的组来进行系统级testing
- 在尽可能多的不同设备上工作。 有几个debugging会话与不同的开发环境。 在开发一个产品的同时,在另一个testing平台上进行testing,并尝试在第三个testing领域再现问题。
- 匆忙发布一个新版本的代码,因为你只改变了一件事情,而且你可能没有改变它。 生产线停工,我们不能浪费任何时间!
- 没有任何forms的testing来警告你,如果优化已被closures。 这可能是不对的? 刚刚安装的新IDE版本不可能破坏该设置。
- 编写代码就够了。 花75%的时间到达那里。
- 不要对function的devise有任何的input。 允许任何function收集天的状态信息。 没有办法为testing注入这个状态信息。 当试图重现人们在现场看到的错误时,这会给你空闲时间,而且制作人员也会欣赏他们的rest时间
从软件的angular度来看,并没有花时间学习硬件。
一些额外的注意事项:
- 留下硬件相关部分的开发和testing,直到最后才发现硬件不工作,不能按预期工作,或者存在一些软件无法修复的缺陷(例如,不需要的非线性失真打破所有进一步的信号处理)。
- 简单地devise模拟数字电路,而不用考虑数字部分发生的事情可能会如何影响模拟部分(例如串扰,导致从ADC读取不良数据)。