嵌入式系统最糟糕的实践?

43

当开发嵌入式系统时,您认为应避免哪些“最差的做法”?

以下是我认为不应该做的几件事:

  • 避免抽象硬件层,而是在代码中分散硬件访问。
  • 没有任何类型的仿真环境,只有实际硬件可执行。
  • 避免单元测试,可能是由于上述两点。
  • 不以分层结构开发系统,使得较高层可以依赖于已调试和工作的低层功能。
  • 选择硬件时没有考虑将使用它的软件和工具。
  • 使用为易于调试而设计的硬件,例如没有测试点、没有调试LED、没有JTAG等。
  • 我相信还有很多关于不应该做的好想法,让我们一起听听!

    21个回答

    61
    • 未初始化的异常向量(你知道,针对“永远不会被触发”的那些)
    • 和任务(或前台循环)共享全局变量时没有保护,说吧:全局变量。
    • 未在必要时使用“volatile”关键字。
    • 有些例程会调用DisableInterrupts(),然后再与之配对的EnableInterrupts()。 明白了吗? 不是RestoreInterrupts(),而是ENABLE。 是的,嵌套。
    • 测试时没有GPIO可切换。
    • 板子上没有测试点。
    • 没有LED或串行端口来查看运行时系统状态。
    • 没有测量CPU繁忙/空闲程度。
    • 在除最极端情况外,都使用内联汇编。 编写一个快速调用。
    • 使用for (i = 0; i < 1000; i++) { } 来“稍微延迟一下”。 是的,这可能导致100种不同的问题...
    • 没有尽可能使用const以保存RAM并减少引导时间(不复制/初始化变量)

    我还有更多,但这应该能让我们开始了....


    不错的列表。如果可以的话,我会给你+2。 - Robert Deml
    如果可以的话,我会给这个加上100分。我会把这个传递给其他同事。 - Renan

    32

    在我伤到自己之前,有人拦住我。

    顺便说一下,我意识到这些并不都严格特定于嵌入式开发,但我认为每个问题在嵌入式世界中至少和现实世界一样重要。

    • 制定时间表时,请假定一切都会第一次就成功。

    • 在没有振荡器和/或逻辑分析仪的情况下进行板子调试。尤其是示波器,从来没用过。

    • 在设计时不考虑电源供应。像热量、效率、纹波对ADC读数和系统行为的影响、EMF辐射、启动时间等问题并不重要。

    • 无论你做什么,都不要使用复位控制器(5美分的IC类型),只使用RC电路(带有很多高频AC噪声耦合的电路)

    • 拥抱宇宙大爆炸! 不要逐步开发小块,并经常集成,傻瓜! 只需与同事一起编写几个月,然后在大型贸易展示之前将所有内容组合在一起!

    • 不要为代码添加调试/跟踪语句。 可见性很差。

    • 在ISR中做很多事情。 冒泡排序,数据库查询等... 嘿,可能没有人会打断你,你有机会发挥!

    • 忽略板子布局设计。 让自动布线工具随便处理匹配阻抗追踪和高电流、高频率电源供应。 嘿,你有更重要的事情要担心,伙计!

    • 使用全新的、测试版的、未发布的、早期采用开发者的芯片,特别是安全关键(航空、医学)或大量生产(采样速度为300 MHz的4核心7级流水线芯片)。 为什么去拉斯维加斯,当这个芯片正在采样呢?


    我相信一旦我压抑的记忆消退并停止抽搐,我就会发现这很有趣。+1 为了我需要休息的“心理健康”日.... :-) - Adam Liss

    26

    好的,第二轮……还有几个:

    • 不要使用看门狗定时器(尤其是内置的!)

    • 在可用缩放整数运算的情况下,使用浮点类型和例程

    • 当没有必要时不要使用RTOS

    • 在真正有意义的情况下使用RTOS

    • 永远不要查看生成的汇编代码以了解底层发生了什么

    • 编写固件使其无法在现场更新

    • 不要记录任何您正在进行的假设

    • 如果在测试/调试过程中看到奇怪的东西,请将其忽略,直到它再次发生;它可能不像电压跌落、未接中断、堆栈破坏的迹象或其他短暂和间歇性问题那样重要

    • 在调整堆栈大小时,最好的策略是“从小开始逐步增加,直到程序停止崩溃,然后我们可能没问题”

    • 不要利用运行时分析工具,例如Micrium的uC/Probe(我相信还有其他工具)

    • 在运行主应用程序之前,不要包括硬件的自检功能 - 嘿,引导代码正在运行,可能有什么不起作用的问题呢?

    • 绝对不要在POST中包含一个RAM测试(上面的), 因为你不会去实现它

    • 如果目标处理器具有MMU,请不要使用那个可怕的MMU!特别是不要让它保护您免受对代码空间的写入、从数据空间执行等的攻击。

    • 如果你已经用某一组编译器选项(例如没有/低优化)进行了测试、调试和集成,请确保在最终发布版本之前打开完整的优化!但是只有在不进行测试时才打开优化。我的意思是,你已经测试了数月 - 会出什么问题呢???


    15

    初始化后的动态内存分配。在系统运行时,内存池应保持静态。


    好的回答,那么如果系统需要处理可变长度的输入呢?例如,我有一个从浏览器中获取 XML 配置文件的系统,生成的数据结构可能很小,也可能非常大。如何最好地处理这种情况? - Fred Basset
    根据系统的大小和时间限制而定。在嵌入式领域的高端,动态分配是合理的。 - Steve Fallows
    如果这是一个一次性事件,那么我不反对动态分配足够大的内存块来容纳文件。 如果这是一个重复出现的事件,但只有在初始化后进行动态分配,那么我认为这也是可以接受的。 - jholl
    一个好的方法是编写一个LIFO或双向LIFO分配器(一个LIFO从底部向上分配,而一个独立的LIFO从顶部向下分配)。如果被分配对象的生命周期符合双向LIFO模式,那么使用它比使用malloc/free更加简洁。 - supercat

    12
    • 忽视日志记录设施。嵌入式系统难以调试,需要大量的日志记录。
    • 没有设置允许分级日志记录的能力。在多个系统中的一个系统出现奇怪的行为时,您需要将该系统的日志记录调试级别设置为更详细的级别。
    • 不允许某种输出端口以允许将日志记录到例如控制台中。
    • 没有“逐步执行”代码的能力。
    • 没有进行编译器剖析代码的能力,以便您可以查看哪些部分需要进行优化,例如使用汇编语言。
    • 没有开发某种“健全性测试”,以便您可以在装载并发运之前快速检查设备是否正常工作。
    • 基于某个“自制”的操作系统设计。

    8

    尝试在没有实际硬件支持的情况下进行开发。


    嘿,据传说,比尔·盖茨是在开发一种基本解释器来运行他从未接触过的机器(根据传说,它第一次被加载到目标机器Altair 8800上就成功了)而创立了他的帝国。这就是模拟器的用途! - Tim Ring
    @Tim:我个人最喜欢的是一个朋友为客户的系统开发,除了通过电子邮件发送代码并获取结果外,没有其他访问该系统的方式。他说他学到了很多东西,但不会再这样做了。 - tloach
    我大多数不同意。平台无关的编码原则意味着您应该能够在没有硬件的情况下走得更远。当然,最终您会需要它,而尽早获取硬件是良好的风险管理。 - Craig McQueen
    2
    @Craig McQueen:平台无关的仿真可以让人们在没有硬件的情况下走得更远。不幸的是,人们可能会发现真实硬件的时间行为与仿真器有足够大的差异,需要进行重大改动。 - supercat

    4

    使用多个处理器来解决问题,并确保它们具有相反的字节序。然后确保它们之间的接口是其中一个直接访问另一个内存。

    是的,我以前编写过这种架构。


    如果我没记错的话,TI的OMAP5912将小端ARM处理器和大端c55 DSP组合在一个设备中,通过共享内存进行通信。就像所有工程领域一样,这引入的复杂性是权衡使用这些经过验证的技术所带来的好处的一部分。 - Jeremy

    3
    假设字节序永远不会改变。(将其扩展到寄存器的大小和任何有关硬件规格的内容)(在评论中解释案例)。

    1
    我曾经需要将一个使用大端字节序的Verifone POS应用程序迁移到使用小端字节序的新版本。这不是先前代码中唯一的错误,但它是最不明显的一个。 - Null303

    3

    如果不对“嵌入式编程”进行更详细的定义,那么就无法确定什么是好的或坏的实践。

    例如,在CE或XPe平台上,使用非标准的'C'方言编写8位微控制器程序时可能会完全不合适。

    在许多情况下,抽象是一种(过度)昂贵的奢侈品,因此“避免它”可能是好的而不是坏的。


    好观点,但有时我会想,与我使用过的某些设备相比,CE 真的是“嵌入式”吗?它真的是嵌入式系统中的“劳斯莱斯”。 - rbrayb

    3

    以下是几点建议:

    • 不要设计一个容易解释的架构,让你的开发人员、经理和客户都能够理解。

    • 嵌入式系统几乎总是成本敏感的平台。不要指望硬件变得更慢(更便宜),也不要计划在关键数据路径中添加新功能。

    • 大多数嵌入式系统都是“无头”(没有键盘、鼠标或任何其他HID)。不要在计划中写调试工具。也不要至少分配一名开发人员来维护它们。

    • 一定要低估获得提示的时间。这是将核心CPU带到可以与您交互的状态所需的时间。

    • 始终假设硬件子系统可以直接使用,例如内存、时钟和电源。


    “而且不要忘记至少分配一名开发人员来维护它们。” 这太真实了。我曾经看到一个开发团队在三年内没有为工具开发分配时间,变得越来越慢。 - Quibblesome

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接