{"id":1238,"date":"2013-09-16T01:00:00","date_gmt":"2013-09-15T23:00:00","guid":{"rendered":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1238"},"modified":"2013-09-30T13:10:53","modified_gmt":"2013-09-30T12:10:53","slug":"chibiosrt","status":"publish","type":"post","link":"https:\/\/www.fussylogic.co.uk\/blog\/?p=1238","title":{"rendered":"ChibiOS\/RT"},"content":{"rendered":"<p><a href=\"http:\/\/chibios.org\/dokuwiki\/doku.php\">ChibiOS<\/a> is an open source RTOS for embedded systems. It\u00e2\u20ac\u2122s comparable with FreeRTOS; but for my money is a nicer project.<\/p>\n<ul>\n<li>Comes with a hardware abstraction layer \u00e2\u20ac\u201c i.e.\u00c2\u00a0device drivers (kind of). That means we target the ChibiOS API rather than a particular platform. A lot of manufacturers supply a device layer specific to their chip; ChibiOS goes a step further \u00e2\u20ac\u201c including a platform-neutral device layer. FreeRTOS has no HAL.<\/li>\n<li>Static memory allocation. FreeRTOS supports dynamic allocation only; ChibiOS supports static and dynamic memory allocation. This can be important if you\u00e2\u20ac\u2122re really memory constrained; and also ensures you don\u00e2\u20ac\u2122t get fragmentation of your heap storage.<\/li>\n<li>I get the feeling there is a better community around ChibiOS; it\u00e2\u20ac\u2122s more inclusive and faster moving. It\u00e2\u20ac\u2122s certainly got less of a corporate feel, concentrating a lot more on the code.<\/li>\n<\/ul>\n<p>Begin then by downloading the ChibiOS source. You can get it from the ChibiOS website, or use the following git mirror.<\/p>\n<pre><code>$ git clone https:\/\/github.com\/ChibiOS-Upstream\/ChibiOS-RT<\/code><\/pre>\n<p>ChibiOS is convenient because it comes with startup code and a build environment that\u00e2\u20ac\u2122s pretty easy to customise. We\u00e2\u20ac\u2122ll begin by building one of the demo applications.<\/p>\n<pre><code>$ cd demos\/ARMCM4-STM32F407-DISCOVERY<\/code><\/pre>\n<p>Now edit the <code>Makefile<\/code> to point at your compiler (I\u00e2\u20ac\u2122d suggest the <a href=\"https:\/\/launchpad.net\/gcc-arm-embedded\/\">ARM-maintained<\/a> gcc). Here\u00e2\u20ac\u2122s my modification:<\/p>\n<pre><code>-TRGT = arm-none-eabi-\n+TRGT = \/opt\/gcc-arm-none-eabi-4_7-2013q2\/bin\/arm-none-eabi-<\/code><\/pre>\n<p>A simple <code>make<\/code> should then create you a binary in <code>build\/ch.bin<\/code>.<\/p>\n<p>Now, we\u00e2\u20ac\u2122ll want to start our own project. Copy the contents of this demo directory to some empty directory outside of the ChibiOS tree (your own projects aren\u00e2\u20ac\u2122t part of ChibiOS so don\u00e2\u20ac\u2122t pollute it with your code). Then edit the <code>Makefile<\/code> again.<\/p>\n<pre><code> # Define project name here\n-PROJECT = ch\n+PROJECT = chibios-test\n \n # Imported source files and paths\n-CHIBIOS = ..\/..\n+CHIBIOS = ..\/..\/..\/YOUR\/PATH\/TO\/ChibiOS\/<\/code><\/pre>\n<p>Before we even start using the multitasking facilities of ChibiOS its HAL let\u00e2\u20ac\u2122s us easily write portable programs. Delete the <code>main.c<\/code> that you copied from the demo and we\u00e2\u20ac\u2122ll start with a clean slate.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"ot\">#include &lt;ch.h&gt;<\/span>\n<span class=\"ot\">#include &lt;hal.h&gt;<\/span>\n\n<span class=\"ot\">#define GPIOD_LED_ORANGE      GPIOD_LED3<\/span>\n\n<span class=\"dt\">int<\/span> main(<span class=\"dt\">void<\/span>)\n{\n    halInit();\n    chSysInit();\n\n    palSetPadMode(GPIOD, GPIOD_LED_ORANGE, PAL_MODE_OUTPUT_PUSHPULL);\n\n    <span class=\"kw\">while<\/span>(<span class=\"dv\">1<\/span>){\n        palSetPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n        palClearPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n    }\n}<\/code><\/pre>\n<p>Note that you will still need the ChibiOS configuration headers, <code>chconf.h<\/code>, <code>halconf.h<\/code>, and <code>mcuconf.h<\/code>. These are pretty self-explanatory and simply enable and disable various ChibiOS components.<\/p>\n<p>Build the binary and then flash it with <em>openocd<\/em> (available in Debian).<\/p>\n<pre><code>openocd \\\n    -f \/usr\/share\/openocd\/scripts\/board\/stm32f4discovery.cfg \\\n    -c &quot;init&quot; \\\n    -c &quot;reset halt&quot; \\\n    -c &quot;sleep 100&quot; \\\n    -c &quot;wait_halt 2&quot; \\\n    -c &quot;echo \\&quot;--- Writing build\/chibios-test.bin\\&quot;&quot; \\\n    -c &quot;flash write_image erase build\/chibios-test.bin 0x08000000&quot; \\\n    -c &quot;sleep 100&quot; \\\n    -c &quot;echo \\&quot;--- Verifying\\&quot;&quot; \\\n    -c &quot;verify_image build\/chibios-test.bin 0x08000000&quot; \\\n    -c &quot;sleep 100&quot; \\\n    -c &quot;echo \\&quot;--- Done\\&quot;&quot; \\\n    -c &quot;resume&quot; \\\n    -c &quot;shutdown&quot;\nOpen On-Chip Debugger 0.7.0 (2013-08-04-10:13)\nLicensed under GNU GPL v2\nFor bug reports, read\n        http:\/\/openocd.sourceforge.net\/doc\/doxygen\/bugs.html\nsrst_only separate srst_nogate srst_open_drain connect_deassert_srst\nInfo : This adapter doesn&#39;t support configurable speed\nInfo : STLINK v2 JTAG v14 API v2 SWIM v0 VID 0x0483 PID 0x3748\nInfo : Target voltage: 2.876056\nInfo : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints\ntarget state: halted\ntarget halted due to debug-request, current mode: Thread \nxPSR: 0x01000000 pc: 0x080001f0 msp: 0x20000400\n--- Writing build\/chibios-test.bin\nauto erase enabled\nInfo : device id = 0x10016413\nInfo : flash size = 1024kbytes\nwrote 16384 bytes from file build\/chibios-test.bin in 1.023979s (15.625 KiB\/s)\n--- Verifying\nverified 7580 bytes in 0.142001s (52.129 KiB\/s)\n--- Done\nshutdown command invoked<\/code><\/pre>\n<p>It might seem large at 7580 bytes for a simple LED flasher, but remember that this is 7580 bytes for ChibiOS too \u00e2\u20ac\u201c which we\u00e2\u20ac\u2122re using very little of. For interest you will find the assembly listing (which includes a lot of debug sections) in <code>build\/lst\/main.lst<\/code>.<\/p>\n<p>It\u00e2\u20ac\u2122s perhaps not clear why the above is so magical. Let\u00e2\u20ac\u2122s look again:<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\">    <span class=\"kw\">while<\/span>(<span class=\"dv\">1<\/span>){\n        palSetPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n        palClearPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n    }<\/code><\/pre>\n<p>Think about this in the context of our normal way of writing embedded software. If we wanted to flash an LED in a larger application, we would have to keep a timer, store a separate state and ensure that we always got back to the flasher code in our main loop for the decision to be made about whether it\u00e2\u20ac\u2122s time to change state. When we\u00e2\u20ac\u2122re using an RTOS, we can write routines without regard (within reason) to what else needs doing. This LED flasher code would be the same whether this is all the program is doing, or if it has ten other things to do.<\/p>\n<p>Let\u00e2\u20ac\u2122s see that facility in action.<\/p>\n<pre class=\"sourceCode C\"><code class=\"sourceCode c\"><span class=\"ot\">#include &lt;ch.h&gt;<\/span>\n<span class=\"ot\">#include &lt;hal.h&gt;<\/span>\n\n<span class=\"ot\">#define UNUSED(x) (void)(x)<\/span>\n\n<span class=\"ot\">#define GPIOD_LED_ORANGE      GPIOD_LED3<\/span>\n<span class=\"ot\">#define GPIOD_LED_GREEN       GPIOD_LED4<\/span>\n<span class=\"ot\">#define GPIOD_LED_BLUE        GPIOD_LED6<\/span>\n\n<span class=\"dt\">static<\/span> WORKING_AREA(waThread1, <span class=\"dv\">128<\/span>);\n<span class=\"dt\">static<\/span> msg_t Thread1(<span class=\"dt\">void<\/span> *arg)\n{\n    UNUSED(arg);\n\n    chRegSetThreadName(<span class=\"st\">&quot;blinker&quot;<\/span>);\n\n    <span class=\"kw\">while<\/span> (TRUE) {\n        palSetPad(GPIOD, GPIOD_LED_BLUE);\n        chThdSleepMilliseconds(<span class=\"dv\">333<\/span>);\n        palClearPad(GPIOD, GPIOD_LED_BLUE);\n        chThdSleepMilliseconds(<span class=\"dv\">333<\/span>);\n    }\n\n    <span class=\"kw\">return<\/span> <span class=\"dv\">0<\/span>;\n}\n\n<span class=\"dt\">int<\/span> main(<span class=\"dt\">void<\/span>)\n{\n    halInit();\n    chSysInit();\n\n    palSetPadMode(GPIOD, GPIOD_LED_ORANGE, PAL_MODE_OUTPUT_PUSHPULL);\n    palSetPadMode(GPIOD, GPIOD_LED_BLUE, PAL_MODE_OUTPUT_PUSHPULL);\n\n    chThdCreateStatic(waThread1, <span class=\"kw\">sizeof<\/span>(waThread1), NORMALPRIO, Thread1, NULL);\n\n    <span class=\"kw\">while<\/span>(<span class=\"dv\">1<\/span>){\n        palSetPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n        palClearPad(GPIOD, GPIOD_LED_ORANGE);\n        chThdSleepMilliseconds(<span class=\"dv\">500<\/span>);\n    }\n}<\/code><\/pre>\n<p>This is exactly as before, but we\u00e2\u20ac\u2122ve added an additional thread on top of the so-called main thread, flashing the blue LED at a slightly different rate. Both flashers are simple, linear code. Have a think about how much infrastructure we would have to implement without ChibiOS just to do this simple task.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>ChibiOS is an open source RTOS for embedded systems. It\u00e2\u20ac\u2122s comparable with FreeRTOS; but for my money is a nicer project. Comes with a hardware abstraction layer \u00e2\u20ac\u201c i.e.\u00c2\u00a0device drivers (kind of). That means we target the ChibiOS API rather than a particular platform. A lot of manufacturers supply a device layer specific to their\u2026 <span class=\"read-more\"><a href=\"https:\/\/www.fussylogic.co.uk\/blog\/?p=1238\">Read More &raquo;<\/a><\/span><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[116,42,114,6],"_links":{"self":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1238"}],"collection":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1238"}],"version-history":[{"count":3,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1238\/revisions"}],"predecessor-version":[{"id":1247,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1238\/revisions\/1247"}],"wp:attachment":[{"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fussylogic.co.uk\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}