{"id":177,"date":"2015-05-08T18:37:24","date_gmt":"2015-05-08T16:37:24","guid":{"rendered":"http:\/\/tronche.com\/blog\/?p=177"},"modified":"2019-01-20T17:08:49","modified_gmt":"2019-01-20T16:08:49","slug":"teensy-3-1-chibios-non-blocking-serial","status":"publish","type":"post","link":"https:\/\/tronche.com\/blog\/2015\/05\/teensy-3-1-chibios-non-blocking-serial\/","title":{"rendered":"Teensy 3.1 + ChibiOs + non-blocking Serial"},"content":{"rendered":"\n<p>Take away: you can use multiple Serial I\/O in Greiman&#8217;s ChibiOs port \nin various tasks without giving it much thought, it will work without \ntasks blocking each other.\n<\/p>\n\n\n\n<p>I was wondering what would happen in using ChibiOs on the Teensy \n3.1 with two threads, say one making the led blink and the other one \nreading on the serial port (the USB one for example). I&#8217;m using Bill \nGreiman&#8217;s ChibiOs port for teensy (<a href=\"https:\/\/github.com\/greiman\/ChibiOS-Arduino\">https:\/\/github.com\/greiman\/ChibiOS-Arduino<\/a>).\n The point is that only the kernel has been ported, not the HAL \n(Hardware Abstraction Layer) part, thus my guess was that a blocking I\/O\n operation would block other tasks, and in particular that it wouldn&#8217;t \nbe feasible to read on multiple serial ports.\n<\/p>\n\n\n\n<p>It turns out this is not the case (for reading multiple serial ports).\n<\/p>\n\n\n\n<p>First, I should have been more clever, since Serial API (the Serial.read()) has a <em>non-blocking<\/em> semantics (it returns -1 if there is nothing to read).\n<\/p>\n\n\n\n<p>Second, by examining the Teensy Serial code, I got that (in HardwareSerial.h):\n<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>int serial_getchar(void) {         \n         uint32_t head, tail;\n         int c;\n\n         head = rx_buffer_head;\n         tail = rx_buffer_tail;\n         if (head == tail) return -1;    \n         if (++tail >= RX_BUFFER_SIZE) tail = 0;\n         c = rx_buffer[tail];\n         rx_buffer_tail = tail;\n         return c; \n} <\/code><\/pre>\n\n\n\n<p>As we can see, there&#8217;s nothing blocking there, we&#8217;re just making some\n in-memory operations, no loop, nothing. But where does the character in\n the buffer come from&nbsp;? \n<\/p>\n\n\n\n<p>The answer is in the uart0_status_isr interrupt routine. I won&#8217;t \ncopy it there, but in short, the ISR is called (by the hardware) when \nthere is something to read in the UART, read it bit by bit and returns. \nThe point is there is no polling, nowhere, and a short interrupt masking\n during the reading of the UART data register.\n<\/p>\n\n\n\n<p>What about writing&nbsp;? First, after all, writing to the UART \ndoesn&#8217;t need to be blocking (if the receiver isn&#8217;t ready, that&#8217;s its \nbusiness). Furthermore, there are generous <strong>yield<\/strong> spreaded through the code, but since I&#8217;m not sure yet how it translates with ChibiOs, I&#8217;ll have to investigate further.\n<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">2015-05-13: Is delay a busy loop&nbsp;?<\/h1>\n\n\n\n<p>However, using a loop with delay in one task blocks the other one, in spite of a yield in the implementation of delay.\n<\/p>\n\n\n\n<p>Actually, if two tasks have the same priority, they don&#8217;t block \neach other. It means however (with ChibiOs), that a task executing delay\n blocks tasks with lower priority (unlike chThreadSleep).\n<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">2015-05-14: At least we know what&#8217;s in yield<\/h1>\n\n\n\n<pre class=\"wp-block-preformatted\">void yield(void) __attribute__ ((weak));\nvoid yield(void)\n{\n        static uint8_t running=0;\n\n        if (running) return; \/\/ TODO: does this need to be atomic?                                  \n\trunning = 1;\n\tif (Serial.available()) serialEvent();\n\tif (Serial1.available()) serialEvent1();\n\tif (Serial2.available()) serialEvent2();\n\tif (Serial3.available()) serialEvent3();\n\trunning = 0;\n};\n\n\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Take away: you can use multiple Serial I\/O in Greiman&#8217;s ChibiOs port in various tasks without giving it much thought, it will work without tasks <a class=\"mh-excerpt-more\" href=\"https:\/\/tronche.com\/blog\/2015\/05\/teensy-3-1-chibios-non-blocking-serial\/\" title=\"Teensy 3.1 + ChibiOs + non-blocking Serial\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[20],"tags":[68,52,91],"class_list":["post-177","post","type-post","status-publish","format-standard","hentry","category-almabraxas","tag-chibios","tag-teensy","tag-uart"],"_links":{"self":[{"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/posts\/177","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/comments?post=177"}],"version-history":[{"count":2,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/posts\/177\/revisions"}],"predecessor-version":[{"id":180,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/posts\/177\/revisions\/180"}],"wp:attachment":[{"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/media?parent=177"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/categories?post=177"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tronche.com\/blog\/wp-json\/wp\/v2\/tags?post=177"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}