15

高度嵌入(有限的代码和内存大小)项目对代码组织提出了独特的挑战。

我见过很多完全没有组织的项目。(主要是硬件工程师,根据我的经验,他们通常不关心代码的非功能方面。)

但是,我一直在尝试相应地组织我的代码:

  1. 硬件特定(驱动程序,初始化)
  2. 特定于应用程序(不太可能被重用)
  3. 可重复使用,独立于硬件

对于每个模块,我都尝试将目的保持在这三种类型中的一种。

由于嵌入式项目的规模有限和对性能的重视,它经常保持这种组织。

在某些情况下,我当前的项目是在具有 8k 闪存和 256 字节 RAM 的 MSP430 上的有限 DSP 应用程序。

4

6 回答 6

7

我已经在包括 MSP430 在内的各种目标微控制器上编写并维护了多个嵌入式产品(30 多个并且还在增加)。我最成功的“经验法则”是:

  • 尽量将通用概念模块化(例如,将驱动程序代码与应用程序代码分开)。- 它使将来更容易维护和重用/移植项目到另一个目标微。
  • 不要一开始就担心优化的代码。尝试先解决域的问题,然后再进行优化。-- 你的目标微机可以处理比你想象的更多的“东西”。
  • 努力确保可读性。尽管大多数嵌入式项目的开发周期似乎都很短,但这些项目的寿命通常比您预期的要长,并且毫无疑问,另一个开发人员必须使用您的代码。
于 2008-10-19T16:04:42.120 回答
2

我试着把它组织起来,就好像我有无限的 RAM 和 ROM,它通常工作得很好。如其他地方所述,在绝对需要之前不要尝试优化它。

如果你能得到一个拥有更多资源的引脚兼容处理器,最好让它在这方面工作,专注于良好的结构和布局,然后在你更好地理解代码时优化尺寸。

于 2008-10-22T02:43:03.470 回答
2

我曾研究过具有类似限制的 8 位 PIC 处理器。

你没有的一个限制是你做了多少评论或者你选择给你的方法、变量等命名。好好利用。速度和规模限制有时会胜过组织,但你总是可以解释的。

另一个技巧是将逻辑源文件分解成比您需要的更多的部分,然后通过将它们绑定到#include编译单元中来绑定它们。这允许您拥有大量可重用的代码(甚至每个文件一个例程),但可以按您需要的任何顺序组合。这很有用,例如在尝试满足编译单元大小限制时,或者在下一个项目中挑选您需要的常用子例程时。

于 2008-10-19T15:25:27.737 回答
2

除非在特殊情况下(见注释),您的代码组织不会影响最终产品。(代码的内容显然是另一回事)

因此,考虑到这一点,您应该像组织任何其他项目一样组织您的代码。

话虽如此,以下是相当典型的:

如果这是您以前使用过或将来会使用的处理器,您通常希望保留一个专用的硬件抽象层,以便将来在项目之间共享。通常,此模块将包含诸如管理任何 uart、计时器等的例程之类的项目。

通常维护一组特定于平台的初始化和设置代码是合理的,这些代码执行所有配置和初始化,直到您的主管接管并运行您的应用程序。它还将包括特定于平台的 hal 例程。

执行程序/应用程序可能作为一个单独的模块进行维护。所有硬件特定的代码都应该隐藏在 hal 中(如上所述)。

通过像这样拆分代码,您还可以选择在完全不同的平台上编译和运行您的应用程序作为模拟,只需将硬件特定代码替换为模拟硬件的例程即可。这对于您可能遇到的单元测试和调试以及算法问题很有用。


异常编译器限制可能导致的异常情况。例如。我遇到了一些编译器,它们期望所有中断服务例程都在单个目标文件中编译。

于 2008-10-22T03:30:49.207 回答
1

尽管有点痛苦,但嵌入式 C 库中有些常见的一种组织技术是将每个函数和变量拆分为单独的 C 源文件,然后将生成的 O 文件集合聚合到库文件中。

这样做的动机是,对于大多数普通链接器,链接单元是一个对象,对于每个对象,您要么得到整个对象,要么一个都没有。由于 C 文件和目标文件之间存在 1-1 的关系,因此将每个符号放在它自己的 C 文件中会给每个符号它自己的对象。这反过来又让链接器只拉入实际使用的函数和变量的子集。

这种游戏对于标题完全没有帮助,它们可以很高兴地保留为单个文件。

于 2008-10-21T10:26:32.847 回答
1

我曾使用过一些传感器,例如 Tmote Sky,我也看到过糟糕的组织,我不得不承认我对此做出了贡献。无论如何,我会说必须有一些混乱,因为加载过多的模块或过多的程序部分也会(恕我直言)资源消耗,因此请尝试了解低资源上的组织和可用性之间的阈值。

显然这并不意味着让 caos 开始,但例如尝试了解tinyOS源代码和应用程​​序的组织,这是我想说的一个想法。

于 2008-10-19T14:19:51.113 回答