Я делаю встроенный слой CAL (с cmake) HAL и пытаюсь добавить библиотеку, специфичную для некоторых MCU. Теперь проблема здесь заключается в доступе к функциям библиотеки с верхнего уровня.
Мое решение для этого состоит в том, чтобы использовать файл cmake для этой конкретной платы, чтобы определить макрос, для которого библиотека (и функция) будет либо исключена, либо включена в верхние уровни. Для этого необходимо отслеживать пары макросов -> библиотека и функции.
В смысле масштабируемости это не совсем хороший способ. Есть ли какой-нибудь более удобный способ (с точки зрения масштабируемости и унаследованности) реализовать аппаратные возможности?
Если у вас есть универсальный HAL, в который вы включаете библиотеку, которая доступна только на некоторых микроконтроллерах, то единственное решение — грязные условные переключатели компилятора: #ifndef SOMETHING #include "library.h" ...
, Они быстро делают код нечитаемым, поэтому они всегда являются последним средством.
Однако все это говорит о том, что у вас есть проблема с дизайном программы. Ваша программа должна работать так (порядок вызовов):
Код приложения -> HAL -> конкретный драйвер MCU
Где каждый из этих 3-х слоев ничего не знает о содержимом внутри других. Естественно, что внутри HAL не должно быть ничего специфичного для MCU. Скорее, это должно быть внутри водителя. Даже в редком случае, когда код в драйвере идентичен (например, при использовании разных производных MCU одного семейства).
Таким образом, на практике вы получите, например, «spi_library.h», который является HAL, и несколько драйверов, таких как «MCUX_SPI.c», «MCUY_SPI.c», где «MCUX» и «MCUY» — это разные MCU. номера деталей.
В C ++ это обычно делается путем реализации HAL как абстрактного базового класса, который наследует каждая реализация MCU. HAL предоставляет чисто виртуальные функции, которые должны быть реализованы драйвером. (Не обязательно public
из них.)
При публикации HAL вы предоставляете все поддерживаемые драйверы. Но приложение должно ссылаться только на соответствующий драйвер. Приложению не нужно знать содержимое этого драйвера, но оно должно знать, какой MCU является целевой сборкой.
Современный CMake работает с целями и свойствами.
Поэтому, когда вы собираете / экспортируете какую-то конкретную библиотеку / цель, вы можете добавить target_compile_definitions с INTERFACE
,
Это добавит определение к любой цели, которая будет использовать эту библиотеку во время компиляции.