earlephilhower / arduino-pico

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

Feature request: Include FreeRTOS for RP2350 (from raspberry pi implementation?) #2428

Closed fietser28 closed 19 hours ago

fietser28 commented 1 week ago

Hello,

Thank you for creating Arduino-pico, I'm a very happy user using rp2040! I'm also impressed how far the RP2350 support already is. Unfortunately for me the main project I'm creating depends on FreeRTOS.

As you stated there is currently no support for FreeRTOS. I've noticed however that raspberry pi have created a FreeRTOS clone with RP2350 support (for ARM M33 cores and based on existing implementation). The repository is: https://github.com/raspberrypi/FreeRTOS-Kernel

Would this help to get FreeRTOS working for rp2350s in Arduino-pico without to much effort?

earlephilhower commented 1 week ago

2406 has been there for a while. There are subtle issues with the 2350 implementation vs. the 2040 one that are causing weird mutex-related behaviour in stress test apps. If you have hacked the FreeRTOS internals, please give it a look and see if you can discover why the tests/freertos_syscallmutex fails to make progress in certain tasks.

fietser28 commented 1 week ago

I scanned the issues but not the branches and pull request.

I did some digging and maybe found something: Adding a delay in the start of the threads solves the problem for this test.

You can find a working test at: https://github.com/fietser28/arduino-pico-freertos-test

earlephilhower commented 1 week ago

Cool, thanks! Doesn't pinpoint anything but now there's a hack I can examine to see what goes differently inside the kernel. Should be no need to sleep before the while(1) especially since there's a delay in every loop...

fietser28 commented 5 days ago

I did some tests to try to help pinpoint and can share the following:

The main test case is after 10 seconds of running: from loop a call to vTaskCoreAffinitySet is done to change the affinity of loop2. This is similar to the original behaviour where after a createTask a vTaskCoreAffinitySet is done but the thread is already running then (that's the way Arduino-pico works) and I avoided that scenario with the delays at the start of the threads. Using this code:

  1. I've copied the content from the *.ino to compile on plain Pico-SDK + FreeRTOS. There the sketch doesn't crash, it works.
  2. To this Pico-SDK + FreeRTOS setup I've tried to add all the things Arduino-pico adds one by one (like idle tasks, stats function, copy FreeRTOS config, ... mainly from variantsHook.cpp). No matter what I add, the program keeps working.
  3. I've played around with enabling/disabling the malloc/free functions in the Arduino-pico repo. That revealed an interesting case: If I replacing the malloc/realloc/free functions with a busy loop in the threads whos affinity is changed the program doesn't crash anymore. I suspect a memory function running in a thread during a vTaskCoreAffinitySet call in another thread to change the affinity during the execution of a memory function.

I've made an update to the repo https://github.com/fietser28/arduino-pico-freertos-test. Setting:

#define BUSY_MALLOC 1

will result in a crash.

define #BUSY_LOOP 1

will result in a program that keeps running.

I suspect (but not sure) the malloc-lock.cpp needs to be made FreeRTOS compatible. Maybe using pvPortMalloc/pvPortFree when FreeRTOS is being used?

earlephilhower commented 5 days ago

The port prefix is generally for "ported" calls in FreeRTOS AIUI. pvPortMalloc is something the app implements to give to FreeRTOS to do it's work. We implement that, using FreeRTOS mutexes, already (or else the RP2040 implementation would fail and most FreeRTOS apps there would simply not even start up).. We use Newlib's malloc implementation, not gcc's FWIW.

Thanks, though, for verifying the RP2350 SDK branch is clean. It doesn't support things like multicore flash writes (or it didn't when I did my original port...I seemed to run into that before the SDK guys did unluckily), but maybe that's a hint. If they're using the intercore FIFO in a different way on the 2350 vs. the 2040 then all bets would be off...

fietser28 commented 3 days ago

Did some more digging (and a lot of learning how all the libraries interact) and came up with this change. When using FreeRTOS I think the handling of critical sections should also be done via FreeRTOS calls. This suddenly made some cases work. Will need to test for more cases.

earlephilhower commented 19 hours ago

Done