{"id":7164,"date":"2021-01-18T07:42:43","date_gmt":"2021-01-18T07:42:43","guid":{"rendered":"https:\/\/www.fambach.net\/?p=7164"},"modified":"2026-10-15T23:19:14","modified_gmt":"2026-10-15T23:19:14","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_89 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\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\/#Task_erstellen\" >Task erstellen<\/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\/#Synchronisation\" >Synchronisation<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Queues\" >Queues<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Semaphoren\" >Semaphoren<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Event_Groups\" >Event Groups<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Stream_Buffer\" >Stream Buffer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Message_Buffer\" >Message Buffer<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Hooks\" >Hooks<\/a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#FreeRtos_Implementierung\" >FreeRtos Implementierung<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-4'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#IDF_Implementierung\" >IDF Implementierung<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Ringbuffer\" >Ringbuffer<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-13\" 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-14\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/#Verwandte_Beitrage\" >Verwandte Beitr\u00e4ge<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" 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\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 class=\"wp-block-paragraph\">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 <span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html\" target=\"_blank\" class=\"ub-content-link__anchor\">Espressif Website \u2013 Kapitel FreeRtos<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span> verwiesen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"grundsaetzliches\"><span class=\"ez-toc-section\" id=\"Grundsatzliches\"><\/span>Grunds\u00e4tzliches<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Tasks k\u00f6nnen als gekapselte Aufgaben betrachtet werden. In der Espressif IDF k\u00f6nnen je nach Anzahl der Prozessor-Kerne ein oder mehrere Tasks parallel\/gleichzeitig ausgef\u00fchrt werden. Grunds\u00e4tzlich k\u00f6nnen aber mehrere Tasks gestartet werden, die um den\/die Prozessorkern(e) konkurrieren. Immer wenn ein Task den Prozessorkern nicht mehr braucht, gibt er ihn frei und der n\u00e4chste Task kommt an die Reihe. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 Schedulers ab. Die Tasks in der IDF stammen aus dem FreeRtos, hier wacht zus\u00e4tzlich ein Wachhund (Watchdog) dar\u00fcber, dass die Tasks nicht zu lange brauchen. Weiterhin wird davon ausgegangen, dass 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 class=\"wp-block-paragraph\">Viele der im Folgenden beschriebenen 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\u00f6nnen, diese enden immer mit \u201aFromISR\u2018.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Es wird im Folgenden meist nur auf die Funktionen mit dynamischer Speicherreservierung eingegangen, f\u00fcr weitere Infos sei auch hier auf die IDF Referenz verwiesen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"task-erstellen\"><span class=\"ez-toc-section\" id=\"Task_erstellen\"><\/span>Task erstellen<span class=\"ez-toc-section-end\"><\/span><\/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\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 class=\"wp-block-paragraph\">Gute 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 eine Aktion warten, sollte er sich schlafen legen und den Prozessor an einen anderen Task weitergeben. 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 Ausf\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 class=\"wp-block-paragraph\">In diesem Fall wartet der Task, bis er wieder von au\u00dfen 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\">FreeRtos-Tasks 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[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 Anweisungen, die auf diesen Befehl folgen nicht mehr ausgef\u00fchrt, weil der Task dann schon gel\u00f6scht ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Das folgende Beispiel erstellt mehrere Tasks, die unterschiedlich lange laufen und, wenn sie aktiv sind, eine Ausgabe erzeugen:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * This example shows how to create tasks\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"freertos\/event_groups.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task\";\n\n\/\/ event groupe things\nstatic TaskHandle_t xHandles[5];\nstatic EventGroupHandle_t xEventGroup;\nstatic EventBits_t uxBits;\n\n#define BIT_0    ( 1 &lt;&lt; 0 )\n#define BIT_1    ( 1 &lt;&lt; 1 )\n#define BIT_2    ( 1 &lt;&lt; 2 )\n#define BIT_3    ( 1 &lt;&lt; 3 )\n#define BIT_4    ( 1 &lt;&lt; 4 )\n\n\n\/** tasks \n *  Simply produce some output\n*\/\nstatic void task(void* arg)\n{\n\t\/\/ get back task index\n    uint32_t task_index = (uint32_t*) arg;\n\tESP_LOGI(TAG,\"Sub Task %i started!\",task_index+1);\t\n\t\t\n\t\/\/ run at minimum 2 times \n\tint count = 2 +  esp_random()%10;\n\t\t\t\n\tfor(int i = 0; i &lt; count ; i++){\n\t\t\t\t\n\t\tESP_LOGD(TAG,\"Task %i (run %i \/ %i )\", task_index+1, i, count);\n\t\t\n\t\t\/\/ random delay 250 - 500 ms\n\t\tint delay = 250 +  esp_random()%250;\n\t\t\n\t\tvTaskDelay(delay);\n\t}\n\t\t\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping %s \", pcTaskGetName(xHandles[task_index]));\n\tvTaskDelete( xHandles[task_index] );\n\t\n\t\/\/ you will never see this message, because task was deleted before!\n\tESP_LOGI(TAG,\"Sub Task %i finished!\",task_index+1);\n\t\n}\n\n\nvoid app_main(void)\n{\n\tESP_LOGI(TAG,\"Main Task started!\");\t\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\t\n\t\/\/ activate random number genneration without wifi\n\t\/\/ deactivate before the use of wifi or I2C\n\tESP_LOGD(TAG,\"Init Random without RF\");\n\tbootloader_random_enable();\n\t\t\t\t\n\t\/\/* init switches and set interupt routines\n\tfor(uint32_t i = 0; i &lt;5;i++){\n\t\t\t\n\t\tchar buf [20];\n\t\tsprintf(buf, \"Task_%i\",i+1);\n\t\t\t\n\t\tESP_LOGD(TAG,\"Creating %s\", buf);\n\t\t\n\t\t\/\/start gpio task to handle the buttons\n\t\txTaskCreate(task, buf, 2048, i, 10, &amp;xHandles[i]);\n\t\t\t\n\t}\n\tESP_LOGI(TAG,\"Main Task finihed!\");\t\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"synchronisation\"><span class=\"ez-toc-section\" id=\"Synchronisation\"><\/span>Synchronisation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">FreeRtos bietet Datenstrukturen zur Synchronisation und \u00dcbergabe der Daten von einem Task zum anderen. Folgende Hilfsmittel konnte ich finden:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>Queues<\/strong> \u2013 Dies ist eine Liste. Hier wartet der lesende Task, bis ein Eintrag in der Liste vorhanden ist.<\/li><li><strong>Semaphoren<\/strong> \u2013 Werden genutzt, um Tasks miteinander zu synchronisieren oder gemeinsam genutzte Ressourcen vor Datenfehlern zu sch\u00fctzen.<\/li><li><strong>Event Gruppen<\/strong> \u2013 Werden zur Synchronisation von Tasks verwendet, sie warten auf das Setzen definierter Bits durch Tasks. Warten kann die Gruppe auf ein oder alle Bits. Sind die Bits gesetzt, wird das Warten der Gruppe beendet. <\/li><li><strong>Stream Buffer<\/strong> \u2013 Daten\u00fcbertragung per Stream. Der lesende Task wartet so lange, bis im Stream Daten vorhanden sind.<\/li><li><strong>Message Buffer<\/strong> \u2013 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> \u2013 Werden verwendet, um Tasks auszuf\u00fchren, wenn der Prozessor gerade nichts zu tun hat.<\/li><li><strong>Ring Buffer<\/strong> \u2013 Ein Ringbuffer ist eine Datenstruktur mit einem fixen Speicher. Wird das Ende des Speichers erreicht, wird versucht, im vorderen Bereich wieder Speicher zu finden. Da der Ringbuffer etwas komplexer ist, habe ich diesen erst mal au\u00dfen vor gelassen.<\/li><li><strong>Timer<\/strong> \u2013 Timer starten Tasks einmalig oder periodisch, f\u00fcr Timer habe ich einen eigenen <span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/www.fambach.net\/espressif-idf-timer\/\" data-type=\"post\" data-id=\"7139\" class=\"ub-content-link__anchor\">Beitrag<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span> erstellt. <\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><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 class=\"wp-block-paragraph\"><strong>Es wird bei den Datenstrukturen, au\u00dfer bei den Semaphoren, immer davon ausgegangen, dass es nur einen Sende-Task und einen Empf\u00e4nger-Task gibt. Wollen beispielsweise mehrere Ressourcen senden, muss die Sendefunktion als kritischer Bereich (z.B. mit Semaphor) gesch\u00fctzt werden.<\/strong><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"queues\"><span class=\"ez-toc-section\" id=\"Queues\"><\/span>Queues<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Queues werden verwendet, um Daten auszutauschen. Der sendende Task \u00fcbergibt Daten an die Queue und kann danach weiterlaufen. Der konsumierende Task holt sich die Daten, wenn er bereit ist.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Daten empfangen:<\/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 class=\"wp-block-paragraph\">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 Schreibe-Task warten muss.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_EVENT_QUEUES\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * Tasks and queues\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task_Queues\";\n\n\/\/ event groupe things\nstatic TaskHandle_t writeTaskHandle;\nstatic TaskHandle_t readTaskHandle;\nstatic QueueHandle_t xQueue;\nstatic const int queueSize = 5;\n\n\/**\n * Read from queue\n*\/\nstatic void write_task (void* arg)\n{\n\tconst TickType_t xTicksToWait = ( TickType_t )0xff;\n\t\n\t\/\/ run forever like a highlander\n\twhile(1)\n\t{\n\t\t\/\/ generate random value\n\t\tuint32_t value = esp_random()%100;\n\t\t\n\t\t\/\/ try to send something\n\t\tif(!xQueueSendToBack(xQueue, (void*)&amp;value, xTicksToWait)){\n\t\t\tESP_LOGW(TAG,\"q - Queue Full\");\n\t\t\tvTaskDelay(500); \/\/ wait longer if queue is full\n\t\t}else {\n\t\t\tESP_LOGI(TAG,\"w &lt;- %i\", value);\n\t\t}\n\t\t\n\t\tvTaskDelay(500);\n\t}\n\t\n}\n\n\n\n\/** \n *  Write to queue\n*\/\nstatic void read_task(void* arg)\n{\n\tconst TickType_t xTicksToWait = ( TickType_t )0xff;\n\tuint32_t value;\n\tint i = 1200;\n\t\/\/ run forever like a highlander\n\twhile(1)\n\t{\n\t\t\/\/ increase read speed \n\t\tif(i &gt; 100){ \n\t\t\ti-=50;\n\t\t}\n\t\t\n\t\t\/\/ try to receive some data\n\t\tif( xQueueReceive( xQueue, &amp;value, xTicksToWait ) ){\n\t\t\tESP_LOGI(TAG,\"r -&gt; %i\", value);\n\t\t} else {\n\t\t\tESP_LOGW(TAG,\"q - Queue empty!\");\n\t\t}\n\t\t\n\t\t\/\/ wait a while \n\t\tvTaskDelay(i);\n\t}\n}\n\nvoid app_main(void)\n{\n\t\n\t\/\/ Create a queue of queueSize x uint32_t\n\txQueue = xQueueCreate( queueSize, sizeof( uint32_t ) );\n\tif( xQueue == 0 )\n\t{\n\t\tESP_LOGE(TAG,\"Error during queue creation\");\n\t}\n\t\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\t\n\tESP_LOGI(TAG,\"Create write task\");\n\txTaskCreate(write_task, \"Write Task\", 2048, NULL , 10, &amp;writeTaskHandle);\n\tconfigASSERT( writeTaskHandle );\n\t\n\tESP_LOGI(TAG,\"Create read task\");\n\txTaskCreate(read_task, \"Read Task\", 2048, NULL, 10, &amp;readTaskHandle);\n\tconfigASSERT( readTaskHandle );\n\t\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"semaphoren\"><span class=\"ez-toc-section\" id=\"Semaphoren\"><\/span>Semaphoren<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<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\u00e4ren Semaphors. Muteces und rekursive Semaphore werden analog erstellt, haben aber noch zus\u00e4tzliche Funktionalit\u00e4ten. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Vor der ersten Nutzung muss der Semaphor einmal freigegeben werden. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Freigeben des Semaphors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>xSemaphoreGive( &lt;Semaphor Handle&gt;);\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Das Beispiel unten erstellt 5 Tasks. Alle m\u00f6chten eine Variable hochz\u00e4hlen. Damit es zu keinen Datenfehlern kommt, ist der kritische Bereich (Hochz\u00e4hlen) mit einem Semaphor gesichert. Innerhalb dieses Bereiches wird den anderen Tasks kurz der Prozessor \u00fcbergeben, sodass sie versuchen k\u00f6nnen, den Semaphor zu belegen. 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\u00fcckgeschrieben. Dies ist keine gute Praxis, hilft aber dem Beispiel ;). Ihr k\u00f6nnt den Semaphor herausnehmen, 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<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_SEMAPHOR\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * This is an example for the use of semaphores\n * We have some tasks that tries to change the same resource\n * the source is shielded by the semaphore.\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"freertos\/semphr.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task\";\n\n\/\/ event groupe things\nstatic TaskHandle_t xHandles[5];\nSemaphoreHandle_t xSemaphore = NULL; \n\nstatic uint32_t specialResource = 0;\n\n\/\/ (de)activat this to dis-\/en-able the semaphores\n#define enable_semaphore\n\n\/** tasks \n *  Simply produce some output\n*\/\nstatic void task(void* arg)\n{\n\t\/\/ get back task index\n    uint32_t task_index = (uint32_t*) arg;\n\t\t\n\t\/\/ run at minimum 2 times \n\tint count = 2 +  esp_random()%10;\n\t\t\t\n\tfor(int i = 0; i &lt; count ; i++){\n\t\t\t\t\n\t\tESP_LOGD(TAG,\"Task %i, try to get the semapore\",task_index+1);\n\t\t\n#ifdef enable_semaphore\n\t\twhile(! xSemaphoreTake( xSemaphore, 90)){\n\t\t\tESP_LOGW(TAG,\"Task %i, didn't get the semaphore\",task_index+1);\n\t\t}\n#endif\n\t\t\n\t\tESP_LOGI(TAG,\"Task %i, got the semophore\",task_index+1);\n\t\t\n\t\t\/\/local copy of resource \n\t\tuint32_t localCopy = specialResource;\n\t\t\t\t\n\t\t\/\/ a short delay to give the other task the chance \n\t\t\/\/ to get the semaphor and change the value ;)\n\t\tvTaskDelay(200);\n\n\t\t\/\/ simply increase the value\n\t\tspecialResource = localCopy + 1; \n\n\t\tESP_LOGI(TAG,\"Task %i, Value = %i -&gt; Give semaphor back\",task_index+1,specialResource);\n\t\t\n#ifdef enable_semaphore\t\t\n\t\t\/\/ give back the semaphore\n\t\txSemaphoreGive( xSemaphore );\n#endif\t\t\n\t\t\n\t\t\/\/ random delay 250 - 500 ms\n\t\tint delay = 250 +  esp_random()%250;\n\t\tvTaskDelay(delay);\n\t}\n\t\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGI(TAG,\"Stopping %s \", pcTaskGetName(xHandles[task_index]));\n\tvTaskDelete( xHandles[task_index] );\n\t\n}\n\n\nvoid app_main(void)\n{\n\t\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\t\n\t\/\/ activate random number genneration without wifi\n\t\/\/ deactivate before the use of wifi or I2C\n\tESP_LOGI(TAG,\"Init Random without RF\");\n\tbootloader_random_enable();\n\t\t\t\t\n\t\t\t\t\n\t\/\/ init the semaphor\n\txSemaphore = xSemaphoreCreateBinary();\n\tif( xSemaphore == NULL )\n\t{ \n\t\tESP_LOGE(TAG,\"Error during creation of semaphor\");\n\t} else {\n\t\tESP_LOGI(TAG,\"Semaphor created!\");\n\t}\n\t\t\t\t\n\t\t\t\t\n\t\/\/* init switches and set interupt routines\n\tfor(uint32_t i = 0; i &lt;5;i++){\n\t\t\t\n\t\tchar buf [20];\n\t\tsprintf(buf, \"Task_%i\",i+1);\n\t\t\t\n\t\tESP_LOGI(TAG,\"Creating %s\", buf);\n\t\t\n\t\t\/\/start gpio task to handle the buttons\n\t\txTaskCreate(task, buf, 2048, i, 10, &amp;xHandles[i]);\n\t\t\t\n\t}\n\t\n\t\/\/ GO GO GO ...\n\t\/\/ before you can use the semaphor you have to release it once\n\txSemaphoreGive( xSemaphore );\t\n}<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Zu den rekursiven Muteces sei noch gesagt, diese k\u00f6nnen immer wieder vom Besitzer-Task belegt werden. Die Anzahl der Belegungen wird mitgez\u00e4hlt und muss sich auch in der Anzahl der Freigaben widerspiegeln. Diese k\u00f6nnen beispielsweise f\u00fcr Rekursionen 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\" id=\"event-groups\"><span class=\"ez-toc-section\" id=\"Event_Groups\"><\/span>Event Groups<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Warten auf gesetzte 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 class=\"wp-block-paragraph\">Hier ein komplettes Beispiel mit mehreren Tasks. Der Haupttask wartet darauf, dass alle Bits gesetzt werden. Sind alle vorhanden, arbeitet der Haupttask weiter. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_EVENT_GROUPS\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * This should be an example for tasks ... \n * this example is not finished jet\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"freertos\/event_groups.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task\";\n\n\/\/ event groupe things\nstatic TaskHandle_t xHandles[5];\nstatic EventGroupHandle_t xEventGroup;\nstatic EventBits_t uxBits;\n\n#define BIT_0    ( 1 &lt;&lt; 0 )\n#define BIT_1    ( 1 &lt;&lt; 1 )\n#define BIT_2    ( 1 &lt;&lt; 2 )\n#define BIT_3    ( 1 &lt;&lt; 3 )\n#define BIT_4    ( 1 &lt;&lt; 4 )\n\n\n\/** tasks \n *  Simply produce some output\n*\/\nstatic void task(void* arg)\n{\n\t\/\/ get back task index\n    uint32_t task_index = (uint32_t*) arg;\n\t\t\n\t\/\/ run at minimum 2 times \n\tint count = 2 +  esp_random()%10;\n\t\t\t\n\tfor(int i = 0; i &lt; count ; i++){\n\t\t\t\t\n\t\tESP_LOGD(TAG,\"Task %i (run %i \/ %i )\", task_index+1, i, count);\n\t\t\n\t\t\/\/ random delay 250 - 500 ms\n\t\tint delay = 250 +  esp_random()%250;\n\t\t\n\t\tvTaskDelay(delay);\n\t}\n\t\n\tuxBits = xEventGroupSetBits(\n                         xEventGroup,    \/\/ The event group being updated.\n                        (1&lt;&lt;task_index)); \/\/ The bits being set.\n\t\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping %s \", pcTaskGetName(xHandles[task_index]));\n\tvTaskDelete( xHandles[task_index] );\n\t\n}\n\n\nvoid app_main(void)\n{\n\t\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\t\n\t\/\/ activate random number genneration without wifi\n\t\/\/ deactivate before the use of wifi or I2C\n\tESP_LOGD(TAG,\"Init Random without RF\");\n\tbootloader_random_enable();\n\t\t\t\t\n\t\/\/* init switches and set interupt routines\n\tfor(uint32_t i = 0; i &lt;5;i++){\n\t\t\t\n\t\tchar buf [20];\n\t\tsprintf(buf, \"Task_%i\",i+1);\n\t\t\t\n\t\tESP_LOGD(TAG,\"Creating %s\", buf);\n\t\t\n\t\t\/\/start gpio task to handle the buttons\n\t\txTaskCreate(task, buf, 2048, i, 10, &amp;xHandles[i]);\n\t\t\t\n\t}\n\t\t\n\txEventGroup = xEventGroupCreate();\n\tif(xEventGroup == NULL){\n\t\tESP_LOGE(TAG,\"Can not create event group\");\n\t}\n\txEventGroupClearBits(xEventGroup, 0xff);\t\n\t\n\tuxBits = xEventGroupWaitBits(\n                 xEventGroup,    \/\/ The event group being tested.\n                 BIT_0 | BIT_1| BIT_2| BIT_3 | BIT_4,  \/\/ The bits within the event group to wait for.\n                 pdFALSE,         \/\/ BIT_0 ... and BIT_4 should be cleared before returning.\n                 pdTRUE,         \/\/ wait for all bits\n                 portMAX_DELAY ); \/\/ Wait a maximum of 100ms for either bit to be set.\n\t\n\tif( xEventGroup == NULL )\n\t{\n\t\tESP_LOGE(TAG,\"Event groupe not created\");\n\t} else if(  (uxBits &amp; ( BIT_0 | BIT_1| BIT_2| BIT_3 | BIT_4) ) == ( BIT_0 | BIT_1| BIT_2| BIT_3 | BIT_4 ) )\n    {\n        ESP_LOGI(TAG,\"Program finshed successfull\");\n    } else {\n        ESP_LOGW(TAG,\"Timeout\");\n    }\n\t\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"stream-buffer\"><span class=\"ez-toc-section\" id=\"Stream_Buffer\"><\/span>Stream Buffer<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Erstellen:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Triggerlevel und MaxAnzBytes sind beide vom Typ const size_t. Ersteres gibt an, wie gro\u00df der Bufferstream ist. Zweiteres beschreibt, ab wie viel 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 class=\"wp-block-paragraph\">Funktion zum Senden:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Beispielprogramm<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_STREAM_BUFFER\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * Tasks and Stream buffer Example\n * Two tasks, one is writing to the stream buffer and one is reading from stream buffer.\n * The writing task is faster than the reader. This has an build in errors, \n * when the buffer is full the writer cannot write to the buffer and gets a timeout for writing. \n * This errors can be prevented by increasing the buffer size or the timeout of the writer.\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"freertos\/stream_buffer.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task\";\n\n\/\/ event groupe things\nstatic TaskHandle_t senderHandle;\nstatic TaskHandle_t receiverHandle;\nstatic StreamBufferHandle_t streamBuffer;\nTickType_t x5s;\n\nstatic const char sendString[40] = \"Go hang a salami - I'm a Lasagna Hog!\";\n\n\n\/** tasks \n *  Simply produce some output\n*\/\nstatic void send(void* arg)\n{\n\twhile (1) {\n\t\tsize_t xBytesSent;\n\n\t\txBytesSent =  xStreamBufferSend( streamBuffer, ( void * ) sendString , sizeof( sendString ), x5s );\n\t\tif(xBytesSent != sizeof( sendString )){\n\t\t\tESP_LOGE(TAG, \"Error while sending only sent %i o %i bytes\",xBytesSent,sizeof( sendString ));\n\t\t} else {\n\t\t\tESP_LOGI(TAG,\"Send Bytes %i\" ,xBytesSent);\n\t\t}\n\t\t\n\t\t\/\/ delay 100 - 500 ms\t\t\t\t\t\n\t\tvTaskDelay(pdMS_TO_TICKS(100+esp_random()%400));\t\t\t\t\n\t}\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping sender\");\n\tvTaskDelete( senderHandle);\n\t\n}\n\nstatic void receive(void* arg){\n\t\n\tchar rxBuffer[40];\n\twhile(1){\n\t\tsize_t xReceivedBytes = xStreamBufferReceive( streamBuffer,\n\t\t\t\t\t\t\t\t\t\t\t( void * ) rxBuffer,\n\t\t\t\t\t\t\t\t\t\t\tsizeof( rxBuffer ),\n\t\t\t\t\t\t\t\t\t\t\tx5s );\n\t\t\t\t\t\t\t\t\t\t\t\n\t\tif( xReceivedBytes &lt; 40){\n\t\t\tESP_LOGI(TAG,\"ERROR Received Bytes %i Content: %s\" ,xReceivedBytes,rxBuffer);\n\t\t} else if(xReceivedBytes &gt; 0 ){ \n\t\t\tESP_LOGI(TAG,\"Received Bytes %i Content: %s\" ,xReceivedBytes,rxBuffer);\n\t\t} else {\n\t\t\tESP_LOGW(TAG,\"No data received\");\n\t\t}\n\t\n\t\t\/\/ delay 500 - 1000 ms\n\t\tvTaskDelay(pdMS_TO_TICKS(500+esp_random()%1000));\n\t}\n\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping receiver \");\n\tvTaskDelete( receiverHandle);\n}\n\n\nvoid app_main(void)\n{\n\t\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\tx5s = pdMS_TO_TICKS( 500 );\n\n\t\n\t\/\/ activate random number genneration without wifi\n\t\/\/ deactivate before the use of wifi or I2C\n\tESP_LOGD(TAG,\"Init Random without RF\");\n\tbootloader_random_enable();\n\t\n\t\/\/ create stream buffer\n\tESP_LOGD(TAG,\"Creating stream buffer!\");\n\t\n\t\/\/ buffer can contain 4 bytes maximum, this is very small let's see if it works\n\tconst size_t xStreamBufferSizeBytes = 40;\n\t\/\/ trigger receiver if 1 byte received (10 = 10 Bytes received)\n\tconst size_t xTriggerLevel = 1;\n\t\n\tstreamBuffer = xStreamBufferCreate( xStreamBufferSizeBytes, xTriggerLevel );\n\n        if( streamBuffer == NULL )\n        {\n           ESP_LOGE(TAG,\"FAILED to create stream buffer!\");\n        }\n        else\n        {\n            ESP_LOGI(TAG,\"Streambuffer created\");\n        }\n\t\n\t\n\tESP_LOGD(TAG,\"Creating receiver\");\n\txTaskCreate(receive, \"Receiver\", 2048, NULL, 10, &amp;receiverHandle);\n\tconfigASSERT( receiverHandle );\n\t\n\t\t\t\t\n\tESP_LOGD(TAG,\"Creating sender\");\n\txTaskCreate(send, \"Sender\", 2048, NULL, 10, &amp;senderHandle);\t\n\tconfigASSERT( senderHandle );\n\t\t\n\t\t\t\n\t\n\t\t\t\n\t\t\n\t\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"message-buffer\"><span class=\"ez-toc-section\" id=\"Message_Buffer\"><\/span>Message Buffer<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der Messagebuffer baut auf dem Streambuffer auf. Zus\u00e4tzlich k\u00f6nnen die Daten in Nachrichten gekapselt werden. Eine Nachricht wird durch ihre L\u00e4nge definiert. Vor Empfang einer Nachricht kann die L\u00e4nge vom Puffer erfragt werden.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Lesen einer Nachricht:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">So sieht der Gesamtcode aus. Dieser unterscheidet sich nur geringf\u00fcgig vom Code des StreamBuffers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_MESSGAE_BUFFER\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** idf example\n *\n * Playing with tasks and message buffer.\n * This example uses two taks and a message buffer to transfer messages from one task to another in a safe manner.\n * Only one reader and one writer is allowed, in case of more than one writer the send function should be part of \n * a critical ares safed by a semaphor or mutex\n *\n * Some parts are copied from the official idf examples found on \n * https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/\n * \n * Modified by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"freertos\/queue.h\"\n#include \"freertos\/message_buffer.h\"\n#include \"sdkconfig.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\n\nstatic const char* TAG = \"L6_Task\";\n\n\/\/ event groupe things\nstatic TaskHandle_t senderHandle;\nstatic TaskHandle_t receiverHandle;\n\nuint16_t recDelay = 500;\n\n\n#define MESSAGE_BUFFER_SIZE 1000\nstatic MessageBufferHandle_t bufferHandle;\nTickType_t timeOut;\n\n\n\n\/\/ some messages ... \nstatic const char* sendString[12] = {\n\"Sore was I ere I saw Eros\",\n\"A man, a plan, a canal -- Panama\",\n\"Never a foot too far, even.\",\n\"Euston saw I was not Sue.\",\n\"Live on evasions? No, I save no evil.\",\n\"Red Roses run no risk, sir, on nurses order.\",\n\"Salisbury moor, sir, is roomy. Rub Silas.\",\n\"Marge, let's went. I await news telegram.\",\n\"A new order began, a more Roman age bred Rowena.\",\n\"I, man, am regal; a German am I.\",\n\"Tracy, no panic in a pony-cart.\",\n\"Egad! Loretta has Adams as mad as a hatter. Old age!\"};\n\n\n\/** tasks \n *  Simply produce some output\n*\/\nstatic void send(void* arg)\n{\n\twhile (1) {\n\t\tsize_t xBytesSent;\n\t\t\n\t\tfor(int i = 0 ; i &lt; 12; i++){\n\t\t\t \n\t\t\txBytesSent =  xMessageBufferSend( bufferHandle, ( void * ) sendString[i], strlen( sendString[i]), timeOut );\n\t\t\tif(xBytesSent &lt; 1){\n\t\t\t\tESP_LOGE(TAG, \"Error while sending only sent %i o %i bytes\",xBytesSent,strlen( sendString[i] ));\n\t\t\t\trecDelay -= 50;\n\t\t\t} else {\n\t\t\t\tESP_LOGI(TAG,\"Send Bytes %i Content: %s\" ,xBytesSent, sendString[i] );\n\t\t\t}\n\t\t\n\t\t\t\/\/ delay 100 - 500 ms\t\t\t\t\t\n\t\t\tvTaskDelay(pdMS_TO_TICKS(100+esp_random()%400));\t\t\t\t\n\t\t}\n\t}\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping sender\");\n\tvTaskDelete( senderHandle);\n\t\n}\n\nstatic void receive(void* arg){\n\t\n\tchar rxBuffer[50];\n\twhile(1){\n\t\t\n\t\tint length = xMessageBufferNextLengthBytes(bufferHandle);\n\t\tsize_t xReceivedBytes = xMessageBufferReceive( bufferHandle,\n\t\t\t\t\t\t\t\t\t\t\t( void * ) rxBuffer,\n\t\t\t\t\t\t\t\t\t\t\tlength,\n\t\t\t\t\t\t\t\t\t\t\ttimeOut );\n\t\t\n\t\t\/\/ fix null termination\t\t\n\t\trxBuffer[length]='\\0';\n\t\t\n\t\tif(xReceivedBytes &gt; 0 ){ \n\t\t\tESP_LOGI(TAG,\"Received Bytes %i Content: %s\" ,xReceivedBytes,(char*)rxBuffer);\n\t\t} else {\n\t\t\tESP_LOGW(TAG,\"No data received\");\n\t\t}\n\t\t\n\t\t\/\/ delay 500 - 1000 ms\n\t\tvTaskDelay(pdMS_TO_TICKS(recDelay+esp_random()%500));\n\t}\n\n\t\/\/ Do not forgett to stop the task.\n\t\/\/ If delete is missing an exception will be thrown\n\tESP_LOGD(TAG,\"Stopping receiver \");\n\tvTaskDelete( receiverHandle);\n}\n\n\nvoid app_main(void)\n{\n\t\/\/Allow other core to finish initialization\n    vTaskDelay(pdMS_TO_TICKS(100));\n\ttimeOut = pdMS_TO_TICKS( 500 );\n\t\n\t\/\/ activate random number genneration without wifi\n\t\/\/ deactivate before the use of wifi or I2C\n\tESP_LOGD(TAG,\"Init Random without RF\");\n\tbootloader_random_enable();\n\t\n\t\/\/ create stream buffer\n\tESP_LOGD(TAG,\"Creating stream buffer!\");\n\n\tbufferHandle = xMessageBufferCreate( MESSAGE_BUFFER_SIZE);\n\n        if( bufferHandle == NULL )\n        {\n           ESP_LOGE(TAG,\"FAILED to create buffer!\");\n        }\n        else\n        {\n           ESP_LOGI(TAG,\"Buffer created\");\n        }\n\t\n\tESP_LOGD(TAG,\"Creating receiver\");\n\txTaskCreate(receive, \"Receiver\", 2048, NULL, 10, &amp;receiverHandle);\n\tconfigASSERT( receiverHandle );\n\t\n\t\t\t\t\n\tESP_LOGD(TAG,\"Creating sender\");\n\txTaskCreate(send, \"Sender\", 2048, NULL, 10, &amp;senderHandle);\t\n\tconfigASSERT( senderHandle );\n\t\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"hooks\"><span class=\"ez-toc-section\" id=\"Hooks\"><\/span>Hooks<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Weiterhin gibt es die Standard-Hooks des FreeRtos und eigene Varianten der IDF.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"freertos-implementierung\"><span class=\"ez-toc-section\" id=\"FreeRtos_Implementierung\"><\/span>FreeRtos Implementierung<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li>Zur Nutzung <span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/kconfig.html#config-freertos-legacy-hooks\" class=\"ub-content-link__anchor\">CONFIG_FREERTOS_LEGACY_HOOKS<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>\u00a0aktivieren<\/li><li>Es kann nur einen Idle und einen Tick Hook geben<\/li><li>FreeRtos Implementierung ist auf single core ausgelegt.<\/li><\/ul>\n\n\n\n<h4 class=\"wp-block-heading\" id=\"idf-implementierung\"><span class=\"ez-toc-section\" id=\"IDF_Implementierung\"><\/span>IDF Implementierung<span class=\"ez-toc-section-end\"><\/span><\/h4>\n\n\n\n<ul class=\"wp-block-list\"><li>Es k\u00f6nnen mehrere Hooks\/Ticks registriert werden.<\/li><li>Ein Hook\/Tick muss seiner CPU zugewiesen werden<\/li><li>Die registrierten Hooks\/Ticks werden rotierend ausgef\u00fchrt.<\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\"><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 durchlaufen werden und sollten m\u00f6glichst kurz sein, da sie sonst andere Tasks behindern k\u00f6nnten.<\/span><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong><span class=\"has-inline-color has-vivid-red-color\">In Ticks d\u00fcrfen zus\u00e4tzlich keine API-Funktionen ohne \u201eFromIsr\u201c verwendet werden. Log-Ausgaben sind ebenfalls nicht m\u00f6glich.<\/span><\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Fehler<\/p>\n\n\n\n<ul class=\"wp-block-list\"><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 class=\"wp-block-paragraph\">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 class=\"wp-block-paragraph\">Hier das Beispielprogramm.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quellcode <code>main.c<\/code> (<span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/github.com\/sfambach\/espressif-idf\/tree\/master\/L6_TASKS_HOOKS\/main\" class=\"ub-content-link__anchor\">GitHub<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"c\" class=\"language-c\">\/** Example\n *\n * Play with tasks, ticks and hooks\n * This example ist the frist I wrote myself, \n * because of the missing espressif examples\n * \n * Created by SteFam @ http:\/\/www.fambach.net\n *\n * GPLv3 \n * Blah blah blah, free to use. \n * I invested some time and money in those examples if you want to delete this header \n * please do not forget to mention at least my website, thanks!\n *\n *\n*\/\n\n\n#include &lt;stdio.h&gt;\n#include &lt;string.h&gt;\n#include &lt;esp_err.h&gt;\n#include \"sdkconfig.h\"\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"esp_freertos_hooks.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"bootloader_random.h\"\n\nstatic TaskHandle_t calcTask;\nstatic TaskHandle_t tickTask1;\nstatic TaskHandle_t tickTask2;\nstatic const char* TAG = \"L6_Task\";\n\n\n\/******************** the hooks *************************\/\n\n\/** Hook 1*\/\nstatic bool hook1(void)\n{\n\tESP_LOGI(TAG,\"Hook 1\");\n\treturn true;\n\t\n}\n\n\/** Hook 2*\/\nstatic bool hook2(void)\n{\n\tESP_LOGI(TAG,\"Hook 2\");\n\treturn true;\n\t\n}\n\n\n\/******************** the tick *************************\/\n\n\/\/ tick counters\nstatic int ctick1 = 0;\nstatic int ctick2 = 0;\n\n\/** the tick *\/\nstatic void tick1(void)\n{\n\tif(ctick1 %100 == 0){\n\t\txTaskResumeFromISR(tickTask1);\t\t\n\t}\n\tctick1++;\n}\n\n\nstatic void tick2(void)\n{\n\tif(ctick2 %100 == 0){\n\t\txTaskResumeFromISR(tickTask2);\n\t\t\n\t}\n\tctick2++;\n}\n\n\nstatic void tick_task(void* args){\n\twhile(1){\n\t\t\/\/ suspend our selves\n\t\tvTaskSuspend(NULL);\n\t\t\n\t\t\/\/ print the tick to log.\n\t\tuint32_t i = (uint32_t) args;\n\t\tESP_LOGI(TAG,\"100x Tick %i\",i);\n\t}\n}\n\n\/******************** calc task *************************\/\n\/**\n * Another calculation task\n * so some calculation to keep the cpu bussy\n*\/\nstatic void calc_task (void* arg)\n{\n\twhile(1){\n\t\tuint32_t result = 10;\n\t\tfor(uint32_t i = 0 ; i &lt; 9000; i++){\n\n\t\t\tresult += i+i*1;\n\t\t\tvTaskDelay(pdMS_TO_TICKS(1));\t\n\t\t}\n\t\tESP_LOGI(TAG,\"2 - result generated\");\n\t\tvTaskDelay(pdMS_TO_TICKS(esp_random()%100));\n\t}\n}\n\n\/******************** main task *************************\/\n\nvoid app_main(void)\n{\n\t\n\tbootloader_random_enable();\n\t\n\t\/\/ register two hooks\n\tESP_ERROR_CHECK(esp_register_freertos_idle_hook(hook1));\n\tESP_ERROR_CHECK(esp_register_freertos_idle_hook(hook2));\n\t\n\t\/\/ register two ticks\n\tESP_ERROR_CHECK(esp_register_freertos_tick_hook(tick1));\n\tESP_ERROR_CHECK(esp_register_freertos_tick_hook(tick2));\n\t\n\t\/\/ create tick tasks\n\txTaskCreate(tick_task, \"Tick Task1\", 2048, 1 , 9000, &amp;tickTask1);\n\tconfigASSERT( tickTask1 );\n\txTaskCreate(tick_task, \"Tick Task2\", 2048, 2 , 9000, &amp;tickTask2);\n\tconfigASSERT( tickTask2 );\n\t\n\t\n\t\n\t\/\/ESP_LOGI(TAG,\"Create calculation task\");\n\txTaskCreate(calc_task, \"Calc Task\", 3048, NULL , 9000000, &amp;calcTask);\n\tconfigASSERT( calcTask );\n\t\n\twhile(1){\n\t\t\n\t\tuint32_t result = 10;\n\t\tfor(uint32_t i = 0 ; i &lt; 9000000; i++){\n\n\t\t\tresult += i+i*1;\n\t\t\t\n\t\t\t\n\t\t}\n\t\tESP_LOGI(TAG,\"1 - result generated\");\n\t\tvTaskDelay(pdMS_TO_TICKS(esp_random()%100));\n\t}\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"ringbuffer\"><span class=\"ez-toc-section\" id=\"Ringbuffer\"><\/span>Ringbuffer<span class=\"ez-toc-section-end\"><\/span><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Der Ringbuffer der IDF ist eine \u201einteressante\u201c Sache. Ich spare ihn mir an dieser Stelle mal f\u00fcr einen anderen Zeitpunkt auf, an dem ich ihn wirklich brauche ;).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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\" id=\"fazit\"><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Fazit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Jede Aktion in einen eigenen Task zu verpacken bedarf einiger \u00dcbung und Planung. Umso wichtiger ist es, die richtigen Bibliotheksfunktionen zur Verf\u00fcgung zu haben. Ob diese Funktionalit\u00e4ten ausreichend sind, muss sich in der Praxis zeigen. Grunds\u00e4tzlich scheint aber alles, was man braucht, zur Verf\u00fcgung zu stehen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"verwandte-beitraege\"><span class=\"ez-toc-section\" id=\"Verwandte_Beitrage\"><\/span>Verwandte Beitr\u00e4ge<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--broken ub-content-link--status-after is-broken\"><a href=\"https:\/\/www.fambach.net\/?p=6943\" class=\"ub-content-link__anchor\" title=\"This link appears to be broken.\">Hauptbeitrag<\/a><span class=\"ub-status ub-status--broken\" title=\"Link status: Broken\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Broken<\/span><\/span><\/span><\/p>\n\n\n<div class=\"display-posts-listing\"><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-projekt-erstellen\/\">Espressif IDF \u2013 Projekt erstellen<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-konsolenausgabe\/\">Espressif IDF \u2013 Konsolenausgabe<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-fehlerbehandlung\/\">Espressif IDF \u2013 Fehlerbehandlung<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-log-nachrichten\/\">Espressif IDF \u2013 Lognachrichten<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-timer\/\">Espressif IDF \u2013 Timer<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-menuconfig\/\">Espressif IDF \u2013 Menuconfig<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks\/\">Espressif IDF \u2013 Tasks<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><div class=\"listing-item\"><span class=\"ub-content-link ub-content-link--unknown ub-content-link--status-after\"><a class=\"title ub-content-link__anchor\" href=\"https:\/\/www.fambach.net\/en\/espressif-idf-tasks-2\/\">Espressif IDF \u2013 GPIOs<\/a><span class=\"ub-status ub-status--unknown\" title=\"Link status: Unknown\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: Unknown<\/span><\/span><\/span><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"quellen\"><span class=\"ez-toc-section\" id=\"Quellen\"><\/span>Quellen<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ub-content-link__anchor\">IDF \u2013 Programming Guide<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html#\" target=\"_blank\" class=\"ub-content-link__anchor\">IDF \u2013 FreeRtos<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a rel=\"noreferrer noopener\" href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos.html#task-api\" target=\"_blank\" class=\"ub-content-link__anchor\">IDF \u2013 FreeRtos Task Api<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/system\/freertos_additions.html#hooks\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ub-content-link__anchor\">IDF \u2013 Hooks <\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><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\" class=\"ub-content-link__anchor\">IDF Beispiel \u2013 Task Watchdog (GitHub)<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><span class=\"ub-content-link ub-content-link--ok ub-content-link--status-after\"><a href=\"https:\/\/www.esp32.com\/viewtopic.php?t=6157\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ub-content-link__anchor\">Infos zu Ticks und Hooks im Espressif Forum<\/a><span class=\"ub-status ub-status--ok\" title=\"Link status: OK\"><span class=\"ub-status__icon\" aria-hidden=\"true\">\u25cf<\/span><span class=\"screen-reader-text\">Link status: OK<\/span><\/span><\/span><\/p>\n\n\n","protected":false},"excerpt":{"rendered":"<p>A task is a (recurring) job for the processor. Multiple tasks compete for the CPU's attention. How these are created and which data structures are available for data transfer and synchronisation will be briefly outlined in this post. Tasks can become a very complex matter, which is why I can only scratch the surface here. Nevertheless\u2026<\/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":83,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164\/revisions"}],"predecessor-version":[{"id":19675,"href":"https:\/\/www.fambach.net\/en\/wp-json\/wp\/v2\/posts\/7164\/revisions\/19675"}],"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}]}}