The PicoBoy

The PicoBoy is a powerful mini handheld measuring just 3×5 ㎝. It is suitable for learning programming, developing your own games or simply playing with it. All you need is a PC, the PicoBoy and a USB-C cable. As the PicoBoy based on the RP2040 SoC [26] by Raspberry Pi Ltd. and is compatible with the Raspberry Pi Pico programming model and process, there are countless other tutorials, examples and libraries on the internet to make programming easier.

Board Overview

Hardware

The PicoBoy [8] [1] is a special mini sized RP2040 development board.

Features and Resources

Printed Circuit Board

5V/125~250㎃ 3.0~3.3V/180~200㎃

133㎒ 2㎆ 264㎅ USB-C CR2032 UF2

RST BOOT UP|DOWN|LEFT|RIGHT|ENTER

RED YELLOW GREEN OLED PASSIVE

9 4 4 1 1

  • Dual core Arm Cortex-M0+ processor running up to 133㎒

  • 264㎅ on-chip SRAM

  • 2㎆ on-board QSPI flash with XIP capabilities

  • USB 1.1 controller (host/device)

  • On-board USB-C connector

  • On-board 3.3V DC-DC buck-boost converter with 600㎃ switch

  • On-board CR2032 coin battery holder

  • On-board RESET button

  • On-board BOOT button

  • On-board 1 User joystick (5 keys)

  • On-board 3 User LEDs

  • On-board 1.3-inch 128×64 pixels OLED, monochrome white (serial)

  • On-board 1 passive magnetic speaker

  • On-board 1 acceleration sensor, 3-axis MEMS (digital)

  • 1 RST signal to OLED controller

  • 1 C/D signal to OLED controller

  • 1 I2C controller for acceleration sensor

  • 1 SPI controller for OLED

  • 4 PWM channels for LEDs and speaker

  • 4 ADC analog inputs

  • 8 Programmable I/O (PIO) state machines for custom peripherals

  • 1 Watchdog timer peripheral

  • 1 Temperature sensor on-chip

Design Data

PicoBoy

Positions

PicoBoy details

Front side:

  1. SH1106
    1.3-inch 128×64 pixels monochrome white OLED
  2. User joystick
    UP, DOWN, LEFT, RIGHT, ENTER
  3. W25Q16JV
    2㎆ NOR-Flash
  4. LED monochrome
    user LEDs for diagnostic (not power indicator)

Back side:

  1. RP2040

  2. USB Type-C connector
    Supports USB1.1 hosts and slave devices
  1. Power Supply Switch

  2. RESET and BOOT button
    press it when resetting to enter download mode
  3. Magnetic Speaker
    3.0Vo-p (2.0~4.0V) @ 4,000㎐ with ≫73㏈A
  4. STK8BA58
    3-axis MEMS acceleration sensor
  5. CR2032
    3.0V @ 235㎃h coin battery holder
  • BL9366
    600㎃ DC-DC buck-boost converter, power switch for 3.3V
  • S8050 (J3Y)
    SMD NPN Transistor 300㎽, 40V @ 500㎃, SOT-23

Data Sheets

Pinouts

The peripherals of the RP2040 SoC [26] can be routed to various pins on the board. The configuration of these routes can be modified through DTS. Please refer to the datasheet to see the possible routings for each peripheral. The default assignments for the PicoBoy on-board wiring is defined below. There are no edge connectors, headers or solder pads with additional signals routed to outside of the board.

Pin Mapping

on-board:

9 4 4 1 1

on-board:

1 RST 1 BOOT 1 CURSOR 1 RED 1 YELLOW 1 GREEN 1 OLED 1 PASSIVE

Default Zephyr On-Board Mapping

 

Buttons

  • ENTER : GP0 (PWM0)
  • UP : GP1 (PWM1)
  • RIGHT : GP2 (PWM2)
  • DOWN : GP3 (PWM3)
  • LEFT : GP4 (PWM4)

LEDs

  • RED : GP5 PWM5
  • YELLOW : GP6 PWM6
  • GREEN : GP7 PWM7

