The Raspberry Pi Pico
Microcontroller Board

Raspberry Pi Pico Microcontroller Board

12/19/2021

Investigating the Raspberry Pi Pico Microcontroller Board

Overview
I’ve finally got around to doing a little more experimenting with the new offering from the Raspberry Pi Foundation
the Pico board based on their new custom built chip the
RP2040.

So let’s get started and look at the features of the new chip...

RP2040 features:
Dual Arm Cortex-M0+ at 133 MHz
264 KB of on-chip RAM
Support for up to 16 MB of off-chip Flash memory via a dedicated QSPI bus
DMA controller
Interpolator and integer divider peripherals
30 GPIO pins, three of which can be used as analog inputs
Two UARTs, two SPI controllers, and two I2C controllers
16 PWM channels
USB 1.1 controller and PHY with host and device support
Eight PIO state machines as a CPU just to make things interesting.

Now in the Pico board implementation only 26 GPIO pins are exposed (3 of which are ADC capable).

Something that you may have not noticed in the above feature list is this:
Support for up to 16 MB of off-chip Flash memory” and no mention of on-chip flash.
That’s because this chip doesn't have ANY on-chip flash, it’s all contained in an external
W25Q16JV serial flash memory chip that contains 2MB of flash memory.
This is something I’ve not encountered in modern microcontrollers before and made me wonder how they can get decent performance using an external serial memory chip.
Well it seems they have done some pretty interesting design to accomplish this. First the flash is accessed over a dedicated QSPI bus. If like me you’re new to this technology, it means the device interface has a typical SPI clock line but FOUR SPI data lines (so 4x the SPI data transfer of a single line chip). Furthermore, the chip provides something called “Execute In Place” (XIP) hardware making the external memory appear to the processor as if it were internal memory. There’s a dedicated 16K cache included in the XIP hardware to keep flash memory access super fast.

Although the processor can be configured to run at 133MHz the default clock rate on the Pico board is 125MHz. Still a lot faster than the 72MHz STM32F103 boards and the 16MHz Arduino boards.

Another quite interesting feature of the Pico board is the power regulator.
While most common development boards include a 5V or 3.3V voltage regulator this board uses an onboard
buck-boost converter to generate a fixed output of 3.3V for the processor using an input voltage as low as 1.8V
and up to 5.5V so one could easily power this board with a few AAA batteries or a single 3.3V Lithium-Ion cell. On the downside, using a supply voltage greater than 5V will require some additional components.
Of course the most common method of powering this board would be through the micro-USB port.

That being said, In case you haven't guessed it by now, the GPIO pins on this board will NOT tolerate inputs above 3.3V. Consider yourself warned.


Development Environment

The preferred development environment is a Raspberry Pi as a host with Micropython as the programming language

I had hoped to find details on how to set up the Eclipse IDE on my Windows PC to program for this device but there was nothing to be found that I could readily understand. This surprised me since I was easily able to configure Eclipse and the GCC Arm Compiler to work with the STM32 and Atmel SAM boards (both using ARM processors as well).
I was however able to find a pre-built setup program that uses Visual Studio Code as the IDE along with the ARM GCC Compiler.
https://github.com/ndabas/pico-setup-windows/releases

This package worked quite smoothly and installed all the tools recommended in the official
Getting Started guide. However this install program was over 370MB and installed 9 programs / packages.
The installation program set up everything with the necessary settings and built a few of the example programs
and commonly used libraries.

The heart of the build system is Cmake which drives the build process via a dizzying collection of scripts and configuration files. Thankfully I was able to somewhat figure out how to use the included “Pico Project Generator” to successfully create a simple project that would compile and run without errors. I was even able to customize it a bit for my own setup.

Programming The Flash
One method of programming the flash on the Pico board is to use the “USB Mass Storage Device Mode”. Holding down the “BOOTSEL” button on the board while applying power will cause it to boot in this mode and appear as a USB hard drive on your PC. Copying the .U2F file generated by the compiler to this drive will program the flash from the file and then re-boot and execute the freshly loaded code. Couldn’t be easier, (or could it…)

