Raspberry Pi Pico with FreeRTOS
FreeRTOS on Raspberry Pi Pico?
After spending many hours trying to get coreMQTT to work with lwIP and BearSSL, I finally gave up. The problem was incompatible APIs. coreMQTT doesn’t really work with asynchronous functions (sending N bytes and being told that M have been sent via an asynchronous callback).
Using the simplified I/O in BearSSL doesn’t work either - coreMQTT wants recv
to return immediately if there’s nothing to read (and a single byte was requested). However, BearSSL insists that recv
blocks until at least one byte has been read.
So after fighting this for a while, I decided to try something new. FreeRTOS.
This and follow-up posts document my attempts at running FreeRTOS, lwIP, mbedTLS and coreMQTT on Raspberry Pi Pico.
FreeRTOS
Following the information in FreeRTOS-Kernel I am using https://github.com/FreeRTOS/FreeRTOS-Kernel/tree/smp). There are fairly clear instructions in the README.
For FreeRTOSConfig.h
I’m using the example from GitHub.
To build it with lwIP, one small change is required:
-#define configENABLE_BACKWARD_COMPATIBILITY 0
+#define configENABLE_BACKWARD_COMPATIBILITY 1
otherwise:
pico/pico-sdk/lib/lwip/contrib/ports/freertos/sys_arch.c: In function 'sys_arch_msleep':
pico/pico-sdk/lib/lwip/contrib/ports/freertos/sys_arch.c:192:39: error: 'portTICK_RATE_MS' undeclared (first use in this function); did you mean 'portTICK_PERIOD_MS'?
TickType_t delay_ticks = delay_ms / portTICK_RATE_MS;
^~~~~~~~~~~~~~~~
portTICK_PERIOD_MS
Now it compiles, but the linker is missing a couple of functions:
- undefined reference to ‘vApplicationMallocFailedHook’
- undefined reference to ‘vApplicationTickHook’
There’s information about those hooks here. It says that setting configUSE_TICK_HOOK
and configUSE_MALLOC_FAILED_HOOK
to 0 should allow this to build without implementing the hooks, but that’s not what I’m seeing.
Using the sample code for now.
Running a minimal amount of code fails immediately with:
assertion "pxNewQueue" failed: file "<path>/FreeRTOS-Kernel/queue.c", line 480, function: xQueueGenericCreate
Adding this to the bottom of lwipopts.h
helps:
#if !NO_SYS
#define TCPIP_THREAD_STACKSIZE 1024
#define DEFAULT_THREAD_STACKSIZE 1024
#define DEFAULT_RAW_RECVMBOX_SIZE 8
#define TCPIP_MBOX_SIZE 8
#define LWIP_TIMEVAL_PRIVATE 0
#define DEFAULT_UDP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
#define DEFAULT_TCP_RECVMBOX_SIZE TCPIP_MBOX_SIZE
// not necessary, can be done either way
#define LWIP_TCPIP_CORE_LOCKING_INPUT 1
#endif
(taken from another example)
and changing the stack size in FreeRTOSConfig.h
-#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 256
+#define configMINIMAL_STACK_SIZE ( configSTACK_DEPTH_TYPE ) 1024
And now things can build and run. But the story isn’t over yet, of course.