关于C#:在嵌入式和非嵌入式代码之间维护单个代码库

Maintaining a single codebase between embedded and non-embedded code

我正在从事一个涉及微控制器编程的机器人研究项目。 我希望能够最大程度地将测试软件与测试硬件分离。 这不仅可以提高开发速度,而且还可以使我在将代码放到机器人上之前更轻松地对其进行单元测试/模拟。 因此,例如,我可以编写一个" MyRobot"库。 然后,我既可以在嵌入式代码中也可以在非嵌入式仿真/测试代码中包含此库。 在运行时,我将提供函数指针,这些指针将读取(在嵌入式情况下)或模拟(在模拟情况下)传感器数据,并将其输入库中。

这样看来,我需要做的就是在编译时生成两个库:一个用于嵌入式代码,一个用于非嵌入式代码。

我的问题是这是否可行/是否有更好的方法/是否有任何陷阱需要我注意。

提前致谢!


这是嵌入式系统开发中的常见情况,通常建议您使用创建两个库的方法。将底层硬件与嵌入式系统固件中的软件解耦是一种最佳实践。

您提到的库通常称为"硬件抽象层"或HAL。可以在名为hal.h之类的单个头文件中提供HAL的API(应用程序编程接口)。您的软件中需要访问硬件的每个源模块在源文件的顶部都有以下行:

1
#include"hal.h"

像这样设计系统的好处包括:

  • 模块化。如果您需要更改时序,例如读取传感器的UART或SPI接口,则即使您的代码中可能有多个位置读取该传感器,也只需更改HAL库。
  • 可移植性。如果以后需要将项目迁移到其他微控制器,则仅需要更改HAL层。
  • 封装。硬件的详细信息隐藏在HAL层中,这使您的其他软件可以在更高的抽象级别上运行。如果您使用的是由微控制器制造商提供的设备库,该设备库提供寄存器,I / O端口等的地址,则可以将对该库的引用封装在HAL库中,因此您的应用程序代码无需了解它。
  • 可测试性。这是您问题的主要重点。您可以编写可以在其他平台(例如Windows)上运行的HAL层的特殊版本,以测试应用程序软件。此特殊版本不需要包含微控制器制造商提供的设备库,因为当您在测试环境中运行时,微控制器不存在,因此不需要通过以下方式访问其寄存器和I / O端口:您的软件。

对于您的两种情况,如您所建议的,您将创建HAL库的两个版本:标准版本,其中包含在嵌入式硬件上运行的代码;模拟版本,该模拟版本用于在硬件中测试软件的目的。控制方式。您可以命名标准库hal.lib(根据开发环境的不同,扩展名可能不同)和模拟库hal_simulated.lib。两者将具有相同的接口,如hal.h中所述。也就是说,两个库都将包含在hal.h中声明的所有函数,例如void halInit()int halReadProximitySensor()等。

假设您的IDE支持ReleaseDebug配置,则可以为软件测试创建名为SW_Test的第三个配置。此配置将与您的Debug配置重复,除了hal_simulated.lib将链接到项目中而不是标准hal.lib

也可以看看

硬件抽象(维基百科)


考虑到您使用的不是面向对象语言的C语言,我将使用具有一些内部逻辑甚至#ifdefs(如果必须要有性能)的单个库,例如:

1
2
3
4
5
6
7
8
9
10
11
12
bool turnOn()
{
   #ifdef DEV
       printf ("Turned On\
"
);
       return true;
   #endif

   #ifdef PROD
      return robot_command_turnOn();
   #endif
}

要么

1
2
3
4
5
6
7
8
9
bool turnOn()
{
   if (inProduction())
      return robot_command_turnOn();

   printf ("Turned On\
"
);
   return true;
}

甚至更好:

1
2
3
4
5
6
7
8
9
10
bool turnOn()
{
   printf ("Turned On\
"
);

   if (!inProduction())
        return true;

  return robot_command_turnOn();
}

有几种方法可以做到这一点。在我看来,我不会选择两个库,因为我需要保持功能签名和版本的同步,这可能是一团糟。

秘诀是为您的硬件(如果是机器人)构建一个接口库,并开发该库以融合所有可能的交互,从而保持与硬件层的抽象水平。该接口库可以控制您是否正在测试设备(使用上面的inProduction()之类的功能),并在允许的情况下将命令发送到硬件。

使用面向对象的语言(如C ++),您可以使用各种模式来帮助您:即:接口模式,工厂模式等。