{"id":7838,"date":"2023-01-29T12:47:30","date_gmt":"2023-01-29T11:47:30","guid":{"rendered":"https:\/\/playembedded.org\/?p=7838"},"modified":"2024-03-10T15:55:31","modified_gmt":"2024-03-10T14:55:31","slug":"simplest-project-chibios","status":"publish","type":"post","link":"https:\/\/playembedded.org\/blog\/simplest-project-chibios\/","title":{"rendered":"The simplest project ever with ChibiOS"},"content":{"rendered":"<h2 class=\"wp-block-heading level_1\" id=\"1_Introduction\">Introduction<\/h2>\n\n\n\n<p class=\"has-text-align-justify\">In this example, we are going to see what is the simplest project you can create in ChibiOS. Following this demo, you will be able to continuously blink an LED with a simple single-thread application stripping down all the extra code. For this exercise, we are going to use the SDP-K1 and we are going to start from its default demo called <em>RT-STM32F469I-EVAL-SDP-CK1Z<\/em> which you can find under the <em>demos<\/em> folder of ChibiOS. Before we begin, if you are not familiar with ChibiOS and the SDP-K1 <a href=\"https:\/\/playembedded.org\/getting-started-chibios-sdp-k1\/\" data-type=\"post\" data-id=\"7713\">this article<\/a> can help you quickly catch up with this demo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"2_Simplifying_the_project\">Simplifying the project<\/h2>\n\n\n\n<p>As an initial step, we will duplicate the project <strong>RT-STM32F469I-EVAL-SDP-CK1Z<\/strong> and rename it. If this project is not visible in your ChibiStudio&rsquo;s Project Explorer, you will need to import it from <em>[ChibiOS root]\\demos\\STM32\\RT-STM32F469I-EVAL-SDP-CK1Z<\/em>. <\/p>\n\n\n\n<p>Importing a project is quite straightforward. If you are unsure how to proceed, refer to the <a href=\"https:\/\/playembedded.org\/how-to-import-a-project\/\" data-type=\"post\" data-id=\"7382\">How to import a project in ChibiStudio<\/a> guide. At this point, we should duplicate the project (refer to &ldquo;<a href=\"https:\/\/playembedded.org\/how-to-duplicate-a-project\/\" data-type=\"post\" data-id=\"7315\">How to duplicate a project in ChibiStudio<\/a>), ensuring to <a href=\"https:\/\/playembedded.org\/how-to-duplicate-a-project\/#5_Fix_the_Makefile\">modify the makefile<\/a> and correct the relative path of ChibiOS.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"3_Overview_of_the_demo\">Overview of the demo <\/h3>\n\n\n\n<p class=\"has-text-align-justify\">Once we have a duplicated building project for out target board, we need to analyze the <em>main.c<\/em> to decide what is actually needed and what is superfluous<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\n    ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio\n\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n        http:\/\/www.apache.org\/licenses\/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n*\/\n\n#include \"ch.h\"\n#include \"hal.h\"\n#include \"rt_test_root.h\"\n#include \"oslib_test_root.h\"\n\n\/*\n * This is a periodic thread that does absolutely nothing except flashing\n * a LED.\n *\/\nstatic THD_WORKING_AREA(waThread1, 128);\nstatic THD_FUNCTION(Thread1, arg) {\n\n  (void)arg;\n  chRegSetThreadName(\"blinker\");\n  while (true) {\n    palSetLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(50);\n    palSetLine(LINE_LED_ORANGE);\n    chThdSleepMilliseconds(50);\n    palSetLine(LINE_LED_RED);\n    chThdSleepMilliseconds(200);\n    palClearLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(50);\n    palClearLine(LINE_LED_ORANGE);\n    chThdSleepMilliseconds(50);\n    palClearLine(LINE_LED_RED);\n    chThdSleepMilliseconds(200);\n  }\n}\n\n\/*\n * Application entry point.\n *\/\nint main(void) {\n\n  \/*\n   * System initializations.\n   * - HAL initialization, this also initializes the configured device drivers\n   *   and performs the board-specific initializations.\n   * - Kernel initialization, the main() function becomes ----a thread and the\n   *   RTOS is active.\n   *\/\n  halInit();\n  chSysInit();\n\n  \/*\n   * Activates the serial driver 5 using the driver default configuration.\n   *\/\n  sdStart(&amp;SD5, NULL);\n\n  \/*\n   * Creates the example thread.\n   *\/\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);\n\n  \/*\n   * Normal main() thread activity, in this demo it does nothing except\n   * sleeping in a loop and check the button state.\n   *\/\n  while (true) {\n    if (!palReadLine(LINE_ARD_A0)) {\n      test_execute((BaseSequentialStream *)&amp;SD5, &amp;rt_test_suite);\n      test_execute((BaseSequentialStream *)&amp;SD5, &amp;oslib_test_suite);\n    }\n    chThdSleepMilliseconds(500);\n  }\n}\n<\/pre>\n\n\n\n<p>This demo consists of two threads<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Main Thread<\/strong> (<code>main<\/code>), function, which performs several key initializations and then enters a loop where it checks the state of a line and if the line is shorted to ground runs the text suite.<\/li>\n\n\n\n<li><strong>Blinker Thread (<\/strong><code>Thread1<\/code><strong>)<\/strong>: which it sequentially sets and clears lines connected to different colored LEDs with specific timing delays between each action resulting in a repeating pattern of LED blinks that continues indefinitely.<\/li>\n<\/ol>\n\n\n\n<p>To proceed with our task we would need to remove one of the threads and simplify the LEDs routing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"4_Removing_the_extra_thread\">Removing the extra thread<\/h3>\n\n\n\n<p>Our purpose is to have a single threaded application (<code>main<\/code> only) which handles one of the LEDs. For this purpose we can cut out the entire <code>Thread1<\/code> declaration:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\n * This is a periodic thread that does absolutely nothing except flashing\n * a LED.\n *\/\nstatic THD_WORKING_AREA(waThread1, 128);\nstatic THD_FUNCTION(Thread1, arg) {\n\n  (void)arg;\n  chRegSetThreadName(\"blinker\");\n  while (true) {\n    palSetLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(50);\n    palSetLine(LINE_LED_ORANGE);\n    chThdSleepMilliseconds(50);\n    palSetLine(LINE_LED_RED);\n    chThdSleepMilliseconds(200);\n    palClearLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(50);\n    palClearLine(LINE_LED_ORANGE);\n    chThdSleepMilliseconds(50);\n    palClearLine(LINE_LED_RED);\n    chThdSleepMilliseconds(200);\n  }\n}\n<\/pre>\n\n\n\n<p class=\"has-text-align-justify\">Similarly, we also need to delete the function call <code>chThdCreateStatic<\/code> which is responsible for the creation of <code>Thread1<\/code>.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">  \/*\n   * Creates the example thread.\n   *\/\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);\n<\/pre>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"5_Amending_the_main_function\">Amending the main function<\/h3>\n\n\n\n<p>Let&rsquo;s look closely to our main function<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/*\n * Application entry point.\n *\/\nint main(void) {\n\n  \/*\n   * System initializations.\n   * - HAL initialization, this also initializes the configured device drivers\n   *   and performs the board-specific initializations.\n   * - Kernel initialization, the main() function becomes ----a thread and the\n   *   RTOS is active.\n   *\/\n  halInit();\n  chSysInit();\n\n  \/*\n   * Activates the serial driver 5 using the driver default configuration.\n   *\/\n  sdStart(&amp;SD5, NULL);\n\n  \/*\n   * Creates the example thread.\n   *\/\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);\n\n  \/*\n   * Normal main() thread activity, in this demo it does nothing except\n   * sleeping in a loop and check the button state.\n   *\/\n  while (true) {\n    if (!palReadLine(LINE_ARD_A0)) {\n      test_execute((BaseSequentialStream *)&amp;SD5, &amp;rt_test_suite);\n      test_execute((BaseSequentialStream *)&amp;SD5, &amp;oslib_test_suite);\n    }\n    chThdSleepMilliseconds(500);\n  }\n}<\/pre>\n\n\n\n<p>The <code>main<\/code>, the application entry point, is actually the starting point of our code execution. In here we have the functions <code>halInit()<\/code> and <code>chSysInit()<\/code> which are crucial for the system initialization and that is why we do not delete them Note that these functions should be kept at the beginning of the main before calls to any other ChibiOS&rsquo; API. <\/p>\n\n\n\n<p>For what concern the Test Suite of ChibiOS, we don&rsquo;t intend to use it. The Suite performs some tests over the various part of ChibiOS printing the results over a Serial Driver (in this case SD5). As we don&rsquo;t intend to use it now the serial driver we can remove the call to <code>sdStart(&amp;SD5, NULL)<\/code> which initializes the serial driver.<\/p>\n\n\n\n<p>Looking at the main loop we have a check on the A0 which will eventually execute the test suite. The loop as well can be clean up removing the entire if branch and replacing it with a call to <code>palToggleLine()<\/code> to change the status of an LED Line.<\/p>\n\n\n\n<p>Performing all these changes we can accomplish the following simplified main<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void) {\n  \/* System initializations HAL and RT. *\/\n  halInit();\n  chSysInit();\n\n  while (true) {\n    palToggleLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(500);\n  }\n}<\/pre>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"6_Removing_extra_inclusion\">Removing extra inclusion <\/h3>\n\n\n\n<p class=\"has-text-align-justify\">Finally we can remove the inclusion of the test suite header at the beginning of the file.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"rt_test_root.h\"\n#include \"oslib_test_root.h\"<\/pre>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"7_Our_simplified_project\">Our simplified project<\/h2>\n\n\n\n<p>With all the changes to our main.c, the project will be very nimble with only few lines to initialize the system and blink the LED.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#include \"hal.h\"\n#include \"ch.h\"\n\nint main(void) {\n  \/* System initializations HAL and RT. *\/\n  halInit();\n  chSysInit();\n\n  while (true) {\n    palToggleLine(LINE_LED_GREEN);\n    chThdSleepMilliseconds(500);\n  }\n}\n<\/pre>\n\n\n\n<p>What we have achieved so far seems to be the stated goal: our application is now single-threaded and reduced to the bare minimum. Now we are ready to connect the SDP-K1 controller board to our laptop and to proceed to test it. <\/p>\n\n\n\n<p>If we have done all the steps above and the <a href=\"https:\/\/playembedded.org\/flash-run\/\">flash and run<\/a> correctly we can actually see the green LED toggling!!<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"688\" style=\"aspect-ratio: 848 \/ 688;\" width=\"848\" autoplay loop muted src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/02\/Green-led-blinking.mp4\"><\/video><figcaption class=\"wp-element-caption\">The green LED of the SDP-K1 blinking<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"8_Further_memory_footprint_optimizations\">Further memory footprint optimizations<\/h2>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"9_The_Binary_file\">The Binary file<\/h3>\n\n\n\n<p>Reducing the code footprint and resource usage is always a crucial consideration when working on embedded system projects. The changes made in the <em>main.c<\/em> file alone may not be sufficient to do that. It&rsquo;s important to keep in mind that when building the project, the opcode instructions are encoded as Binary and are stored in a file with the .bin extension, named ch.bin. <\/p>\n\n\n\n<p>This file often referred to as binary image, is copied one to one in the flash memory of the microcontroller and its size represents the space that will be occupied in flash after the programming.<\/p>\n\n\n\n<p>It takes just a few seconds to check the size of the ch.bin file. You can navigate to the build folder of the project you are working on, right-click the <strong>ch.bin<\/strong> file, and select properties. For example, the size of the demo <strong>RT-STM32F469I-EVAL-SDP-CK1Z<\/strong> built with GCC 10.3.1 is 56.5KB.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"673\" height=\"531\" src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/01\/Full-size-PE.png\" alt=\"\" class=\"wp-image-8446\" srcset=\"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Full-size-PE.png 673w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Full-size-PE-300x237.png 300w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Full-size-PE-150x118.png 150w\" sizes=\"auto, (max-width: 673px) 100vw, 673px\"><figcaption class=\"wp-element-caption\">Default demo ch.bin size <\/figcaption><\/figure>\n\n\n\n<p>In our project, the ch.bin size has undergone a reduction of memory footprint from 56.5kB to 6.64kB. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"784\" height=\"641\" src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/01\/Demo-smaller-size-PE.png\" alt=\"\" class=\"wp-image-8450\" srcset=\"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Demo-smaller-size-PE.png 784w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Demo-smaller-size-PE-300x245.png 300w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Demo-smaller-size-PE-150x123.png 150w\" sizes=\"auto, (max-width: 784px) 100vw, 784px\"><figcaption class=\"wp-element-caption\">Single thread main <\/figcaption><\/figure>\n\n\n\n<p>Even if the size has been reduced when building our project we can see that the system still does compilation regarding the Test Suite and the Serial Driver. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"842\" height=\"812\" src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/01\/Console.png\" alt=\"\" class=\"wp-image-8453\" srcset=\"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Console.png 842w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Console-300x289.png 300w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Console-150x145.png 150w\" sizes=\"auto, (max-width: 842px) 100vw, 842px\"><figcaption class=\"wp-element-caption\">The building process completed with Test Suite and Serial Driver still compiled <\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"10_How_to_optimize_memory_usage\">How to optimize memory usage<\/h3>\n\n\n\n<p>To further optimize the code, we can edit the <strong>Makefile<\/strong> by deleting or commenting out all lines of code labeled as &ldquo;optional&rdquo; related to the Test Suite and can reduce the flash memory occupancy even more by disabling the Serial Driver in the <code>halconf.h<\/code> file.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Other files (optional).\n# include $(CHIBIOS)\/os\/test\/test.mk\n# include $(CHIBIOS)\/test\/rt\/rt_test.mk\n# include $(CHIBIOS)\/test\/oslib\/oslib_test.mk<\/pre>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">\/**\n * @brief   Enables the SERIAL subsystem.\n *\/\n#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)\n#define HAL_USE_SERIAL                      FALSE\n#endif<\/pre>\n\n\n\n<p>Now by performing one more time check on the <strong>ch.bin<\/strong> file size, we can see the file has been further reduced going from 6.64KB to 4.57KB.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"675\" height=\"511\" src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/01\/Smallest-size-PE.png\" alt=\"\" class=\"wp-image-8454\" srcset=\"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Smallest-size-PE.png 675w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Smallest-size-PE-300x227.png 300w, https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/Smallest-size-PE-150x114.png 150w\" sizes=\"auto, (max-width: 675px) 100vw, 675px\"><figcaption class=\"wp-element-caption\">Binary file size is reduced even further<\/figcaption><\/figure>\n\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this example, we are going to see what is the simplest project you can create in ChibiOS. Following this demo, you will be able to continuously blink an LED with a simple single-thread application stripping down all the extra code. For this exercise, we are going to use the SDP-K1 and we are [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":8464,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1260],"tags":[1293,1304],"coauthors":[1282],"class_list":["post-7838","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-examples-and-exercises","tag-1293","tag-chibios-rt","gold"],"views":5592,"jetpack_featured_media_url":"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/01\/The-simplest-project-ever-with-ChibiOS-PE.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/7838","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/comments?post=7838"}],"version-history":[{"count":0,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/7838\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media\/8464"}],"wp:attachment":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media?parent=7838"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/categories?post=7838"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/tags?post=7838"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/coauthors?post=7838"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}