Драйверы поддаются слоистому подходу.
Ваши драйверы могут иметь несколько «классов»:
- Только вход
- Только вывод
- как I, так и O.
У них должен быть стандартизированный интерфейс, например:
GetKnobLevel()
GetNextKeyboardButton
Или, другой подход - это что-то вроде
syscall(DRIVERNUMBER, command)
, помещающее параметры / результаты в указанные регистры.
Это простой, удобный подход.Более сложный вариант может заключаться в том, чтобы иметь круговые очереди между вашим аппаратным кодом связи и вашим программным кодом связи вместо регистров.
Вот ментальная модель, которую я использую:
---
Application
---
OS
---
Driver communicators
---
drivers
---
hardware
Тамявляется четко определенным интерфейсом без дисперсии между каждым слоем (я продолжаю воображать слоеный пирог с толстой глазурью между слоями ...).Конечно, ОС может не существовать для вас.
Если ваш MCU поддерживает программные и аппаратные прерывания, такие как процессор x86, вы можете использовать их для изоляции драйверов от коммуникаторов драйверов.
Этоесли честно, это немного "сверхинженерное" решение.Но в ситуации, когда ваша сложность становится значительной, легче иметь плотную инженерию, чем свободную инженерию.
Если вы общаетесь между уровнями, вы можете использовать глобальную переменную для каждого коммуникационного "канала",и доступ к нему в дисциплинированном виде, используя только функции для доступа к нему.
Как правило, вы захотите сделать бумажные проекты на каком-то уровне, некоторые исследовательские работы и перепроектировать, прежде чем вы действительно приступите к написанию кода своего проекта.Блок-схемы и схемы шинного перехода здесь хорошо работают.
Это подход, который я предпочел в работе со встроенными системами, и он хорошо работает для меня.
Кроме того - это проблемное пространство недостаточно хорошо изучено в традиционных программах по информатике.Это гораздо менее простительно, чем Интернет или современные операционные системы.