Display and Speaker

  • OLED : GP8 (PWM8)
    on-board OLED data/cmd OLED_DC
  • OLED : GP9 (PWM9)
    on-board OLED reset OLED_RST
  • OLED : GP10 (PWM10)
    on-board OLED chip select OLED_CS
  • n.c. : GP11 (PWM11)
  • n.c. : GP12 (PWM12)
  • n.c. : GP13 (PWM13)
  • n.c. : GP14 (PWM14)
  • PASSIVE : GP15 PWM15
  • n.c. SPI0_RX : GP16 (PWM0)
  • n.c. SPI0_CSN : GP17 (PWM1)
  • OLED SPI0_SCK : GP18 (PWM2)
    on-board OLED i/f clock OLED_CLK
  • OLED SPI0_TX : GP19 (PWM3)
    on-board OLED i/f data OLED_DIN

Sensors and ADCs

  • I2C0_SDA : GP20 (PWM4)
    on-board acceleration sensor i/f data ACCS_SDA
  • I2C0_SCL : GP21 (PWM5)
    on-board acceleration sensor i/f clock ACCS_SCL
  • n.c. : GP22 (PWM6)
  • n.c. : GP23 (PWM7)
  • n.c. : GP24 (PWM8)
  • n.c. : GP25 (PWM9)
  • n.c. ADC_CH0 : GP26 (PWM10)
  • n.c. ADC_CH1 : GP27 (PWM11)
  • n.c. ADC_CH2 : GP28 (PWM12)
  • n.c. ADC_CH3 : GP29 (PWM13)

Supported Features

Similar to the Raspberry Pi Pico the PicoBoy board configuration supports the following hardware features:

Peripheral

Kconfig option

Devicetree compatible

Zephyr API

PINCTRL

CONFIG_PINCTRL

raspberrypi,pico-pinctrl

Pin Control API

GPIO

CONFIG_GPIO

raspberrypi,pico-gpio

General-Purpose Input/Output (GPIO)

USB Device

CONFIG_USB_DEVICE_STACK

raspberrypi,pico-usbd

USB device support APIs

I2C

CONFIG_I2C

Inter-Integrated Circuit (I2C) Bus

SPI

CONFIG_SPI

raspberrypi,pico-spi

Serial Peripheral Interface (SPI) Bus

PWM

CONFIG_PWM

raspberrypi,pico-pwm

Pulse Width Modulation (PWM)

ADC

CONFIG_ADC

raspberrypi,pico-adc

Analog-to-Digital Converter (ADC)

Temperature (Sensor)

CONFIG_SENSOR

raspberrypi,pico-temp (!!)

Sensors

Timer (Counter)

CONFIG_COUNTER

raspberrypi,pico-timer

Counter

Watchdog Timer (WDT)

CONFIG_WATCHDOG

raspberrypi,pico-watchdog

Watchdog

Flash

CONFIG_FLASH

raspberrypi,pico-flash-controller

Flash and Flash map

PIO

CONFIG_PIO_RPI_PICO

raspberrypi,pico-pio

N/A

SPI (PIO)

CONFIG_SPI

raspberrypi,pico-spi-pio

Serial Peripheral Interface (SPI) Bus

DMA

CONFIG_DMA

raspberrypi,pico-dma

Direct Memory Access (DMA)

CLOCK

CONFIG_CLOCK_CONTROL

Clock Control

RESET

CONFIG_RESET

raspberrypi,pico-reset

Reset Controller

VREG

CONFIG_REGULATOR

raspberrypi,core-supply-regulator

Regulators

NVIC

N/A

arm,v6m-nvic

Nested Vector Interrupts Controller

HWINFO

CONFIG_HWINFO

N/A

Hardware Information

(!) Designware I2C driver has issues:

The Raspberry Pi Pico I2C driver is using the Designware I2C driver automatically. According to our observation, this driver has some shortcomings in interrupt handling and leads to a dead-lock of the entire runtime system. Also known is the lack of support for 0 byte transfers, which prevents a proper I2C device scan. Thus, the PicoBoy board will be configured to use the simple GPIO-I2C bit-bang driver as long as this driver is not applicable as expected.

See also: https://github.com/zephyrproject-rtos/zephyr/pull/60427

(!!) Die-Temperature Sensor driver has issues:

It seems the RP2040 Die-Temperature sensor driver has also race conditions and leads to a dead-lock of the entire runtime system. Thus, all PicoBoy board will be configured to disable this sensor node in DTS explicitly. As a workaround the ADC channel 4 can be used, but that result have to convert manually to the corresponding chip temperature following the formula that can be found in the RP2040 Datasheet [27], section with title “Temperature Sensor”.

