RP2040 I2C Host Firmware

This page details the firmware which runs on RP2040-based I²C host devices. When running, the firmware listens to the UART hosted by the RP2040’s USB connection for the following commands and for read/write indicators.

'A matrix display client and the CPU activity display example running on a Raspberry Pi 400'

The current version is 1.1.1

Processing Incoming Data

The first received byte is checked by the firmware. If the value is less than 0x80, the code checks for a command, otherwise it processes the bytes as a read or write operation.

Commands

Command

Arguments

Description

?

Get I²C host device info

*

{1|0}

Set the I²C host’s LED state1

!

Respond to connection request

c

{bus_index}
{SDA_pin}
{SCL_pin}

Configure the I²C bus. This must be performed before the bus is
initialised. The first argument is 0 or 1; only bit 0 is checked.
The other args are 8-bit values

1

Set I²C bus frequency to 100kHz

4

Set I²C bus frequency to 400kHz

i

Initialise the I²C bus for use

x

Reset the I²C bus

p

Manually issue an I²C STOP signal

s

{bitfield}2

Start an I²C read or write operation targeting a specific device

d

Scan the I²C bus for devices. If the bus is not initialised when this
command is issued, it will be initialised automatically with default
values

g

{bitfield}3

Set or get a GPIO pin. The pins must not be those used for I²C

1 If SHOW_HEARTBEAT is not defined in CmakeLists.txt, this call will respond with an ERR signal.

2 Bits 7 through 1 are the target device’s I²C address. Bit 0 is the operation required: 1 for read, 0 for write.

3 Bit 7 is the pin state: 1 for logic high, 0 for logic low. This is ignored in read operations. Bit 6 is the pin direction: 1 for an output, 0 for an input. Bit 5 is the operation required: 1 for read, 0 for write. Bits 4 through 8 are the target pin number (0-31).

Commands are acknowledged with an ACK (0x0F) or an ERR (0xF0). Note that these values may change.

Commands that return arbitrary amounts of data append the data with \r\n as an end-of-sequence marker.

Read and Write I²C Operations

The outcome depends on the value of the first byte in the sequence.

If the value is in the range 0x80 to 0xBF, it is a read operation and the number of bytes to read is given by: value - 0x80 + 1.

If the value is in the range 0xC0 to 0xFF, it is a write operation and the number of bytes to write is given by: value - 0xC0 + 1. These bytes follow the state byte.

Only 64 bytes can be requested/written at a time. This is usually sufficient, but for larger amounts, issue subsequent requests for 64 bytes or less.

Device Scan Format

Requesting a device scan returns is a string of I2C addresses separated by full-stops. Each address is a 7-bit value encoded as two-digit hex numbers.

If no devices are present, Z\r\n is returned.

Host Information Format

Requesting host information returns a sequence of integers and strings separated by full stops and followed by \r\n.

Value

Size

Notes

Is I2C ready?

2

Binary value: 1 == true, 0 == false

Is I2C being used?

2

Binary value: 1 == true, 0 == false

I2C bus ID

2

1 or 0

I2C SDA pin

2-3

0-31 in decimal form

I2C SCL pin

2-3

0-31 in decimal form

I2C bus frequency

2

1 (100kHz) or 4 (400kHz)

I2C address

2-4

8-127 in decimal form

Firmware version

6-12

Major, minor and patch values as separate fields

Firmware build

2-4

1-999

Unique RP20240 ID

17

16-byte value as two-digit hex values

Board type

2-17

Per board ID string, eg. RP-PI-PICO

Note Size includes the post-value separator.

Source code

The I²C Host firmware source code can be found in this GitHub repo.

Build and Deploy the I²C Host Firmware

  1. Clone the repo.

  2. Navigate to the repo directory.

  3. Run cmake -S . -B firmwarebuild.

  4. Run cmake --build firmwarebuild.

  5. Write the firmware depending on which board you are using:

    • ./deploy.sh /path/to/device firmwarebuild/firmware/pico/firmware_pico_rp2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/qtpy/firmware_qtpy_rp2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/promicro/firmware_promicro.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/tiny/firmware_tiny2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/trinkey/firmware_trinkey2040.uf2

The deploy script tricks the RP2040-based board into booting into disk mode, then copies over the newly build firmware. When the copy completes, the RP2040 automatically reboots. This saves of a lot of tedious power-cycling with the BOOT button held down.

Supported Boards