首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >面向嵌入式系统编程的松耦合模式

面向嵌入式系统编程的松耦合模式
EN

Stack Overflow用户
提问于 2010-01-05 00:10:56
回答 6查看 2.8K关注 0票数 21

我在哪里可以找到一些关于用C编写可扩展的、模块化的、松耦合的代码的优秀的、经过验证的指导方针或示例(如果可能)?

我们问题的背景是,我们正在为一个计算和内存资源有限的低成本微控制器维护大型的纯C语言遗留代码项目。由于系统必须非常可靠,而内存又相当有限,因此第一个约束之一是根本不能使用动态内存分配。所有结构都是静态映射的。

因此,我们正在寻找使代码更具可维护性和模块化的方法。我们对编码标准不感兴趣,而是对设计建议感兴趣。我们有很好的编码约定(命名、组织代码、SVN),所以这不是问题。

从我在网络上看到的(我可能错了),似乎大多数只用纯C或汇编语言编程的程序员,至少在uC/Embedded社区中,都会克制自己,不再使用纯过程编程。

例如,我们可以在普通C中使用回调函数、包含函数指针的结构和类似的东西获得大多数OOP好处和解耦(它不需要动态分配,只传递指向结构的指针),但我们想看看是否已经有一些经过验证的方法。

你知道这样的资源吗,或者除了来自的“为什么不切换到C++或其他编程语言”之外,还有类似的建议?

编辑

非常感谢你的所有答案,我还没有时间来检查它们。平台是16位(XC166或类似的) uC,裸硬件(无实时操作系统)。

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2010-01-05 00:53:32

我们也处于类似的境地。为了解决这些问题,我们实现了一个支持所需接口的多个实现的构建系统(所使用的实现是编译目标的函数),并避免使用可移植包装器中未包含的API功能。包装器定义驻留在#include特定于实现的头文件的.h文件中。下面的模型演示了我们如何处理信号量接口:

代码语言:javascript
复制
#ifndef __SCHEDULER_H
#define __SCHEDULER_H

/*! \addtogroup semaphore Routines for working with semaphores.
 * @{
 */

/* impl/impl_scheduler.h gets copied into place before any file using
 * this interface gets compiled. */
#include "impl/impl_scheduler.h"

/* semaphore operation return values */
typedef enum _semaphoreErr_e
{
    SEMAPHORE_OK = impl_SEMAPHORE_OK,
    SEMAPHORE_TIMEOUT = impl_SEMAPHORE_TIMEOUT
} semaphoreErr_e;

/*! public data type - clients always use the semaphore_t type. */
typedef impl_semaphore_t semaphore_t;

/*! create a semaphore. */
inline semaphore_t *semaphoreCreate(int InitialValue) {
  return impl_semaphoreCreate(InitialValue);
}
/*! block on a semaphore. */
inline semaphoreErr_e semaphorePend(semaphore_t *Sem, int Timeout) {
  return impl_semaphorePend(Sem, Timeout);
}
/*! Allow another client to take a semaphore. */
inline void semaphorePost(semaphore_t *Sem) {
  impl_semaphorePost(Sem);
}

/*! @} */

#endif

公共API记录在案以供使用,并且实现在编译之前是隐藏的。使用这些包装器也不会增加任何开销(尽管可能会增加,这取决于您的编译器)。不过,这涉及到很多纯粹的机械打字。

票数 3
EN

Stack Overflow用户

发布于 2010-01-05 00:39:42

您可能想看看xDAIS算法标准。它是为DSP应用而设计的,但它的设计思想也可以调整为低资源的嵌入式设计。

http://en.wikipedia.org/wiki/XDAIS_algorithms

简而言之: xDAIS是一种OOP风格的接口约定,与C语言的COM没有什么不同。您有一组固定的接口,模块可以通过函数指针结构实现这些接口。

接口是严格定义的,因此很容易交换组件,将它们堆叠在一起以构建更高级别的功能等。接口(和代码检查器)还确保所有组件保持分离。如果使用代码检查器,则不可能编写直接调用其他组件私有函数的组件。

内存分配通常在初始化时完成,并在系统设计器的控制下进行(它是所有组件必须实现的主接口的一部分)。

静态和动态分配策略是可能的。您甚至可以在没有内存碎片风险的情况下实现动态,因为所有组件都必须能够将自己重新定位到不同的内存地址。

xDAIS标准定义了一种非常精简的OOP风格的继承机制。这对于调试和日志记录非常方便。有一个能做有趣事情的算法吗?只需在现有算法周围添加一个简单的单文件包装器,并记录对UART的所有调用。由于严格定义了接口,因此不需要猜测模块如何工作以及参数是如何传递的。

我以前用过xDAIS它,它工作得很好。习惯它需要一段时间,但即插即用体系结构的好处和调试的简易性超过了最初的努力。

票数 3
EN

Stack Overflow用户

发布于 2010-01-05 00:44:56

我将尝试在这里开始回答。如果我想到了什么,我会回到这里,因为这个问题很有趣。我也会关注这个问题的其他答案。

  • 分离逻辑和执行:

与大型业务应用程序一样,嵌入式系统也可以从逻辑和I/O的分离中获益。

例如,如果您正在为一些嵌入式设备编写代码,这些设备读取、解释这些值并根据这些读数更改某些内容,那么您可能希望将“逻辑”部分与您实际与网络、硬件、用户或任何外部实体通信的部分完全分开。

当您可以在某种内存结构或C代码中完整地描述“规则”,而不需要链接到消息传递例程或类似程序之外的任何内容时,您就有了我想要描述的东西。简而言之,减少副作用使代码更加模块化。

  • 我不知道你是否在使用线程,但无论哪种方式,proto threads都提供了类似的抽象,不如线程强大,但也不太可能在

上混淆

  • ,我很难忘记这一点。一个ROM可读的操作系统,但很容易通过可加载的库在RAM中进行扩展。对于紧凑的代码和快速的消息,大量使用pointer passing

阅读来自Nils Pipenbrinck的另一个答案,他建议使用xDAIS看起来是实现这一点的一个很好的(但远非唯一的)方式。如果您的大部分代码都使用类似这样的消息约定,那么您的代码很可能是模块化的和可维护的。

我还会在编译目标代码之前启动正在运行的预处理器或预编译器传递,但随后我们就会陷入灰色地带……这几乎就像是切换语言,而要求是C语言。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2000464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档