Domanda tosta.
Io la vedo così: l'interfaccia del sistema operativo con l'hardware è parte del sistema operativo.
Se il S.O. è fatto bene, questa interfaccia è organizzata come uno "strato" (layer).
Se si vuole portare il S.O. su un altro HW, basta (in teoria) cambiare questo strato. Questo è uno dei benefici di confinare l'interfaccia in uno strato (e non sparpagliarla dentro tutto il S.O.).
Se esiste un "porting" di quel S.O. a una certa piattaforma HW, allora lo strato di interfaccia è già stato adattato a quell'hardware.
Che cosa c'è dentro lo strato di interfaccia? Bè, in generale ci saranno funzioni che "nascondono" le particolarità dell'hardware e permettono di accedervi con comode funzioni dai parametri standardizzati (esempio: far uscire un certo livello logico da un piedino, o un byte da una porta seriale, far partire un timer). Dovranno esserci anche funzioni che permettono la "subscription" (abbonamento) di altre funzioni (generalmente gestori di interruzione) agli eventi segnalati dall'hardware (esempio: è cambiato un livello logico su un piedino di ingresso, è arrivato un byte su una porta seriale, è terminata la scrittura su una EEPROM, è scaduto un timer). Oppure si salta a piè pari la subscription e si implementano i gestori di interrupt direttamente come parte del layer di interfaccia.
Molte di queste funzioni si considerano parti di "device drivers".
Il tema non è per nulla banale, non lo conosco nei dettagli e spero di non aver scritto qualche castroneria.
Per i dettagli dovresti andarti a studiare gli strati bassi del porting di qualche sistema operativo (per esempio
freeRTOS) su qualche piattaforma HW che ti interessa.
Buono studio.