Other hardware features are not currently supported by Zephyr. The default configuration can be found in the following Kconfig file:

Board Configurations

The PicoBoy board can be configured only for the following single use cases.

west build -b picoboy

Use the native USB device port with CDC-ACM as Zephyr console and for the shell.

Connections and IOs

The PicoBoy [1] website has detailed information about board connections. Download the different datasheets there or as linked above on the positions for more details.

System Clock

The RP2040 [26] MCU is configured to use the 12㎒ external crystal with the on-chip PLL generating the 125㎒ system clock. The internal AHB and APB units are set up in the same way as the upstream Raspberry Pi Pico C/C++ SDK [3] libraries.

GPIO (PWM) Ports

The RP2040 [26] MCU has 1 GPIO cell which covers all I/O pads and 8 PWM function unit each with 2 channels beside a dedicated Timer unit. On the PicoBoy, only 4 PWM channels are available on the three user LEDs and the passive magnetic speaker.

ADC/TS Ports

The RP2040 [26] MCU has 1 ADC with 4 channels and an additional fifth channel for the on-chip temperature sensor (TS). The ADC channels 0-3 are no available for any on-board function and may be completely unusable, but they ar all configured.

Also it is completely unclear if the external voltage reference ADC_VREF is connected to any voltage level, e.g. to the 3.3V power supply.

SPI Port

The RP2040 [26] MCU has 2 SPIs. The serial bus SPI0 is connect to the on-board OLED display over GP19 (MOSI), GP16 (MISO), GP18 (SCK), and GP17 (CSn), but only MOSI and SCK is really used for the OLED. The display chip-select signal will driven as simple GPIO by GP10 and the display itself does not provide any data out signal (MISO). SPI1 is not available in any default setup.

I2C Port

The RP2040 [26] MCU has 2 I2Cs. The serial bus I2C0 is connect to the on-board acceleration sensor over GP20 (I2C0_SDA), GP21 (I2C0_SCL). I2C1 is not available in any default setup.

Serial Port

The RP2040 [26] MCU has 2 UARTs. Neither UART0 nor UART1 are available in any of the default setups. Then ever a Zephyr serial console will be needed, the USB port have to be used.

USB Device Port

The RP2040 [26] MCU has a (native) USB device port that can be used to communicate with a host PC. See the USB device support samples sample applications for more, such as the USB CDC-ACM sample which sets up a virtual serial port that echos characters back to the host PC. The PicoBoy provides the Zephyr console per default on the USB port as CDC ACM:

USB device idVendor=2e8a, idProduct=000a, bcdDevice= 3.06
USB device strings: Mfr=1, Product=2, SerialNumber=3
Product: PicoBoy (CDC ACM)
Manufacturer: JSED (Raspberry Pi)
SerialNumber: BD774B2618DAAA7D

Programmable I/O (PIO)

The RP2040 SoC [26] comes with two PIO periherals. These are two simple co-processors that are designed for I/O operations. The PIOs run a custom instruction set, generated from a custom assembly language. PIO programs are assembled using pioasm, a tool provided by Raspberry Pi. Further informations can be found in the Raspberry Pi Pico C/C++ SDK [3] document, section with title “Using PIOASM, the PIO Assembler”.

Zephyr does not (currently) assemble PIO programs. Rather, they should be manually assembled and embedded in source code. An example of how this is done can be found at drivers/serial/uart_rpi_pico_pio.c or drivers/spi/spi_rpi_pico_pio.c.

Programming and Debugging

Flashing

The PicoBoy can only be flashed with a UF2 file. There is no SWD connector.

Using UF2

By default, building an app for the PicoBoy board will generate a build/zephyr/zephyr.uf2 file. If the board is powered on with the BOOTSEL button pressed, it will appear on the host as a mass storage device:

USB device idVendor=2e8a, idProduct=0003, bcdDevice= 1.00
USB device strings: Mfr=1, Product=2, SerialNumber=3
Product: RP2 Boot
Manufacturer: Raspberry Pi
SerialNumber: E0C9125B0D9B

The UF2 file should be drag-and-dropped or copied on command line to the device, which will then flash the PicoBoy board.

Each RP2040 SoC [26] ships the UF2 compatible [2] bootloader pico-bootrom [5], a native support in silicon. The full source for the RP2040 bootrom at pico-bootrom [5] includes versions 1, 2 and 3 of the bootrom, which correspond to the B0, B1 and B2 silicon revisions, respectively.

