Embedded 如何在嵌入式项目中组织代码?

Embedded 如何在嵌入式项目中组织代码?,embedded,code-organization,Embedded,Code Organization,高度嵌入式(有限的代码和ram大小)项目为代码组织带来了独特的挑战 我见过不少没有组织的项目。(根据我的经验,硬件工程师通常不关心代码的非功能方面。) 但是,我一直在尝试相应地组织我的代码: 特定于硬件(驱动程序、初始化) 特定于应用程序(不可能重复使用) 可重用、独立于硬件 对于每一个模块,我都试着将目的保持在这三种类型中的一种 由于嵌入式项目的规模有限,且强调性能,因此通常需要保留此组织 在某些情况下,我目前的项目是一个在MSP430上的有限DSP应用程序,具有8k闪存和256字节ram。我

高度嵌入式(有限的代码和ram大小)项目为代码组织带来了独特的挑战

我见过不少没有组织的项目。(根据我的经验,硬件工程师通常不关心代码的非功能方面。)

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

  • 特定于硬件(驱动程序、初始化)
  • 特定于应用程序(不可能重复使用)
  • 可重用、独立于硬件
  • 对于每一个模块,我都试着将目的保持在这三种类型中的一种

    由于嵌入式项目的规模有限,且强调性能,因此通常需要保留此组织


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

    我曾与一些传感器(如Tmote Sky)合作过,我也看到过组织不善的情况,我不得不承认我对此做出了贡献。无论如何,我要说的是,一定会有一些混淆,因为加载太多的模块或太多的程序部分也会(imho)扼杀资源,所以在资源较低的情况下,要注意组织和可用性之间的界限


    显然,这并不意味着让CAO开始,但举例来说,试着看看源代码和应用程序的组织,这是我想说的一个想法。

    我在8位PIC处理器上工作过,有类似的限制

    一个你没有的限制是你做了多少评论或者你选择了什么来命名你的方法、变量等等。。占便宜。速度和规模限制有时确实胜过组织,但你总能解释


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

    我在各种目标微型机(包括MSP430)上编写并维护了多个嵌入式产品(30+和计数)。我最成功的“经验法则”是:

    • 尽量将通用概念模块化(例如,将驱动程序代码与应用程序代码分开)。——它有助于在将来更容易地维护和重用/将项目移植到另一个目标micro
    • 不要一开始就担心优化的代码。首先尝试解决域的问题,然后进行优化。-你的target micro可以处理比你预期多得多的“东西”
    • 努力确保可读性。尽管大多数嵌入式项目的开发周期似乎很短,但项目的寿命通常比您预期的要长,毫无疑问,其他开发人员将不得不使用您的代码

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

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


    这种类型的游戏对标题没有任何帮助,它们可以很高兴地作为单个文件保留。

    我尝试将其组织起来,就像我有无限的RAM和ROM一样,通常效果很好。正如其他地方提到的,在您完全需要之前,不要尝试优化它


    如果您可以获得一个具有更多资源的pin兼容处理器,那么最好让它工作,专注于良好的结构和布局,然后在以后更好地理解代码时优化大小。

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

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

    尽管如此,以下是相当典型的:

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

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

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

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



    异常编译器限制可能施加的特殊情况。我遇到过一些编译器,它们希望所有中断服务例程都在一个对象文件中编译。

    在编写通用/重用的库时,这一点绝对重要。我不确定所有编译器,但IAR链接器只包含