logo elektroda
logo elektroda
X
logo elektroda

[Solved] [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions

NIXIE_123 6108 56
Best answers

How should I use ESP32 interrupts with FreeRTOS: should the ISR only wake a task, what is the lightest way to wake a task without passing data, and why do very short periodic timer callbacks seem limited to about 1 ms or clash with Wi‑Fi?

Use the ISR only for very short, time-critical work; if the work is not tiny, let the ISR just wake a task that does the rest [#19448979] The lightest wake-up method without passing data is a queue, while `vTaskSuspend()`/`xTaskResumeFromISR()` was not recommended here [#19448979] The 1 ms FreeRTOS tick only limits scheduler timeout resolution, not whether an interrupt can trigger work sooner, but a task you wake may still run only when the scheduler gives it CPU time [#19448979] For `esp_timer`, ESP-IDF normally dispatches callbacks through the high-priority `esp_timer` task rather than as a raw ISR, and periodic software timers below about 50 µs are considered impractical; for 35–111 µs work, a hardware timer or a peripheral like RMT is a better fit [#19448979][#19448941][#19571581] If you stay with a timer ISR, keep the handler and all accessed data in IRAM/internal RAM and prefer direct GPIO register writes (`W1TS`/`W1TC`) over slower helpers like `gpio_set_level()`, because flash access and Wi‑Fi can block or break non-IRAM handlers [#19545217][#19550193]
Generated by the language model.
ADVERTISEMENT
Treść została przetłumaczona polish » english Zobacz oryginalną wersję tematu
  • #1 19448833
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Hi

    I have a couple of questions about esp32 and the RTOS that appears in it

    1)Is it true that when using interrupts (e.g. from a timer), the best practice is to make them only wake up the task that "does" all the work?
    Because the fact that ISRs are supposed to be the shortest is obvious, but are we even better programmers by flipping even a short instruction in a task?

    2)What is the best (lightest) way to wake up a task from an interrupt assuming we don't need to pass data? Here it is written that using a queue. I used it in my project and it does indeed work. I also tried vTaskSuspend(); and waking xTaskResumeFromISR(); but esp32 was doing a panic. Here it says it's normal because the function wasn't tested and runs some kind of watchdog. I know it can be turned off but that's probably not the point here.

    3)Does the fact that the system Tick is at 1ms mean that the task cannot execute more often than every 1ms?
    Why I ask - I have in the project an interrupt from gpio exactly every second which wakes up the task using queue(in the task an infinite loop which is blocked by xQueueReceive). And it works, I have no objections.
    I also have a timer interrupt triggered every 35µs. Its instructions are in the ISR everything works.
    When I move these instructions to the task in the ISR I just wake it up, the function slows down terribly I would say it executes every 1ms. The method of waking up is identical to the one in the task, which is every second. Again, it is possible to change the Tick system but I don't want to do that

    4)After switching from avr am I wandering around and unnecessarily using interrupts for the timer. Maybe there is another simpler way to wake up tasks with timer
  • ADVERTISEMENT
  • Helpful post
    #2 19448979
    Anonymous
    Level 1  
  • #3 19449929
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    khoam wrote:
    If these are interrupts from esp_timer
    .
    Yes, they are triggered by the timer.

    khoam wrote:
    task "esp_timer" which controls the ISR calls from esp_timer
    .
    I understand that the interrupt forces the "esp_timer" task to execute itself which is why it runs more than 1ms, and when I created a separate task and only woke it up with the timer it had to wait for each subsequent tick of the system i.e. 1ms

    khoam wrote:
    It all depends on how critical shuffles are to be implemented in the ISR - if very much and they are short, it is better to stay with just interrupts.
    .

    The mentioned function running every 35µs multiplexes the display in the nixie watch. It has to be so often because it supports 6 lamps, a crossfade effect and 1/6 pwm dimming. I didn't want it to, for example, hinder the processor from handling the wi-fi connection I want to add in a while. It's not super critical somehow but it has to execute frequently otherwise you can see the multiplexing.
    Since
    khoam wrote:
    interrupts from esp_timer, then by default ISRs are already "converted" to shuffles
    .
    then it probably won't be a tragedy.
  • ADVERTISEMENT
  • #4 19449941
    Anonymous
    Level 1  
  • #5 19545151
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    I have this problem:

    An interrupt from the timer every 111µs interferes with the wifi connection. A panic is created. I just uncomment the initialization of the timer and all the code works. The other way when I throw away the wifi connection and leave the timer also everything works.
    I tried first with a simple example_connect(); and now with a full-fledged station mode. Always the same effect.

    The timer works nicely only the addition of wifi remains
  • #6 19545217
    Anonymous
    Level 1  
  • #7 19545251
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    khoam wrote:
    how long does it take to operate a single esp_timer thread?
    .
    How to check this? The interrupt is a bit of variable and port setting.

    khoam wrote:
    does the problem only occur at WiFi initiation (STA or AP) or also during WiFi operation?
    .
    So far I have not started the watch with wifi so on initiation. I would like there to be no conflict even at initiation because the clock will sync every half hour and it won't always have access to the wifi network. I don't want workarounds like turning off the display for sync time etc.
    khoam wrote:
    By default esp_timer and WiFi support are executed on the same Core 0 (PRO_CPU), so they "fight" for resources and esp_timer always wins.
    .
    Well, that's right, after all this hardware has two cores. Can it be split into two? That was probably the designers' intention. One core for the program and the other for wifi and bluetooth
  • #8 19545433
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #9 19546113
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Code: C / C++
    Log in, to see the code
    .

    every 200ms ESP_LOG with time value

    Stands at 5µs. Occasionally peaks to 8 top 10
  • #10 19546151
    Anonymous
    Level 1  
  • #11 19546162
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Code: C / C++
    Log in, to see the code
    .
  • #12 19546332
    Anonymous
    Level 1  
  • #13 19546428
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Exception decoder I found only for arduino. I downloaded arduino IDE but when I paste the code it sees the library from wifi but still there are errors from wifi and it doesn't compile. I guess there is no point in doing the code under arduino because there will be another exception or it will work.
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .
  • #14 19546435
    Anonymous
    Level 1  
  • #15 19546441
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .
  • #16 19546466
    Anonymous
    Level 1  
  • #17 19547626
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Thank you for leaning into my case.
    khoam wrote:
    With this configuration It works WiFi correctly
    .
    Quote:
    .divider = 10000


    Unfortunately with a divider of 10,000 the interrupt will be triggered every 13.875ms rather than 111µs

    80MHz/10 000 = 8kHz
    1/8kHz = 125µs
    125µs * 111 = 13.875ms

    And I need

    80MHz/80 = 1MHz
    1/1MHz = 1µs
    1µs * 111 = 111µs
  • #18 19547733
    Anonymous
    Level 1  
  • #19 19550055
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    I repeated your test at my place and unfortunately it doesn't work at my place. Even after increasing CONFIG_FREERTOS_HZ to 1000

    However, the whole clock works when I use
    timer_isr_register(TIMER_GROUP_0, TIMER_0, przerwanie_od_timer, NULL, 0, NULL);
    .
    And it works even when I go down from 111µs to 35µs.

    Link .
    ESP_Sprite wrote:
    The thing is flash (write) accesses.
    An interrupt marked as in IRAM will keep functioning when a flash write happens (which in this case is what happens when you initialize NVS), a non-IRAM interrupt will be disabled for as long as the flash write takes.
    However, you must guarantee that the interrupt handler plus all data it accesses are in internal memory for you to be able to mark it as in IRAM, otherwise you'll get crashes like this.
    .
  • #20 19550140
    Anonymous
    Level 1  
  • #21 19550160
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Well yes, it is a workaround but it gives an interrupt which does nothing and there is still a conflict then what am I left with?
  • Helpful post
    #22 19550193
    Anonymous
    Level 1  
  • #23 19550199
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    But I have removed this function completely. The interruption does exactly nothing. Nevertheless, there is a conflict
    Code: C / C++
    Log in, to see the code
  • #24 19550214
    Anonymous
    Level 1  
  • #25 19550222
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    And which chip do you have?
    I esp32 rev. 1
    wroom-32
  • #26 19550228
    Anonymous
    Level 1  
  • #27 19550365
    mpier
    Level 29  
    Posts: 817
    Help: 153
    Rate: 141
    Hello,
    I might hit you with a question: do "timer_spinlock_take()" and the rest have IRAM_ATTR to work without flash access? This is where I would look, maybe it can be done differently.

    Greetings.
  • #28 19550445
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    Very good point. After upgrading to esp-idf v4.3 this function is not found at all. In read the docs it says that this function is deprecated and use a better one. I am currently trying to come to terms after the upgrade.
  • #29 19550573
    Anonymous
    Level 1  
  • ADVERTISEMENT
  • #30 19550615
    NIXIE_123
    Level 34  
    Posts: 2087
    Help: 288
    Rate: 606
    NIXIE_123 wrote:
    I repeated your test with me and unfortunately it does not work with me.
    .
    After upgrading to v4.3 it already works (empty interrupt)
    Now I have these circuses for a change:
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .

    Everything compiles 0 errors 0 warnings and it does not see the BUTTON_DOWN defined. Pressing ctrl and left button on an item not found flips me to it as if it sees it. The program loads and the clock now acts as a paper button....
    My hands are falling off.
    I have already done a fullclean and a build but to no avail
    [RTOS][esp-idf] ESP32 interrupts and shuffles some basic questions .

