обычно разделяю системный (дрова и прочий низ) слой и прикладной. в
прикладном, например, в тексте нет работы с GPIO - из системного
торчат функциональные устройства - не в пин 1 порта Б записать 0, а
ЖКИ.подсветка.включить. время только в реальных единицах измерения
- напрример, через обёртки IO_Time_mS(100), Core_Time_uS(10).
Никаких USART в приложении - Serial-ы с DCB, побайтовым и/или
пакетным обменом, над которыми опять же функциональные устройства в
своих модулях. и т.д .
ещё насчёт времени - код приложения не знает о тактовой и о смене тактовой (допустим подключили USB-кабель)