While examining the SDK source code for the USB Virtual Serial Port this board supports, I came across a constant defined as “PICO_STDIO_USB_RESET_MAGIC_BAUD_RATE” a little more poking around and I discovered that if
one had the board programmed to use the USB Virtual Serial Port (which happens to be the most convenient way to communicate with a project), and the host PC attempts to open the virtual COM port it presented at 1200 baud, the board would reset in BOOTSEL mode.

I tried this manually and it worked!!! This gave me an idea.

The Arduino DUE board has the need to press a similar button to program it’s ARM chip but the Arduino folks would have none of that and also used the “open COM port at 1200 baud” trick to switch it to programming mode. For supporting that board in the eclipse IDE, I previously built a small PC program called COM1200.exe that would simply attempt to open a selected COM port at 1200 baud and then exit.
For the Pico board, by invoking COM1200 through a batch file that would then pause for a second (to allow the BOOTSEL program to execute and the board to appear as a USB drive), then copy a specified file to the new drive, I could flash the board with a few clicks of the mouse.
Later I was able to integrate the launching of this batch file into the Visual Studio Code IDE.
This is
VERY specific to the system it’s working with as the USB virtual COM port created by the Pico board ( for me, COM8) as well as the drive letter it creates in BOOTSEL mode (for me, H:) are specific to my setup. If either of these change I’ll have to adjust the batch file accordingly as would anybody using the file I will share below on their own systems. (see pico_tools.zip in the downloads section at the bottom of this page)

Documentation
The documentation for this new microcontroller board is quite well done considering it’s such a new product.
You can find links for all the docs here:
https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html

These include:
Getting started with Raspberry Pi Pico
Raspberry Pi Pico Datasheet
Raspberry Pi Pico C/C++ SDK
Raspberry Pi Pico Python SDK
RP2040 Datasheet

Notable Features
Dual Cores:
This is the first time I’ve experimented with a multi-core microcontroller.
Using one of the example programs as a guide I was easily able to get the second core running with
a simple LED blinking program that had a lot of blocking delay commands. By running this program
on the main core (Core0) I could demonstrate that everything else stopped until it completed.
When I launched it on the secondary core (Core1), I was still able to perform tasks on the main core.
Launching the second core was much easier than I had expected.

Programmable PIO: Another quite interesting feature of the RP2040 is the programmable PIO support.
This is basically a way to write simple code that will control any GPIO pin with little or no CPU overhead.
The examples provided ranged from simple blinking of an LED to programming an additional UART and
even a simple logic analyzer. I was able to modify the blinking led example and had that figured
out pretty well with 3 LEDs all blinking at different rates without effecting the operation of other functions.
I’ll need to study the datasheet and examples a LOT more to figure out anything more complex using PIO.

Features Investigated So Far…
At the time of this writing I’ve written sample code using the UART and USB Serial communication ports.
I've coded sample projects that work with the PIO and multicore. (mostly just slight mods of the example code from the SDK) and of course I’ve done GPIO output and input as well as SPI and PWM examples.
I’ll share a few of these project in the download section at the very bottom of this page.

Tips for using the sample projects I've shared below:
Make sure you have the Pico Project Generator working in your development environment.

Generate a new project with the same name as one of my samples. "USBIO_Menu" is a good one to start with.
Download and unzip the sample project replacing the generated files with those from the .zip file.

Edit CmakeLists.txt and change the PICO_SDK_PATH setting to match YOUR ..\Pico\pico-sdk location.

Launch Visual Studio Code and build the new project.


Pico Board Top & Bottom

My Pico Breadboard

Pico Pinout

Visual Studio Code Screen

Modified Visual Studio Code Task Menu (see pico_tools_readme.txt for details )

Description of download links:

pico_tools.zip A few utilities I used to support flashing the board from the VS Code IDE
pio_blink.zip PIO sample project
UART0_Menu.zip UART sample project using hardware UART0
USBIO_LCD2x16.zip Drive a standard (HD44780) 2 Line x 16 char LCD
USBIO_Menu.zip USB Serial I/O sample project
USBIO_Multicore.zip Multicore sample project
USBIO_OLEDLCD.zip I2C sample project driving an SSD1303 128x64 OLED display
USBIO_PWM.zip PWM sample project