Note that every time you build a program for the RP2040, the Pico SDK selects an appropriate second stage bootloader based on what kind of external QSPI Flash type the board configuration you are building for was giving. There are several versions of boot2 [4] for different flash chips, and each one is exactly 256 bytes of code which is put right at the start of the eventual program binary. On Zephyr the boot2 versions are part of the Raspberry Pi Pico HAL [7] module. Possible selections:

CONFIG_RP2_FLASH_AT25SF128A:

boot2_at25sf128a.S

CONFIG_RP2_FLASH_GENERIC_03H:

boot2_generic_03h.S

CONFIG_RP2_FLASH_IS25LP080:

boot2_is25lp080.S

CONFIG_RP2_FLASH_W25Q080:

boot2_w25q080.S

CONFIG_RP2_FLASH_W25X10CL:

boot2_w25x10cl.S

The PicoBoy board set this option to CONFIG_RP2_FLASH_W25Q080. Further informations can be found in the RP2040 Datasheet [27], sections with title “Bootrom” and “Processor Controlled Boot Sequence” or Brian Starkey’s Blog article Pico serial bootloader [6]

Debugging

The PicoBoy does not provide any SWD connector, thus debugging software is not possible.

More Samples

LED Blinky and Fade

Red User LED Blinky by GPIO

See also Zephyr sample: Blinky

west build -b picoboy -p -d build/picoboy zephyr/samples/basic/blinky
west flash -d build/picoboy

Red User LED Blinky by PWM

See also Zephyr sample: PWM Blinky

west build -b picoboy -p -d build/picoboy zephyr/samples/basic/blinky_pwm
west flash -d build/picoboy

Red User LED Fade by PWM

See also Zephyr sample: Fade LED

west build -b picoboy -p -d build/picoboy zephyr/samples/basic/fade_led
west flash -d build/picoboy

Red User LED On/Off by GPIO Button (Joystick ENTER)

See also Zephyr sample: Button

west build -b picoboy -p -d build/picoboy zephyr/samples/basic/button
west flash -d build/picoboy

Hello Shell on the USB-CDC/ACM Console

Hello Shell

west build -b picoboy -p -d build/picoboy bridle/samples/helloshell
west flash -d build/picoboy

Simple test execution on target

(text in bold is a command input)

uart:~$ hello -h
hello - say hello
uart:~$ hello
Hello from shell.

uart:~$ hwinfo devid
Length: 8
ID: 0xbd774b2618daaa7d

uart:~$ kernel version
Zephyr version 3.6.0

uart:~$ bridle version
Bridle version 3.6.1

uart:~$ bridle version long
Bridle version 3.6.1.0

uart:~$ bridle info
Zephyr: 3.6.0
Bridle: 3.6.1

uart:~$ device list
devices:
- clock-controller@40008000 (READY)
- reset-controller@4000c000 (READY)
- cdc_acm_console_uart (READY)
- timer@40054000 (READY)
- gpio@40014000 (READY)
- adc@4004c000 (READY)
- flash-controller@18000000 (READY)
- i2c@40044000 (READY)
- pwm@40050000 (READY)
- vreg@40064000 (READY)
- pwm_leds (READY)

uart:~$ history
[  0] history
[  1] device list
[  2] bridle info
[  3] bridle version long
[  4] bridle version
[  5] kernel version
[  6] hwinfo devid
[  7] hello
[  8] hello -h

Input dump on the USB-CDC/ACM Console

Print the input events related to the five on-board joystick keys using the Input subsystem API. That are:

UP : zephyr,code = <INPUT_KEY_UP>;
DOWN : zephyr,code = <INPUT_KEY_DOWN>;
LEFT : zephyr,code = <INPUT_KEY_LEFT>;
RIGHT : zephyr,code = <INPUT_KEY_RIGHT>;
ENTER : zephyr,code = <INPUT_KEY_ENTER>;

See also Zephyr sample: Input dump.

Joystick Test

west build -b picoboy -p -d build/picoboy zephyr/samples/subsys/input/input_dump
west flash -d build/picoboy

Simple logging output on target

***** delaying boot 4000ms (per build configuration) *****
W: BUS RESET
W: BUS RESET
*** Booting Zephyr OS … … … (delayed boot 4000ms) ***
Input sample started
I: input event: dev=gpio_keys        SYN type= 1 code=103 value=1
I: input event: dev=gpio_keys        SYN type= 1 code=103 value=0
I: input event: dev=gpio_keys        SYN type= 1 code=108 value=1
I: input event: dev=gpio_keys        SYN type= 1 code=108 value=0
I: input event: dev=gpio_keys        SYN type= 1 code=105 value=1
I: input event: dev=gpio_keys        SYN type= 1 code=105 value=0
I: input event: dev=gpio_keys        SYN type= 1 code=106 value=1
I: input event: dev=gpio_keys        SYN type= 1 code=106 value=0
I: input event: dev=gpio_keys        SYN type= 1 code= 28 value=1
I: input event: dev=gpio_keys        SYN type= 1 code= 28 value=0

Sounds from the speaker on the USB-CDC/ACM Console

Speaker Test

PicoBoy Speaker Test

The sample is prepared for the on-board PWM_SPEAKER connected to the PWM channel at GP15 / PWM15 (PWM7CHB).

The PWM period is 880 ㎐, twice the concert pitch frequency of 440 ㎐.

core_speaker.dtsi
 1/ {
 2	aliases {
 3		pwm-buzzer0 = &pwm_speaker0;
 4	};
 5
 6	pwm_buzzers {
 7		compatible = "pwm-buzzers";
 8		status = "okay";
 9
10		pwm_speaker0: pwm_speaker0 {
11			pwms = <&pwm 15 PWM_HZ(880) PWM_POLARITY_NORMAL>;
12			label = "User PWM_SPEAKER";
13		};
14	};
15};
16
17&pwm {
18	divider-int-7 = <255>;
19};

Invoke west build and west flash:

west build -b picoboy -p -d build/picoboy bridle/samples/buzzer
west flash -d build/picoboy

Simple test execution on target

  1. play a beep

  2. play a folk song

  3. play a chrismas song

uart:~$ buzzer beep
uart:~$ buzzer play folksong
uart:~$ buzzer play xmastime

Display Test and Demonstration

The following samples work with the chosen display. That is:

OLED : chosen { zephyr,display = &oled_panel; };
SH1106 : oled_panel: &sh1106_128x64 {};

Devicetree compatible

  • zephyr,lvgl-keypad-input with devicetree relation lvgl_keypad: lvgl-keypad { input = <&gpio_keys>; };

    UP : input-codes = <INPUT_KEY_UP>; : lvgl-codes = <LV_KEY_UP>;
    DOWN : input-codes = <INPUT_KEY_DOWN>; : lvgl-codes = <LV_KEY_DOWN>;
    LEFT : input-codes = <INPUT_KEY_LEFT>; : lvgl-codes = <LV_KEY_LEFT>;
    RIGHT : input-codes = <INPUT_KEY_RIGHT>; : lvgl-codes = <LV_KEY_RIGHT>;
    ENTER : input-codes = <INPUT_KEY_ENTER>; : lvgl-codes = <LV_KEY_ENTER>;

LCD Orientation and Bit Order Test

PicoBoy Display Test

Draw some basic rectangles onto the display using the Display driver API. See also Zephyr sample: Display.

west build -b picoboy -p -d build/picoboy zephyr/samples/drivers/display
west flash -d build/picoboy

LVGL Basic Sample

Displays “Hello World!” in the center of the screen and a counter at the bottom which increments every second using the LVGL module on top of the Display driver API. See also Zephyr sample: LVGL basic sample.

west build -b picoboy -p -d build/picoboy zephyr/samples/subsys/display/lvgl
west flash -d build/picoboy

This sample comes with a Shell command line access to the LVGL backend on the console, here configured for a USB console:

Simple test execution on target

uart:~$ lvgl
lvgl - LVGL shell commands
Subcommands:
  stats   :Show LVGL statistics
  monkey  :LVGL monkey testing

uart:~$ lvgl stats
stats - Show LVGL statistics
Subcommands:
  memory  :Show LVGL memory statistics
           Usage: lvgl stats memory [-c]
           -c  dump chunk information

uart:~$ lvgl stats memory
Heap at 0x20001270 contains 2047 units in 11 buckets

  bucket#    min units        total      largest      largest
             threshold       chunks      (units)      (bytes)
  -----------------------------------------------------------
        0            1            1            1            4
        1            2            1            2           12
       10         1024            1         1824        14588

14604 free bytes, 1544 allocated bytes, overhead = 232 bytes (1.4%)

References