簡體   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