繁体   English   中英

C ++编译时间检查是否已经从其他源文件初始化了微控制器引脚

[英]C++ Compile time check if a microcontroller pin is already initialized from other source file

通常,微控制器的引脚可以通过端口号和引脚号来识别,两者都是编译时间常数。 引脚可以具有多种功能,如果在大型项目中使用,则多个源文件可以初始化同一引脚并破坏其他模块中实现的功能。

我想实现一个编译时间列表,该列表最初为空,并且每次初始化引脚时,都会检查该列表中是否已存在该引脚,如果存在,它将给出一个静态的断言,否则将在列表中插入引脚信息。 运行时不需要列表。

我对元编程没有足够的了解,如果有人可以为我提供实现的指导,那将是非常不错的。如果已经有一些用于此目的的库,请提供链接

您想要的是不可能的。 C ++元编程没有状态 ,它更像是一种功能性语言,而不是声明性语言。 因此,您不能拥有可变的列表。 可以通过创建新类型来引入唯一状态,但是没有可用的语法来检查是否声明或定义了特定的非嵌套名称。

多个源文件(编译单元)是独立编译的,因此肯定没有“全局状态”,这使它变得更加不可能。

另外,请注意,您所做的本质是运行时。 编译器没有工具来检查您是否两次调用了初始化函数。 这些调用可能隐藏在某些运行时if-else决策之后。 并简单地编写HAL_GPIO_Init(); 不管在整个程序中多少次都不是错误。

我能想到的最简单的事情是创建一个C ++单例类,该类负责与引脚进行通信。 您可以使用error_codes或异常(如果已启用)使用专用的int init_GPIO方法。 代替static_assert您将不得不依赖测试-单例可以正常工作,并且init_GPIO的返回值不会被忽略。

如果您真的不想打扰单例,则此功能模板也可以使用:

template<std::size_t GPIO, std::size_t port> int GPIO_init(GPIO_InitStruct& s){
    static bool initialized=false;
    if(initialized) return <already_called>;
    initialized=true;
    //Assuming that you want to propagate the return value.
    return HAL_GPIO_Init(GPIO, port, s);// Replace with the correct call.
}

如果需要线程安全的初始化,请使用:

template<std::size_t GPIO, std::size_t port> int GPIO_init(GPIO_InitStruct& s){
    static std::once_flag initialized;
    int ret_val = <already_called>;
    auto call = [&](){ret_val = HAL_GPIO_Init(GPIO, port, s)};
    std::call_once(initialized, call);
    return ret_val;
}

假设每个驱动程序或HAL都有一个头文件,并且有一个main.cpp包含所有这些头,则可以使用预处理器来完成此操作。

(可选)使用以下枚举创建项目范围的头文件“ pintype.h”:

// pintype.h

typedef enum
{
  PIN_GPIO,
  PIN_PWM,
  PIN_ADC,
  PIN_UART,
  ...
} pin_t;

然后,对于每个头文件,编写预处理程序检查,例如:

// pwm.h, header of the pwm driver or HAL
#include "pintype.h"

#ifdef PIN9
  #error Pin 9 already taken
#else
  #define PIN9 PIN_PWM
#endif

严格来说,不需要#error ,因为如果发生冲突,编译器将抱怨同一转换单元(main.cpp的定义)中的多个定义。

当编写驱动程序的开发人员收到错误消息时,他们可以转到引脚的预处理器定义,并找出项目中已经声明该功能的其他模块,而无需深入研究该驱动程序的内部实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM