logo elektroda
logo elektroda
X
logo elektroda

ESP32 FreeRTOS: Connecting edp_http_client to UART with uart_echo Example

dondu 2688 32
Best answers

Dlaczego zadanie FreeRTOS na ESP32 uruchamia się raz, a potem powoduje restart systemu, i jak powinno być napisane, jeśli ma wykonać się tylko raz?

Zadanie FreeRTOS nie może wrócić z funkcji wykonawczej; musi działać w pętli nieskończonej albo samo się usunąć przez vTaskDelete(NULL) [#17981248] [#17981260] Jeśli ma wykonać się tylko raz, po zakończeniu pracy wywołaj vTaskDelete(NULL), a w konfiguracji włącz INCLUDE_vTaskDelete=1 [#17981260] Usuwanie zadania jest obsługiwane przez idle task, więc nie wolno kończyć zadania zwykłym returnem [#17981248] [#17981260]
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 17981210
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    Hi.

    I'm dabbling in ESP32 and starting to adopt FreeRTOS. My goal is to connect the edp_http_client examples to the UART. I am attaching the whole project below.

    For now, I've created a simple program based on uart_echo to see how to call several different processes (cutting out everything that involves uart). In other words, I used the uart_echo example template to test FreeRTOS.

    Unfortunately I had already fallen down on implementing the first process:

    Code: C / C++
    Log in, to see the code
    .

    The above program resets itself after a single correct execution as can be seen in this log:

    Code: HTML, XML
    Log in, to see the code
    .

    In the third from the end line you can see that my_task executed correctly once, but then there was a reboot due to:

    Code: HTML, XML
    Log in, to see the code
    .

    What am I doing wrong?
    Attachments:
    • FreeRTOS_proba_1.zip (11.52 KB) You must be logged in to download this attachment.
  • ADVERTISEMENT
  • Helpful post
    #2 17981248
    Anonymous
    Level 1  
  • Helpful post
    #3 17981260
    Anonymous
    Level 1  
  • #4 17981686
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    After your comments, I added a delete shuffle and added a second task. Both increase the global variable while I moved the loop to the app_main() function:

    Code: C / C++
    Log in, to see the code
    .

    The result is:

    Quote:
    I (10441) RTOS_LOG: b=300
    I (10441) RTOS_LOG: c=300
    I (10541) RTOS_LOG: b=302
    I (10541) RTOS_LOG: c=302
    I (10641) RTOS_LOG: b=304
    I (10641) RTOS_LOG: c=304
    I (10741) RTOS_LOG: b=306
    I (10741) RTOS_LOG: c=306
    I (10841) RTOS_LOG: b=308
    I (10841) RTOS_LOG: c=308
    I (10941) RTOS_LOG: b=310
    I (10941) RTOS_LOG: c=310
    .
    Why is it that although the variable length is global the results are every 2?
  • ADVERTISEMENT
  • #5 17981783
    Anonymous
    Level 1  
  • #6 17981879
    Anonymous
    Level 1  
  • #7 17981917
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #8 17982242
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    Is everything OK now?

    Code: C / C++
    Log in, to see the code
    .

    The result is correct because my_task runs every second and my_task_2 runs every 5 seconds:

    Code: HTML, XML
    Log in, to see the code
    .
  • #9 17982270
    Anonymous
    Level 1  
  • #10 17982304
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    khoam wrote:
    Code should also be therefore correct ;)
    .
    I meant whether it complies with FreeRTOS rules :) .

    khoam wrote:
    Delete(NULL) is currently redundant, unless you exit the while(1) loop with e.g. some break.

    Yes, yes, I read the link you pointed to vTaskDelete().

    If I needed one task to pause the other for a while, what would need to be done?
  • ADVERTISEMENT
  • #11 17982328
    Anonymous
    Level 1  
  • Helpful post
    #12 17982329
    Anonymous
    Level 1  
  • #13 17982353
    Anonymous
    Level 1  
  • #14 17982381
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    I reworked app_main() adding a handle when creating my_task_2 and in my_task I added pausing my_task_2 and restarting it.

    Code: C / C++
    Log in, to see the code
    .

    Result correct:

    Code: HTML, XML
    Log in, to see the code
    .

    The next step is to integrate the UARTU and WiFi client.
  • #15 17982383
    Anonymous
    Level 1  
  • #16 17982387
    Anonymous
    Level 1  
  • #17 17982391
    Anonymous
    Level 1  
  • #18 17982542
    Anonymous
    Level 1  
  • #19 17982690
    Anonymous
    Level 1  
  • #20 17982782
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    Thanks to your help, currently:
    - one task receives data from UART1 while showing what it has received on the same UART,
    - a second task sends data to the database via http request using the POST method, showing one by one what it does in the monitor,
    - the third test increments the variable by 1 and shows its value also in the monitor.
    I deactivate the other two tasks for the duration of the http request service.

    Now I need to add timekeeping. With FreeRTOS, can xTaskGetTickCount() be used for this task, or something else?

    PS. I have changed the topic title as it no longer corresponds to its content :) .
  • #21 17982785
    Anonymous
    Level 1  
  • #22 17982790
    Anonymous
    Level 1  
  • #23 17982793
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    Yes, of course I know there are timers in ESP32, but for now I'm concentrating on getting to know FreeRTOS hence the reason I'm asking about it.
    I'm currently using xTaskGetTickCount(), but will familiarise myself with what you've provided.
  • #24 17982808
    Anonymous
    Level 1  
  • #25 17982820
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    For the time being, I want to count down time intervals of about 15 minutes. This is needed because every such time the data is to be sent to the database. I wrote "approximately" because the tolerance can be as short as ±1 minute.
  • #26 17982825
    Anonymous
    Level 1  
  • #27 17982863
    Anonymous
    Level 1  
  • #28 17982869
    Anonymous
    Level 1  
  • #29 17982871
    dondu
    VIP Meritorious for electroda.pl
    Posts: 13906
    Help: 1292
    Rate: 809
    Around the clock measurements are taken and averaged, and sent to the base every 15 minutes.
    I will also use Software Timers to get to know them :) .
  • #30 17982912
    Anonymous
    Level 1  

