Стараюсь сочетать варианты 1 и 2. Сочетание сводится к тому, что прокладки поддержки железа разбиты на отдельные файлы :) При портировании кусков проекта так удобнее. Привожу картинку проекта.
В проекте видно несколько цепочек входимости:
(hardware)ports.h -> (hardware)ADCexternal ->(services) Temperature ->(services)Regulator ->(functionality)Working
(hardware)ports -> (hardware)EEPROM -> (services)Areas -> (functionality) Waiting
Больше всего файлов в группе services, обычно это автоматы состояний внешних устройств. Прокладка работы с железом присутствует обязательно, но гарантировать, что она полностью независима от семейства, сложно.