Topic summary

✨ The discussion revolves around the use of interrupts in the ESP32 with the ESP-IDF RTOS. Key points include best practices for handling interrupts, such as using them to wake tasks rather than performing extensive operations within ISRs. The participants explore methods for waking tasks from interrupts, with queues being a recommended approach. Concerns about the system tick rate limiting task execution frequency to 1ms are addressed, along with issues related to WiFi interference when using timer interrupts. The conversation also touches on the importance of managing execution time within ISRs to avoid conflicts with other processes, particularly WiFi operations. Solutions include using direct GPIO manipulation for efficiency and the potential of using the RMT module to reduce CPU load. The discussion concludes with successful implementations of timer interrupts and HTTP server setups for configuration via a web interface.
Generated by the language model.

FAQ

TL;DR: 35 μs timer ISRs run ~5 µs each (“fast enough if kept in IRAM” [Elektroda, khoam, post #19547733]) and an ADC2-Wi-Fi clash causes 100 % failure when both are active [Espressif Docs]. "Keep ISRs tiny" [Elektroda, khoam, post #19448979]

Why it matters: These micro-timing rules decide whether your ESP32 reboots or streams data reliably.

Quick Facts

• Minimum reliable esp_timer period: 50 µs (Espressif v4.2 docs) • esp_timer task priority: 22 (ESP_TASK_PRIO_MAX-3) [Elektroda, khoam, post #19448979] • Default ISR stack: 1 536 bytes (CONFIG_FREERTOS_ISR_STACKSIZE) [Elektroda, khoam, post #19547733] • ADC2 is unavailable while Wi-Fi is on; ADC1 always works (Technical Reference v4.3) • System tick default: 1 ms; can be raised to 1 kHz by setting CONFIG_FREERTOS_HZ=1000 [Elektroda, khoam, post #19546466]

Should I put all my work inside an ESP32 interrupt or wake a task?

Keep the ISR minimal and defer heavy work to a task unless the work must finish inside a few microseconds. "If very short and critical, stay in the interrupt." [Elektroda, khoam, post #19448979]

What is the lightest way to wake a FreeRTOS task from an ISR when no data is sent?

Use xQueueSendFromISR to a zero-length queue or a binary semaphore. Espressif confirms queues are tested and watchdog-safe, whereas xTaskResumeFromISR can trigger panics [Elektroda, NIXIE_123, post #19448833]

Does the 1 ms system tick cap task frequency?

The scheduler can’t unblock a delay shorter than one tick automatically, but an ISR can force a ready state at any time, so tasks may still run faster than 1 kHz when woken by interrupts [Elektroda, khoam, post #19448979]

Why did my 35 µs esp_timer callback slow to 1 ms after I moved code into a task?

Because esp_timer’s default dispatcher runs in a high-priority task. When you defer work, the task waits for the next tick. Using CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD or direct hardware timers avoids the 1 ms bottleneck [Elektroda, khoam, post #19448979]

What’s the minimum safe period for esp_timer?

Espressif warns that periods below 50 µs consume “most of the CPU time”; use hardware peripherals or DMA for faster needs [Elektroda, khoam, post #19449941]

Why does Wi-Fi crash when my timer ISR runs?

esp_timer callbacks run at priority 22 on core 0, pre-empting Wi-Fi tasks on the same core. Long ISRs starve the Wi-Fi stack and trigger panics [Elektroda, khoam, post #19545217]

Can I fix the Wi-Fi clash by moving the timer to core 1?

Yes. Create the timer inside a task pinned to core 1 with xTaskCreatePinnedToCore, or call esp_ipc_call to execute setup on core 1 [Elektroda, khoam, post #19563512]

Why does ADC2 stop working when Wi-Fi is enabled?

ADC2 hardware is shared with the Wi-Fi radio. Reading ADC2 while Wi-Fi runs returns ESP_ERR_TIMEOUT or causes panics. Use ADC1 channels (GPIO 34-39) or stop Wi-Fi before sampling [Elektroda, NIXIE_123, post #19558056]

How do I guarantee my ISR code stays in RAM?

Add IRAM_ATTR to the callback and any helper it calls, ensure variables it touches are in DRAM, and register the interrupt with ESP_INTR_FLAG_IRAM; otherwise flash writes will disable the handler [Elektroda, ESP_Sprite, post #19550055]

Edge case: why does timer_spinlock_take disappear after upgrading IDF?

The call is deprecated beyond v4.3; switch to timer_isr_callback_add, which wraps the critical section for you [Elektroda, khoam, post #19550573]

How can I update Wi-Fi credentials via a browser without Arduino libraries?

Run the ESP32 in AP mode, host an HTTP server, parse the POST data, and store SSID, password, and variables to NVS. Only 4 kB flash and 20 kB RAM are needed (typical) [Espressif HTTP Server Guide].

Quick How-To: create a 111 µs hardware timer ISR

  1. Configure divider = 80 and alarm_value = 111.
  2. Register ISR with timer_isr_callback_add(..., ESP_INTR_FLAG_IRAM).
  3. In ISR, clear the interrupt: write 1 to TIMERG0.int_clr_timers.t0. [Elektroda, 19546162]
Generated by the language model.
ADVERTISEMENT