Raspberry Pi Pico W
Overview
This tutorial demonstrates how Mongoose Library can be used to implement a device dashboard on a Raspberry Pi Pico W using the Pico-SDK with FreeRTOS and lwIP.
This tutorial is an example following on the device dashboard tutorial. You should read and follow that tutorial first.
Project structure
This example uses the Pico-SDK and includes configuration files for lwIP and FreeRTOS:
main.c
- main application file, contains Mongoose logic and WiFi network initialization codemongoose.c
- Mongoose Library source codemongoose.h
- Mongoose Library header filenet.c
- the common code for this examplepacked_fs.c
- a packed filesystem containing the web files to be servedlwipopts.h
- some lwIP config macros tweaked to suit this implementationFreeRTOSConfig.h
- some FreeRTOS config macros tweaked to suit this implementationCMakeLists.txt
- A cmake file that selects the source files and compilation optionsMakefile
- mainly pulls FreeRTOS and the Pico-SDK from their Github repos and calls cmake
https://github.com/cesanta/mongoose/blob/master/examples/pico-sdk/pico-w-picosdk-freertos-lwip/
Build the project
It is assumed that you're using Linux or Mac as a workstation, you have Docker installed, and your user is able to run it. If in doubt, check it:
$ docker ps
Start a terminal in the project directory; clone the Mongoose Library repo,
and run the make
command:
$ git clone https://github.com/cesanta/mongoose
$ cd mongoose/examples/pico-sdk/pico-w-picosdk-freertos-lwip
$ make build
- Once the build succeeds, boot your Pico W in USB Mass Storage Mode by holding down the
BOOTSEL
button while you plug it into the USB port. Once it is connected, then release theBOOTSEL
button. It should automatically mount as a new USB disk in your machine. Now either manually copy or drag and drop the generatedfirmware.uf2
file into this new USB disk device. - The Pico W will flash this code and reboot, unmounting this disk and running the flashed code.
- Now open a second terminal, this will be our serial console to see the logs. Run a serial port software (we use minicom; make sure you configure it at 115200bps). Device name is usually
/dev/ttyACM0
$ minicom -D /dev/ttyACM0
Try it out
Start a browser on http://IP_ADDRESS
where IP_ADDRESS
is the board's IP address assigned by your DHCP server. You should see a login screen.
From here on, please go to the device dashboard tutorial and repeat some of the steps depicted there
Main task
The main()
function initializes the board and starts the FreeRTOS scheduler, creating a new task for us. This task has two blocks:
- Initialize WiFi and wait until the network is ready (DHCP has assigned us an IP address)
- Run Mongoose
Initialize the network
We call the function in charge of initializing the wireless chip, then call the WiFi connect function, which is a blocking function and returns when we have a valid IP address or the process has failed
Run Mongoose
Next goes Mongoose. It should be run after network initialization is complete. The logic is standard; we initialize the event manager, start a listener, and fall into an infinite event loop:
For this example we've chosen to embed all the web files in a packed filesystem, more information on the embedded filesystem tutorial
Note that Mongoose has been configured to run under FreeRTOS and lwIP, we do so in the Makefile by defining MG_ARCH=MG_ARCH_FREERTOS
and MG_ENABLE_LWIP=1
We have covered those aspects that are specific to the Pico W implementation, for the details on the application and the UI, please see the device dashboard tutorial.
Configuring FreeRTOS
- Task Memory allocation defaults to dynamic. This means that memory for the stack of each new task, will be allocated from FreeRTOS heap. To work with applications requiring a high stack size, FreeRTOS heap size must be large:
- Some tasks, like the WiFi chip driver, need a stack a bit over the bare minimum that is usually FreeRTOS default. As it will use the configured minimum, we define that on the FreeRTOS configuration file (in words):
- Mongoose needs a large stack, we specify that at the task creation function call (in words):
Configuring lwIP
- Since we'll be using several connections simultaneously, we need to tell lwIP so. Even though we are using the socket interface, internally in lwIP it uses a decoupling API called netconn, so we'll set the number of allowed connections high enough: Make sure you don't modify `LWIP_NETCONN`, the default is for it to be enabled, so leave it as it is and don't redefine it in your lwipopts.h file
- lwIP default priorities are simple numbers which might or might not coincide with the RTOS defined range; we take care to assign them in accordance with the rest of our project. Don't go much higher as the WiFi chip driver task is currently at tskIDLE_PRIORITY + 4. Furthermore, lwIP stack size default definitions are in bytes, while FreeRTOS uses words, so there is a macro to clearly express our choice on the stack sizes beyond doubt: