{"id":7164,"date":"2021-01-18T07:42:43","date_gmt":"2021-01-18T07:42:43","guid":{"rendered":"https:\/\/www.fambach.net\/?p=7164"},"modified":"2021-01-18T07:46:27","modified_gmt":"2021-01-18T07:46:27","slug":"espressif-idf-tasks","status":"publish","type":"post","link":"https:\/\/www.fambach.net\/en\/espressif-idf-tasks\/","title":{"rendered":"Espressif IDF \u2013 Tasks"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_73 ez-toc-wrap-left counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\">\n<span class=\"ez-toc-title-toggle\"><a href=\"#\" class=\"ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle\" aria-label=\"Toggle Table of Content\"><span class=\"ez-toc-js-icon-con\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewbox=\"0 0 24 24\" version=\"1.2\" baseprofile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/span><\/a><\/span><\/div>\n<nav><ul class='ez-toc-list ez-toc-list-level-1' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Grundsatzliches\" title=\"Grunds\u00e4tzliches\">Grunds\u00e4tzliches<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Ausgang\" title=\"Ausgang\">Ausgang<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Eingang\" title=\"Eingang\">Eingang<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Fazit\" title=\"Conclusion\">Conclusion<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Verwandte_Beitrage\" title=\"Related Posts\">Related Posts<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Quellen\" title=\"Sources\">Sources<\/a><\/li><\/ul><\/nav><\/div>\n\n<p>Ein Task ist eine (wiederkehrende) Aufgabe f\u00fcr den Prozessor. Mehrere Tasks ringen um die Aufmerksamkeit der CPU. Wie diese erstellt werden und welche Datenstrukturen zur Daten\u00fcbermittlung und Synchronisation vorhanden sind, wird in diesem Beitrag kurz umrissen. <\/p>\n\n\n\n<p>Tasks k\u00f6nnen zu einer sehr komplexen Angelegenheit werden, weshalb ich hier nur die Spitze des Eisberges ankratzen kann. Dennoch handelt es sich hierbei, um den bisher l\u00e4ngsten Beitrag der Serie. F\u00fcr die weitere Recherche sei auch auf die <a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html\" target=\"_blank\">Espressif Website &#8211; Kapitel FreeRtos<\/a> verwiesen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Grundsatzliches\"><\/span>Grunds\u00e4tzliches<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Tasks k\u00f6nnen als gekapselte Aufgaben betrachtet werden. In der Espressif IDF k\u00f6nnen je nach Anzahl der Prozessor-Kerne ein oder mehrere Task parallel\/geleichzeitig ausgef\u00fchrt werden. Grunds\u00e4tzlich k\u00f6nnen aber mehrere Tasks gestartet werden, die um den\/die Prozessorkern(e) konkurieren. Immer wenn ein Task den Prozessorkern nicht mehr braucht gibt er ihn frei und der n\u00e4chste Tasks kommt an die Reihe. <\/p>\n\n\n\n<p>Welcher Task als n\u00e4chstes bevorzugt wird h\u00e4ngt grunds\u00e4tzlich mit seiner Priorit\u00e4t zusammen und wie lange er schon wartet. Wie genau die Abarbeitungsreihenfolge ist h\u00e4ngt von der Implementierung des Shedulers ab. Die Tasks in der IDF stammen aus dem FreeRtos hier wacht zus\u00e4tzlich ein Wachhund (Watchdog) dar\u00fcber, dass die Task nicht zu lange brauchen. Weiterhin wird davon ausgegangen das Tasks ewig laufen, sollte ein Task beendet werden muss dieser vorher gel\u00f6scht werden sonst kommt es zu einem Fehler.<\/p>\n\n\n\n<p>Viele der im folgenden beschiebenen Funktionen gibt es mehrfach. Zum einen kann bei der Erstellung bestimmt werden, ob der Speicher dynamisch oder statisch zur Kompilierzeit reserviert werden soll. Die statischen Funktionen enden immer mit static.<\/p>\n\n\n\n<p>Zum Anderen gibt es Funktionen die aus einem Interrupt gerufen werden k\u00f6nnen, diese enden immer mit &#8218;FromISR&#8216;.<\/p>\n\n\n\n<p>Es wird im fogenden meist nur auf die Funktionen mit  dynamischer Speicher Reservierung eingegangen, f\u00fcr weitere Infos sei auch hier auf die IDF Referenz verwiesen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Task Erstellen<\/h2>\n\n\n\n<p>Bibliotheken:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"<\/code><\/pre>\n\n\n\n<p>Erstellt werden Tasks mit dem Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xTaskCreate(\n   &lt;pointer zur Task Funktion, \n   &lt;Task Name&gt;, \n   &lt;Speicher f\u00fcr Task&gt;, \n   &lt;Task parameter&gt;, \n   &lt;Priotit\u00e4t&gt;,\n   &lt;Referenz f\u00fcr Handle&gt;);<\/code><\/pre>\n\n\n\n<p>Gut Programmierpraxis ist es einen Task immer<strong> nur<\/strong> so lange laufen zu lassen wie wirklich n\u00f6tig ist. Muss ein Task auf einen Wert oder Aktion warten sollte er sich schlafen legen und den Prozessor an einen anderen Task weiter geben. Das Schlafen kann mit der folgenden Funktion eingeleitet werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void vTaskDelay(const TickType_t xTicksToDelay);<\/code><\/pre>\n\n\n\n<p>Mit diesem Befehl wartet der Task eine bestimmte Zeit bevor er wieder bereit zur Auf\u00fchrung ist. Generell schlafen legen kann man den Task mit dem folgenden Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ speziellen Task anhalten\nvoid vTaskSuspend(&lt;TaskHandle&gt;);\n\/\/ Task aus interupt routine anhalten\nBaseType_t xTaskResumeFromISR(&lt;TaskHandle&gt;)\n\/\/ eigenen Task anhalten\nvTaskSuspend(NULL);<\/code><\/pre>\n\n\n\n<p>In diesem Fall wartet der Task bis er wieder von aussen aktiviert wird. Dies geschieht mit dem folgenden Befehl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ normale Freigabe\nvoid xTaskResume(&lt;TaskHandle&gt;);\n\/\/ aus Interrupt Routine\nvoid xTaskResumeFromISR(&lt;TaskHandle&gt;);<\/code><\/pre>\n\n\n\n<p>Freetos Task werden normal nicht beendet, wenn sie wie im Beispiel dennoch enden, wird ein Fehler geworfen. Um dies zu verhindern muss der Task vor Ende gel\u00f6scht werden. Dies geschieht mit der Anweisung:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vTaskDelete( xHandles&#91;task_index] );<\/code><\/pre>\n\n\n\n<p>Zu Beachten ist, wenn wie im Beispiel das xTaskDelete in seiner eigenen Task-Funktion aufgerufen wird, werden alle Anweisung die auf diesen Befehl folgen nicht mehr ausgef\u00fchrt, weil der Task dann schon gel\u00f6scht ist.<\/p>\n\n\n\n<p>Das folgende Beispiel erstellt mehrere Task, die unterschiedlich lange laufen und wenn sie aktiv sind eine Ausgabe erzeugen:<\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_Tasks\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h2 class=\"wp-block-heading\">Synchronisation<\/h2>\n\n\n\n<p>Freetos bietet Datenstrukturen zur Synchronisation und \u00dcbergabe der Daten von einem Task zum anderen. Folgende Hilfmittel konnte ich finden:<\/p>\n\n\n\n<ul><li><strong>Queues<\/strong> - Dies ist eine Liste. Hier wartet der lesende Task bis ein Eintrag in der Liste vorhanden ist.<\/li><li><strong>Semaphoren<\/strong> - Werden genutzt um Task mit einander zu Synchronisieren oder gemeinsam genutze Resourcen  vor Datennfehlern zu sch\u00fctzen.<\/li><li><strong>Event Gruppen<\/strong> - Werden zur Synchronisation von Tasks verwendet, sie warte auf das setzen definierter Bits durch Tasks. Warten kann die Grupe auf ein oder alle Bits. Sind die Bits gesetzt, wird das Warten der Gruppe beendet. <\/li><li><strong>Stream Buffer<\/strong> - Daten\u00fcbertragung per Stream. Der lesende Task wartet so lange bis im Stream Daten vorhanden sind.<\/li><li><strong>Message Buffer<\/strong> - Basiert auf dem Stream Buffer. Ein Task kann Nachrichten in den Buffer legen und ein anderer kann auf sie warten.<\/li><li><strong>Hooks<\/strong> - Werden verwendet um Task auszuf\u00fchren wenn der Prozessor gerade nicht zu tun hat.<\/li><li><strong>Ring Buffer<\/strong> - Ein Rinbuffer ist eine Datenstruktur mit einem fixen Speicher. Wird das Ende des Speichers erreicht wird versucht im vorderen Bereich wieder Speicher zu finden. Da der Rinbuffer etwas Komplexer ist habe ich diesen erstmal aussen vor gelassen.<\/li><li><strong>Timer<\/strong> - Timer starten Tasks einmalig oder periodisch, f\u00fcr Timer habe ich einen eigenen <a href=\"https:\/\/www.fambach.net\/en\/espressif-idf-timer\/\" data-type=\"post\" data-id=\"7139\">Beitrag<\/a> erstellt. <\/li><\/ul>\n\n\n\n<p><strong>Werden diese Datenstrukturen aus Interruptroutinen heraus benutzt, m\u00fcssen die gleichnamigen ISR Funktionen zum Aufruf verwendet werden. <\/strong><\/p>\n\n\n\n<p><strong>Es wird bei den Datenstrukturen, ausser bei den Semaphoren immer davon ausgegangen dass es nur einen Sende-Task und einen Empf\u00e4nger-Task gib. Wollen beispielsweise mehere Ressourcen senden, muss die Sendefunktion als kritischer Breich (z.B. mit Semaphor) gesch\u00fctzt werden.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Queues<\/h3>\n\n\n\n<p>Queues werden verwendet um Daten auszutauschen. Der sendende Task \u00fcbergibt Daten an die Queue und kann danach weiter laufen. Der konsumierende Task holt sich die Daten wenn er bereit ist.<\/p>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"<\/code><\/pre>\n\n\n\n<p>Queue erstellen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>QueueHandle_t xQueue; \nxQueue = xQueueCreate( &lt;L\u00e4nge Queue&gt;, &lt;gr\u00f6\u00dfe der Fehler&gt;);\nif( xQueue == 0 )\n{\n\/\/ Fehler Erkennung\n  ESP_LOGE(TAG,\"Error during queue creation\");\n}<\/code><\/pre>\n\n\n\n<p>Daten senden:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if(!xQueueSendToBack(&lt;queue&gt;, (void*)&amp;&lt;wert&gt;, &lt;timeout&gt;)) {\n   \/\/ queue voll\n   ESP_LOGW(TAG,\"q - Queue Full\");\n}<\/code><\/pre>\n\n\n\n<p>Daten emfangen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if( ! xQueueReceive( &lt;queu&gt;, &lt;value&gt;, &lt;timeout&gt;) ){\n  ESP_LOGW(TAG,\"q - Queue empty!\");\n}<\/code><\/pre>\n\n\n\n<p>Das Beispiel unten arbeitet mit zwei Tasks. Einer f\u00fcllt die Queue der andere liest die Werte aus. Dadurch, dass der Lese-Task am Anfang langsamer als der Schreibe-Task ist, wird die Queue gef\u00fcllt, bis sie voll ist und keinen Wert mehr aufnehmen kann. Durch die folgende Beschleunigung des Lese-Tasks, wird die Queue k\u00fcrzer bis sie leer ist und der Lese-Task auf den schreiben Task warten muss.<\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASKS_QUEUES\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Semaphoren<\/h3>\n\n\n\n<p>Semaphoren und Muteces dienen dazu Bereiche zu sichern und Threads zu synchronisieren. Ich beschreibe hier die Handhabung mit Hilfe des bin\u00e4ren Semaphors. Muteces und recursive Semaphore werden analog erstellt habe aber noch zus\u00e4tzliche Funktionalit\u00e4ten. <\/p>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/semphr.h\"<\/code><\/pre>\n\n\n\n<p>Semaphor erstellen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SemaphoreHandle_t xSemaphore = NULL; \nxSemaphore = xSemaphoreCreateBinary();\nif( xSemaphore == NULL ){ \n   \/\/ Fehler\n}<\/code><\/pre>\n\n\n\n<p>Vor der ersten Nutzung muss der Semaphor einmal Freigegeben werden. <\/p>\n\n\n\n<p>Semaphor holen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>if( xSemaphoreTake( &lt;Semaphor Handle&gt;, timeout) == pdTRUE )\n {\n    \/\/hat geklapp ...\n    xSemaphoreGive( &lt;Semaphor Handle&gt; );\n} else {\n    \/\/ hat nicht geklappt\n}<\/code><\/pre>\n\n\n\n<p>Freigeben des Semaphor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xSemaphoreGive( &lt;Semaphor Handle&gt;);\n<\/code><\/pre>\n\n\n\n<p>Das Bespiel unten erstellt 5 Tasks. Alle m\u00f6chten eine Variable hochz\u00e4hlen. Damit es zu keinen Datenfehlern kommt ist der kritische Bereiche (hochz\u00e4hlen) mit einem Semaphor gesichert. Innerhalb dieses Bereiches wird den anderen Tasks kurz der Prozessor \u00fcbergeben, so dass sie versuchen k\u00f6nnen den Semaphor zu belgen. Es wird hier explizit der Wert der Variablen erst Kopiert, dann den anderen Prozessen die Gelegenheit zur \u00c4nderung gegeben und dann erst der ge\u00e4nderte Wert zur\u00fcck geschieben.  Dies ist keine gute Praxis, hilft aber dem Beispiel ;). Ihr k\u00f6nnt den Semaphor heraus nehmen indem ihr das u.s. define ausdokumentiert. Die Tasks verhalten sich nun anders ;).<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ (de)activat this to dis-\/en-able the semaphores\n#define enable_semaphore<\/code><\/pre>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASK_SEMAPHOR\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<p>Zu den rekursiven Mutece sei noch gesagt, diese k\u00f6nnen immer wieder von Besitzer-Task belegt werden. Die Anzahl der Belegungen wird mit gez\u00e4hlt und muss sich auch in der Anzahl der Freigaben wiederspiegeln. Diese k\u00f6nnen beispielsweise f\u00fcr Recursionen verwendet werden, bei denen die gleiche Funktion immer wieder, indem sie sich selbst aufruft, auf die selben Daten zugreifen muss.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Event Groups<\/h3>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/event_groups.h\"<\/code><\/pre>\n\n\n\n<p>Bit Setzen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>EventBits_t xEventGroupSetBits(\n                  &lt;Eventgruppen Handle&gt;,\n                  &lt;Bit welches gesetzt werden soll&gt;\n);<\/code><\/pre>\n\n\n\n<p>Bei der Wiederverwendung einer bestehenden Gruppe m\u00fcssen die Bits zur\u00fcckgesetzt werden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>EventBits_t xEventGroupClearBits(\n                   &lt;Gruppen Handle&gt;, \n                   &lt;Bits zum R\u00fccksetzten&gt;\n);\n<\/code><\/pre>\n\n\n\n<p>Warte gesetzten Bits, dies geschieht mit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xEventGroupWaitBits(\n                    &lt;Gruppen Handle&gt;, \n                    &lt;BIT_0 | BIT_1| ... | BIT_n&gt;,  \n                    &lt;Bit L\u00f6schen vor R\u00fcckgabe&gt;,\n                    &lt;Ein- od. Alle Bits&gt;,\n                    &lt;Wie lange soll auf die Bits gewartet werden&gt;\n ); \n\/\/ Auswertung \nif( xEventGroup == NULL )\n {\n \/\/ EVG konnte nicht erstellt werden\n    ESP_LOGE(TAG,\"Event groupe not created\");\n} else if(  (uxBits &amp; ( BIT_0 | BIT_1| ... | BIT_n) ) == ( BIT_0 | BIT_1| BIT_2| ... | BIT_n ) )\n {\n \/\/ alle bits wurden gesetzt\n        ESP_LOGI(TAG,\"Program finshed successfull\");\n} else {\n \/\/ nicht alle Bits wurden gesetzt, timeout\n       ESP_LOGW(TAG,\"Timeout\");\n}<\/code><\/pre>\n\n\n\n<p>Hier ein komplettes Beispiel mit mehreren Tasks. Der Haupttask wartet darauf, dass alle Bit gesetzt werden. Sind alle vorhanden arbeitet der Haupttask weiter. <\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASKS_EVENT_GROUPS\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Stream Buffer<\/h3>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/stream_buffer.h\"<\/code><\/pre>\n\n\n\n<p>Erstellen:<\/p>\n\n\n\n<p>Triggerlevel und MaxAnzBytes sind beide vom Typ const size_t. Ersteres gibt an wie gro\u00df der Bufferstream ist. Zweiteres beschreibt ab wieviel Bytes der Empf\u00e4nger aus seiner Wartehaltung erl\u00f6st wird.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xStreamBufferCreate(&lt;MaxAnzBytes&gt;, &lt;TriggerLevel&gt;)<\/code><\/pre>\n\n\n\n<p>Funktion zum Senden:<\/p>\n\n\n\n<p>Die Funktion nimmt einen Streambuffer und die zu sendenden Daten auf. Der R\u00fcckgabewert liefert die Anzahl der gesendeten Daten zur\u00fcck.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>size_t xStreamBufferSend(\n           &lt;StreamBuffer&gt;, \n           &lt;SendeDaten&gt;, \n           &lt;L\u00e4ngeDerSendeDaten&gt;, \n           &lt;Timeout&gt;)<\/code><\/pre>\n\n\n\n<p>Empfangen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>size_t  xStreamBufferReceive( \n             &lt;Stream Buffer&gt;,\n             ( void * )&amp;&lt;Buffer f\u00fcr Empfangsdaten&gt;,\n             &lt;G\u00f6\u00dfe Emfpangsbuffer&gt;,\n             &lt;Timeout&gt; );\n<\/code><\/pre>\n\n\n\n<p>Beispiel Programm<\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASKS_STREAM_BUFFER\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Message Buffer<\/h3>\n\n\n\n<p>Der Messagebuffer baut auf dem Streambuffer auf. Zus\u00e4tzlich k\u00f6nen die Daten in Nachrichten gekapselt werden. Eine Nachricht wird durch ihre L\u00e4nge definiert. Vor Empfang einer Nachricht kann die L\u00e4nger vom Puffer erfragt werden.<\/p>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/message_buffer.h\"<\/code><\/pre>\n\n\n\n<p>Erstellen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>MessageBufferHandle_t xMessageBufferCreate( \n              &lt;size_t GreoesseInBytes&gt; \n);<\/code><\/pre>\n\n\n\n<p>Schreiben:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>size_t xMessageBufferSend( \n             &lt;BufferHandle&gt;,\n             ( void * ) &lt;Nachricht&gt;, \n             &lt;laengeDerNachricht&gt;, \n             &lt;TimeOut&gt;\n);<\/code><\/pre>\n\n\n\n<p>Lesen einer Nachricht:<\/p>\n\n\n\n<p>Vorab die L\u00e4nge der n\u00e4chsten Nachricht erfragen:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>size_t xMessageBufferNextLengthBytes(&lt;BufferHandle&gt;);<\/code><\/pre>\n\n\n\n<p>F\u00fcr den eigentlichen Empfang wird die folgende Funktion verwendet<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>size_t xStreamBufferReceive( \n               &lt;BufferHandle&gt;,\n               ( void * ) &lt;EmpfangsBuffer&gt;,\n               &lt;LaengeDerNachricht&gt;,\n\t       &lt;TimeOut&gt;\n);<\/code><\/pre>\n\n\n\n<p>So sieht der Gesamtcode aus. Dieser unterscheidet sich nur geringf\u00fcgig vom Code des StreamBuffers.<\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASKS_MESSAGE_BUFFER\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Hooks<\/h3>\n\n\n\n<p>Es gibt Idle und Tick Hooks. Idle Hooks werden ausgel\u00f6st wenn die CPU im leerlauf ist. Tickhooks werden \u00fcber den Tickinterrupt ausgel\u00f6st. Zweiteres soll Zeitlich nicht sehr zuverl\u00e4ssig sein. F\u00fcr zeitliche Abfolgen sollten eher Timer oder PWM Signale verwendet werden.<\/p>\n\n\n\n<p>Weiterhin gibt es die standard Hooks des FreeRtos und eigene Varianten der IDF.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">FreeRtos Implementierung<\/h4>\n\n\n\n<ul><li>Zur Nutzung <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/kconfig.html#config-freertos-legacy-hooks\">CONFIG_FREERTOS_LEGACY_HOOKS<\/a>&nbsp;aktivieren<\/li><li>Es kann nur einen Idle und eine Tick Hook geben<\/li><li>FreeRtos Implementierung ist auf single core ausgelegt.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">IDF Implementierung<\/h4>\n\n\n\n<ul><li>Es k\u00f6nnen mehrer Hooks\/Ticks registriert werden.<\/li><li>Ein Hooks\/Ticks mus seiner CPU zugewiesen werden<\/li><li>Die registrierten Hooks\/Ticks werden routierend ausgef\u00fchrt.<\/li><\/ul>\n\n\n\n<p><strong><span class=\"has-inline-color has-vivid-red-color\">Es d\u00fcrfen niemals blockierende Codestellen in Hooks und Ticks verwendet werden. Diese m\u00fcssen immer komplett durhlaufen werden und sollten m\u00f6glichst kurz sein, da sie sonst andere Tasks behindern k\u00f6nnten.<\/span><\/strong><\/p>\n\n\n\n<p><strong><span class=\"has-inline-color has-vivid-red-color\">In Ticks d\u00fcrfen zus\u00e4tzlich keine API Funktionionen ohne \"FromIsr\" verwendet werden. LogAusgaben sind ebenfalls nicht m\u00f6glich.<\/span><\/strong><\/p>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"esp_freertos_hooks.h\"<\/code><\/pre>\n\n\n\n<p>Idle Hook erstellen<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>esp_err_t esp_register_freertos_idle_hook_for_cpu(\n    &lt;Funktion f\u00fcr Callback&gt;, \n    &lt;CPU ID&gt;\n)\n\/\/ oder \nesp_err_t esp_register_freertos_idle_hook_for_cpu(\n    &lt;Funktion f\u00fcr Callback&gt;\n)\n \n\/\/ Funktionsprototyp\nstatic bool hook1(void)\n{}\n<\/code><\/pre>\n\n\n\n<p>Tick  erstellen<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>esp_err_t esp_register_freertos_tick_hook(\n     &lt;tickFunctionName&gt;\n     &lt;CPU ID&gt;\n);\n\n\/\/ oder \nesp_err_t esp_register_freertos_tick_hook(\n     &lt;tickFunctionName&gt;\n);\n\n\/\/ Funktionsprototyp\nstatic void tick2(void)\n{}\n<\/code><\/pre>\n\n\n\n<p>Fehler<\/p>\n\n\n\n<ul><li>ESP_OK: Hat geklappt<\/li><li>ESP_ERR_NO_MEM: Kein Speicher f\u00fcr den Prozessorkern um einen Hook zu registrieren<\/li><li>ESP_ERR_INVALID_ARG: Ung\u00fcltige CPU<\/li><\/ul>\n\n\n\n<p>CPU ID abfragen<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ core des aktuellen Tasks\nconst uint32_t core_id = xPortGetCoreID(); \n\n\/\/ bei zwei Kernen den anderen bekommen \nconst uint32_t core_id = !xPortGetCoreID(); <\/code><\/pre>\n\n\n\n<p>Hier das Beispielprogramm.<\/p>\n\n\n\n<script>\nvar project = \"sfambach\/espressif-idf\/tree\/master\/L6_TASKS_HOOKS\";\nvar file = \"\/main\/main.c\";\nvar test = project + file;\nvar startAt = 16;\nvar endAt = 0;\n\ndocument.write('<a href=\"https:\/\/github.com\/'+project+'\" target=\"_blank\">Link zu Git<\/a>');\ndocument.write('<div><a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/a><\/div>');\n\ndocument.write('<div style=\"font-size:1vw\">');\ndocument.write('<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/div>');\n<\/script>\n\n\n\n<h3 class=\"wp-block-heading\">Ringbuffer<\/h3>\n\n\n\n<p>Der Ringbuffer der IDF sind eine \"interessante\" Sache. Ich spare sie mir an dieser Stelle mal auf f\u00fcr einen anderen Zeitpunkt auf, andem ich sie wirklich brauche ;).<\/p>\n\n\n\n<p>Bibliothek:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Conclusion<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Jede Aktion in einen eigenen Task zu verpacken bedarf einiger \u00dcbung und Planung. Um so wichtiger ist es die richtigen Bibliotheksfunktionen zur Verf\u00fcgung zu habe. Ob diese Funktionalit\u00e4ten ausreichend sind, muss sich in der Praxis zeigen. Grunds\u00e4tzlich scheint aber alle was man brauch zur Verf\u00fcgung zu stehen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Verwandte_Beitrage\"><\/span>Related Posts<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><a href=\"https:\/\/www.fambach.net\/en\/?p=6943\">Hauptbeitrag<\/a><\/p>\n\n\n<div class=\"display-posts-listing\">\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-projekt-erstellen\/\">Espressif IDF \u2013 Create Project<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-konsolenausgabe\/\">Espressif IDF \u2013 Console Output<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-fehlerbehandlung\/\">Espressif IDF \u2013 Error Handling<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-log-nachrichten\/\">Espressif IDF \u2013 Log Messages<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-timer\/\">Espressif IDF \u2013 Timer<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-menuconfig\/\">Espressif IDF \u2013 Menuconfig<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks\/\">Espressif IDF \u2013 Tasks<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/\">Espressif IDF \u2013 GPIOs<\/a><\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Quellen\"><\/span>Sources<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">IDF - Programming Guide<\/a><\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html#\" target=\"_blank\">IDF - FreeRtos<\/a><\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html#task-api\" target=\"_blank\">IDF - FreeRtos Tak Api<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos_additions.html#hooks\" target=\"_blank\" rel=\"noreferrer noopener\">IDF - Hooks <\/a><\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/espressif\/esp-idf\/blob\/master\/examples\/system\/task_watchdog\/main\/task_watchdog_example_main.c\" target=\"_blank\">IDF Beispiel - Task Watchdog (GitHub)<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.esp32.com\/viewtopic.php?t=6157\" target=\"_blank\" rel=\"noreferrer noopener\">Infos zu Ticks und Hooks im Espressif Forum<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Ein Task ist eine (wiederkehrende) Aufgabe f\u00fcr den Prozessor. Mehrere Tasks ringen um die Aufmerksamkeit der CPU. Wie diese erstellt werden und welche Datenstrukturen zur Daten\u00fcbermittlung und Synchronisation vorhanden sind, wird in diesem Beitrag kurz umrissen. Tasks k\u00f6nnen zu einer sehr komplexen Angelegenheit werden, weshalb ich hier nur die Spitze des Eisberges ankratzen kann. Dennoch &#8230;<\/p>\n<a href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/\" class=\"read-more-link\">Continue reading <span class=\"screen-reader-text\">\"Espressif IDF &#8211; GPIOs\"<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a>","protected":false},"author":1,"featured_media":7259,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"no","_lmt_disable":"no","footnotes":""},"categories":[184,188,472,473,496],"tags":[465,474,498,492,476,493,491],"modified_by":"sfambach","_links":{"self":[{"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164"}],"collection":[{"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/comments?post=7164"}],"version-history":[{"count":72,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164\/revisions"}],"predecessor-version":[{"id":7262,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164\/revisions\/7262"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/media\/7259"}],"wp:attachment":[{"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/media?parent=7164"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/categories?post=7164"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/tags?post=7164"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}