RTOS running on one core only

User avatar
HelWeb
Posts: 36
Joined: Sat Mar 23, 2019 8:39 am

Re: RTOS running on one core only

Postby HelWeb » Wed Apr 10, 2019 12:44 am

A picture tells more than 1000 words ;)
Attachments
xtask (3).jpg
xtask (3).jpg (80.36 KiB) Viewed 13857 times
Fast is not fast enough :D

chrismerck
Posts: 76
Joined: Tue May 29, 2018 8:00 pm

Re: RTOS running on one core only

Postby chrismerck » Wed May 01, 2019 3:23 pm

@HelWeb:

Just want to thank you for posting your technique for running without RTOS on Core1. This is extremely useful information to my team here to work around interrupt performance issues on Core0. We will let you know our results!

Merci vielmal!

apuder
Posts: 53
Joined: Mon Mar 26, 2018 7:27 pm

Re: RTOS running on one core only

Postby apuder » Wed Jun 05, 2019 2:59 am

Thanks for the nice explanations. I have been trying the same thing. I have a question about portDISABLE_INTERRUPTS(): does this turn off interrupts only on the core where that function is called or turn off interrupts for both cores? I am calling this function on core 1, but then I noticed some unusual behavior on core 0 (more precisely, on core 0 I try to connect to WiFi but nothing happens (with "nothing" I mean no error, no log; as if I didn't call any WiFi API))
TIA,
AP

apuder
Posts: 53
Joined: Mon Mar 26, 2018 7:27 pm

Re: RTOS running on one core only

Postby apuder » Wed Jun 05, 2019 6:48 pm

followup to my own question. portDISABLE_INTERRUPTS() only disables interrupts on the core where that function is called. So in the scenario discussed here, interrupts on core 0 are still enabled. However, I have noticed that FreeRTOS will create an "ipc" task on core 1. I wonder if disabling interrupts on core 1 might have impact on IPC on core 0. That could explain the behavior I observe. Anyone out there has an idea?
AP

apuder
Posts: 53
Joined: Mon Mar 26, 2018 7:27 pm

Re: RTOS running on one core only

Postby apuder » Wed Jun 05, 2019 11:13 pm

more digging: the problem seems to be indeed related to IPC. I logged esp_ipc_call() for core 1 and I was surprised how much code is executed on that core. E.g., calling nvs_flash_init() will trigger esp_ipc_call() on core 1. If interrupts are disabled on core 1 at that moment, then the ESP32 will just hang.

Anyone out there know why so much code is executed on core 1 via esp_ipc_call()? Could this be related to the interrupt that is used to synchronize D-port accesses?

AP

chrismerck
Posts: 76
Joined: Tue May 29, 2018 8:00 pm

Re: RTOS running on one core only

Postby chrismerck » Thu Sep 05, 2019 12:32 pm

Hey AP, in fact, we have run into a similar issue here.

If you read in the ESP-IDF version of FreeRTOS code, you will see conditional compilation in many places like this:

Code: Select all

#if !CONFIG_FREERTOS_UNICORE
You will often see while loops used to spinlock waiting for the other core to release some resource. It is unclear to me at this time exactly what all the shared resources are, but it is definitely related to flash access.

The problem we have is that we need to read/write a flash-based database on Core 0 whilst we are performing timing-sensitive RF work on Core 1 (12uS deadlines). We tried adding the following to the Core 1 loop:

Code: Select all

      portENABLE_INTERRUPTS();
      ets_delay_us(1);
      portDISABLE_INTERRUPTS();
Which relieves the deadlock, but unfortunately introduces >12uS of latency and breaks our RF requirements.

We are currently investigating how to use the UNICORE mode of FreeRTOS and manually launch our small RF code on Core 1 -- a major departure from HelWeb's method.

apuder
Posts: 53
Joined: Mon Mar 26, 2018 7:27 pm

Re: RTOS running on one core only

Postby apuder » Thu Sep 05, 2019 2:20 pm

The synchronization between the cores is definitely related to NVS access. I saw that when the ESP performs a core dump, it can write to NVS *without* syncing with the second core. In another thread I asked the question if I could use the same trick:
https://esp32.com/viewtopic.php?f=2&t=10901

Someone replied by saying probably not. I haven't tried it yet. My solution is to have a global volatile variable where core 0 sets a bit to signal to core 1 that it should temporarily enable interrupts. Core 0 does this just before it wants to access NVS. Part of the busy-wait loop on core 1 I also check this volatile variable. Most of the time I can keep interrupts turned off on core 1 and only for brief moments when I need to access NVS on core 0 I turn on interrupts. This is a little better than what you do.
AP

chrismerck
Posts: 76
Joined: Tue May 29, 2018 8:00 pm

Re: RTOS running on one core only

Postby chrismerck » Thu Sep 05, 2019 4:16 pm

only for brief moments
Thanks for the quick reply!

The minimum duration of those brief moments is dictated by the design of ESP-IDF. I'm not sure what Espressif's design latency is, but empirical testing on our end makes it seem greater than our requirement of <12uS, because we are missing deadlines when we enable interrupts even for just 1 uS of busywait.

apuder
Posts: 53
Joined: Mon Mar 26, 2018 7:27 pm

Re: RTOS running on one core only

Postby apuder » Thu Sep 05, 2019 4:43 pm

Not sure I understand what you are saying. Did you disable the watchdog timer on core 1? With that I can keep interrupts on core 1 turned off indefinitely as long as core 0 is not using the NVS. What I was proposing with the volatile global variable is just a simple signaling mechanism where I can temporarily enable interrupts again on core 1. The code sniplet you posted in your original message seems to suggest that you disable and enable interrupts with each iteration of your busywait loop on core 1. That is not necessary.
AP

chrismerck
Posts: 76
Joined: Tue May 29, 2018 8:00 pm

Re: RTOS running on one core only

Postby chrismerck » Thu Sep 05, 2019 5:49 pm

temporarily enable interrupts again on core 1
At which time you introduce potential delays into the code executing on core 1.
The code sniplet you posted in your original message seems to suggest that you disable and enable interrupts with each iteration of your busywait loop on core 1.
Our requirement is that we have a deadline every 25uS, continuously---we are servicing I/O pins based on an external 40kHz clock. Any missed deadline results in a corrupted transmit/receive signal. We we need to run about 13uS of code each deadline, so that leaves 12uS of time left to potentially service interrupts between deadlines. There's never a time to take a breath and accept a longer interruption.

We clearly didn't realize that the ESP-IDF design requires interrupts to be serviced by core 1 to permit core 0 operations. A DMA peripheral would be preferable, but RMT cannot sync to the external 40kHz bit clock, and the SPI driver doesn't seem to support the use case either. But we may need to revisit the SPI possibility.

Who is online

Users browsing this forum: Google [Bot] and 134 guests