Skip to content

Commit 45a181c

Browse files
committed
Add task stats
1 parent 9c2fd8d commit 45a181c

File tree

3 files changed

+79
-5
lines changed

3 files changed

+79
-5
lines changed

samples/Esp32_Dual_Core/README.rst

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,51 @@
11
ESP32 Dual Core
22
===============
33

4+
.. highlight:: text
5+
46
Basic example of using second core of Esp32 chip.
57

6-
Code should be in IRAM and avoid accessing flash, especially the filing system.
8+
.. important::
9+
10+
Sming is NOT thread-safe! In general, only re-entrant code and code intended to be called from interrupt context is safe to use from multiple cores.
11+
12+
If code is timing sensitive then it should be run from IRAM.
13+
14+
Flash and filing system access must only be done from the main Sming application.
15+
16+
17+
Required steps
18+
--------------
19+
20+
- Override IDF SDK config settings as in ``esp-dual-core.cfg``.
21+
- Add line to project's ``component.mk``: *SDK_CUSTOM_CONFIG := esp32-dual-core.cfg*
22+
- Add application code to run on second core and call to start for that core
23+
- Run `make sdk-config-clean` to ensure custom configuration values are picked up
24+
25+
The custom configuration enables dual-core operation (``CONFIG_FREERTOS_UNICORE=n``) and disables the idle task for the second core (``CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n``). This ensures that code will run uninterrupted.
26+
27+
Task stats shows this when running::
28+
29+
# | Core | Prio | Handle | Run Time | % Time | Name
30+
1 | 0 | 24 | 3ffaee9c | 0 | 0% | ipc0
31+
3 | 0 | 22 | 3ffaf568 | 3226 | 0% | esp_timer
32+
5 | 0 | 0 | 3ffb8974 | 1996774 | 49% | IDLE0
33+
2 | 1 | 24 | 3ffaf404 | 0 | 0% | ipc1
34+
8 | 1 | 18 | 3ffbdf44 | 33156 | 0% | Sming
35+
7 | 1 | 5 | 3ffb9d24 | 1966844 | 49% | Sming2
36+
6 | 1 | 0 | 3ffb9118 | 0 | 0% | IDLE1
37+
38+
39+
Bare Metal
40+
----------
41+
42+
Because we rely on the IDF and its dependency on FreeRTOS, the above approach also ensures that calls such as ``System.queueCallback`` will work. This is the recommended way to communicate between code running on different cores.
43+
44+
The default mode for Sming runs without FreeRTOS on the second core (*CONFIG_FREERTOS_UNICORE=y*) which provides a smaller set of tasks and thus lower system memory usage::
45+
46+
# | Core | Prio | Handle | Run Time | % Time | Name
47+
1 | 0 | 22 | 3ffaf470 | 29 | 0% | esp_timer
48+
4 | 0 | 18 | 3ffb778c | 11016 | 0% | Sming
49+
3 | 0 | 0 | 3ffafdb0 | 1988955 | 49% | IDLE
750

8-
Sming is NOT thread-safe!
51+
In this state it is technically possible to get code running on the second core by hooking a low-level startup routine. The application would need to handle stack/heap allocation and code would be far more limited in what it can safely do.

samples/Esp32_Dual_Core/app/application.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,55 @@
11
#include <SmingCore.h>
2+
#include <Services/Profiling/TaskStat.h>
3+
4+
namespace
5+
{
6+
Profiling::TaskStat taskStat(Serial);
7+
SimpleTimer statTimer;
28

39
void handleNotification(uint32_t param)
410
{
5-
Serial << "NOTIFY " << param << endl;
11+
debug_i("NOTIFY %u", param);
612
}
713

814
// Code to run on second CPU
915
void IRAM_ATTR app2_main(void*)
1016
{
1117
static unsigned count;
1218

19+
// Using a polled timer has virtually zero overhead as it accesses timing hardware directly
20+
PeriodicFastUs timer(100);
21+
1322
for(;;) {
14-
System.queueCallback(handleNotification, count);
23+
if(!timer.expired()) {
24+
continue;
25+
}
26+
27+
if(count % 10000 == 0) {
28+
System.queueCallback(handleNotification, count);
29+
30+
debug_i("TICK");
31+
32+
// This is required if CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
33+
// WDT.alive();
34+
}
1535
++count;
16-
delay(500);
1736
}
1837
}
1938

39+
} // namespace
40+
2041
void init()
2142
{
2243
Serial.begin(SERIAL_BAUD_RATE);
2344
Serial.systemDebugOutput(true);
2445

2546
Serial.println(_F("ESP32 dual-core demo."));
2647

48+
// Provide some periodic status so we can see what tasks are active
49+
statTimer.initializeMs<2000>([]() { taskStat.update(); });
50+
statTimer.start();
51+
52+
// Create task running on second core
2753
const unsigned stackSize = 2048;
2854
const unsigned priority = 5;
2955
xTaskCreatePinnedToCore(app2_main, "Sming2", stackSize, nullptr, priority, nullptr, 1);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1+
# Enable dual-core operation
12
CONFIG_FREERTOS_UNICORE=n
3+
4+
# If watchdog is required, code will need to suspend periodically via `WDT.alive`.
5+
# Leaving it disabled ensures code runs uninterrupted on second core.
6+
CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=n

0 commit comments

Comments
 (0)