在尝试提高嵌入式软件技能(在过程C中,使用C ++ 11功能)时,我想学习构造/打包嵌入式系统源代码的最佳方法是什么。
我正在构建没有RTOS的小型系统(在具有1-k4k RAM内存的单个微控制器上)。为了能够在目标环境之外调试软件,我想在主机上模拟我的系统。
我发现在board support package中存储有关处理器及其内部设备(RAM,ROM,计时器等)的信息是标准的。
但是在我的嵌入式项目中,我还使用通过PCB连接到微控制器的其他外部设备(按钮,LED,LCD,伺服,IO多路复用器等)。专用PCB上的源代码抽象层的标准方式/标准名称是什么?
我已经搜索了有关实时系统工程的书籍(David Simon的嵌入式软件入门,Jim Cooling的实时系统软件工程和LaPlante的实时系统:设计和分析),但找不到很好的代码参考。嵌入式系统中的结构化。
最佳答案
根据wikipedia entry for BSP,其目的是提供特定OS所需的板级支持(不仅仅是微型)。因此,对于相同的硬件,不同的操作系统可能需要不同的BSP,所以我认为这不是您要遵循的术语。
您所描述的就是我所说的硬件抽象层/ HAL,我相信这是一个很普通的名字。原则上,该名称可以包括整个PCB或仅包括MCU。
HAL中的重要部分是抽象。良好的抽象将使其易于替换,例如如果要测试构建在HAL脱机目标之上的代码。这也将使将代码移植到其他硬件平台上变得更加容易。
我发现许多供应商提供的库在这方面都达不到要求:您可以调用函数而不是直接修改或读取寄存器,但是函数调用通常直接对应于寄存器。也就是说,它们的库可能隐藏了与芯片接口所必需的编译器扩展的抽象概念,但没有太多其他东西。因此,我倾向于不使用供应商提供的库作为HAL,而可以使用它来实现一个(或直接访问寄存器)。
HAL的最佳结构取决于您的设计目标。您已经说明了能够脱机调试应用程序的一个目标。您还说过,您不打算运行操作系统。您可能打算支持单个MCU或MCU系列,或支持来自不同供应商的多个MCU。您可能正在计划单个板设计,或基于一个公共平台的多个定制板。这些都会影响HAL设计中的设计选择。
我经常从事不使用RTOS的项目。通常,硬件从一个或多个较旧的设计继承某些方面,并具有一些新的东西。新内容可能有小有大变化(包括不同的MCU或MCU系列)。
在这种情况下,我对HAL的方法已发展为:
为HAL中的每个组件定义一个API(通常是指向功能的指针的结构,例如adc_driver_api_t
,uart_driver_api_t
,i2c_driver_api_t
等)。这些API不使用任何芯片/编译器扩展或包含扩展,但通常遵循语言标准(C89 / C99)。
给定平台的HAL提供了针对这些平台的实现,例如msp430_adc12_driver
,msp430_adc10_driver
,pic18_adc12_driver
,avr_adc_driver
等均使用相应平台上可用的不同外围设备来实现adc_driver_api_t
接口。每个实现都在实现头文件中公开实现的驱动程序的const全局实例。 (使用C)extern const adc_driver_api_t msp430_adc12_driver;
。这些实现使用芯片/编译器扩展或按要求包括。
使用HAL获取ADC读数的组件将通过const adc_driver_api_t *
实现以及API所需的其他任何内容(可能是adc通道)进行初始化。组件和ADC驱动器实现都将在程序初始化时被初始化并连接在一起,例如main()
的顶部
我尝试保持HAL API的精益。例如,某些外设可能允许您将12位结果放入16位寄存器的高12位或低12位。我不允许通过HAL API进行配置,但可以提供一个函数来直接在实现HAL API的模块中进行设置,因此在msp430_adc12_driver.h中可能存在一个函数msp430_adc12_driver_set_result_alignment()
,可以在系统初始化期间调用。
我发现这种方法允许以独立于硬件的方式在HAL之上构建组件,因此我可以轻松地在不同平台上重用组件。它还允许对组件进行写入,调试和脱机单元测试,并对HAL进行两次测试。
关于c - 如何构建嵌入式软件的源代码,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31565858/