如何构建嵌入式软件的源代码

时间:2015-07-22 14:21:05

标签: c embedded software-design

在尝试提高我的嵌入式软件技能时(在程序C中,使用C ++ 11特性),我想了解什么是构建/打包嵌入式系统源代码的最佳方法。

我正在努力构建小型系统(在具有1k4k RAM内存的单个微型控制器上)而不使用RTOS。为了能够在目标环境之外调试我的软件,我想在我的主机上模拟我的系统。

我发现在board support package中存储有关处理器及其内部设备(RAM,ROM,定时器等)的信息是标准的。

但在我的嵌入式项目中,我还使用其他外部设备(按钮,LED,LCD,伺服器,IO多路复用器等),这些设备通过PCB连接到微控制器。 特定于应用程序的PCB上的源代码抽象层的标准方式/标准名称是什么?

我搜索过有关实时系统工程的书籍(David Simon的嵌入式软件入门,Jim Cooling&#i>实时系统的软件工程< / i>和LaPlante的实时系统:设计和分析),但无法为嵌入式系统中的代码结构找到一个很好的参考。

1 个答案:

答案 0 :(得分:3)

根据wikipedia entry for BSP,其目的是提供特定操作系统所需的板级支持(而不仅仅是微型)。因此,对于相同的硬件,不同的操作系统可能需要不同的BSP,因此我认为这不是您所追求的术语。

您所描述的是我称之为硬件抽象层/ HAL,我相信这是一个非常常见的名称。原则上,此名称可能包括整个PCB,或仅包括MCU。

HAL中的重要部分是抽象。良好的抽象将使其易于更换,例如如果你想测试构建在HAL off-target之上的代码。它还可以更容易地将代码移植到不同的硬件平台。

我发现许多供应商提供的库在这方面都不尽如人意:您可以调用函数而不是直接修改或读取寄存器,但函数调用通常直接对应寄存器。也就是说,他们的库可能隐藏了与芯片接口所需的编译器扩展的抽象背后,但不是很多。因此,我倾向于不使用供应商提供的库作为HAL,但可以使用它来实现一个(或者只是直接访问寄存器)

HAL的最佳结构取决于您的设计目标。您已经说过一个目标,即能够将您的应用程序调试到目标之外。您还声明您不打算运行操作系统。您可能计划支持单个MCU或MCU系列,或来自不同供应商的多个MCU。您可能正在计划单板设计,或基于通用平台的多个定制板。这些都将影响HAL设计中的设计选择。

我经常处理不使用RTOS的项目。通常,硬件从一个或多个旧设计继承某些方面,并且具有一些新的东西。新的东西可能是小的或大的变化(包括不同的MCU或MCU系列)。

在这种情况下,我对HAL的态度发展如下:

  1. 为HAL中的每个组件定义API(通常是指向功能的指针的结构,例如adc_driver_api_tuart_driver_api_ti2c_driver_api_t等。这些API不使用任何芯片/编译器扩展或包含,但通常遵循语言标准(C89 / C99)。

  2. 给定平台的HAL提供了这些实现,例如: msp430_adc12_drivermsp430_adc10_driverpic18_adc12_driveravr_adc_driver等都使用相应平台上提供的不同外围设备实现adc_driver_api_t接口。每个实现在实现头文件中公开实现的驱动程序的const全局实例,例如, (使用C)extern const adc_driver_api_t msp430_adc12_driver;。这些实现使用芯片/编译器扩展或根据需要包含。

  3. 使用HAL获取ADC读数的组件将使用const adc_driver_api_t *实现以及API所需的任何其他内容(可能是adc通道)进行初始化。在程序初始化中,组件和ADC驱动器实现都将被初始化并连接在一起,例如, main()

  4. 的顶部
  5. 我尝试保持HAL API精简。例如,某些外设可能允许您将12位结果放入16位寄存器的前12位或后12位。我不允许通过HAL API配置它,但是可以提供一个函数来直接在实现HAL API的模块中设置它,所以在msp430_adc12_driver.h中可能有一个函数msp430_adc12_driver_set_result_alignment()可以在调用期间调用系统初始化。

  6. 我发现这种方法允许以与硬件无关的方式在HAL之上构建组件,因此我可以轻松地在不同平台上重用组件。它还允许组件被编写,调试和单元测试组件偏离目标,具有HAL的测试双精度。