嵌入式系统最差的做法

时间:2008-10-30 19:26:14

标签: embedded anti-patterns

在开发嵌入式系统时,您会考虑采用哪种“最差做法”?

我对不该做的一些想法是:

  • 避免抽象硬件层,而是在整个代码中传播硬件访问。
  • 没有任何类型的仿真环境,只有exe / cute的实际硬件。
  • 避免单元测试,可能是由于上述两点
  • 不在分层结构中开发系统,因此较高层可能依赖于调试和工作的较低层功能
  • 选择硬件而不考虑软件和将使用它的工具
  • 使用专为简化调试而设计的硬件,例如没有测试点,没有调试LED,没有JTAG等

    我确信那里有很多好的想法,不该做什么,让我们听听他们!

  • 21 个答案:

    答案 0 :(得分:54)

    • 未初始化的异常向量(您知道,对于那些“永远不会到达”的
    • 跟我说:全局变量。特别是在没有保护的情况下在ISR和任务(或前台循环)之间共享的。
    • 在必要时未使用“volatile”。
    • 具有DisableInterrupts()然后EnableInterrupts()配对的例程。了解?不是 RestoreInterrupts(),而是 ENABLE 。是的,筑巢。
    • 测试时没有GPIO切换。
    • 船上没有测试点。
    • 没有用于查看运行时系统状态的LED或串行端口。
    • 无法测量CPU的忙/空闲程度。
    • 对除最严重的情况之外的所有情况使用内联汇编。写一个快速标注。
    • 使用for(i = 0; i <1000; i ++){}来“延迟一点”。是的,那不会用一百种不同的方式咬你......
    • 不使用const可以保留RAM并减少启动时间(不复制/初始化变量)

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

    答案 1 :(得分:28)

    有人在我伤害自己之前阻止了我。

    BTW,我意识到并非所有这些都是嵌入式开发的严格特定,但我相信它们在嵌入式世界中至少与现实世界一样重要。

    • 制定时间表时,请继续&amp;假设一切都将在第一时间发挥作用。

    • 在没有示波器和/或逻辑分析仪的情况下接近电路板。 ESP。范围,从来没用过。

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

    • 无论你做什么,都不要使用复位控制器(5美分IC类型),只需使用RC电路(希望其中有很多高频交流噪声耦合到其中)

    • 拥抱大爆炸!不要逐步发展小块。经常整合,傻傻的!只需和旁边的同事一起编写好几个月的代码,然后在大型贸易展演示前一晚将它们拼凑起来!

    • 请勿使用调试/跟踪语句检测代码。可见性很差。

    • 你的ISR中有很多东西。泡泡排序,数据库查询等...嘿,没有人会打扰你,你发言,享受它的伙伴!!!

    • 忽略设计中的电路板布局。让自动布线器通过那些匹配的阻抗走线和高电流高频电源进入城镇。嘿,你有更重要的事情需要担心,伙伴!!!

    • 使用全新的,未经发布的,未发布的早期采用者芯片,特别是如果它是安全关键(航空,医疗)或大批量(召回100万个单位很有趣)。为什么在那个4芯300 MHz 7级流水线芯片上进行新的硅采样时去维加斯?

    答案 2 :(得分:23)

    OK第2轮......再多一点:

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

    • 使用浮点类型&amp;缩放整数数学时的例程就足够了

    • 在不保证的情况下使用RTOS

    • 确实

    • 时,不要使用RTOS

    • 永远不要看生成的汇编代码,以了解幕后发生的事情

    • 编写固件,使其无法在字段中更新

    • 不记录您正在做的任何假设

    • 如果你在测试/调试时看到一些奇怪的东西,只要忽略它,直到它再次发生;它可能不是什么重要的事情,如停电,错过的中断,堆栈损坏的迹象,或其他一些稍纵即逝的&amp;间歇性问题

    • 在调整堆栈时,最好的理念是“从小开始并继续增加,直到程序停止崩溃,然后我们可能会好”

    • 不要利用像Micrium的uC / Probe这样的运行时分析工具(我确定还有其他人)

    • 在运行主应用程序之前,请不要包含硬件的开机自检 - 嘿,启动代码正在运行,哪些可能无法正常工作?

    • 绝对不要在你不打算实施的POST(上面)中包含RAM测试

    • 如果目标处理器有MMU,对于所有神圣的东西,请不要使用那个可怕的MMU!特别是不要让它保护你免受代码空间的写入,数据空间的执行等等。

    • 如果你一直在测试,调试&amp;与一组特定的编译器选项集成(例如,没有/低优化),确保在最终发布版本之前完全优化!但是如果你不打算测试,只能打开优化。我的意思是,你已经测试了几个月 - 可能出现什么问题?!?? ??

    答案 3 :(得分:14)

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

    答案 4 :(得分:12)

    • 在伐木设施上吝啬。嵌入式系统很难调试,您需要大量的日志记录。
    • 无法允许记录级别。许多系统中的一个系统会出现奇怪的行为,您需要将该系统的日志记录的调试级别设置为更详细的。
    • 不允许某种输出端口允许记录到例如控制台。
    • 无法“单步执行”代码。
    • 无法分析代码,因此您可以查看哪些位需要优化,例如在汇编程序中。
    • 没有开发某种“健全性测试”,因此您可以在装载前和装运前快速检查设备是否正常工作。
    • 基于某些“本土化”操作系统的设计

    答案 5 :(得分:8)

    尝试开发而无需访问您正在开发的实际硬件。

    答案 6 :(得分:4)

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

    是的,我之前编写过该架构。

    答案 7 :(得分:3)

    假设endianess将永远相同。

    (将其扩展到寄存器的大小以及有关硬件规范的任何内容)

    (评论中的案例说明)。

    答案 8 :(得分:3)

    如果不再定义“嵌入式编程”,那么就不可能说出什么是好的或坏的做法。

    例如,在CE或XPe平台上,您可能会使用许多技术来编写一个8位微控制器,并采用笨拙的非标准方言“C”进行编程。

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

    答案 9 :(得分:3)

    以下是一些:

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

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

    • 大多数嵌入式系统都是“无头”(没有键盘或鼠标或任何其他HID)。不要在计划中计划编写调试工具。并且不要为至少一个开发人员提供资源来维护它们。

    • 请务必低估获取提示所需的时间。这就是将核心CPU带到可以与您和您交谈的程度所需的时间。

    • 始终假设硬件子系统开箱即用,如内存,时钟和电源。

    答案 10 :(得分:2)

    不要:

    • 保留未使用的未使用的中断向量(毕竟,它们永远不会被触发,所以那里的伤害......),而不是让它们跳转到默认的未使用的中断处理程序一些有用的东西。

    • 不熟悉您正在使用的处理器的细节,特别是如果您正在编写任何低级驱动程序。

    • 选择具有最小闪存量的处理器系列的版本,理由是您可以随时“升级”,除非成本无法避免。

    答案 11 :(得分:1)

    • 假设微处理器完成了数据表中所说的那样做/不做数据表承诺不会做的事情。
    • 将看门狗服务程序置于高优先级的定时中断中,这样无论发生什么其他情况,看门狗都不会失败。
    • 使用互联网上显示的任何代码,特别是如果它来自Arduino / Pic网站。
    • 假设从一个组件到下一个组件有任何标准的定义,例如Tx / Rx(我们这里有一个Sony单元,上面有2个通信端口,一个有相对于另一个的Tx / Rx反转)。
    • 认为顾客在他们卖出至少100个单位之前会费心去检查/测试任何东西
    • 假设该领域的任何其他参与者实际上知道他们正在做什么(我们有一个标准文件说“我们认为这是我们的旧协议所做的,但没有人真正记得”)

    答案 12 :(得分:0)

    根据我在嵌入式系统工作8年以上的经验以及教授嵌入式系统的经验,一些最糟糕的做法是:

    1. 数据类型的选择-嵌入式系统资源稀缺。如果数据的范围是5-200,则没有必要将其声明为int。所需的只有8位,而使用的是32位。浪费24位。

    错误的数据类型也可能是灾难性的。

    1. 在ISR中进行大量工作-ISR应该尽可能短。我见过的一些人在ISR中实现了整个逻辑,这是非常非常糟糕的。太糟糕了,应将其列为犯罪。改用标志

    2. 使用整数作为标志-这更多地是对点1的扩展。您只需要一位。请勿为此使用16位或32位。

    3. 但是,我所见过的最糟糕的事情是反复思考该算法,以获得最佳和最完美的方法。停止!!牢记最佳实践,并使系统首先运行。

    还有更多。您可以read some of them here

    答案 13 :(得分:0)

    一些额外的注意事项:

    • 将硬件相关部件的开发和测试留到最后才发现硬件不起作用,不能按预期工作或有一些无法在软件中修复的缺陷(例如,不需要的非线性失真打破了所有进一步的信号处理)。
    • 简单地设计模拟数字电路,而不考虑数字部分中发生的事情可能会影响模拟部分(例如串扰,导致从ADC读取错误的数据)。

    答案 14 :(得分:0)

    从软件的角度来看,没有花时间学习硬件。

    答案 15 :(得分:0)

    这在很大程度上取决于您编程的控制器类型。有时费用是最重​​要的,你试图尽可能少地接受。这就是我常常使用的船。以下是我用过的最糟糕的做法:

    • 不要专注于改进流程。下次再尝试一下。后来,当我们不忙于在现场支持所有这些错误的同时忙于发布新产品时,我们可以担心这些问题。
    • 避免设计工程工具以使您的生活更轻松,如果您构建一个,请不要让它向设备发送无效输入
    • 不要质疑优化。这是魔法。编译器知道它在做什么。永远不会有编译器错误,尤其不适用于您的客户7位PIC子微控制器。太多人会注意到了吗?
    • 像运行物理引擎一样划分和乘法,不要担心溢出,精度损失,向下舍入为零。
    • 如果您的时间似乎有效,请不要检查您是否已经离开1或者您是否随着时间的推移而漂移。你在高中打过打击乐,你会注意到7200000时钟周期与7200001之间的差异。
    • 依赖于对您的固件一无所知的小组进行系统级测试
    • 尽可能多地使用不同的设备。有几个调试器会话与不同的开发环境。开发一种产品,同时对另一种产品进行测试,并尝试在第三种产品上重现现场问题。
    • 匆忙发布新版本的代码因为你只改变了一件事而你可能没有破坏它。生产线下降,我们不能浪费任何时间!
    • 如果已关闭优化,请勿进行任何类型的测试来警告您。这可能不对?您刚安装的新IDE版本可能无法破坏该设置。
    • 写好代码就可以了。花75%的时间花在那里。
    • 对功能的设计没有任何意见。允许任何功能收集状态信息的天数。无法为测试注入此状态信息。当你试图重现人们在现场看到的错误时,这将给你空闲时间,制作人员也会欣赏他们的休假时间

    答案 16 :(得分:0)

    这不仅适用于嵌入式系统,而是花费所有这些时间来查找错误(调试),而不是避免使用像代码评论绝对是一种常用的最差实践。

    另一个是让一个巨大的处理器完成所有工作,而不是将问题分解成小问题,例如更少的处理器。还记得COCOMO吗?

    答案 17 :(得分:0)

    这可能更多的是硬件答案 - 但是从头开始新项目,低估资源需求是一个大问题,尤其是在使用小型自包含微控制器时,没有简单的方法来扩展代码/存储大小。

    答案 18 :(得分:0)

    printf的。

    如果您的跟踪工具需要上下文切换和/或中断,那么即使模糊地与时间相关,您也永远无法调试任何内容。

    写入内存缓冲区(memcpy'ing枚举的奖励积分而不是s(n)printf),并在其他时间读取。

    答案 19 :(得分:0)

    • 将您的FW模块写成完全通用的,接受每个可能的参数作为变量,即使上面的图层总是使用相同的参数调用。

    • 即使系统中有DMA引擎,也要在代码中的任何地方使用 memcpy (为什么要打扰硬件)。

    • 设计复杂的分层FW架构,然后让模块直接访问更高级别模块所拥有的全局变量。

    • 选择RTOS,但不要费心去测试其实际表现(我们不能相信供应商提供的数字吗?)

    答案 20 :(得分:0)

    嵌入式系统中的一个重要事项是独立于您的应用程序来评估软件(编译器,库,操作系统)和硬件(芯片组)。避免使用试验台是危险的。应该购买评估套件或建立他/她自己的测试床。