This is so incorrect I made an account.
Yes, empty functions can be optimized out by the compiler. They are not always, but most often are. It is unwise to speak in absolutes.
loop() is not doing anything except what's inside loop() -- Arduino cannot/does not arbitrarily add code within another function in this manner. On the AVR platform, loop() is called within an infinite loop which also processes serial events, immediately after the user's setup() is called, after core timers and ISRs (including timer0 for millis() which comes up soon...) and other things are initialized. On the Espressif32 platform, loop() is called by void loopTask(void *pvParameters)
within cores/esp32/main.cpp --
void loopTask(void *pvParameters)
{
setup();
for(;;) {
#if CONFIG_FREERTOS_UNICORE
yieldIfNecessary();
#endif
if(loopTaskWDTEnabled){
esp_task_wdt_reset();
}
loop();
if (serialEventRun) serialEventRun();
}
}
If you were to find a way to omit loop() from your own code, it's still called within a hard infinite loop with a few other tasks. Killing that loop (the one loop() is called inside) would disable the wdt timer reset (IE WDT would kick if not externally tamed) on the ESP32, and hardware serial event triggers on both ESP32 and AVR platforms.
The idea that millis()
is "updated" conveys a full lack of comprehension of how any of this works behind the scenes. On AVR platforms, the millis() function boils down to returning the variable volatile unsigned long timer0_millis
(aka uint64) declared in cores/arduino/wiring.c and that specific long is updated by the ISR for hardware timer0, it isn't "updated" in a loop.
On the Espressif32 platform, millis()
is the result of dividing the return of int64_t esp_timer_get_time(void);
(a core library function whose source is not provided in the platform files) which is, again, not "run in a loop" -- it's a core library call to a counter which is incremented in hardware every clock cycle the device is powered. It's hardware, not software, which is what makes it ground-truth level accurate. (Similar to the AVR's timer0 ISR; that's the closest the AVR platform has to "ground truth" regarding the concept of time.)
The Wifi stack and other processes, etc are run in their own functions, called by their own hardware and/or triggers. With Arduino, ESP32 runs FreeRTOS -- yes, an entire operating system -- and calls your setup() and loop() functions as tasks within that OS.
When you write code in void loop() { ... }
Arduino DOES NOT add things to it. That's your function. Arduino calls it regularly.
@sword111 --- vTaskDelete(null) -- PS, case matters in C -- tells FreeRTOS to delete the task it is called from within. (source) On Espressif32 this means the entire loopTask function I mentioned above. Repercussions appear to be serialEventRun() and wdt taming events won't happen. Do note, these tasks are run by a scheduler and the core is designed to avoid running 100% full hard loop like the AVR platform did. You likely won't see much power savings or performance increase. There appears to be no harm to it.
I've been throwing baremetal and Arduino code at AVRs for decades. I just started working with the ESP32 three days ago and had to do a ton of learning this to rebase a very complicated timing-critical project onto something with considerably more torque behind it.