{"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_85 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\" >Grunds&auml;tzliches<\/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\" >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\" >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\" >Fazit<\/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\" >Verwandte Beitr&auml;ge<\/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\" >Quellen<\/a><\/li><\/ul><\/nav><\/div>\n\n<p class=\"wp-block-paragraph\">Ein Task ist eine (wiederkehrende) Aufgabe f&uuml;r den Prozessor. Mehrere Tasks ringen um die Aufmerksamkeit der CPU. Wie diese erstellt werden und welche Datenstrukturen zur Daten&uuml;bermittlung und Synchronisation vorhanden sind, wird in diesem Beitrag kurz umrissen. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Tasks k&ouml;nnen 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&auml;ngsten Beitrag der Serie. F&uuml;r 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&auml;tzliches<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tasks k&ouml;nnen als gekapselte Aufgaben betrachtet werden. In der Espressif IDF k&ouml;nnen je nach Anzahl der Prozessor-Kerne ein oder mehrere Task parallel\/geleichzeitig ausgef&uuml;hrt werden. Grunds&auml;tzlich k&ouml;nnen 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&auml;chste Tasks kommt an die Reihe. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Welcher Task als n&auml;chstes bevorzugt wird h&auml;ngt grunds&auml;tzlich mit seiner Priorit&auml;t zusammen und wie lange er schon wartet. Wie genau die Abarbeitungsreihenfolge ist h&auml;ngt von der Implementierung des Shedulers ab. Die Tasks in der IDF stammen aus dem FreeRtos hier wacht zus&auml;tzlich ein Wachhund (Watchdog) dar&uuml;ber, dass die Task nicht zu lange brauchen. Weiterhin wird davon ausgegangen das Tasks ewig laufen, sollte ein Task beendet werden muss dieser vorher gel&ouml;scht werden sonst kommt es zu einem Fehler.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Zum Anderen gibt es Funktionen die aus einem Interrupt gerufen werden k&ouml;nnen, diese enden immer mit &#8218;FromISR&#8216;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es wird im fogenden meist nur auf die Funktionen mit  dynamischer Speicher Reservierung eingegangen, f&uuml;r 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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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&uuml;r Task&gt;, \n   &lt;Task parameter&gt;, \n   &lt;Priotit&auml;t&gt;,\n   &lt;Referenz f&uuml;r Handle&gt;);<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Gut Programmierpraxis ist es einen Task immer<strong> nur<\/strong> so lange laufen zu lassen wie wirklich n&ouml;tig 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 class=\"wp-block-paragraph\">Mit diesem Befehl wartet der Task eine bestimmte Zeit bevor er wieder bereit zur Auf&uuml;hrung 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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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&ouml;scht werden. Dies geschieht mit der Anweisung:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vTaskDelete( xHandles[task_index] );<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">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&uuml;hrt, weil der Task dann schon gel&ouml;scht ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit<\/script><p>&#8218;);\n\ndocument.write(&#8218;<\/p><div style=\"font-size:1vw\">&#8218;);\ndocument.write(&#8218;<script src=\"https:\\\/\\\/gist-it.appspot.com\\\/github.com\\\/'+test+'\\?slice='+startAt+':'+endAt+'\"><\\\/script>');\ndocument.write('<\/script><p>&#8218;);\n\n\n\n\n<\/p><h2 class=\"wp-block-heading\">Synchronisation<\/h2><p class=\"wp-block-paragraph\">Freetos bietet Datenstrukturen zur Synchronisation und &Uuml;bergabe der Daten von einem Task zum anderen. Folgende Hilfmittel konnte ich finden:<\/p><ul class=\"wp-block-list\"><li><strong>Queues<\/strong> &#8211; Dies ist eine Liste. Hier wartet der lesende Task bis ein Eintrag in der Liste vorhanden ist.<\/li><li><strong>Semaphoren<\/strong> &#8211; Werden genutzt um Task mit einander zu Synchronisieren oder gemeinsam genutze Resourcen  vor Datennfehlern zu sch&uuml;tzen.<\/li><li><strong>Event Gruppen<\/strong> &#8211; 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> &#8211; Daten&uuml;bertragung per Stream. Der lesende Task wartet so lange bis im Stream Daten vorhanden sind.<\/li><li><strong>Message Buffer<\/strong> &#8211; 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> &#8211; Werden verwendet um Task auszuf&uuml;hren wenn der Prozessor gerade nicht zu tun hat.<\/li><li><strong>Ring Buffer<\/strong> &#8211; 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> &#8211; Timer starten Tasks einmalig oder periodisch, f&uuml;r Timer habe ich einen eigenen <a href=\"https:\/\/www.fambach.net\/espressif-idf-timer\/\" data-type=\"post\" data-id=\"7139\">Beitrag<\/a> erstellt. <\/li><\/ul><p class=\"wp-block-paragraph\"><strong>Werden diese Datenstrukturen aus Interruptroutinen heraus benutzt, m&uuml;ssen die gleichnamigen ISR Funktionen zum Aufruf verwendet werden. <\/strong><\/p><p class=\"wp-block-paragraph\"><strong>Es wird bei den Datenstrukturen, ausser bei den Semaphoren immer davon ausgegangen dass es nur einen Sende-Task und einen Empf&auml;nger-Task gib. Wollen beispielsweise mehere Ressourcen senden, muss die Sendefunktion als kritischer Breich (z.B. mit Semaphor) gesch&uuml;tzt werden.<\/strong><\/p><h3 class=\"wp-block-heading\">Queues<\/h3><p class=\"wp-block-paragraph\">Queues werden verwendet um Daten auszutauschen. Der sendende Task &uuml;bergibt Daten an die Queue und kann danach weiter laufen. Der konsumierende Task holt sich die Daten wenn er bereit ist.<\/p><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Queue erstellen:<\/p><pre class=\"wp-block-code\"><code>QueueHandle_t xQueue; \nxQueue = xQueueCreate( &lt;L&auml;nge Queue&gt;, &lt;gr&ouml;&szlig;e der Fehler&gt;);\nif( xQueue == 0 )\n{\n\/\/ Fehler Erkennung\n  ESP_LOGE(TAG,\"Error during queue creation\");\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Daten senden:<\/p><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><p class=\"wp-block-paragraph\">Daten emfangen:<\/p><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><p class=\"wp-block-paragraph\">Das Beispiel unten arbeitet mit zwei Tasks. Einer f&uuml;llt 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&uuml;llt, bis sie voll ist und keinen Wert mehr aufnehmen kann. Durch die folgende Beschleunigung des Lese-Tasks, wird die Queue k&uuml;rzer bis sie leer ist und der Lese-Task auf den schreiben Task warten muss.<\/p><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><h3 class=\"wp-block-heading\">Semaphoren<\/h3><p class=\"wp-block-paragraph\">Semaphoren und Muteces dienen dazu Bereiche zu sichern und Threads zu synchronisieren. Ich beschreibe hier die Handhabung mit Hilfe des bin&auml;ren Semaphors. Muteces und recursive Semaphore werden analog erstellt habe aber noch zus&auml;tzliche Funktionalit&auml;ten. <\/p><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/semphr.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Semaphor erstellen:<\/p><pre class=\"wp-block-code\"><code>SemaphoreHandle_t xSemaphore = NULL; \nxSemaphore = xSemaphoreCreateBinary();\nif( xSemaphore == NULL ){ \n   \/\/ Fehler\n}<\/code><\/pre><p class=\"wp-block-paragraph\">Vor der ersten Nutzung muss der Semaphor einmal Freigegeben werden. <\/p><p class=\"wp-block-paragraph\">Semaphor holen:<\/p><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><p class=\"wp-block-paragraph\">Freigeben des Semaphor:<\/p><pre class=\"wp-block-code\"><code>xSemaphoreGive( &lt;Semaphor Handle&gt;);\n<\/code><\/pre><p class=\"wp-block-paragraph\">Das Bespiel unten erstellt 5 Tasks. Alle m&ouml;chten eine Variable hochz&auml;hlen. Damit es zu keinen Datenfehlern kommt ist der kritische Bereiche (hochz&auml;hlen) mit einem Semaphor gesichert. Innerhalb dieses Bereiches wird den anderen Tasks kurz der Prozessor &uuml;bergeben, so dass sie versuchen k&ouml;nnen den Semaphor zu belgen. Es wird hier explizit der Wert der Variablen erst Kopiert, dann den anderen Prozessen die Gelegenheit zur &Auml;nderung gegeben und dann erst der ge&auml;nderte Wert zur&uuml;ck geschieben.  Dies ist keine gute Praxis, hilft aber dem Beispiel ;). Ihr k&ouml;nnt den Semaphor heraus nehmen indem ihr das u.s. define ausdokumentiert. Die Tasks verhalten sich nun anders ;).<\/p><pre class=\"wp-block-code\"><code>\/\/ (de)activat this to dis-\/en-able the semaphores\n#define enable_semaphore<\/code><\/pre><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><p class=\"wp-block-paragraph\">Zu den rekursiven Mutece sei noch gesagt, diese k&ouml;nnen immer wieder von Besitzer-Task belegt werden. Die Anzahl der Belegungen wird mit gez&auml;hlt und muss sich auch in der Anzahl der Freigaben wiederspiegeln. Diese k&ouml;nnen beispielsweise f&uuml;r Recursionen verwendet werden, bei denen die gleiche Funktion immer wieder, indem sie sich selbst aufruft, auf die selben Daten zugreifen muss.<\/p><h3 class=\"wp-block-heading\">Event Groups<\/h3><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/event_groups.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Bit Setzen:<\/p><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><p class=\"wp-block-paragraph\">Bei der Wiederverwendung einer bestehenden Gruppe m&uuml;ssen die Bits zur&uuml;ckgesetzt werden.<\/p><pre class=\"wp-block-code\"><code>EventBits_t xEventGroupClearBits(\n                   &lt;Gruppen Handle&gt;, \n                   &lt;Bits zum R&uuml;cksetzten&gt;\n);\n<\/code><\/pre><p class=\"wp-block-paragraph\">Warte gesetzten Bits, dies geschieht mit:<\/p><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&ouml;schen vor R&uuml;ckgabe&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><p class=\"wp-block-paragraph\">Hier ein komplettes Beispiel mit mehreren Tasks. Der Haupttask wartet darauf, dass alle Bit gesetzt werden. Sind alle vorhanden arbeitet der Haupttask weiter. <\/p><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><h3 class=\"wp-block-heading\">Stream Buffer<\/h3><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/stream_buffer.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Erstellen:<\/p><p class=\"wp-block-paragraph\">Triggerlevel und MaxAnzBytes sind beide vom Typ const size_t. Ersteres gibt an wie gro&szlig; der Bufferstream ist. Zweiteres beschreibt ab wieviel Bytes der Empf&auml;nger aus seiner Wartehaltung erl&ouml;st wird.<\/p><pre class=\"wp-block-code\"><code>xStreamBufferCreate(&lt;MaxAnzBytes&gt;, &lt;TriggerLevel&gt;)<\/code><\/pre><p class=\"wp-block-paragraph\">Funktion zum Senden:<\/p><p class=\"wp-block-paragraph\">Die Funktion nimmt einen Streambuffer und die zu sendenden Daten auf. Der R&uuml;ckgabewert liefert die Anzahl der gesendeten Daten zur&uuml;ck.<\/p><pre class=\"wp-block-code\"><code>size_t xStreamBufferSend(\n           &lt;StreamBuffer&gt;, \n           &lt;SendeDaten&gt;, \n           &lt;L&auml;ngeDerSendeDaten&gt;, \n           &lt;Timeout&gt;)<\/code><\/pre><p class=\"wp-block-paragraph\">Empfangen:<\/p><pre class=\"wp-block-code\"><code>size_t  xStreamBufferReceive( \n             &lt;Stream Buffer&gt;,\n             ( void * )&amp;&lt;Buffer f&uuml;r Empfangsdaten&gt;,\n             &lt;G&ouml;&szlig;e Emfpangsbuffer&gt;,\n             &lt;Timeout&gt; );\n<\/code><\/pre><p class=\"wp-block-paragraph\">Beispiel Programm<\/p><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><h3 class=\"wp-block-heading\">Message Buffer<\/h3><p class=\"wp-block-paragraph\">Der Messagebuffer baut auf dem Streambuffer auf. Zus&auml;tzlich k&ouml;nen die Daten in Nachrichten gekapselt werden. Eine Nachricht wird durch ihre L&auml;nge definiert. Vor Empfang einer Nachricht kann die L&auml;nger vom Puffer erfragt werden.<\/p><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/message_buffer.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Erstellen:<\/p><pre class=\"wp-block-code\"><code>MessageBufferHandle_t xMessageBufferCreate( \n              &lt;size_t GreoesseInBytes&gt; \n);<\/code><\/pre><p class=\"wp-block-paragraph\">Schreiben:<\/p><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><p class=\"wp-block-paragraph\">Lesen einer Nachricht:<\/p><p class=\"wp-block-paragraph\">Vorab die L&auml;nge der n&auml;chsten Nachricht erfragen:<\/p><pre class=\"wp-block-code\"><code>size_t xMessageBufferNextLengthBytes(&lt;BufferHandle&gt;);<\/code><\/pre><p class=\"wp-block-paragraph\">F&uuml;r den eigentlichen Empfang wird die folgende Funktion verwendet<\/p><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><p class=\"wp-block-paragraph\">So sieht der Gesamtcode aus. Dieser unterscheidet sich nur geringf&uuml;gig vom Code des StreamBuffers.<\/p><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><h3 class=\"wp-block-heading\">Hooks<\/h3><p class=\"wp-block-paragraph\">Es gibt Idle und Tick Hooks. Idle Hooks werden ausgel&ouml;st wenn die CPU im leerlauf ist. Tickhooks werden &uuml;ber den Tickinterrupt ausgel&ouml;st. Zweiteres soll Zeitlich nicht sehr zuverl&auml;ssig sein. F&uuml;r zeitliche Abfolgen sollten eher Timer oder PWM Signale verwendet werden.<\/p><p class=\"wp-block-paragraph\">Weiterhin gibt es die standard Hooks des FreeRtos und eigene Varianten der IDF.<\/p><h4 class=\"wp-block-heading\">FreeRtos Implementierung<\/h4><ul class=\"wp-block-list\"><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><h4 class=\"wp-block-heading\">IDF Implementierung<\/h4><ul class=\"wp-block-list\"><li>Es k&ouml;nnen mehrer Hooks\/Ticks registriert werden.<\/li><li>Ein Hooks\/Ticks mus seiner CPU zugewiesen werden<\/li><li>Die registrierten Hooks\/Ticks werden routierend ausgef&uuml;hrt.<\/li><\/ul><p class=\"wp-block-paragraph\"><strong><span class=\"has-inline-color has-vivid-red-color\">Es d&uuml;rfen niemals blockierende Codestellen in Hooks und Ticks verwendet werden. Diese m&uuml;ssen immer komplett durhlaufen werden und sollten m&ouml;glichst kurz sein, da sie sonst andere Tasks behindern k&ouml;nnten.<\/span><\/strong><\/p><p class=\"wp-block-paragraph\"><strong><span class=\"has-inline-color has-vivid-red-color\">In Ticks d&uuml;rfen zus&auml;tzlich keine API Funktionionen ohne \"FromIsr\" verwendet werden. LogAusgaben sind ebenfalls nicht m&ouml;glich.<\/span><\/strong><\/p><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"esp_freertos_hooks.h\"<\/code><\/pre><p class=\"wp-block-paragraph\">Idle Hook erstellen<\/p><pre class=\"wp-block-code\"><code>esp_err_t esp_register_freertos_idle_hook_for_cpu(\n    &lt;Funktion f&uuml;r Callback&gt;, \n    &lt;CPU ID&gt;\n)\n\/\/ oder \nesp_err_t esp_register_freertos_idle_hook_for_cpu(\n    &lt;Funktion f&uuml;r Callback&gt;\n)\n \n\/\/ Funktionsprototyp\nstatic bool hook1(void)\n{}\n<\/code><\/pre><p class=\"wp-block-paragraph\">Tick  erstellen<\/p><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><p class=\"wp-block-paragraph\">Fehler<\/p><ul class=\"wp-block-list\"><li>ESP_OK: Hat geklappt<\/li><li>ESP_ERR_NO_MEM: Kein Speicher f&uuml;r den Prozessorkern um einen Hook zu registrieren<\/li><li>ESP_ERR_INVALID_ARG: Ung&uuml;ltige CPU<\/li><\/ul><p class=\"wp-block-paragraph\">CPU ID abfragen<\/p><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><p class=\"wp-block-paragraph\">Hier das Beispielprogramm.<\/p><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');\ndocument.write('<a href=\"https:\/\/downgit.github.io\/#\/home?url=https:\/\/github.com\/'+project+'\" target=\"_blank\">Download des Projektes mit DownGit');\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('');\n<\/script><h3 class=\"wp-block-heading\">Ringbuffer<\/h3><p class=\"wp-block-paragraph\">Der Ringbuffer der IDF sind eine \"interessante\" Sache. Ich spare sie mir an dieser Stelle mal auf f&uuml;r einen anderen Zeitpunkt auf, andem ich sie wirklich brauche ;).<\/p><p class=\"wp-block-paragraph\">Bibliothek:<\/p><pre class=\"wp-block-code\"><code>#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"<\/code><\/pre><h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Fazit<span class=\"ez-toc-section-end\"><\/span><\/h2><p class=\"wp-block-paragraph\">Jede Aktion in einen eigenen Task zu verpacken bedarf einiger &Uuml;bung und Planung. Um so wichtiger ist es die richtigen Bibliotheksfunktionen zur Verf&uuml;gung zu habe. Ob diese Funktionalit&auml;ten ausreichend sind, muss sich in der Praxis zeigen. Grunds&auml;tzlich scheint aber alle was man brauch zur Verf&uuml;gung zu stehen.<\/p><h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Verwandte_Beitrage\"><\/span>Verwandte Beitr&auml;ge<span class=\"ez-toc-section-end\"><\/span><\/h2><p class=\"wp-block-paragraph\"><a href=\"https:\/\/www.fambach.net\/?p=6943\">Hauptbeitrag<\/a><\/p><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 &#8211; Projekt erstellen<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-konsolenausgabe\/\">Espressif IDF &#8211; Konsolenausgabe<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-fehlerbehandlung\/\">Espressif IDF &#8211; Fehlerbehandlung<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-log-nachrichten\/\">Espressif IDF &#8211; Lognachrichten<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-timer\/\">Espressif IDF &#8211; Timer<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-menuconfig\/\">Espressif IDF &#8211; Menuconfig<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks\/\">Espressif IDF &#8211; Tasks<\/a><\/div>\n<div class=\"listing-item\"><a class=\"title\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/\">Espressif IDF &#8211; GPIOs<\/a><\/div>\n<\/div>\n\n\n\n<\/p><h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Quellen\"><\/span>Quellen<span class=\"ez-toc-section-end\"><\/span><\/h2><p class=\"wp-block-paragraph\"><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">IDF - Programming Guide<\/a><\/p><p class=\"wp-block-paragraph\"><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><p class=\"wp-block-paragraph\"><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><p class=\"wp-block-paragraph\"><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><p class=\"wp-block-paragraph\"><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><p class=\"wp-block-paragraph\"><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>\n","protected":false},"excerpt":{"rendered":"<p>Ein Task ist eine (wiederkehrende) Aufgabe f&uuml;r den Prozessor. Mehrere Tasks ringen um die Aufmerksamkeit der CPU. Wie diese erstellt werden und welche Datenstrukturen zur Daten&uuml;bermittlung und Synchronisation vorhanden sind, wird in diesem Beitrag kurz umrissen. Tasks k&ouml;nnen 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\">Carry on reading <span class=\"screen-reader-text\">\"Espressif IDF &#8211; GPIOs\"<\/span> <span class=\"meta-nav\">\u2192<\/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],"class_list":["post-7164","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c-c","category-esp-32","category-esp32-s2","category-espressif-idf","category-how-to","tag-espressif","tag-espressif-idf","tag-framework","tag-howto","tag-idf","tag-lehrgang","tag-tutorial","penguin-post","penguin-post-not-sticky"],"modified_by":"sfambach","_links":{"self":[{"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164","targetHints":{"allow":["GET"]}}],"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}]}}