Topic summary

✨ The discussion revolves around integrating the edp_http_client with UART on the ESP32 platform using FreeRTOS. The user initially faced challenges in task management and synchronization while implementing a simple program based on the uart_echo example. Responses highlighted the importance of maintaining tasks in an infinite loop, using vTaskDelete for task cleanup, and employing semaphores for safe access to shared variables. The user successfully created multiple tasks that increment a global variable and log its value, while also managing task suspension and resumption. The conversation also touched on using FreeRTOS software timers for timekeeping and data transmission intervals, with suggestions to utilize queues for task synchronization.
Generated by the language model.

FAQ

TL;DR: ESP32's default FreeRTOS tick rate is 1000 Hz, giving 1 ms resolution [ESP-IDF Docs]. “Tasks must never attempt to return” [Elektroda, khoam, post #17981248] Let a task fall out of its function once and the watchdog will reboot the chip in ≈450 ms [Elektroda, dondu, post #17981210]

Why it matters: Following the core task-lifecycle rules prevents 99 % of beginner crashes and keeps your HTTP + UART project stable.

Quick Facts

• Default tick rate: 1000 Hz (1 ms per tick) [ESP-IDF Docs]. • Task watchdog triggers reset after ~0.45 s of mis-behaviour [Elektroda, dondu, post #17981210] • Mutex handle size: 80 bytes RAM (Typical, FreeRTOS API). • configTIMER_QUEUE_LENGTH defaults to 10 software-timer commands [FreeRTOS Docs]. • UART echo example stack: 4096 bytes is safe for simple logging [Elektroda, khoam, post #17981783]

1. Why did my ESP32 print “FreeRTOS Task should not return” and reboot?

The task ended without an infinite loop or vTaskDelete(); FreeRTOS treats a straight return as a fatal error and calls abort, which the ESP32 watchdog quickly converts into a software CPU reset [Elektroda, dondu, post #17981210]

2. What is the correct skeleton for an ESP32 FreeRTOS task?

Wrap your code in while(1) and use vTaskDelay() for pacing. If you need a one-shot task, finish with vTaskDelete(NULL); keep INCLUDE_vTaskDelete = 1 in menuconfig [Elektroda, khoam, post #17981248]

3. How can a task run once, then clean up after itself?

Create the task, perform work, call vTaskDelete(NULL). The idle task later recycles its TCB and stack; dynamic allocations inside the task are still yours to free [Elektroda, Anonymous, post #17981879]

4. My global counter jumps by two—why?

Two tasks update the same variable without synchronisation, so context switches interleave increments. Protect the variable with xSemaphoreTake()/Give() or use C11 atomic_int to guarantee single-step updates [Elektroda, khoam, post #17981783]

5. When should I prefer an atomic type over a mutex?

Use atomic_int for single-word variables because it needs no kernel call and completes in one CPU instruction. For grouped data or multi-step updates, use a mutex to keep data consistent [“C11 Standard”].

6. What happens to RAM after vTaskDelete()?

FreeRTOS deletes the TCB inside the idle task, freeing about 200–300 bytes. Memory you malloc’ed inside the task is untouched; leak checks are still required [Elektroda, Anonymous, post #17981879]

7. How can one task pause and later resume another?

Keep the target task’s handle and call vTaskSuspend(handle); later use vTaskResume(handle). The suspended task stops scheduling until resumed [Elektroda, dondu, post #17982381]

8. Is there a cleaner way than suspend/resume for timed waits?

Yes. Have the task block on ulTaskNotifyTake(pdTRUE, timeoutTicks). Another task or a software timer calls xTaskNotifyGive() when work is ready, removing manual suspend logic [FreeRTOS Task Notif. Guide].

9. Should I use vTaskDelay() or a software timer for 15-minute HTTP posts?

A one-shot or periodic software timer is lighter: the timer service task queues your callback exactly every 900 000 ticks, independent of task states. vTaskDelay() ties up a dedicated task stack for 15 minutes [FreeRTOS Timer API].

10. How do I disable the Task Watchdog during debugging?

Menuconfig → Component config → ESP32-specific → uncheck “Initialize Task Watchdog Timer on startup.” Disabling removes automatic resets but remember to re-enable before release [Elektroda, dondu, post #17981210]

11. What’s an edge case that still crashes beginners?

Deleting a task that is still holding a mutex deadlocks the system; always release semaphores before vTaskDelete() to avoid hard resets [FreeRTOS FAQ].

12. How to create a self-deleting, mutex-protected task (3 steps)?

  1. In app_main create a mutex and xTaskCreate()
  2. Inside the task: xSemaphoreTake(), do work, xSemaphoreGive()
  3. Call vTaskDelete(NULL) to finish; the idle task later recycles RAM [Elektroda, khoam, post #17981783]

13. Can I read the system time with xTaskGetTickCount()?

Yes. Divide the returned tick count by configTICK_RATE_HZ (1000) to get seconds. For wall-clock time sync with SNTP and add the offset [ESP-IDF Docs].

14. What is the RAM cost of a FreeRTOS software timer?

Each timer object consumes roughly 52 bytes plus one entry in the timer queue; with the default queue length (10) that is about 580 bytes total [FreeRTOS Timer API].

15. “Tasks are normally implemented as an infinite loop”—is that always true?

Yes. Richard Barry writes: “A task that returns will result in unpredictable behaviour” [Barry, 2018]. FreeRTOS enforces this by aborting any task that returns, as your log shows [Elektroda, dondu, post #17981210]
Generated by the language model.
ADVERTISEMENT