Especially for embedded work (but for regular software too!) I've bought into the "sans-io pattern" for a lot of the software i write anymore
https://sans-io.readthedocs.io/how-to-sans-io.html
Keeping all of the actual hardware/network/io interface code separate really makes writing unit tests and porting to different computers much simpler