{"id":149,"date":"2025-09-24T11:43:34","date_gmt":"2025-09-24T09:43:34","guid":{"rendered":"https:\/\/microsproject.dev\/?p=149"},"modified":"2025-09-24T11:43:34","modified_gmt":"2025-09-24T09:43:34","slug":"micros-initialization-framework-structured-startup-for-embedded-systems","status":"publish","type":"post","link":"https:\/\/microsproject.dev\/index.php\/2025\/09\/24\/micros-initialization-framework-structured-startup-for-embedded-systems\/","title":{"rendered":"MicrOS Initialization Framework: Structured Startup for Embedded Systems"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">One of the challenges of building an embedded operating system is handling <strong>system initialization<\/strong> in a clean, modular way. As MicrOS grows, we don\u2019t want board bring-up code, driver setup, and diagnostics all crammed inside <code>main()<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That\u2019s why we\u2019ve added a <strong>lightweight initialization framework<\/strong> to MicrOS, inspired by how Linux and other RTOSes structure their startup phases.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The Idea<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Instead of a hardcoded sequence, MicrOS lets you <strong>register init functions<\/strong> with priorities.<br>The kernel then automatically calls these functions at the right time during boot.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is powered by <strong>linker sections<\/strong> (<code>.preinit_array<\/code>, <code>.init_array<\/code>, <code>.fini_array<\/code>), which GCC and newlib already support. By placing pointers into these sections, we can let the startup code walk through them and invoke each function in order.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">The API<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We provide simple macros in <code>micros\/init.h<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define MICROS_REGISTER_INIT_FUNCTION(func, priority)\n#define MICROS_REGISTER_INIT_EARLY_FUNCTION(func, priority)\n#define MICROS_REGISTER_FINISH_FUNCTION(func, priority)\n<\/code><\/pre>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>INIT<\/strong> \u2192 runs during normal initialization<\/li>\n\n\n\n<li><strong>INIT_EARLY<\/strong> \u2192 runs before almost everything else (clocks, low-level setup)<\/li>\n\n\n\n<li><strong>FINISH<\/strong> \u2192 runs after <code>main()<\/code> exits (shutdown hooks, cleanup)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Each function can be given a <strong>priority number<\/strong>, so you can order initialization stages.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Example<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Here\u2019s a sample application using the framework:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void clock_init(void) {\n    printf(\"--&gt; System clock initialized - simulated\\n\");\n}\n\nvoid uart_init(void) {\n    printf(\"--&gt; UART initialized - simulated\\n\");\n}\n\nvoid diagnostics_init(void) {\n    printf(\"--&gt; System initialized successfully\\n\");\n}\n\nvoid very_early_init_func(void) {\n    printf(\"--&gt; Very early init function in section .init.05\\n\");\n}\n\nvoid very_late_fini_func(void) {\n    printf(\"--&gt; Very late fini function in section .fini_array\\n\");\n}\n\n\/* Register the functions *\/\nMICROS_REGISTER_INIT_EARLY_FUNCTION(clock_init, 0);\nMICROS_REGISTER_INIT_FUNCTION(uart_init, 1);\nMICROS_REGISTER_INIT_FUNCTION(diagnostics_init, 5);\nMICROS_REGISTER_INIT_FUNCTION(very_early_init_func, 55);\nMICROS_REGISTER_FINISH_FUNCTION(very_late_fini_func, 0);\n\nint main(void) {\n    printf(\"&#91;main] MicrOS Initialization Framework Example\\n\");\n    printf(\"&#91;main] System is up and running!\\n\");\n    return 0;\n}\n<\/code><\/pre>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Console Output in QEMU<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Running this sample on the LM3S board in QEMU:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>--&gt; System clock initialized - simulated\n--&gt; UART initialized - simulated\n--&gt; System initialized successfully\n--&gt; Very early init function in section .init.05\n&#91;main] MicrOS Initialization Framework Example\n&#91;main] System is up and running!\n&#91;main] Main function is exiting now.\n&#91;boot] Main function returned with code 0\n--&gt; Very late fini function in section .fini_array\n&#91;boot] System halted after main return\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can clearly see:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Early init (<code>clock_init<\/code>) ran first, before <code>main<\/code>.<\/li>\n\n\n\n<li>Normal init functions (<code>uart_init<\/code>, <code>diagnostics_init<\/code>) followed.<\/li>\n\n\n\n<li><code>main()<\/code> executed.<\/li>\n\n\n\n<li>Finally, a <strong>finish function<\/strong> ran before halting.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Why This Matters<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This framework gives MicrOS a <strong>scalable, modular startup sequence<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Board files can register their own init hooks.<\/li>\n\n\n\n<li>Drivers can self-register without editing core startup code.<\/li>\n\n\n\n<li>Cleanup routines can run automatically at shutdown.<\/li>\n\n\n\n<li>The system stays predictable: <strong>priority values control order<\/strong>.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">This makes MicrOS easier to extend as more subsystems appear \u2014 from schedulers and filesystems to networking stacks.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">With initialization under control, the next step is to start wiring up <strong>driver subsystems<\/strong> (like UART and GPIO) to use this mechanism. That way, enabling or disabling a peripheral becomes just a matter of toggling its init function registration.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p class=\"wp-block-paragraph\">\ud83d\udc49 You can see the full code in the <a href=\"https:\/\/github.com\/microsproject\/micros\" target=\"_blank\" rel=\"noreferrer noopener\">MicrOS repository<\/a> and try it out yourself on QEMU or real hardware boards.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of the challenges of building an embedded operating system is handling system initialization in a clean, modular way. As MicrOS grows, we don\u2019t want board bring-up code, driver setup, and diagnostics all crammed inside main(). That\u2019s why we\u2019ve added a lightweight initialization framework to MicrOS, inspired by how Linux and other RTOSes structure their [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-149","post","type-post","status-publish","format-standard","hentry","category-announcement"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/posts\/149","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/comments?post=149"}],"version-history":[{"count":1,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/posts\/149\/revisions"}],"predecessor-version":[{"id":150,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/posts\/149\/revisions\/150"}],"wp:attachment":[{"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/media?parent=149"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/categories?post=149"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/microsproject.dev\/index.php\/wp-json\/wp\/v2\/tags?post=149"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}