Skip to content
This repository has been archived by the owner on Jan 23, 2025. It is now read-only.
b-ferd edited this page Dec 27, 2023 · 15 revisions

This project turns the Raspberry Pi Pico into a USB I/O Board.

It implements the USB protocol used in the DLN-2 Linux drivers:

Alternative projects

Linux kernel

The following patches might be necessary depending on use case:

Raspberry Pi OS

The drivers are not enabled in the official Pi kernel so the following has to be added:

$ sudo modprobe configs
$ zgrep DLN2 /proc/config.gz
CONFIG_I2C_DLN2=m
CONFIG_SPI_DLN2=m
CONFIG_GPIO_DLN2=m
CONFIG_MFD_DLN2=m
CONFIG_DLN2_ADC=m

UDEV

It's necessary to add the USB ID 1d50:6170 to the Linux driver. This can be done with the help of a UDEV rule.

/etc/udev/rules.d/40-usb-dln2.rules

ACTION=="add", SUBSYSTEM=="usb", \
        ATTR{idVendor}=="1d50", ATTR{idProduct}=="6170", \
        RUN+="/sbin/modprobe -b dln2"

ACTION=="add", SUBSYSTEM=="drivers", ENV{DEVPATH}=="/bus/usb/drivers/dln2", \
        ATTR{new_id}="1d50 6170 ff"

Note: ff is VENDOR class interface

Show the added id:

$ cat /sys/bus/usb/drivers/dln2/new_id
1d50 6170 ff

Functions

All pins except GP17 (SPI CS) can be used as GPIOs as long as the alternate function is not in use (see details further down below).

The pin config is the same as the Pico reset state:

Output:
Drive strength: 4mA
Slew rate:      Slow
Input:
Hysteresis:     Enabled (Schmitt trigger mode)
Pull:           Down (50-80kΩ)

GPIO

All GPIOs 1 to 28 are fully usable - except for GPIOs 4, 5, 17, 23, 24 and 25, which are treated specially:

  • GPIOs 4 and 5 are allocated as i2c pins as soon as the Linux host sends the DLN2_I2C_ENABLE command during probing.
  • GPIO 17 is allocated as SPI pin as soon as the Linux host sends the DLN2_SPI_SS_MULTI_ENABLE command during probing.
  • GPIO 23 and 24 are not present on the RPi Pico pin header, and are disabled. Accessing them will result in an I/O error on the host.
  • GPIO 25 is connected to the on-board green LED of the Pico, and behaves "sticky", i.e.: it keeps its high/low state even after the GPIO is released (in contrast to the other GPIOs)

If you need to use GPIOs 4, 5 and 17 in our design, make sure the Linux drivers for dln2 i2c and spi are not loaded. The described probing and allocation of the pins as i2c/SPI already happens during plugin of the Pico via USB!

All GPIOs keep their input/output state, even when the GPIO is released on the USB host.

Example:

$ sudo apt install gpiod

$ gpiodetect
gpiochip0 [pinctrl-bcm2711] (58 lines)
gpiochip1 [raspberrypi-exp-gpio] (8 lines)
gpiochip2 [dln2] (29 lines)

# Board LED
$ gpioset dln2 25=1
$ gpioset dln2 25=0

# Read pin
$ gpioget dln2 12

# Monitor pin
$ gpiomon dln2 12
event: FALLING EDGE offset: 12 timestamp: [    9041.005754092]
event:  RISING EDGE offset: 12 timestamp: [    9041.721137181]

ADC

The Pico has a 12-bit ADC, but this is reduced to 10-bit to match the Linux driver.

Example:

$ sudo cat /sys/bus/iio/devices/iio\:device0/in_voltage{0,1,2}_raw
1
163
171

$ sudo iio_readdev -b1 -s1 iio:device0 | xxd
WARNING: High-speed mode not enabled
00000000: 0200 a900 ac00 0000 a4d9 58b6 a210 ad16  ..........X.....

$ sudo iio_readdev -b1 -s1 iio:device0 voltage0 voltage1 voltage2 timestamp | xxd
WARNING: High-speed mode not enabled
00000000: 0300 a700 aa00 0000 70a8 2e9c b010 ad16  ........p.......

I2C

The Linux driver does not support Repeated-Start. It will do Start-Stop on multi message transfers.

UART

There are 2 CDC UARTS avaiable. The pins will be set to the UART function on first use and they will stay like that even if the port is closed.

ModemManager might be a problem if it probes the uart for a modem because it will claim the uart pins making them unusable as a gpio.

Solution: How to communicate with instruments under Linux

Clone this wiki locally