I think the end result will heavily depend on the architecture and the chosen tools (e.g. IDE).
Here I suggest one of the possible approaches.
If you decide on the bare metal approach, you can take the skeleton from my bare metal programming guide:
https://github.com/cpq/bare-metal-programming-guideAt the beginning, there is a table with template projects. Yes, with blinky.
The organisation of the project is as follows:
1. each component goes into its own .c/.h file, which must contain the superloop task function, if any, and interrupt handler, if any
2. main.c #includes all ".h" files and contains the superloop:
for (;
{
component1_task();
component2_task();
...
}
3. Component priorities are handled by setting IRQ priorities
4. The project is integrated into Github Actions automated build + unit test CI - see guide for an example
5. Additionally, you can set up an automated hardware test as well, see guide
I'd start by creating a general wireframes, and stub all components.
Add CI immediately, and unit tests.
Then add component by components, with respective tests.
Keep your GA Actions green.