This bears repeating:
DON’T RETURN VOID.
Even when there’s no way for a function to fail, return an integer.
Because it allows the user to go on autopilot. If all of your functions return int (except for a few explicitly-named constructors – these can return the desired struct), the end user can just work your code into his error-handling framework without complaint.
When some return int, some return char *, some return uint8_t, and some return void, it makes the user think about how to deal with every function, adding complexity where it doesn’t need to be.
Complexity is the enemy. Keep it simple.