There are a lot of embedded platforms with different performance today. Many devices have the same functionality and similar features. Thus, a developer accustomed to a variety of hardware platforms is very difficult to surprise with something really new.
What can the new board Raspberry Pi Pico, based on their own chip RP2040, surprise us with?
Raspberry Pi Pico is not such a high performance platform as other Raspberry Pi boards are, but much cheaper than others. Its performance can be compared with Arduino Due or ESP32.
This is a really very interesting device, based on two Cortex M0+ cores with a unique PIO module, that works like FPGA pins and can be programmed in Assembler language(I would say simplified Assembler).
Support for Raspberry Pi Pico is impressive. There are different programming languages such as Assembler, C, C++ and Python, used for programming the Raspberry Pi Pico.
Raspberry Pi Pico can be programmed in Arduino IDE as well.
RP2040 chip and Raspberry Pi Pico board are well documented, the documentation contains datasheets for both, hardware design with RP2040 and getting started with the board.
Raspberry Pi Foundation provides two SDKs to develop applications in Python and C/C++.
Let’s begin with the main features of the board :
- RP2040 microcontroller chip designed by Raspberry Pi in the United Kingdom
- Dual-core Arm Cortex M0+ processor, flexible clock running up to 133 MHz
- 264KB of SRAM, and 2MB of on-board Flash memory
- Castellated module allows soldering direct to carrier boards
- USB 1.1 with device and host support
- Low-power sleep and dormant modes
- Drag-and-drop programming using mass storage over USB
- 26 × multi-function GPIO pins
- 2 × SPI, 2 × I2C, 2 × UART, 3 × 12-bit ADC, 16 × controllable PWM channels
- Accurate clock and timer on-chip
- Temperature sensor
- Accelerated floating-point libraries on-chip
- 8 × Programmable I/O (PIO) state machines for custom peripheral support
Raspberry Pi Pico datasheet is available here https://datasheets.raspberrypi.org/pico/pico-datasheet.pdf
This contains an electrical schematic of Raspberry Pi Pico as well.
Look at the pinout diagram. As you can see, the board has a SWD connector for debugging, a user’s LED, micro USB connector, BOOTSEL button and 2×20 expansion contacts.
First of all, we need to read ‘Getting started with Raspberry Pi Pico’ https://datasheets.raspberrypi.org/pico/getting-started-with-pico.pdf and follow the instructions there.
If you are going to use the RPi 4B or RPi 400 board to develop applications for RPi Pico, it is very simple to deploy a developing environment there . The following actions should be performed on Raspberry Pi 4B/400 (make sure that you have an internet connection) :
- Download an installation script
$ wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh
- Add permissions to execute the script
$ chmod +x pico_setup.sh
- Run the installation script
$ ./pico_setup.sh
- Reboot your operating system
$ sudo reboot
If not, it depends on your host operating system. I use Ubuntu 20.04 LTS, so I had to read ‘Chapter 2. The SDK’.
Windows and OSX users should read ‘Chapter 9. Building on other platforms’ of ‘Getting started with RPi Pico’.
Author of the documentation prefers us to use Visual Studio Code. If you are not used to developing in Visual Studio Code, you can choose anything else, for example Eclipse or Clion.
After installing the necessary tools, it is time to blink the LED of the Raspberry Pi Pico. Run the following commands in the terminal:
$ cd ~/pico/pico-examples
$ mkdir build && cd build
$ export PICO_SDK_PATH=../../pico-sdk
$ cmake ..
$ cd blink
$ make -j $(nproc)
That’s all. Now we can upload the firmware to the Raspberry Pi Pico board.
Updating and debugging firmware
If you are running the Ubuntu 20.04 LTS Desktop like me, the Raspberry Pi Pico should automatically mount as a USB Mass Storage Device. From here, you can Drag-and-drop blink.uf2 onto the Mass Storage Device. RP2040 will reboot, unmounting itself as a Mass Storage Device, and start to run the flashed code. Next time, when you want to upgrade the firmware, you have to push the BOOT button before you power on the Raspberry Pi Pico to enter the upgrade mode.
If your application does not work or you want to understand how it works, you can use in-circuit debugging via SWD connector. But you have to have some hardware JTAG/SWD adapter such as J-Link, DAP-Link or another Raspberry Pi board with a pin expansion connector.
Using Picoprobe
From the documentation ‘Getting started with RPi Pico’ I knew that it is possible to use another Raspberry Pi Pico board as a SWD adapter (see ‘Appendix A. Using Picoprobe’).
This is a very interesting possibility, considering the low cost of the board. Let’s try it.
If I am not mistaken, picoprobe is a DAP-Link firmware, based on open standard CMSIS-DAP for Cortex-M microcontrollers, that provides USB-UART and USB-SWD bridge.
All we have to do is load the special firmware(picoprobe) onto the second Pico board. After that, we will get a full-fledged SWD adapter at the price of the Pico board.
By the way, you can use it for debugging other Cortex-M microcontrollers as well.
You have to read ‘Appendix A. Using Picoprobe’ to know what you need to do.
Here is the same description for Linux, because I am using Ubuntu 20.04 LTS.
For picoprobe to work, you need to build openocd with the picoprobe driver enabled:
$ sudo apt update
$ sudo apt install automake autoconf build-essential texinfo libtool libftdi-dev libusb-1.0-0-dev
$ cd ~/pico && git clone https://github.com/raspberrypi/openocd.git --branch picoprobe --depth=1 --no-single-branch
$ cd openocd && ./bootstrap
$ ./configure --enable-picoprobe
$ make -j$(nproc) && sudo make install
It is time to build and flash picoprobe :
$ cd ~/pico && git clone https://github.com/raspberrypi/picoprobe.git
$ cd picoprobe
$ mkdir build && cd build
$ cmake .. && make -j$(nproc)
Boot the Raspberry Pi Pico you would like to act as a debugger with the BOOTSEL button pressed and drag on picoprobe.uf2.
What we got in the end, it is a debugger with two interfaces, one of them is SWD, the other is UART to work as a USB-UART adapter independently of the first one.
The wiring between the two Pico boards is shown in the following table:
Pico A (picoprobe) | Pico B (dev board) |
GND | GND |
GP2 | SWCLK |
GP3 | SWDIO |
GP4/UART1 TX | GP1/UART0 RX |
GP5/UART1 RX | GP0/UART0 TX |
On a bright orange background, it looks like this:
To use picoprobe’s UART you can engage any terminal utility, for example minicom.
First, add yourself to dialout users’ group and reboot:
$ sudo usermod -a -G dialout $USER
$ sudo reboot
After that, check if you are in dialout group doing following:
$ groups
If so, let’s run minicom :
$ minicom -D /dev/ttyACM0 -b 115200
Using OpenOCD and GDB
To use debugging via SWD you need to launch openocd as a server and gdb as a client :
$ openocd -f interface/picoprobe.cfg -f target/rp2040.cfg -s tcl
Open On-Chip Debugger 0.10.0+dev-g18b4c35-dirty (2021-08-12-18:55)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'swd'
Warn : Transport "swd" was already selected
adapter speed: 5000 kHz
Info : Hardware thread awareness created
Info : Hardware thread awareness created
Info : RP2040 Flash Bank Command
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 5000 kHz
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x00000001
Info : SWD DPIDR 0x0bc12477
Info : SWD DLPIDR 0x10000001
Info : rp2040.core0: hardware has 4 breakpoints, 2 watchpoints
Info : rp2040.core1: hardware has 4 breakpoints, 2 watchpoints
Info : starting gdb server for rp2040.core0 on 3333
Info : Listening on port 3333 for gdb connections
Install gdb:
$ sudo apt install gdb-multiarch -y
Launch gdb:
$ cd ~/pico/pico-examples/build/blink
$ gdb-multiarch blink.elf
(gdb) target remote loacalhost:3333
(gdb) load
(gdb) b main
(gdb) c
Of Course , you can debug your application in your favorite IDE, in this case the IDE works as a client.
Automatic Project Generation
To create a new project automatically you can use a Python script that can run in GUI mode and command line mode.
Want to make use of this you’ll need to go ahead and clone the project creation script from its Git repository:
$ cd ~/pico && git clone https://github.com/raspberrypi/pico-project-generator.git
Do not forget to install TKInter library for using GUI:
$ sudo apt-get install python3-tk
Then it can be run in graphical mode:
$ cd pico-project-generator
$ ./pico_project.py --gui
Adding Pico to Arduino IDE
It is also possible to program Raspberry Pi Pico in Arduino IDE. Even a new version of Arduino Nano based on the RP 2040 chip was released.
If you decide to work with Raspberry Pi Pico in Arduino IDE, you will have to add support of the board first. For this, select File->Preferences menu item of Arduino IDE, then fill in ‘Additional Board Manager URLs’ with the link https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
After that select ‘Board: “Arduino Uno”->Board Manager…’ menu item, type ‘raspberry pi pico’ and install ‘Raspberry Pi Pico/RP2040’ package, which is installed in my picture.
When the package is installed, we need to select the board in ‘Tools->Boards: “Arduino Uno”->Raspberry Pi RP2040 Boards(1.9.4)->Raspberry Pi Pico’ menu item. The board information appears in the Tools menu.
C/C++ SDK Workflow
In this article I will show you that programming Raspberry Pi Pico using C/C++ SDK is no more difficult than in Arduino IDE. Even so, you use the Linux command shell.
Add the pico-project-generator path to your .bashrc config file:
$ gedit ~/.bashrc
export PATH=$PATH:~/pico/pico-project-generator
Then reboot the system :
$ sudo reboot
After that you can launch pico_project.py from any directory.
Let’s create a new directory for our experiments :
$ cd ~/pico && mkdir pico-workspace && cd pico-workspace
$ pico_project.py --gui
Select Project Name and Location, then click OK button
Blinking the LED
Now we can open automatically generated C file, edit it :
$ cd blink
$ gedit blink.c
1 2 3 4 5 6 7 8 9 10 11 12 |
#include <stdio.h> #include "pico/stdlib.h" int main() { stdio_init_all(); puts("Hello, world!"); return 0; } |
I am using White LED Module from Keyestudio Sensor Kit KS0068 https://wiki.keyestudio.com/Ks0068_keyestudio_37_in_1_Sensor_Kit_for_Arduino_Starters :
If you have the same module, connect it with the Raspberry Pi Pico as shown in the next table:
Raspberry Pi Pico | White LED Module |
GND | G |
3V3 | V |
GP15 | S |
Let’s modify our automatically generated project with following changes:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include <stdio.h> #include "pico/stdlib.h" int main() { const uint LED_PIN = 15;//GP15 gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); while (true) { gpio_put(LED_PIN, 1); sleep_ms(1000); gpio_put(LED_PIN, 0); sleep_ms(1000); } } |
Hold down the BOOTSEL button, then connect your Raspberry Pi Pico to your PC using micro USB cable, release the button. A new Mass Storage Device should appear.
Build the project and upload the firmware by copying the blink.uf2 file onto the device:
$ cd build
$ cmake .. && make -j$(nproc)
$ cp blink.uf2 /media/$USER/RPI-RP2
If you did everything right, the white LED should flash at 0.5 Hz (every two seconds).
As you can see, I’ve just changed the GPIO pin number and delay in the blink project from pico-examples. It works without debugging! It is easy!
This example is located here https://github.com/PetroShevchenko/cxemotexnika/tree/master/Examples/Raspberry-Pi-Pico/blink
You can download all examples from my GitHub repository by the link https://github.com/PetroShevchenko/cxemotexnika.
Automation using pico.sh
In order not to enter all these commands manually, I created a shell script called pico.sh https://github.com/PetroShevchenko/cxemotexnika/blob/master/Examples/Raspberry-Pi-Pico/ADXL345/pico.sh
Run this script without any parameters to see help message:
$ ./pico.sh
[./pico.sh] : use "./pico.sh create" to launch pico_project.py in GUI mode
[./pico.sh] : use "./pico.sh build" to compile the project
[./pico.sh] : use "./pico.sh clean" to remove temporary files
[./pico.sh] : use "./pico.sh upgrade" to copy the firmware to the device
[./pico.sh] : use "./pico.sh debug" to launch openocd
[./pico.sh] : use "./pico.sh monitor" to launch minicom
[./pico.sh] : use "./pico.sh show" to show a tree of current directory
Reading from the ADXL345 sensor
You can say “blinking a LED is simple on any board”. Since I undertook to prove that programming Raspberry Pi Pico in the C/C++ SDK is as easy as in Arduino, let’s try to connect the Pico board to a more complex module from the KS0068 Sensor Kit.
In my opinion, the ADXL345 module is complex enough for demonstration. This is a 3-axis MEMS accelerometer with high resolution (13-bit) measurement at up to +-16 g. Digital output data is formatted as 16-bit twos complement and is accessible through either a SPI (3- or 4-wire) or I2C digital interface.
I’ll just try to remake the example for Arduino using the API of the SDK.
Let’s take a look, what we can use from the SDK API to communicate through I2C.
For this let’s open pico-examples/i2c. There are three functions to work with I2C there:
1 2 3 4 5 6 |
uint i2c_init(i2c_inst_t *i2c, uint baudrate); int i2c_write_blocking(i2c_inst_t *i2c, uint8_t addr, const uint8_t *src, size_t len, bool nostop); int i2c_read_blocking(i2c_inst_t *i2c, uint8_t addr, uint8_t *dst, size_t len, bool nostop); |
I just rewrote the Arduino sketch and it worked almost immediately. Here is the original sketch for Arduino https://wiki.keyestudio.com/Ks0068_keyestudio_37_in_1_Sensor_Kit_for_Arduino_Starters#Project_29:_ADXL345_Three_Axis_Acceleration .
But there was one problem. The integer type (int) in Arduino sketch means a signed 16-bit variable, and Pico is a 32-bit microcontroller which has a 32-bit integer type. I used the int16_t type instead.
This example is located here https://github.com/PetroShevchenko/cxemotexnika/tree/master/Examples/Raspberry-Pi-Pico/ADXL345
If you have the ADXL345 module from the KS0068 Sensor Kit, connect it with the Raspberry Pi Pico as shown in the next table:
Raspberry Pi Pico | ADXL345 Module |
GND | GND |
3V3 | 3V3 |
GP8 | SDA |
GP9 | SCL |
Let’s build and upload the example:
$ cd && git clone https://github.com/PetroShevchenko/cxemotexnika.git
$ cp -r ~/cxemotexnika/Examples/Raspberry-Pi-Pico/ADXL345/ ~/pico/pico-workspace/
$ cd ~/pico/pico-workspace/ADXL345
$ ./pico.sh build
$ ./pico.sh upgrade
Now we can connect USB-UART of picoprobe and run minicom:
$ ./pico.sh monitor
[ 3934.052504] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
Welcome to minicom 2.7.1
OPTIONS: I18n
Compiled on Dec 23 2019, 02:06:26.
Port /dev/ttyACM0, 22:26:58
Press CTRL-A Z for help on special keys
RAW: -29 11 -243
ACCEL: -0.113100 0.042900 -0.947700
RAW: -23 14 -238
ACCEL: -0.089700 0.054600 -0.928200
RAW: -23 12 -242
ACCEL: -0.089700 0.046800 -0.943800
RAW: -25 19 -238
ACCEL: -0.097500 0.074100 -0.928200
RAW: -20 19 -230
ACCEL: -0.078000 0.074100 -0.897000
RAW: -28 10 -240
ACCEL: -0.109200 0.039000 -0.936000
RAW: -27 10 -232
ACCEL: -0.105300 0.039000 -0.904800
The ADXL345 accelerometer works!
Conclusion: We can use other Arduino examples to change them a bit and use along with Raspberry Pi Pico C/C++ SDK.
That is all for now. Wish you a good Raspberry Pi Pico experience!
Viewed 40445 times by 11443 viewers
Comments