{"id":8523,"date":"2023-02-25T22:22:45","date_gmt":"2023-02-25T21:22:45","guid":{"rendered":"https:\/\/playembedded.org\/?p=8523"},"modified":"2024-02-24T16:31:43","modified_gmt":"2024-02-24T15:31:43","slug":"parametric-threads-with-chibios","status":"publish","type":"post","link":"https:\/\/playembedded.org\/blog\/parametric-threads-with-chibios\/","title":{"rendered":"Parametric Threads with ChibiOS"},"content":{"rendered":"<h2 class=\"wp-block-heading level_1\" id=\"1_Introduction\">Introduction<\/h2>\n\n\n\n<p>In this article, we will demonstrate how to create multiple threads using parametric functions. This means that while the function executed by each thread is the same, the specific behavior is influenced by passing different parameters each time.<\/p>\n\n\n\n<p>To illustrate how parametric threads work, we will blink multiple LEDs in different ways defining a single function. We will begin with <a href=\"https:\/\/playembedded.org\/simplest-project-chibios\/\" data-type=\"post\" data-id=\"7838\">the simplest project ever<\/a> and gradually modify it to create a project that blinks two LEDs in counter phase.<\/p>\n\n\n\n<p>Before starting, make sure you have the latest version of ChibiStudio installed and have the Analog Devices EVAL-SDP-CK1Z board to fully engage in this hands-on experience.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"2_How_to_parametrize_a_thread\">How to parametrize a thread<\/h2>\n\n\n\n<p>To <a href=\"https:\/\/playembedded.org\/mastering-multithreading-with-chibios-a-beginners-guide\/#12_Static_thread\">create a static thread<\/a> without a parameter, we pass <code>NULL<\/code> during creation and we cast the argument to <code>void<\/code> in the thread function to avoid compiler warnings<\/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=\"\">static THD_WORKING_AREA(waThread1, 128);\nstatic THD_FUNCTION(Thread1, arg) {\n  \n  \/* Unused argument. *\/\n  (void) arg;\n  while (true) {\n    chThdSleepMilliseconds(50);\n  }\n}\n\nint main(void) {\n  \n  ...\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, NULL);\n  ...\n}<\/pre>\n\n\n\n<p>However, ChibiOS offer the chance to parameterize threads by passing a <a href=\"https:\/\/playembedded.org\/demystifying-c-pointers\/#18_Passing_a_pointer_of_an_unknown_type_to_a_function\">pointer to void<\/a> at creation time as shown in the following example<\/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=\"\">static THD_WORKING_AREA(waThread1, 128);\nstatic THD_FUNCTION(Thread1, arg) {\n  \n  \/* Using a temporary variable and recasting the type of arg. *\/\n  uint32_t* myargp = (uint32_t*)arg;\n  while (true) {\n\n    \/* Using the parameter. *\/\n    myargp++;\n    chprintf(chp, \"%d\", *myargp);\n    chThdSleepMilliseconds(50);\n  }\n}\n\nint main(void) {\n  \n  ... \n  uint32_t myarg;\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, Thread1, &amp;myarg);\n  ...\n}<\/pre>\n\n\n\n<p>In many cases, the application requires passing multiple arguments and this is when you turn to structures as we are going to show in this demo. In general, this involves defining a new structure and passing that to the thread.<\/p>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"3_LEDs_in_counter_phase\">LEDs in counter phase<\/h2>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"4_Working_with_a_structure\">Working with a structure <\/h3>\n\n\n\n<p>Since this demo is about two LEDs blinking in counter-phase both with a 50% duty cycle, multiple parameters are necessary. Hence, we need to group together variables of different types and this can be done with a structure. <\/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 * @brief   LED configuration structure.\n *\/\ntypedef struct {\n  \/**\n   * @brief Line associated to LED\n   *\/\n  ioline_t                  led;\n  \/**\n   * @brief Time associated to LED.\n   *\/\n  systime_t                 time;\n  \/**\n   * @brief Line status associated to LED.\n   *\/\n  uint32_t                  status;\n} LEDconfig_t;<\/pre>\n\n\n\n<p>The first thing we need is a <code>ioline_t<\/code> to identify the line where the LED of interest is connected. The second member is related to the time the LED needs to blink on and off, and its type is <code>systime_t<\/code>. Since we are assuming a 50% duty cycle, no additional time-related parameters are necessary. To achieve the counter-phase effect between two LEDs we need to set the initial logical state of the line. This information can be represented using a Boolean value thus we add an addition uint32_t member. <\/p>\n\n\n\n<p>Once the structure is defined, we can create two new <code>LEDConfig_t<\/code> variables, <code>redledconfig <\/code>and <code>greenledconfig<\/code>. These will be used to specify the configuration for the red and the green LEDs, respectively. <\/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 * Creating configuration for the thread for the red LED \n *\/\nstatic LEDconfig_t redledconfig = {\n  .led = LINE_LED_RED,\n  .time = 500,\n  .status = TRUE\n};<\/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 * Creating configuration for the thread for the green LED \n *\/\nstatic LEDconfig_t greenledconfig = {\n  .led = LINE_LED_GREEN,\n  .time = 500,\n  .status = FALSE\n};<\/pre>\n\n\n\n<p>To achieve the counter-phase behavior, we set the initial state of the red LED to <code>TRUE <\/code>and the green LED to <code>FALSE<\/code>. However, this is a personal choice and you can switch the initial states if desired. <\/p>\n\n\n\n<p>As the function <code>palToggleLine<\/code> inverts the logical state of a line, if a LED is initially on, calling the function on its line will turn it off and vice versa.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"5_Two_threads_one_function\">Two threads one function<\/h3>\n\n\n\n<p>At this point, we are ready to define the parametric thread function that both threads will execute.<\/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\/* Blinking Thread Definition                                                *\/\n\/*===========================================================================*\/\n\nstatic THD_FUNCTION(ThreadBlinker, arg) {\n  \n  \/* Using a temporary variable to make our code more readable. *\/\n  LEDconfig_t* mycfg = (LEDconfig_t*)arg;\n  \n  \/* Configuring the line to the initial value. *\/\n  palWriteLine(mycfg-&gt;led, mycfg-&gt;status);\n\n  while (true) {\n    palToggleLine(mycfg-&gt;led);\n    chThdSleepMilliseconds(mycfg-&gt;time);\n  }\n}<\/pre>\n\n\n\n<p>The first parameter (<code>ThreadBlinker<\/code>) refers to the name and the pointer to the thread function. The second parameter (<code>arg<\/code>) represents the argument that will be passed to this function. In this case, <code>arg<\/code> will be one of our two <code>LEDConfig_t<\/code> configurations.<\/p>\n\n\n\n<h3 class=\"wp-block-heading level_2\" id=\"6_Status_LED\">Status LED <\/h3>\n\n\n\n<p>In this demo, having two LEDs blinking in counter-phase was specifically chosen to showcase the functionality of parametric threads. However, when the results of the parametric threads are not immediately apparent, the status LED can be used as a quick way to check if the system is running or the application has crashed. As a good measure, we will add to our main loop a LED blinking at a different speed.<\/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\n  ...\n\n  while (true) {\n    palToggleLine(LINE_PROCESSOR_STATUS);\n    chThdSleepMilliseconds(50);\n  }\n}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading level_1\" id=\"7_Composing_the_puzzle\">Composing the puzzle <\/h2>\n\n\n\n<p>At this point, we can see how the entire <code>main.c<\/code> looks like<\/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    PLAY Embedded demos - Copyright (C) 2014...2023 Elisa Bellacosa\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#include \"ch.h\"\n#include \"hal.h\"\n\n\/**\n * @brief   LED configuration structure.\n *\/\ntypedef struct {\n  \/**\n   * @brief Line associated to LED\n   *\/\n  ioline_t                  led;\n  \/**\n   * @brief Time associated to LED.\n   *\/\n  systime_t                 time;\n  \/**\n   * @brief Line status associated to LED.\n   *\/\n  uint32_t                  status;\n} LEDconfig_t;\n\n\/**\n * @brief   Parametric thread function.\n *\/\nstatic THD_FUNCTION(ThreadBlinker, arg) {\n  \n  \/* Using a temporary variable to make our code more readable. *\/\n  LEDconfig_t* mycfg = (LEDconfig_t*)arg;\n  \n  \/* Configuring the line to the initial value. *\/\n  palWriteLine(mycfg-&gt;led, mycfg-&gt;status);\n\n  while (true) {\n    palToggleLine(mycfg-&gt;led);\n    chThdSleepMilliseconds(mycfg-&gt;time);\n  }\n}\n\n\/*===========================================================================*\/\n\/* Thread 1 related                                                          *\/\n\/*===========================================================================*\/\n\n\/* Thread 1 working area. *\/\nstatic THD_WORKING_AREA(waThread1, 128);\n\n\/* Thread 1 parameters. *\/\nstatic LEDconfig_t redledconfig = {\n  .led = LINE_LED_RED,\n  .time = 500,\n  .status = TRUE\n};\n\n\/*===========================================================================*\/\n\/* Thread 2 related                                                          *\/\n\/*===========================================================================*\/\n\n\/* Thread 2 working area. *\/\nstatic THD_WORKING_AREA(waThread2, 128);\n\n\/* Thread 2 parameters. *\/\nstatic LEDconfig_t greenledconfig = {\n  .led = LINE_LED_GREEN,\n  .time = 500,\n  .status = FALSE\n};\n\n\/*===========================================================================*\/\n\/* Application entry point.                                                  *\/\n\/*===========================================================================*\/\n\nint main(void) {\n\n  \/*\n   * System initializations HAL and RT.\n   *\/\n  halInit();\n  chSysInit();\n\n  \/*\n   * Creates the two threads.\n   *\/\n  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO + 1, ThreadBlinker, &amp;redledconfig);\n  chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO + 1, ThreadBlinker, &amp;greenledconfig);\n\n  \/*\n   * Status LED blinking.\n   *\/\n  while (true) {\n    palToggleLine(LINE_PROCESSOR_STATUS);\n    chThdSleepMilliseconds(50);\n  }\n}<\/pre>\n\n\n\n<p>At the beginning of the file, we define the format of the thread configuration as well as the parametric function. For each thread, we then have to define a dedicated working area and the appropriate configuration<\/p>\n\n\n\n<p class=\"has-text-align-justify\">The <code>main()<\/code> initializes the system as usual and then creates the two threads: note that the two creations use the same function but the specific working area and configuration.<\/p>\n\n\n\n<p class=\"has-text-align-justify\">If we connect the SDP-K1 to our laptop and proceed with the <a href=\"https:\/\/playembedded.org\/flash-run\/\">flash and run<\/a> of our program, we can observe our two LEDs blink in counter-phase while the Processor status LED blinks on its own.<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"624\" style=\"aspect-ratio: 848 \/ 624;\" width=\"848\" autoplay loop muted src=\"https:\/\/playembedded.org\/wp-content\/uploads\/2023\/02\/Leds-blinking.mp4\"><\/video><figcaption class=\"wp-element-caption\">Status LED blinking together with the red and the green LEDs <\/figcaption><\/figure>\n\n\n\n<p class=\"has-text-align-justify\">The synchronism between the LEDs (and therefore between threads) is kept even after long runs. This result demonstrates that we are working with a hard real-time operating system (<strong>RTOS<\/strong>). An RTOS is a type of operating system that is specifically designed to guarantee a deterministic response time to a given set of tasks or inputs, regardless of the other activities running on the system. The RTOS must meet its timing constraints with absolute certainty, regardless of any external factors that may be affecting the system. <\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this article, we will demonstrate how to create multiple threads using parametric functions. This means that while the function executed by each thread is the same, the specific behavior is influenced by passing different parameters each time. To illustrate how parametric threads work, we will blink multiple LEDs in different ways defining a [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":8695,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1260],"tags":[1304,1299],"coauthors":[1282],"class_list":["post-8523","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-examples-and-exercises","tag-chibios-rt","tag-rtos","gold"],"views":2594,"jetpack_featured_media_url":"https:\/\/playembedded.org\/blog\/wp-content\/uploads\/2023\/02\/Parametric-threads-with-ChibiOS-PE-1.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/8523","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=8523"}],"version-history":[{"count":0,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/posts\/8523\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media\/8695"}],"wp:attachment":[{"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/media?parent=8523"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/categories?post=8523"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/tags?post=8523"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/playembedded.org\/blog\/wp-json\/wp\/v2\/coauthors?post=8523"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}