earlephilhower / arduino-pico

Raspberry Pi Pico Arduino core, for all RP2040 and RP2350 boards
GNU Lesser General Public License v2.1
2.02k stars 421 forks source link

PicoW hang during init when using FreeRTOS #1394

Closed earlephilhower closed 1 year ago

earlephilhower commented 1 year ago

Discussed in https://github.com/earlephilhower/arduino-pico/discussions/1390

Originally posted by **ruifig** April 22, 2023 I'm experimenting with adding FreeRTOS tasks. With a minimal application it works fine but with my actual project, it's freezing at startup with this callstack: ``` sleep_until@0x1003774a (\sleep_until.dbgasm:43) capture_additional_rosc_samples@0x10045778 (Unknown Source:151) initialise_rand@0x10045822 (Unknown Source:210) get_rand_64@0x10045822 (\get_rand_64.dbgasm:66) get_rand_32@0x100459c2 (\get_rand_32.dbgasm:3) udp_init@0x10042196 (\udp_init.dbgasm:3) lwip_init@0x1004794c (\lwip_init.dbgasm:7) lwip_nosys_init@0x10045550 (\lwip_nosys_init.dbgasm:8) cyw43_arch_init@0x1003d088 (\cyw43_arch_init.dbgasm:14) cyw43_arch_init_with_country@0x1003ce82 (\cyw43_arch_init_with_country.dbgasm:5) initVariant@0x100035cc (c:\Users\Rui\.platformio\packages\framework-arduinopico\variants\rpipicow\picow_init.cpp:65) main@0x10034326 (c:\Users\Rui\.platformio\packages\framework-arduinopico\cores\rp2040\main.cpp:99) ``` Still investigating to see if I can pinpoint why it works with one and fails with another, but any tips are welcome if this rings any bells. :) The only thing that crosses my mind is that maybe I have some global objects with non-trivial constructors that somehow messes things up before main is called, but don't think that's the case. For context, what I'm trying to do is to make use of the rp2040 watchdog in my application, which works fine using Arduino-Pico's `rp2040` object. But as far I've noticed, there is no way to disable the watchdog once enabled, so if we call into any third-party code or Arduino-Pico's code that takes too long to complete, like for example connecting to Wifi, then there a good chance it will trigger a watchdog reboot. The workaround I'm trying is to create a very simple FreeRTOS task that allows me to implement a watchdog pause of sorts. For example, I created a task like this (stays suspended) ``` void autoResetTask(void* pvParameters) { while(true) { rp2040.wdt_reset(); delay(250); } } ``` Under normal circumstances, my application calls `rp2040.wtd_reset()` periodically, then when I know I'm calling code that potentially can take longer than 8300ms, I wrap that code with a vTaskResume / vTasSuspend to enable/disable the watchdog auto reset. This is all working fine with a minimal(ish) sample application I was playing around with, but with my actual application if freezes at startup as explained above. I know this won't work with cooperative multitasking (I think Arduino-Pico's FreeRTOS uses cooperative, right?), but I'm not too bothered, since Wifi code does a few delays when connecting.
earlephilhower commented 1 year ago

From the discussion....

Seems like the other core is not doing anything yet:

image

Also, figured out why the sample application worked and my real application didn't.

extern "C" void initVariant() {
    __isPicoW = CheckPicoW();
    if (__isPicoW) {
        cyw43_arch_init_with_country(WIFICC);
    }
}

The sample application was setup to use a Pico while my real application uses a PicoW. Once I change the sample application to use a PicoW, it also freezes.

Regarding pinging the WDT in a while loop in a separate task, that's just a workaround to avoid the WTD triggering while calling code that takes too long and I can't or don't want to change, like connecting to WiFi. For example, calling WifiMulti::run can take longer than 8300ms, triggering the WTD.

So, back to the freeze, seems like the easiest way to repro this is to simply create a minimal application for PicoW and include the FreeRTOS.h header. It has nothing to do with using the WTD. That was just a coincidence. This is enough to repro:

#include <Arduino.h>
#include <FreeRTOS.h> // << Just including this causes the freeze

void setup()
{
    Serial.begin(115200);
    Serial.println("Hello world");
}

void loop()
{
    Serial.println(millis());
    delay(1000);
}

My platformio.ini

[platformio]
default_envs = earlephilhower

;
; Custom data group
; can be use in [env:***] via ${common.***}
[common]
picoprobe_tools_path = B:/Utils/Picoprobe

[env:earlephilhower]
platform = https://github.com/maxgerhardt/platform-raspberrypi#5a533d6b36844183bb72794bc53091206165e921
board = rpipicow
framework = arduino
board_build.core = earlephilhower
build_type = debug
upload_protocol = custom
upload_command = ${common.picoprobe_tools_path}/upload_openocd.bat "$BUILD_DIR/${PROGNAME}.elf" "$PROJECT_DIR"
debug_tool = custom
debug_server = 
    ${common.picoprobe_tools_path}/debug_openocd.bat
debug_port = localhost:3333
lib_ldf_mode=chain+
earlephilhower commented 1 year ago

Moved to an issue since we have a nice simple MCVE!