Disclaimer: my experiences with the realities of embedded are limited. You may find this guidance doesn't match well with the constraints you are operating under.
TDD loves functions. Strange, given its lineage, but so it goes. It's often the case that your starting point is to think, and in doing so discover a function that encapsulates most of the logical complexity of your problem, then concentrate your early efforts on generating tests that induce the implementation of that logic.
In this case, it might be a function that accepts your configuration settings as an argument, and returns a linked list of descriptions of calls to set registers (which is to say, an identifier for each function, and the arguments to pass to it -- the sort of thing you could pass to a dumb switch statement).
You would then flesh out the implementation of this function by specifying variations of configurations, and what constraint needs to be satisfied by the returned result.
The earliest test would be chosen to select the simplest list of calls, and then additional tests would be ordered based on which example introduces the minimal amount of new complexity into the production code.
If return values from earlier function calls are part of the logic for computing later calls, then you may be looking for something more like a protocol library (see this talk by Cory Benfield)
Add or modifying initialization has become a pain as most tests need to be rewritten.
Extending the implementation to meet new requirements should be relatively painless, given the earlier behaviors don't change.
Modification -- meaning the actual requirement has changed; yeah, that can be painful.
Sometimes this indicates that the tests overfit the implementation. This symptom is common in UI tests, where cosmetic changes make the result look significantly different to the test harness, and so you may be running into something similar.