5696 lines
292 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# GPIO
Chapter 9. GPIO
 CAUTION
Under certain conditions, pull-down does not function as expected. For more information, see RP2350-E9.
9.1. Overview
RP2350 has up to 54 multi-functional General Purpose Input / Output (GPIO) pins, divided into two banks:
Bank 0
30 user GPIOs in the QFN-60 package (RP2350A), or 48 user GPIOs in the QFN-80 package
Bank 1
six QSPI IOs, and the USB DP/DM pins
You can control each GPIO from software running on the processors, or by a number of other functional blocks. To
meet USB rise and fall specifications, the analogue characteristics of the USB pins differ from the GPIO pads. As a
result, we do not include them in the 54 GPIO total. However, you can still use them for UART, I2C, or processorcontrolled GPIO through the single-cycle IO subsystem (SIO).
In a typical use case, the QSPI IOs are used to execute code from an external flash device, leaving 30 or 48 Bank 0
GPIOs for the programmer to use. The QSPI pins might become available for general purpose use when booting the chip
from internal OTP, or controlling the chip externally through SWD in an IO expander application.
All GPIOs support digital input and output. Several Bank 0 GPIOs can also be used as inputs to the chips Analogue to
Digital Converter (ADC):
• GPIOs 26 through 29 inclusive (four total) in the QFN-60 package
• GPIOs 40 through 47 (eight total) in the QFN-80 package
Bank 0 supports the following functions:
• Software control via SIO — Section 3.1.3, “GPIO control”
• Programmable IO (PIO) — Chapter 11, PIO
• 2 × SPI — Section 12.3, “SPI”
• 2 × UART — Section 12.1, “UART”
• 2 × I2C (two-wire serial interface) — Section 12.2, “I2C”
• 8 × two-channel PWM in the QFN-60 package, or 12 × in QFN-80 — Section 12.5, “PWM”
• 2 × external clock inputs — Section 8.1.2.4, “External clocks”
• 4 × general purpose clock output — Section 8.1, “Overview”
• 4 × input to ADC in the QFN-60 package, or 8 × in QFN-80 — Section 12.4, “ADC and Temperature Sensor”
• 1 × HSTX high-speed interface — Section 12.11, “HSTX”
• 1 × auxiliary QSPI chip select, for a second XIP device — Section 12.14, “QSPI memory interface (QMI)”
• CoreSight execution trace output — Section 3.5.7, “Trace”
• USB VBUS management — Section 12.7.3.10, “VBUS control”
• External interrupt requests, level or edge-sensitive — Section 9.5, “Interrupts”
Bank 1 contains the QSPI and USB DP/DM pins and supports the following functions:
RP2350 Datasheet
9.1. Overview 587
• Software control via SIO — Section 3.1.3, “GPIO control”
• Flash execute in place (Section 4.4, “External flash and PSRAM (XIP)”) via QSPI Memory Interface (QMI) — Section
12.14, “QSPI memory interface (QMI)”
• UART — Section 12.1, “UART”
• I2C (two-wire serial interface) — Section 12.2, “I2C”
The logical structure of an example IO is shown in Figure 41.
Figure 41. Logical
structure of a GPIO.
Each GPIO can be
controlled by one of a
number of peripherals,
or by software control
registers in the SIO.
The function select
(FSEL) selects which
peripheral output is in
control of the GPIOs
direction and output
level, and which
peripheral input can
see this GPIOs input
level. These three
signals (output level,
output enable, input
level) can also be
inverted or forced high
or low, using the GPIO
control registers.
9.2. Changes from RP2040
RP2350 GPIO differs from RP2040 in the following ways:
• 18 more GPIOs in the QFN-80 package
• Addition of a third PIO to GPIO functions
• USB DP/DM pins can be used as GPIO
• Addition of isolation register to pad registers (preserves pad state while in a low power state, cleared by software
on power up)
• Changed default reset state of pad controls
• Both Secure and Non-secure access to GPIOs (see Section 10.6)
• Double the number of GPIO interrupts to differentiate between Secure and Non-secure
• Interrupt summary registers added so you can quickly see which GPIOs have pending interrupts
9.3. Reset state
At first power up, Bank 0 IOs (GPIOs 0 through 29 in the QFN-60 package, and GPIOs 0 through 47 in the QFN-80
package) assume the following state:
• Output buffer is high-impedance
• Input buffer is disabled
• Pulled low
• Isolation latches are set to latched (Section 9.7)
The pad output disable bit (GPIO0.OD) for each pad is clear at reset, but the IO muxing is reset to the null function,
RP2350 Datasheet
9.2. Changes from RP2040 588
which ensures that the output buffer is high-impedance.
 IMPORTANT
The pad reset state is different from RP2040, which only disables digital inputs on GPIOs 26 through 29 (as of
version B2) and does not have isolation latches. Applications must enable the pad input (GPIO0.IE = 1) and disable
pad isolation latches (GPIO0.ISO = 0) before using the pads for digital I/O. The gpio_set_function() SDK function
performs these tasks automatically.
Bank 1 IOs have the same reset state as Bank 0 GPIOs, except for the input enable (IE) resetting to 1, and different pullup/pull-down states: SCK, SD0 and SD1 are pull-down, but SD2, SD3 and CSn are pull-up.
 NOTE
To use a Bank 0 GPIO as a second chip select, you need an external pull-up to ensure the second QSPI device does
not power up with its chip select asserted.
The pads return to the reset state on any of the following:
• A brownout reset
• Asserting the RUN pin low
• Setting SW-DP CDBGRSTREQ via SWD
• Setting RP-AP rescue reset via SWD
If a pads isolation latches are in the latched state (Section 9.7) then resetting the PADS and IO registers does not
physically return the pad to its reset state. The isolation latches prevent upstream signals from propagating to the pad.
Clear the ISO bit to allow signals to propagate.
9.4. Function select
To allocate a function to a GPIO, write to the FUNCSEL field in the CTRL register corresponding to the pin. For a list of GPIOs
and corresponding registers, see Table 645. For an example, see GPIO0_CTRL. The descriptions for the functions listed
in this table can be found in Table 646.
Each GPIO can only select one function at a time. Each peripheral input (e.g. UART0 RX) should only be selected by one
GPIO at a time. If you connect the same peripheral input to multiple GPIOs, the peripheral sees the logical OR of these
GPIO inputs.
RP2350 Datasheet
9.4. Function select 589
Table 645. General
Purpose Input/Output
(GPIO) Bank 0
Functions
GPIO F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11
0 SPI0 RX UART0 TX I2C0 SDA PWM0 A SIO PIO0 PIO1 PIO2 QMI CS1n USB OVCUR DET
1 SPI0 CSn UART0 RX I2C0 SCL PWM0 B SIO PIO0 PIO1 PIO2 TRACECLK USB VBUS DET
2 SPI0 SCK UART0 CTS I2C1 SDA PWM1 A SIO PIO0 PIO1 PIO2 TRACEDATA0 USB VBUS EN UART0 TX
3 SPI0 TX UART0 RTS I2C1 SCL PWM1 B SIO PIO0 PIO1 PIO2 TRACEDATA1 USB OVCUR DET UART0 RX
4 SPI0 RX UART1 TX I2C0 SDA PWM2 A SIO PIO0 PIO1 PIO2 TRACEDATA2 USB VBUS DET
5 SPI0 CSn UART1 RX I2C0 SCL PWM2 B SIO PIO0 PIO1 PIO2 TRACEDATA3 USB VBUS EN
6 SPI0 SCK UART1 CTS I2C1 SDA PWM3 A SIO PIO0 PIO1 PIO2 USB OVCUR DET UART1 TX
7 SPI0 TX UART1 RTS I2C1 SCL PWM3 B SIO PIO0 PIO1 PIO2 USB VBUS DET UART1 RX
8 SPI1 RX UART1 TX I2C0 SDA PWM4 A SIO PIO0 PIO1 PIO2 QMI CS1n USB VBUS EN
9 SPI1 CSn UART1 RX I2C0 SCL PWM4 B SIO PIO0 PIO1 PIO2 USB OVCUR DET
10 SPI1 SCK UART1 CTS I2C1 SDA PWM5 A SIO PIO0 PIO1 PIO2 USB VBUS DET UART1 TX
11 SPI1 TX UART1 RTS I2C1 SCL PWM5 B SIO PIO0 PIO1 PIO2 USB VBUS EN UART1 RX
12 HSTX SPI1 RX UART0 TX I2C0 SDA PWM6 A SIO PIO0 PIO1 PIO2 CLOCK GPIN0 USB OVCUR DET
13 HSTX SPI1 CSn UART0 RX I2C0 SCL PWM6 B SIO PIO0 PIO1 PIO2 CLOCK GPOUT0 USB VBUS DET
14 HSTX SPI1 SCK UART0 CTS I2C1 SDA PWM7 A SIO PIO0 PIO1 PIO2 CLOCK GPIN1 USB VBUS EN UART0 TX
15 HSTX SPI1 TX UART0 RTS I2C1 SCL PWM7 B SIO PIO0 PIO1 PIO2 CLOCK GPOUT1 USB OVCUR DET UART0 RX
16 HSTX SPI0 RX UART0 TX I2C0 SDA PWM0 A SIO PIO0 PIO1 PIO2 USB VBUS DET
17 HSTX SPI0 CSn UART0 RX I2C0 SCL PWM0 B SIO PIO0 PIO1 PIO2 USB VBUS EN
18 HSTX SPI0 SCK UART0 CTS I2C1 SDA PWM1 A SIO PIO0 PIO1 PIO2 USB OVCUR DET UART0 TX
19 HSTX SPI0 TX UART0 RTS I2C1 SCL PWM1 B SIO PIO0 PIO1 PIO2 QMI CS1n USB VBUS DET UART0 RX
20 SPI0 RX UART1 TX I2C0 SDA PWM2 A SIO PIO0 PIO1 PIO2 CLOCK GPIN0 USB VBUS EN
21 SPI0 CSn UART1 RX I2C0 SCL PWM2 B SIO PIO0 PIO1 PIO2 CLOCK GPOUT0 USB OVCUR DET
22 SPI0 SCK UART1 CTS I2C1 SDA PWM3 A SIO PIO0 PIO1 PIO2 CLOCK GPIN1 USB VBUS DET UART1 TX
RP2350 Datasheet
9.4. Function select 590
GPIO F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11
23 SPI0 TX UART1 RTS I2C1 SCL PWM3 B SIO PIO0 PIO1 PIO2 CLOCK GPOUT1 USB VBUS EN UART1 RX
24 SPI1 RX UART1 TX I2C0 SDA PWM4 A SIO PIO0 PIO1 PIO2 CLOCK GPOUT2 USB OVCUR DET
25 SPI1 CSn UART1 RX I2C0 SCL PWM4 B SIO PIO0 PIO1 PIO2 CLOCK GPOUT3 USB VBUS DET
26 SPI1 SCK UART1 CTS I2C1 SDA PWM5 A SIO PIO0 PIO1 PIO2 USB VBUS EN UART1 TX
27 SPI1 TX UART1 RTS I2C1 SCL PWM5 B SIO PIO0 PIO1 PIO2 USB OVCUR DET UART1 RX
28 SPI1 RX UART0 TX I2C0 SDA PWM6 A SIO PIO0 PIO1 PIO2 USB VBUS DET
29 SPI1 CSn UART0 RX I2C0 SCL PWM6 B SIO PIO0 PIO1 PIO2 USB VBUS EN
GPIOs 30 through 47 are QFN-80 only:
30 SPI1 SCK UART0 CTS I2C1 SDA PWM7 A SIO PIO0 PIO1 PIO2 USB OVCUR DET UART0 TX
31 SPI1 TX UART0 RTS I2C1 SCL PWM7 B SIO PIO0 PIO1 PIO2 USB VBUS DET UART0 RX
32 SPI0 RX UART0 TX I2C0 SDA PWM8 A SIO PIO0 PIO1 PIO2 USB VBUS EN
33 SPI0 CSn UART0 RX I2C0 SCL PWM8 B SIO PIO0 PIO1 PIO2 USB OVCUR DET
34 SPI0 SCK UART0 CTS I2C1 SDA PWM9 A SIO PIO0 PIO1 PIO2 USB VBUS DET UART0 TX
35 SPI0 TX UART0 RTS I2C1 SCL PWM9 B SIO PIO0 PIO1 PIO2 USB VBUS EN UART0 RX
36 SPI0 RX UART1 TX I2C0 SDA PWM10 A SIO PIO0 PIO1 PIO2 USB OVCUR DET
37 SPI0 CSn UART1 RX I2C0 SCL PWM10 B SIO PIO0 PIO1 PIO2 USB VBUS DET
38 SPI0 SCK UART1 CTS I2C1 SDA PWM11 A SIO PIO0 PIO1 PIO2 USB VBUS EN UART1 TX
39 SPI0 TX UART1 RTS I2C1 SCL PWM11 B SIO PIO0 PIO1 PIO2 USB OVCUR DET UART1 RX
40 SPI1 RX UART1 TX I2C0 SDA PWM8 A SIO PIO0 PIO1 PIO2 USB VBUS DET
41 SPI1 CSn UART1 RX I2C0 SCL PWM8 B SIO PIO0 PIO1 PIO2 USB VBUS EN
42 SPI1 SCK UART1 CTS I2C1 SDA PWM9 A SIO PIO0 PIO1 PIO2 USB OVCUR DET UART1 TX
43 SPI1 TX UART1 RTS I2C1 SCL PWM9 B SIO PIO0 PIO1 PIO2 USB VBUS DET UART1 RX
44 SPI1 RX UART0 TX I2C0 SDA PWM10 A SIO PIO0 PIO1 PIO2 USB VBUS EN
RP2350 Datasheet
9.4. Function select 591
GPIO F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11
45 SPI1 CSn UART0 RX I2C0 SCL PWM10 B SIO PIO0 PIO1 PIO2 USB OVCUR DET
46 SPI1 SCK UART0 CTS I2C1 SDA PWM11 A SIO PIO0 PIO1 PIO2 USB VBUS DET UART0 TX
47 SPI1 TX UART0 RTS I2C1 SCL PWM11 B SIO PIO0 PIO1 PIO2 QMI CS1n USB VBUS EN UART0 RX
RP2350 Datasheet
9.4. Function select 592
Table 646. GPIO User
Bank function
descriptions
Function Name Description
SPIx Connect one of the internal PL022 SPI peripherals to GPIO.
UARTx Connect one of the internal PL011 UART peripherals to GPIO.
I2Cx Connect one of the internal DW I2C peripherals to GPIO.
PWMx A/B Connect a PWM slice to GPIO. There are twelve PWM slices, each with two output
channels (A/B). The B pin can also be used as an input, for frequency and duty cycle
measurement.
SIO Software control of GPIO from the Single-cycle IO (SIO) block. The SIO function (F5)
must be selected for the processors to drive a GPIO, but the input is always connected,
so software can check the state of GPIOs at any time.
PIOx Connect one of the programmable IO blocks (PIO) to GPIO. PIO can implement a wide
variety of interfaces, and has its own internal pin mapping hardware, allowing flexible
placement of digital interfaces on Bank 0 GPIOs. The PIO function (F6, F7, F8) must be
selected for PIO to drive a GPIO, but the input is always connected, so the PIOs can
always see the state of all pins.
HSTX Connect the high-speed transmit peripheral (HSTX) to GPIO.
CLOCK GPINx General purpose clock inputs. Can be routed to a number of internal clock domains on
RP2350, e.g. to provide a 1Hz clock for the AON Timer, or can be connected to an
internal frequency counter.
CLOCK GPOUTx General purpose clock outputs. Can drive a number of internal clocks (including PLL
outputs) onto GPIOs, with optional integer divide.
TRACECLK, TRACEDATAx CoreSight execution trace output from Cortex-M33 processors (Arm-only).
USB OVCUR DET/VBUS
DET/VBUS EN
USB power control signals to/from the internal USB controller.
QMI CS1n Auxiliary chip select for QSPI bus, to allow execute-in-place from an additional flash or
PSRAM device.
Bank 1 function select operates identically to Bank 0, but its registers are in a different register block, starting with
USBPHY_DP_CTRL.
Table 647. GPIO Bank
1 Functions
Pin F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11
USB DP UART1 TX I2C0 SDA SIO
USB DM UART1 RX I2C0 SCL SIO
QSPI SCK QMI SCK UART1 CTS I2C1 SDA SIO UART1 TX
QSPI CSn QMI CS0n UART1 RTS I2C1 SCL SIO UART1 RX
QSPI SD0 QMI SD0 UART0 TX I2C0 SDA SIO
QSPI SD1 QMI SD1 UART0 RX I2C0 SCL SIO
QSPI SD2 QMI SD2 UART0 CTS I2C1 SDA SIO UART0 TX
QSPI SD3 QMI SD3 UART0 RTS I2C1 SCL SIO UART0 RX
Table 648. GPIO bank
1 function
descriptions
Function Name Description
UARTx Connect one of the internal PL011 UART peripherals to GPIO.
I2Cx Connect one of the internal DW I2C peripherals to GPIO.
RP2350 Datasheet
9.4. Function select 593
Function Name Description
SIO Software control of GPIO, from the single-cycle IO (SIO) block. The SIO function (F5) must be selected
for the processors to drive a GPIO, but the input is always connected, so software can check the state
of GPIOs at any time.
QMI QSPI memory interface peripheral, used for execute-in-place from external QSPI flash or PSRAM
memory devices.
The six QSPI Bank GPIO pins are typically used by the XIP peripheral to communicate with an external flash device.
However, there are two scenarios where the pins can be used as software-controlled GPIOs:
• If a SPI or Dual-SPI flash device is used for execute-in-place, then the SD2 and SD3 pins are not used for flash
access, and can be used for other GPIO functions on the circuit board.
• If RP2350 is used in a flashless configuration (USB and OTP boot only), then all six pins can be used for softwarecontrolled GPIO functions.
9.5. Interrupts
An interrupt can be generated for every GPIO pin in four scenarios:
• Level High: the GPIO pin is a logical 1
• Level Low: the GPIO pin is a logical 0
• Edge High: the GPIO has transitioned from a logical 0 to a logical 1
• Edge Low: the GPIO has transitioned from a logical 1 to a logical 0
The level interrupts are not latched. This means that if the pin is a logical 1 and the level high interrupt is active, it will
become inactive as soon as the pin changes to a logical 0. The edge interrupts are stored in the INTR register and can be
cleared by writing to the INTR register.
There are enable, status, and force registers for three interrupt destinations: proc 0, proc 1, and dormant_wake. For proc
0 the registers are enable (PROC0_INTE0), status (PROC0_INTS0), and force (PROC0_INTF0). Dormant wake is used to
wake the ROSC or XOSC up from dormant mode. See Section 6.5.6.2 for more information on dormant mode.
There is an interrupt output for each combination of IO bank, IRQ destination, and security domain. In total there are
twelve such outputs:
• IO Bank 0 to dormant wake (Secure and Non-secure)
• IO Bank 0 to proc 0 (Secure and Non-secure)
• IO Bank 0 to proc 1 (Secure and Non-secure)
• IO QSPI to dormant wake (Secure and Non-secure)
• IO QSPI to proc 0 (Secure and Non-secure)
• IO QSPI to proc 1 (Secure and Non-secure)
Each interrupt output has its own array of enable registers (INTE) that configures which GPIO events cause the interrupt
to assert. The interrupt asserts when at least one enabled event occurs, and de-asserts when all enabled events have
been acknowledged via the relevant INTR register.
This means the user can watch for several GPIO events at once.
Summary registers can be used to quickly check for pending GPIO interrupts. See IRQSUMMARY_PROC0_NONSECURE0
for an example.
RP2350 Datasheet
9.5. Interrupts 594
9.6. Pads
 CAUTION
Under certain conditions, pull-down does not function as expected. For more information, see RP2350-E9.
Each GPIO is connected off-chip via a pad. Pads are the electrical interface between the chips internal logic and
external circuitry. They translate signal voltage levels, support higher currents and offer some protection against
electrostatic discharge (ESD) events. You can adjust pad electrical behaviour to meet the requirements of external
circuitry in the following ways:
• Output drive strength can be set to 2mA, 4mA, 8mA or 12mA.
• Output slew rate can be set to slow or fast.
• Input hysteresis (Schmitt trigger mode) can be enabled.
• A pull-up or pull-down can be enabled, to set the output signal level when the output driver is disabled.
• The input buffer can be disabled, to reduce current consumption when the pad is unused, unconnected or
connected to an analogue signal.
An example pad is shown in Figure 42.
PAD
GPIO
Muxing
Slew Rate
Output Enable
Output Data
Drive Strength
Input Enable
Input Data
Schmitt Trigger
Pull Up / Pull Down
2
2
Figure 42. Diagram of
a single IO pad.
The pads Output Enable, Output Data and Input Data ports connect, via the IO mux, to the function controlling the pad.
All other ports are controlled from the pad control register. You can use this register to disable the pads output driver by
overriding the Output Enable signal from the function controlling the pad. See GPIO0 for an example of a pad control
register.
Both the output signal level and acceptable input signal level at the pad are determined by the digital IO supply (IOVDD).
IOVDD can be any nominal voltage between 1.8V and 3.3V, but to meet specification when powered at 1.8V, the pad
input thresholds must be adjusted by writing a 1 to the pad VOLTAGE_SELECT registers. By default, the pad input thresholds
are valid for an IOVDD voltage between 2.5V and 3.3V. Using a voltage of 1.8V with the default input thresholds is a safe
operating mode, but it will result in input thresholds that dont meet specification.
 WARNING
Using IOVDD voltages greater than 1.8V, with the input thresholds set for 1.8V may result in damage to the chip.
Pad input threshold are adjusted on a per bank basis, with separate VOLTAGE_SELECT registers for the pads associated with
the User IO bank (IO Bank 0) and the QSPI IO bank. However, both banks share the same digital IO supply (IOVDD), so
both register should always be set to the same value.
Pad register details are available in Section 9.11.3, “Pad Control - User Bank” and Section 9.11.4, “Pad Control - QSPI
Bank”.
RP2350 Datasheet
9.6. Pads 595
9.6.1. Bus keeper mode
For each pad, only the pull-up or the pull-down resistor can be enabled at any given time. It is impossible to enable both
simultaneously. Instead, if you set both the GPIO0.PDE and GPIO0.PUE bits simultaneously then you enable bus keeper
mode, where the pad is:
• Pulled up when its input is high.
• Pulled down when its input is low.
When the output buffer is disabled, and the pad is not driven by any external source, this mode weakly retains the pads
current logical state. The pad does not float to mid-rail.
Bus keeper mode relies on control logic in the switched core domain, so does not function when the core is powered
down. Rather, powering down the core when bus keeper mode is enabled latches the current output controls (pull-up or
pull-down) in the pad isolation latches, as described in Section 9.7.
9.7. Pad isolation latches
RP2350 features extended low-power states that allow all internal logic, with the exception of POWMAN and some
CoreSight debug logic, to fully power down under software control. This includes powering down all peripherals, the IO
muxing, and the pad control registers, which brings with it the risk that pad signals may experience unwanted
transitions when entering and exiting low-power states.
To ensure that pad states are well-defined at all times, all signals passing from the switched core power domain to the
pads pass through isolation latches. In normal operation, the latches are transparent, so the pads are controlled fully by
logic inside the switched core power domain, such as UARTs or the processors. However, when the ISO bit for each pad
is set (e.g. GPIO0.ISO) or the switched core domain is powered down, the control signals currently presented to that pad
are latched until the isolation is disabled. This includes the output enable state, output high/low level, and pull-up/pulldown resistor enable. The input signal from the pad back into the switched core domain is not isolated.
Consequently, when switched core logic is powered down, all Bank 0 and Bank 1 pads maintain the output state they
held immediately before the power down, unless overridden by always-on logic in POWMAN. When the switched core
power domain powers back up, all the GPIO ISO bits reset to 1, so the pre-power down state continues to be maintained
until user software starts up and clears the ISO bit to indicate it is ready to use the pad again. Pads whose IO muxing
has not yet been set up can be left isolated indefinitely, and will maintain their pre-power down state.
when software has finished setting up the IO muxing for a given pad, and the peripheral that is to be muxed in, the ISO
bit should be cleared. At this point the isolation latches will become transparent again: output signals passing through
the IO muxing block are now reflected in the pad output state, so peripherals can communicate with the outside world.
This process allows the switched core domain to be power cycled without causing any transitions on the pad outputs
that may interfere with the operation of external hardware connected to the pads.
 NOTE
Non-SDK applications ported from RP2040 must clear the ISO bit before using a GPIO, as this feature was not
present on RP2040. The SDK automatically clears the ISO bit when gpio_set_function() is called.
The isolation latches themselves are reset by the always-on power domain reset, namely any one of:
• Power-on reset
• Brownout reset
• RUN pin being asserted low
• SW-DP CDBGRSTREQ
• RP-AP rescue reset
The latches reset to the reset value of the signal being isolated. For example, on Bank 0 GPIOs, the input enable control
RP2350 Datasheet
9.7. Pad isolation latches 596
(GPIO0.IE) resets to 0 (input-disabled), so the isolation latches for these signals also take a reset value of 0. Resetting
the isolation latch forces the pad to assume its reset state even if it is currently isolated.
The ISO control bits (e.g. GPIO0.ISO) are reset by the top-level switched core domain isolation signal, which is asserted
by POWMAN before powering down the switched core domain and de-asserted after it is powered up. This means that
entering and exiting a sleep state where the switched core domain is unpowered leaves all GPIOs isolated after power
up; you can then re-engage them individually. The ISO control bits are not reset by the PADS register block reset driven
by the RESETS control registers: resetting the PADS register block returns non-isolated pads to their reset state, but has
no effect on isolated pads.
9.8. Processor GPIO controls (SIO)
The single-cycle IO subsystem (Section 3.1) contains memory-mapped GPIO registers. The processors can use these to
perform input/output operations on GPIOs:
• The GPIO_OUT and GPIO_HI_OUT registers set the output level: 1 = high, 0 = low
• The GPIO_OE and GPIO_HI_OE registers set the output enable: 1 = output, 0 = input
• The GPIO_IN and GPIO_HI_IN registers read the GPIO inputs
These registers are all 32 bits in size. The low registers (e.g. GPIO_OUT) connect to GPIOs 0 through 31, and the high
registers (e.g. GPIO_HI_OUT) connect to GPIOs 32 through 47, the QSPI pads, and the USB DM/DP pads.
For the output and output enable registers to take effect, the SIO function must be selected on each GPIO (function 5).
However, the GPIO input registers read back the GPIO input values even when the SIO function is not selected, so the
processor can always check the input state of any pin.
The SIO GPIO registers are shared between the two processors and between the Secure and Non-secure security
domains. This avoids programming errors introduced by selecting multiple GPIO functions for access from different
contexts.
Non-secure codes view of the SIO registers is restricted by the Non-secure GPIO mask defined in GPIO_NSMASK0 and
GPIO_NSMASK1. Non-secure writes to Secure GPIOs are ignored. Non-secure reads of Secure GPIOs return 0.
These registers are documented in more detail in the SIO GPIO register section (Section 3.1.3).
The DMA cannot access registers in the SIO subsystem. The recommended method to DMA to GPIOs is a PIO program
that continuously transfers TX FIFO data to the GPIO outputs, which provides more consistent timing than DMA directly
into GPIO registers.
9.9. GPIO coprocessor port
Coprocessor port 0 on each Cortex-M33 processor connects to a GPIO coprocessor interface. These coprocessor
instructions provide fast access to the SIO GPIO registers from Arm software:
• The equivalent of any SIO GPIO register access is a single instruction, without having to materialise a 32-bit
register address beforehand
• An indexed write operation on any single GPIO is a single instruction
• 64 bits can be read/written in a single instruction
This reduces the timing impact of GPIO accesses on surrounding software, for example when GPIO tracing has been
added to interrupt handlers diagnose complex timing issues.
Both Secure and Non-secure code may access the coprocessor. Non-secure code sees a restricted view of the GPIO
registers, defined by ACCESSCTRL GPIO_NSMASK0/1.
The GPIO coprocessor instruction set is documented in Section 3.6.1.
RP2350 Datasheet
9.8. Processor GPIO controls (SIO) 597
9.10. Software examples
9.10.1. Select an IO function
An IO pin can perform many different functions and must be configured before use. For example, you may want it to be
a UART_TX pin, or a PWM output. The SDK provides gpio_set_function for this purpose. Many SDK examples call
gpio_set_function early on to enable printing to a UART.
The SDK starts by defining a structure to represent the registers of IO Bank 0, the User IO bank. Each IO has a status
register, followed by a control register. For N IOs, the SDK instantiates the structure containing a status and control
register as io[N] to repeat it N times.
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2350/hardware_structs/include/hardware/structs/io_bank0.h Lines 179 - 445
179 typedef struct {
180 io_bank0_status_ctrl_hw_t io[48];
181
182 uint32_t _pad0[32];
183
184 // (Description copied from array index 0 register IO_BANK0_IRQSUMMARY_PROC0_SECURE0
applies similarly to other array indexes)
185 _REG_(IO_BANK0_IRQSUMMARY_PROC0_SECURE0_OFFSET) // IO_BANK0_IRQSUMMARY_PROC0_SECURE0
186 // 0x80000000 [31] GPIO31 (0)
187 // 0x40000000 [30] GPIO30 (0)
188 // 0x20000000 [29] GPIO29 (0)
189 // 0x10000000 [28] GPIO28 (0)
190 // 0x08000000 [27] GPIO27 (0)
191 // 0x04000000 [26] GPIO26 (0)
192 // 0x02000000 [25] GPIO25 (0)
193 // 0x01000000 [24] GPIO24 (0)
194 // 0x00800000 [23] GPIO23 (0)
195 // 0x00400000 [22] GPIO22 (0)
196 // 0x00200000 [21] GPIO21 (0)
197 // 0x00100000 [20] GPIO20 (0)
198 // 0x00080000 [19] GPIO19 (0)
199 // 0x00040000 [18] GPIO18 (0)
200 // 0x00020000 [17] GPIO17 (0)
201 // 0x00010000 [16] GPIO16 (0)
202 // 0x00008000 [15] GPIO15 (0)
203 // 0x00004000 [14] GPIO14 (0)
204 // 0x00002000 [13] GPIO13 (0)
205 // 0x00001000 [12] GPIO12 (0)
206 // 0x00000800 [11] GPIO11 (0)
207 // 0x00000400 [10] GPIO10 (0)
208 // 0x00000200 [9] GPIO9 (0)
209 // 0x00000100 [8] GPIO8 (0)
210 // 0x00000080 [7] GPIO7 (0)
211 // 0x00000040 [6] GPIO6 (0)
212 // 0x00000020 [5] GPIO5 (0)
213 // 0x00000010 [4] GPIO4 (0)
214 // 0x00000008 [3] GPIO3 (0)
215 // 0x00000004 [2] GPIO2 (0)
216 // 0x00000002 [1] GPIO1 (0)
217 // 0x00000001 [0] GPIO0 (0)
218 io_ro_32 irqsummary_proc0_secure[2];
219
220 // (Description copied from array index 0 register IO_BANK0_IRQSUMMARY_PROC0_NONSECURE0
applies similarly to other array indexes)
221 _REG_(IO_BANK0_IRQSUMMARY_PROC0_NONSECURE0_OFFSET) //
IO_BANK0_IRQSUMMARY_PROC0_NONSECURE0
222 // 0x80000000 [31] GPIO31 (0)
RP2350 Datasheet
9.10. Software examples 598
223 // 0x40000000 [30] GPIO30 (0)
224 // 0x20000000 [29] GPIO29 (0)
225 // 0x10000000 [28] GPIO28 (0)
226 // 0x08000000 [27] GPIO27 (0)
227 // 0x04000000 [26] GPIO26 (0)
228 // 0x02000000 [25] GPIO25 (0)
229 // 0x01000000 [24] GPIO24 (0)
230 // 0x00800000 [23] GPIO23 (0)
231 // 0x00400000 [22] GPIO22 (0)
232 // 0x00200000 [21] GPIO21 (0)
233 // 0x00100000 [20] GPIO20 (0)
234 // 0x00080000 [19] GPIO19 (0)
235 // 0x00040000 [18] GPIO18 (0)
236 // 0x00020000 [17] GPIO17 (0)
237 // 0x00010000 [16] GPIO16 (0)
238 // 0x00008000 [15] GPIO15 (0)
239 // 0x00004000 [14] GPIO14 (0)
240 // 0x00002000 [13] GPIO13 (0)
241 // 0x00001000 [12] GPIO12 (0)
242 // 0x00000800 [11] GPIO11 (0)
243 // 0x00000400 [10] GPIO10 (0)
244 // 0x00000200 [9] GPIO9 (0)
245 // 0x00000100 [8] GPIO8 (0)
246 // 0x00000080 [7] GPIO7 (0)
247 // 0x00000040 [6] GPIO6 (0)
248 // 0x00000020 [5] GPIO5 (0)
249 // 0x00000010 [4] GPIO4 (0)
250 // 0x00000008 [3] GPIO3 (0)
251 // 0x00000004 [2] GPIO2 (0)
252 // 0x00000002 [1] GPIO1 (0)
253 // 0x00000001 [0] GPIO0 (0)
254 io_ro_32 irqsummary_proc0_nonsecure[2];
255
256 // (Description copied from array index 0 register IO_BANK0_IRQSUMMARY_PROC1_SECURE0
applies similarly to other array indexes)
257 _REG_(IO_BANK0_IRQSUMMARY_PROC1_SECURE0_OFFSET) // IO_BANK0_IRQSUMMARY_PROC1_SECURE0
258 // 0x80000000 [31] GPIO31 (0)
259 // 0x40000000 [30] GPIO30 (0)
260 // 0x20000000 [29] GPIO29 (0)
261 // 0x10000000 [28] GPIO28 (0)
262 // 0x08000000 [27] GPIO27 (0)
263 // 0x04000000 [26] GPIO26 (0)
264 // 0x02000000 [25] GPIO25 (0)
265 // 0x01000000 [24] GPIO24 (0)
266 // 0x00800000 [23] GPIO23 (0)
267 // 0x00400000 [22] GPIO22 (0)
268 // 0x00200000 [21] GPIO21 (0)
269 // 0x00100000 [20] GPIO20 (0)
270 // 0x00080000 [19] GPIO19 (0)
271 // 0x00040000 [18] GPIO18 (0)
272 // 0x00020000 [17] GPIO17 (0)
273 // 0x00010000 [16] GPIO16 (0)
274 // 0x00008000 [15] GPIO15 (0)
275 // 0x00004000 [14] GPIO14 (0)
276 // 0x00002000 [13] GPIO13 (0)
277 // 0x00001000 [12] GPIO12 (0)
278 // 0x00000800 [11] GPIO11 (0)
279 // 0x00000400 [10] GPIO10 (0)
280 // 0x00000200 [9] GPIO9 (0)
281 // 0x00000100 [8] GPIO8 (0)
282 // 0x00000080 [7] GPIO7 (0)
283 // 0x00000040 [6] GPIO6 (0)
284 // 0x00000020 [5] GPIO5 (0)
285 // 0x00000010 [4] GPIO4 (0)
RP2350 Datasheet
9.10. Software examples 599
286 // 0x00000008 [3] GPIO3 (0)
287 // 0x00000004 [2] GPIO2 (0)
288 // 0x00000002 [1] GPIO1 (0)
289 // 0x00000001 [0] GPIO0 (0)
290 io_ro_32 irqsummary_proc1_secure[2];
291
292 // (Description copied from array index 0 register IO_BANK0_IRQSUMMARY_PROC1_NONSECURE0
applies similarly to other array indexes)
293 _REG_(IO_BANK0_IRQSUMMARY_PROC1_NONSECURE0_OFFSET) //
IO_BANK0_IRQSUMMARY_PROC1_NONSECURE0
294 // 0x80000000 [31] GPIO31 (0)
295 // 0x40000000 [30] GPIO30 (0)
296 // 0x20000000 [29] GPIO29 (0)
297 // 0x10000000 [28] GPIO28 (0)
298 // 0x08000000 [27] GPIO27 (0)
299 // 0x04000000 [26] GPIO26 (0)
300 // 0x02000000 [25] GPIO25 (0)
301 // 0x01000000 [24] GPIO24 (0)
302 // 0x00800000 [23] GPIO23 (0)
303 // 0x00400000 [22] GPIO22 (0)
304 // 0x00200000 [21] GPIO21 (0)
305 // 0x00100000 [20] GPIO20 (0)
306 // 0x00080000 [19] GPIO19 (0)
307 // 0x00040000 [18] GPIO18 (0)
308 // 0x00020000 [17] GPIO17 (0)
309 // 0x00010000 [16] GPIO16 (0)
310 // 0x00008000 [15] GPIO15 (0)
311 // 0x00004000 [14] GPIO14 (0)
312 // 0x00002000 [13] GPIO13 (0)
313 // 0x00001000 [12] GPIO12 (0)
314 // 0x00000800 [11] GPIO11 (0)
315 // 0x00000400 [10] GPIO10 (0)
316 // 0x00000200 [9] GPIO9 (0)
317 // 0x00000100 [8] GPIO8 (0)
318 // 0x00000080 [7] GPIO7 (0)
319 // 0x00000040 [6] GPIO6 (0)
320 // 0x00000020 [5] GPIO5 (0)
321 // 0x00000010 [4] GPIO4 (0)
322 // 0x00000008 [3] GPIO3 (0)
323 // 0x00000004 [2] GPIO2 (0)
324 // 0x00000002 [1] GPIO1 (0)
325 // 0x00000001 [0] GPIO0 (0)
326 io_ro_32 irqsummary_proc1_nonsecure[2];
327
328 // (Description copied from array index 0 register
IO_BANK0_IRQSUMMARY_DORMANT_WAKE_SECURE0 applies similarly to other array indexes)
329 _REG_(IO_BANK0_IRQSUMMARY_DORMANT_WAKE_SECURE0_OFFSET) //
IO_BANK0_IRQSUMMARY_DORMANT_WAKE_SECURE0
330 // 0x80000000 [31] GPIO31 (0)
331 // 0x40000000 [30] GPIO30 (0)
332 // 0x20000000 [29] GPIO29 (0)
333 // 0x10000000 [28] GPIO28 (0)
334 // 0x08000000 [27] GPIO27 (0)
335 // 0x04000000 [26] GPIO26 (0)
336 // 0x02000000 [25] GPIO25 (0)
337 // 0x01000000 [24] GPIO24 (0)
338 // 0x00800000 [23] GPIO23 (0)
339 // 0x00400000 [22] GPIO22 (0)
340 // 0x00200000 [21] GPIO21 (0)
341 // 0x00100000 [20] GPIO20 (0)
342 // 0x00080000 [19] GPIO19 (0)
343 // 0x00040000 [18] GPIO18 (0)
344 // 0x00020000 [17] GPIO17 (0)
345 // 0x00010000 [16] GPIO16 (0)
RP2350 Datasheet
9.10. Software examples 600
346 // 0x00008000 [15] GPIO15 (0)
347 // 0x00004000 [14] GPIO14 (0)
348 // 0x00002000 [13] GPIO13 (0)
349 // 0x00001000 [12] GPIO12 (0)
350 // 0x00000800 [11] GPIO11 (0)
351 // 0x00000400 [10] GPIO10 (0)
352 // 0x00000200 [9] GPIO9 (0)
353 // 0x00000100 [8] GPIO8 (0)
354 // 0x00000080 [7] GPIO7 (0)
355 // 0x00000040 [6] GPIO6 (0)
356 // 0x00000020 [5] GPIO5 (0)
357 // 0x00000010 [4] GPIO4 (0)
358 // 0x00000008 [3] GPIO3 (0)
359 // 0x00000004 [2] GPIO2 (0)
360 // 0x00000002 [1] GPIO1 (0)
361 // 0x00000001 [0] GPIO0 (0)
362 io_ro_32 irqsummary_dormant_wake_secure[2];
363
364 // (Description copied from array index 0 register
IO_BANK0_IRQSUMMARY_DORMANT_WAKE_NONSECURE0 applies similarly to other array indexes)
365 _REG_(IO_BANK0_IRQSUMMARY_DORMANT_WAKE_NONSECURE0_OFFSET) //
IO_BANK0_IRQSUMMARY_DORMANT_WAKE_NONSECURE0
366 // 0x80000000 [31] GPIO31 (0)
367 // 0x40000000 [30] GPIO30 (0)
368 // 0x20000000 [29] GPIO29 (0)
369 // 0x10000000 [28] GPIO28 (0)
370 // 0x08000000 [27] GPIO27 (0)
371 // 0x04000000 [26] GPIO26 (0)
372 // 0x02000000 [25] GPIO25 (0)
373 // 0x01000000 [24] GPIO24 (0)
374 // 0x00800000 [23] GPIO23 (0)
375 // 0x00400000 [22] GPIO22 (0)
376 // 0x00200000 [21] GPIO21 (0)
377 // 0x00100000 [20] GPIO20 (0)
378 // 0x00080000 [19] GPIO19 (0)
379 // 0x00040000 [18] GPIO18 (0)
380 // 0x00020000 [17] GPIO17 (0)
381 // 0x00010000 [16] GPIO16 (0)
382 // 0x00008000 [15] GPIO15 (0)
383 // 0x00004000 [14] GPIO14 (0)
384 // 0x00002000 [13] GPIO13 (0)
385 // 0x00001000 [12] GPIO12 (0)
386 // 0x00000800 [11] GPIO11 (0)
387 // 0x00000400 [10] GPIO10 (0)
388 // 0x00000200 [9] GPIO9 (0)
389 // 0x00000100 [8] GPIO8 (0)
390 // 0x00000080 [7] GPIO7 (0)
391 // 0x00000040 [6] GPIO6 (0)
392 // 0x00000020 [5] GPIO5 (0)
393 // 0x00000010 [4] GPIO4 (0)
394 // 0x00000008 [3] GPIO3 (0)
395 // 0x00000004 [2] GPIO2 (0)
396 // 0x00000002 [1] GPIO1 (0)
397 // 0x00000001 [0] GPIO0 (0)
398 io_ro_32 irqsummary_dormant_wake_nonsecure[2];
399
400 // (Description copied from array index 0 register IO_BANK0_INTR0 applies similarly to
other array indexes)
401 _REG_(IO_BANK0_INTR0_OFFSET) // IO_BANK0_INTR0
402 // Raw Interrupts
403 // 0x80000000 [31] GPIO7_EDGE_HIGH (0)
404 // 0x40000000 [30] GPIO7_EDGE_LOW (0)
405 // 0x20000000 [29] GPIO7_LEVEL_HIGH (0)
406 // 0x10000000 [28] GPIO7_LEVEL_LOW (0)
RP2350 Datasheet
9.10. Software examples 601
407 // 0x08000000 [27] GPIO6_EDGE_HIGH (0)
408 // 0x04000000 [26] GPIO6_EDGE_LOW (0)
409 // 0x02000000 [25] GPIO6_LEVEL_HIGH (0)
410 // 0x01000000 [24] GPIO6_LEVEL_LOW (0)
411 // 0x00800000 [23] GPIO5_EDGE_HIGH (0)
412 // 0x00400000 [22] GPIO5_EDGE_LOW (0)
413 // 0x00200000 [21] GPIO5_LEVEL_HIGH (0)
414 // 0x00100000 [20] GPIO5_LEVEL_LOW (0)
415 // 0x00080000 [19] GPIO4_EDGE_HIGH (0)
416 // 0x00040000 [18] GPIO4_EDGE_LOW (0)
417 // 0x00020000 [17] GPIO4_LEVEL_HIGH (0)
418 // 0x00010000 [16] GPIO4_LEVEL_LOW (0)
419 // 0x00008000 [15] GPIO3_EDGE_HIGH (0)
420 // 0x00004000 [14] GPIO3_EDGE_LOW (0)
421 // 0x00002000 [13] GPIO3_LEVEL_HIGH (0)
422 // 0x00001000 [12] GPIO3_LEVEL_LOW (0)
423 // 0x00000800 [11] GPIO2_EDGE_HIGH (0)
424 // 0x00000400 [10] GPIO2_EDGE_LOW (0)
425 // 0x00000200 [9] GPIO2_LEVEL_HIGH (0)
426 // 0x00000100 [8] GPIO2_LEVEL_LOW (0)
427 // 0x00000080 [7] GPIO1_EDGE_HIGH (0)
428 // 0x00000040 [6] GPIO1_EDGE_LOW (0)
429 // 0x00000020 [5] GPIO1_LEVEL_HIGH (0)
430 // 0x00000010 [4] GPIO1_LEVEL_LOW (0)
431 // 0x00000008 [3] GPIO0_EDGE_HIGH (0)
432 // 0x00000004 [2] GPIO0_EDGE_LOW (0)
433 // 0x00000002 [1] GPIO0_LEVEL_HIGH (0)
434 // 0x00000001 [0] GPIO0_LEVEL_LOW (0)
435 io_rw_32 intr[6];
436
437 union {
438 struct {
439 io_bank0_irq_ctrl_hw_t proc0_irq_ctrl;
440 io_bank0_irq_ctrl_hw_t proc1_irq_ctrl;
441 io_bank0_irq_ctrl_hw_t dormant_wake_irq_ctrl;
442 };
443 io_bank0_irq_ctrl_hw_t irq_ctrl[3];
444 };
445 } io_bank0_hw_t;
A similar structure is defined for the pad control registers for IO bank 1. By default, all pads come out of reset ready to
use, with input enabled and output disable set to 0. Regardless, gpio_set_function in the SDK sets the input enable and
clears the output disable to engage the pads IO buffers and connect internal signals to the outside world. Finally, the
desired function select is written to the IO control register (see GPIO0_CTRL for an example of an IO control register).
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_gpio/gpio.c Lines 36 - 53
36 // Select function for this GPIO, and ensure input/output are enabled at the pad.
37 // This also clears the input/output/irq override bits.
38 void gpio_set_function(uint gpio, gpio_function_t fn) {
39 check_gpio_param(gpio);
40 invalid_params_if(HARDWARE_GPIO, ((uint32_t)fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB) &
~IO_BANK0_GPIO0_CTRL_FUNCSEL_BITS);
41 // Set input enable on, output disable off
42 hw_write_masked(&pads_bank0_hw->io[gpio],
43 PADS_BANK0_GPIO0_IE_BITS,
44 PADS_BANK0_GPIO0_IE_BITS | PADS_BANK0_GPIO0_OD_BITS
45 );
46 // Zero all fields apart from fsel; we want this IO to do what the peripheral tells it.
47 // This doesn't affect e.g. pullup/pulldown, as these are in pad controls.
48 io_bank0_hw->io[gpio].ctrl = fn << IO_BANK0_GPIO0_CTRL_FUNCSEL_LSB;
49 // Remove pad isolation now that the correct peripheral is in control of the pad
RP2350 Datasheet
9.10. Software examples 602
50 hw_clear_bits(&pads_bank0_hw->io[gpio], PADS_BANK0_GPIO0_ISO_BITS);
51 }
9.10.2. Enable a GPIO interrupt
The SDK provides a method of being interrupted when a GPIO pin changes state:
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_gpio/gpio.c Lines 186 - 196
186 void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled) {
187 // either this call disables the interrupt or callback should already be set.
188 // this protects against enabling the interrupt without callback set
189 assert(!enabled || irq_has_handler(IO_IRQ_BANK0));
190
191 // Separate mask/force/status per-core, so check which core called, and
192 // set the relevant IRQ controls.
193 io_bank0_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ?
194 &io_bank0_hw->proc1_irq_ctrl : &io_bank0_hw-
>proc0_irq_ctrl;
195 _gpio_set_irq_enabled(gpio, events, enabled, irq_ctrl_base);
196 }
gpio_set_irq_enabled uses a lower level function _gpio_set_irq_enabled:
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_gpio/gpio.c Lines 173 - 184
173 static void _gpio_set_irq_enabled(uint gpio, uint32_t events, bool enabled,
io_bank0_irq_ctrl_hw_t *irq_ctrl_base) {
174 // Clear stale events which might cause immediate spurious handler entry
175 gpio_acknowledge_irq(gpio, events);
176
177 io_rw_32 *en_reg = &irq_ctrl_base->inte[gpio / 8];
178 events <<= 4 * (gpio % 8);
179
180 if (enabled)
181 hw_set_bits(en_reg, events);
182 else
183 hw_clear_bits(en_reg, events);
184 }
The user provides a pointer to a callback function that is called when the GPIO event happens. An example application
that uses this system is hello_gpio_irq:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/gpio/hello_gpio_irq/hello_gpio_irq.c
1 /**
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdio.h>
8 #include "pico/stdlib.h"
9 #include "hardware/gpio.h"
10
11 #define GPIO_WATCH_PIN 2
12
RP2350 Datasheet
9.10. Software examples 603
13 static char event_str[128];
14
15 void gpio_event_string(char *buf, uint32_t events);
16
17 void gpio_callback(uint gpio, uint32_t events) {
18 // Put the GPIO event(s) that just happened into event_str
19 // so we can print it
20 gpio_event_string(event_str, events);
21 printf("GPIO %d %s\n", gpio, event_str);
22 }
23
24 int main() {
25 stdio_init_all();
26
27 printf("Hello GPIO IRQ\n");
28 gpio_init(GPIO_WATCH_PIN);
29 gpio_set_irq_enabled_with_callback(GPIO_WATCH_PIN, GPIO_IRQ_EDGE_RISE |
GPIO_IRQ_EDGE_FALL, true, &gpio_callback);
30
31 // Wait forever
32 while (1);
33 }
34
35
36 static const char *gpio_irq_str[] = {
37 "LEVEL_LOW", // 0x1
38 "LEVEL_HIGH", // 0x2
39 "EDGE_FALL", // 0x4
40 "EDGE_RISE" // 0x8
41 };
42
43 void gpio_event_string(char *buf, uint32_t events) {
44 for (uint i = 0; i < 4; i++) {
45 uint mask = (1 << i);
46 if (events & mask) {
47 // Copy this event string into the user string
48 const char *event_str = gpio_irq_str[i];
49 while (*event_str != '\0') {
50 *buf++ = *event_str++;
51 }
52 events &= ~mask;
53
54 // If more events add ", "
55 if (events) {
56 *buf++ = ',';
57 *buf++ = ' ';
58 }
59 }
60 }
61 *buf++ = '\0';
62 }
9.11. List of registers
9.11.1. IO - User Bank
The User Bank IO registers start at a base address of 0x40028000 (defined as IO_BANK0_BASE in SDK).
RP2350 Datasheet
9.11. List of registers 604
Table 649. List of
IO_BANK0 registers
Offset Name Info
0x000 GPIO0_STATUS
0x004 GPIO0_CTRL
0x008 GPIO1_STATUS
0x00c GPIO1_CTRL
0x010 GPIO2_STATUS
0x014 GPIO2_CTRL
0x018 GPIO3_STATUS
0x01c GPIO3_CTRL
0x020 GPIO4_STATUS
0x024 GPIO4_CTRL
0x028 GPIO5_STATUS
0x02c GPIO5_CTRL
0x030 GPIO6_STATUS
0x034 GPIO6_CTRL
0x038 GPIO7_STATUS
0x03c GPIO7_CTRL
0x040 GPIO8_STATUS
0x044 GPIO8_CTRL
0x048 GPIO9_STATUS
0x04c GPIO9_CTRL
0x050 GPIO10_STATUS
0x054 GPIO10_CTRL
0x058 GPIO11_STATUS
0x05c GPIO11_CTRL
0x060 GPIO12_STATUS
0x064 GPIO12_CTRL
0x068 GPIO13_STATUS
0x06c GPIO13_CTRL
0x070 GPIO14_STATUS
0x074 GPIO14_CTRL
0x078 GPIO15_STATUS
0x07c GPIO15_CTRL
0x080 GPIO16_STATUS
0x084 GPIO16_CTRL
0x088 GPIO17_STATUS
0x08c GPIO17_CTRL
RP2350 Datasheet
9.11. List of registers 605
Offset Name Info
0x090 GPIO18_STATUS
0x094 GPIO18_CTRL
0x098 GPIO19_STATUS
0x09c GPIO19_CTRL
0x0a0 GPIO20_STATUS
0x0a4 GPIO20_CTRL
0x0a8 GPIO21_STATUS
0x0ac GPIO21_CTRL
0x0b0 GPIO22_STATUS
0x0b4 GPIO22_CTRL
0x0b8 GPIO23_STATUS
0x0bc GPIO23_CTRL
0x0c0 GPIO24_STATUS
0x0c4 GPIO24_CTRL
0x0c8 GPIO25_STATUS
0x0cc GPIO25_CTRL
0x0d0 GPIO26_STATUS
0x0d4 GPIO26_CTRL
0x0d8 GPIO27_STATUS
0x0dc GPIO27_CTRL
0x0e0 GPIO28_STATUS
0x0e4 GPIO28_CTRL
0x0e8 GPIO29_STATUS
0x0ec GPIO29_CTRL
0x0f0 GPIO30_STATUS
0x0f4 GPIO30_CTRL
0x0f8 GPIO31_STATUS
0x0fc GPIO31_CTRL
0x100 GPIO32_STATUS
0x104 GPIO32_CTRL
0x108 GPIO33_STATUS
0x10c GPIO33_CTRL
0x110 GPIO34_STATUS
0x114 GPIO34_CTRL
0x118 GPIO35_STATUS
0x11c GPIO35_CTRL
RP2350 Datasheet
9.11. List of registers 606
Offset Name Info
0x120 GPIO36_STATUS
0x124 GPIO36_CTRL
0x128 GPIO37_STATUS
0x12c GPIO37_CTRL
0x130 GPIO38_STATUS
0x134 GPIO38_CTRL
0x138 GPIO39_STATUS
0x13c GPIO39_CTRL
0x140 GPIO40_STATUS
0x144 GPIO40_CTRL
0x148 GPIO41_STATUS
0x14c GPIO41_CTRL
0x150 GPIO42_STATUS
0x154 GPIO42_CTRL
0x158 GPIO43_STATUS
0x15c GPIO43_CTRL
0x160 GPIO44_STATUS
0x164 GPIO44_CTRL
0x168 GPIO45_STATUS
0x16c GPIO45_CTRL
0x170 GPIO46_STATUS
0x174 GPIO46_CTRL
0x178 GPIO47_STATUS
0x17c GPIO47_CTRL
0x200 IRQSUMMARY_PROC0_SECURE0
0x204 IRQSUMMARY_PROC0_SECURE1
0x208 IRQSUMMARY_PROC0_NONSECURE0
0x20c IRQSUMMARY_PROC0_NONSECURE1
0x210 IRQSUMMARY_PROC1_SECURE0
0x214 IRQSUMMARY_PROC1_SECURE1
0x218 IRQSUMMARY_PROC1_NONSECURE0
0x21c IRQSUMMARY_PROC1_NONSECURE1
0x220 IRQSUMMARY_COMA_WAKE_SECURE
0
0x224 IRQSUMMARY_COMA_WAKE_SECURE
1
RP2350 Datasheet
9.11. List of registers 607
Offset Name Info
0x228 IRQSUMMARY_COMA_WAKE_NONSE
CURE0
0x22c IRQSUMMARY_COMA_WAKE_NONSE
CURE1
0x230 INTR0 Raw Interrupts
0x234 INTR1 Raw Interrupts
0x238 INTR2 Raw Interrupts
0x23c INTR3 Raw Interrupts
0x240 INTR4 Raw Interrupts
0x244 INTR5 Raw Interrupts
0x248 PROC0_INTE0 Interrupt Enable for proc0
0x24c PROC0_INTE1 Interrupt Enable for proc0
0x250 PROC0_INTE2 Interrupt Enable for proc0
0x254 PROC0_INTE3 Interrupt Enable for proc0
0x258 PROC0_INTE4 Interrupt Enable for proc0
0x25c PROC0_INTE5 Interrupt Enable for proc0
0x260 PROC0_INTF0 Interrupt Force for proc0
0x264 PROC0_INTF1 Interrupt Force for proc0
0x268 PROC0_INTF2 Interrupt Force for proc0
0x26c PROC0_INTF3 Interrupt Force for proc0
0x270 PROC0_INTF4 Interrupt Force for proc0
0x274 PROC0_INTF5 Interrupt Force for proc0
0x278 PROC0_INTS0 Interrupt status after masking & forcing for proc0
0x27c PROC0_INTS1 Interrupt status after masking & forcing for proc0
0x280 PROC0_INTS2 Interrupt status after masking & forcing for proc0
0x284 PROC0_INTS3 Interrupt status after masking & forcing for proc0
0x288 PROC0_INTS4 Interrupt status after masking & forcing for proc0
0x28c PROC0_INTS5 Interrupt status after masking & forcing for proc0
0x290 PROC1_INTE0 Interrupt Enable for proc1
0x294 PROC1_INTE1 Interrupt Enable for proc1
0x298 PROC1_INTE2 Interrupt Enable for proc1
0x29c PROC1_INTE3 Interrupt Enable for proc1
0x2a0 PROC1_INTE4 Interrupt Enable for proc1
0x2a4 PROC1_INTE5 Interrupt Enable for proc1
0x2a8 PROC1_INTF0 Interrupt Force for proc1
0x2ac PROC1_INTF1 Interrupt Force for proc1
RP2350 Datasheet
9.11. List of registers 608
Offset Name Info
0x2b0 PROC1_INTF2 Interrupt Force for proc1
0x2b4 PROC1_INTF3 Interrupt Force for proc1
0x2b8 PROC1_INTF4 Interrupt Force for proc1
0x2bc PROC1_INTF5 Interrupt Force for proc1
0x2c0 PROC1_INTS0 Interrupt status after masking & forcing for proc1
0x2c4 PROC1_INTS1 Interrupt status after masking & forcing for proc1
0x2c8 PROC1_INTS2 Interrupt status after masking & forcing for proc1
0x2cc PROC1_INTS3 Interrupt status after masking & forcing for proc1
0x2d0 PROC1_INTS4 Interrupt status after masking & forcing for proc1
0x2d4 PROC1_INTS5 Interrupt status after masking & forcing for proc1
0x2d8 DORMANT_WAKE_INTE0 Interrupt Enable for dormant_wake
0x2dc DORMANT_WAKE_INTE1 Interrupt Enable for dormant_wake
0x2e0 DORMANT_WAKE_INTE2 Interrupt Enable for dormant_wake
0x2e4 DORMANT_WAKE_INTE3 Interrupt Enable for dormant_wake
0x2e8 DORMANT_WAKE_INTE4 Interrupt Enable for dormant_wake
0x2ec DORMANT_WAKE_INTE5 Interrupt Enable for dormant_wake
0x2f0 DORMANT_WAKE_INTF0 Interrupt Force for dormant_wake
0x2f4 DORMANT_WAKE_INTF1 Interrupt Force for dormant_wake
0x2f8 DORMANT_WAKE_INTF2 Interrupt Force for dormant_wake
0x2fc DORMANT_WAKE_INTF3 Interrupt Force for dormant_wake
0x300 DORMANT_WAKE_INTF4 Interrupt Force for dormant_wake
0x304 DORMANT_WAKE_INTF5 Interrupt Force for dormant_wake
0x308 DORMANT_WAKE_INTS0 Interrupt status after masking & forcing for dormant_wake
0x30c DORMANT_WAKE_INTS1 Interrupt status after masking & forcing for dormant_wake
0x310 DORMANT_WAKE_INTS2 Interrupt status after masking & forcing for dormant_wake
0x314 DORMANT_WAKE_INTS3 Interrupt status after masking & forcing for dormant_wake
0x318 DORMANT_WAKE_INTS4 Interrupt status after masking & forcing for dormant_wake
0x31c DORMANT_WAKE_INTS5 Interrupt status after masking & forcing for dormant_wake
IO_BANK0: GPIO0_STATUS Register
Offset: 0x000
Table 650.
GPIO0_STATUS
Register
Bits Description Type Reset
31:27 Reserved. - -
26 IRQTOPROC: interrupt to processors, after override is applied RO 0x0
25:18 Reserved. - -
17 INFROMPAD: input signal from pad, before filtering and override are applied RO 0x0
RP2350 Datasheet
9.11. List of registers 609
Bits Description Type Reset
16:14 Reserved. - -
13 OETOPAD: output enable to pad after register override is applied RO 0x0
12:10 Reserved. - -
9 OUTTOPAD: output signal to pad after register override is applied RO 0x0
8:0 Reserved. - -
IO_BANK0: GPIO0_CTRL Register
Offset: 0x004
Table 651.
GPIO0_CTRL Register
Bits Description Type Reset
31:30 Reserved. - -
29:28 IRQOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the interrupt
0x1 → INVERT: invert the interrupt
0x2 → LOW: drive interrupt low
0x3 → HIGH: drive interrupt high
27:18 Reserved. - -
17:16 INOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the peri input
0x1 → INVERT: invert the peri input
0x2 → LOW: drive peri input low
0x3 → HIGH: drive peri input high
15:14 OEOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output enable from peripheral signal selected by
funcsel
0x1 → INVERT: drive output enable from inverse of peripheral signal selected
by funcsel
0x2 → DISABLE: disable output
0x3 → ENABLE: enable output
13:12 OUTOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output from peripheral signal selected by funcsel
0x1 → INVERT: drive output from inverse of peripheral signal selected by
funcsel
RP2350 Datasheet
9.11. List of registers 610
Bits Description Type Reset
0x2 → LOW: drive output low
0x3 → HIGH: drive output high
11:5 Reserved. - -
4:0 FUNCSEL: 0-31 → selects pin function according to the gpio table
31 == NULL
RW 0x1f
Enumerated values:
0x00 → JTAG_TCK
0x01 → SPI0_RX
0x02 → UART0_TX
0x03 → I2C0_SDA
0x04 → PWM_A_0
0x05 → SIO_0
0x06 → PIO0_0
0x07 → PIO1_0
0x08 → PIO2_0
0x09 → XIP_SS_N_1
0x0a → USB_MUXING_OVERCURR_DETECT
0x1f → NULL
IO_BANK0: GPIO1_STATUS Register
Offset: 0x008
Table 652.
GPIO1_STATUS
Register
Bits Description Type Reset
31:27 Reserved. - -
26 IRQTOPROC: interrupt to processors, after override is applied RO 0x0
25:18 Reserved. - -
17 INFROMPAD: input signal from pad, before filtering and override are applied RO 0x0
16:14 Reserved. - -
13 OETOPAD: output enable to pad after register override is applied RO 0x0
12:10 Reserved. - -
9 OUTTOPAD: output signal to pad after register override is applied RO 0x0
8:0 Reserved. - -
IO_BANK0: GPIO1_CTRL Register
Offset: 0x00c
Table 653.
GPIO1_CTRL Register
Bits Description Type Reset
31:30 Reserved. - -
RP2350 Datasheet
9.11. List of registers 611
Bits Description Type Reset
29:28 IRQOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the interrupt
0x1 → INVERT: invert the interrupt
0x2 → LOW: drive interrupt low
0x3 → HIGH: drive interrupt high
27:18 Reserved. - -
17:16 INOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the peri input
0x1 → INVERT: invert the peri input
0x2 → LOW: drive peri input low
0x3 → HIGH: drive peri input high
15:14 OEOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output enable from peripheral signal selected by
funcsel
0x1 → INVERT: drive output enable from inverse of peripheral signal selected
by funcsel
0x2 → DISABLE: disable output
0x3 → ENABLE: enable output
13:12 OUTOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output from peripheral signal selected by funcsel
0x1 → INVERT: drive output from inverse of peripheral signal selected by
funcsel
0x2 → LOW: drive output low
0x3 → HIGH: drive output high
11:5 Reserved. - -
4:0 FUNCSEL: 0-31 → selects pin function according to the gpio table
31 == NULL
RW 0x1f
Enumerated values:
0x00 → JTAG_TMS
0x01 → SPI0_SS_N
0x02 → UART0_RX
0x03 → I2C0_SCL
0x04 → PWM_B_0
RP2350 Datasheet
9.11. List of registers 612
Bits Description Type Reset
0x05 → SIO_1
0x06 → PIO0_1
0x07 → PIO1_1
0x08 → PIO2_1
0x09 → CORESIGHT_TRACECLK
0x0a → USB_MUXING_VBUS_DETECT
0x1f → NULL
IO_BANK0: GPIO2_STATUS Register
Offset: 0x010
Table 654.
GPIO2_STATUS
Register
Bits Description Type Reset
31:27 Reserved. - -
26 IRQTOPROC: interrupt to processors, after override is applied RO 0x0
25:18 Reserved. - -
17 INFROMPAD: input signal from pad, before filtering and override are applied RO 0x0
16:14 Reserved. - -
13 OETOPAD: output enable to pad after register override is applied RO 0x0
12:10 Reserved. - -
9 OUTTOPAD: output signal to pad after register override is applied RO 0x0
8:0 Reserved. - -
IO_BANK0: GPIO2_CTRL Register
Offset: 0x014
Table 655.
GPIO2_CTRL Register
Bits Description Type Reset
31:30 Reserved. - -
29:28 IRQOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the interrupt
0x1 → INVERT: invert the interrupt
0x2 → LOW: drive interrupt low
0x3 → HIGH: drive interrupt high
27:18 Reserved. - -
17:16 INOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the peri input
0x1 → INVERT: invert the peri input
RP2350 Datasheet
9.11. List of registers 613
Bits Description Type Reset
0x2 → LOW: drive peri input low
0x3 → HIGH: drive peri input high
15:14 OEOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output enable from peripheral signal selected by
funcsel
0x1 → INVERT: drive output enable from inverse of peripheral signal selected
by funcsel
0x2 → DISABLE: disable output
0x3 → ENABLE: enable output
13:12 OUTOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output from peripheral signal selected by funcsel
0x1 → INVERT: drive output from inverse of peripheral signal selected by
funcsel
0x2 → LOW: drive output low
0x3 → HIGH: drive output high
11:5 Reserved. - -
4:0 FUNCSEL: 0-31 → selects pin function according to the gpio table
31 == NULL
RW 0x1f
Enumerated values:
0x00 → JTAG_TDI
0x01 → SPI0_SCLK
0x02 → UART0_CTS
0x03 → I2C1_SDA
0x04 → PWM_A_1
0x05 → SIO_2
0x06 → PIO0_2
0x07 → PIO1_2
0x08 → PIO2_2
0x09 → CORESIGHT_TRACEDATA_0
0x0a → USB_MUXING_VBUS_EN
0x0b → UART0_TX
0x1f → NULL
IO_BANK0: GPIO3_STATUS Register
Offset: 0x018
RP2350 Datasheet
9.11. List of registers 614
Table 656.
GPIO3_STATUS
Register
Bits Description Type Reset
31:27 Reserved. - -
26 IRQTOPROC: interrupt to processors, after override is applied RO 0x0
25:18 Reserved. - -
17 INFROMPAD: input signal from pad, before filtering and override are applied RO 0x0
16:14 Reserved. - -
13 OETOPAD: output enable to pad after register override is applied RO 0x0
12:10 Reserved. - -
9 OUTTOPAD: output signal to pad after register override is applied RO 0x0
8:0 Reserved. - -
IO_BANK0: GPIO3_CTRL Register
Offset: 0x01c
Table 657.
GPIO3_CTRL Register
Bits Description Type Reset
31:30 Reserved. - -
29:28 IRQOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the interrupt
0x1 → INVERT: invert the interrupt
0x2 → LOW: drive interrupt low
0x3 → HIGH: drive interrupt high
27:18 Reserved. - -
17:16 INOVER RW 0x0
Enumerated values:
0x0 → NORMAL: dont invert the peri input
0x1 → INVERT: invert the peri input
0x2 → LOW: drive peri input low
0x3 → HIGH: drive peri input high
15:14 OEOVER RW 0x0
Enumerated values:
0x0 → NORMAL: drive output enable from peripheral signal selected by
funcsel
0x1 → INVERT: drive output enable from inverse of peripheral signal selected
by funcsel
0x2 → DISABLE: disable output
0x3 → ENABLE: enable output
13:12 OUTOVER RW 0x0
12.7. USB
12.7.1. Overview
 NOTE
Prerequisite knowledge required
This section requires knowledge of the USB protocol. If you arent yet familiar with the USB protocol, we recommend
the archive of the very useful USB Made Simple website. For formal definitions of the terminology used in this
section, see the USB 2.0 Specification.
RP2350 contains a USB 2.0 controller that can operate as either:
• a Full Speed (FS) device (12 Mb/s)
• a host that can communicate with both Low Speed (LS) (1.5 Mb/s) and Full Speed devices, including multiple
downstream devices connected to a USB hub
There is an integrated USB 1.1 PHY which interfaces the USB controller with the DP and DM pins of the chip. You may use
this as 3.3 V GPIO when the USB controller is not in use.
RP2350 Datasheet
12.7. USB 1141
12.7.1.1. Features
The USB controller hardware handles the low level USB protocol. The programmer must configure the controller, provide
data buffers, and consume or provide data buffers in response to events on the bus. The controller interrupts the
processor when it needs attention. The USB controller has 4 kB of dual-port SRAM (DPSRAM) used for configuration
and data buffers.
12.7.1.1.1. Device Mode
In Device Mode, the USB controller has the following characteristics:
• USB 2.0-compatible Full Speed device (12 Mb/s)
• Supports up to 32 endpoints (Endpoints 0 → 15 in both in and out directions)
• Supports Control, Isochronous (ISO), Bulk, and Interrupt endpoint types
• Supports double buffering
• 3840 bytes of usable buffer space in DPSRAM. This is equivalent to 60 × 64-byte buffers
12.7.1.1.2. Host Mode
In Host Mode, the USB controller can:
• communicate with Full Speed (12 Mb/s) devices and Low Speed devices (1.5 Mb/s)
• communicate with multiple devices via a USB hub, including Low Speed devices connected to a Full Speed hub
• poll up to 15 interrupt endpoints in hardware (used by hubs to notify the host of connect/disconnect events, used
by mice to notify the host of movement, etc.)
12.7.1.1.3. USB DPRAM
The USB controller uses 4 kB of dual-port SRAM (DPSRAM) to exchange data and control information with the
controller. This is also referred to as dual-port RAM (DPRAM). One port is accessible from the system bus, clocked by
clk_sys. The other port is accessible from the controller, clocked by clk_usb. The DPRAM is mapped in the system
address space starting from 0x50100000, USBCTRL_DPRAM_BASE.
The USB DPRAM supports 32-bit, 16-bit and 8-bit reads and writes. Writes complete in one cycle. Reads complete in two
cycles.
You can store general user data in USB DPRAM space not required for USB controller operation. When the controller is
disabled, all 4 kB of DPRAM is available. Before accessing the DPRAM, you must take the USB controller out of reset.
Since the USB controller is in the peripheral address space, it is not accessible for processor instruction fetch.
Attempting to fetch instructions from USB DPRAM unconditionally returns a bus error response, no matter the
configuration of the processor SAU/MPU/PMP or the system ACCESSCTRL registers.
As peripheral addresses are marked Exempt in the IDAU (Section 10.2.2), the SAU configuration for this address range
is ignored. Accesses to USB DPRAM are controlled only by the processor MPU/PMP and the ACCESSCTRL USBCTRL
register.
12.7.2. Changes from RP2040
All changes from RP2040 are a superset of the RP2040 features. Existing software for the RP2040 USB controller will
continue to work with one exception: you must clear the MAIN_CTRL.PHY_ISO bit at startup and after power down
events. We recommend leaving the LINESTATE_TUNING register at its reset value. Software should not clear this
register.
RP2350 Datasheet
12.7. USB 1142
12.7.2.1. Errata fixes
RP2350 fixes all RP2040 USB errata. This includes fixes for the following RP2040B0 and B1 errata which are also fixed
by RP2040B2:
• RP2040-E2: USB device endpoint abort is not cleared
• RP2040-E5: USB device fails to exit RESET state on busy USB bus
For more information about RP2040B2, see the RP2040 datasheet.
RP2350 fixes the following RP2040B2 errata, which require software workarounds on RP2040B2:
• RP2040-E3: USB host: interrupt endpoint buffer done flag can be set with incorrect buffer select
• RP2040-E4: USB host writes to upper half of buffer status in single buffered mode
• RP2040-E15: USB Device controller will hang if certain bus errors occur during an IN transfer (see Section
12.7.2.2.4)
12.7.2.2. New features
12.7.2.2.1. General
• The USB PHY DP and DM can be used as regular GPIO pins. See the GPIO muxing Table 646 in Section 9.4..
• A MAIN_CTRL.PHY_ISO control isolates the PHY from the switched core power domain while the switched core
domain is powered down. The isolation control resets to 1, meaning the MAIN_CTRL.PHY_ISO bit needs to be
cleared before the PHY can be used. For more information on isolation, see Chapter 9.
• SIE_CTRL.PULLDOWN_EN defaults to a 1 to match the reset state of isolation latches in the USB PHY. Pulling the
DP and DM pins down by default saves power by preventing them from floating when unused.
• The USB_MUXING.TO_PHY bit defaults to a 1 to match the reset state of isolation latches.
• Added SM_STATE, which exposes the internal state of the controllers modules.
12.7.2.2.2. Host
• You can now optionally stop a transaction if a NAK is received. This allows the USB host to stop a bulk transaction if
the device is not able to transfer data. Some devices using bulk endpoints, such as a UART, will return NAKs until a
character is received. Stopping the transaction in hardware rather than using software means the host can get a
NAK and guarantee no data has been dropped. RP2350 adds two register bits and an interrupt to support this:
The NAK_POLL.STOP_EPX_ON_NAK control, which enables and disables the feature.
The NAK_POLL.EPX_STOPPED_ON_NAK status bit, which also has an associated interrupt
INTS.EPX_STOPPED_ON_NAK.
• RP2350 increases inter-packet and turnaround timeouts to accommodate worst-case hub delays. This issue, only
seen with long chains of USB hubs, was never seen in practice. Timings in the host state machine have been
corrected to match USB spec. This fix is enabled by LINESTATE_TUNING.MULTI_HUB_FIX.
12.7.2.2.3. Device
• Added wake from suspend fix: Any bus activity (defined as K or SE0) should cause a wake from suspend, not just a
qualified period of resume signalling. This fix is enabled by default and can be disabled with
LINESTATE_TUNING.DEV_LS_WAKE_FIX (LS means line state in this instance, not low speed).
• Added DPSRAM double read feature to ensure data consistency. This avoids the need to set the AVAILABLE bit in the
buffer control register separate to the rest of the buffer information. This feature is enabled by default and
controlled by LINESTATE_TUNING.DEV_BUFF_CONTROL_DOUBLE_READ_FIX.
RP2350 Datasheet
12.7. USB 1143
• Added ability to stop DEVICE OUT FROM HOST when a short packet is received. For EP0 this is controlled by
SIE_CTRL.EP0_STOP_ON_SHORT_PACKET. This is done by stopping the transaction and then not toggling the
buffer if in double buffered mode. Also added short_packet interrupt to notify software that a short packet has been
received (INTS.RX_SHORT_PACKET)
12.7.2.2.4. Device error handling
• Added DEV_RX_ERR_QUIESCE feature: the device endpoint error count replicates the hosts internal Cerr count so
software can detect if the host has probably halted the endpoint after three consecutive errors. The various stages
of RX decode generate their own error signals that propagate to the top level. These error signals arrive at different
times, so two error interrupts generate for every failed transfer. Added an optional override for this behaviour by
forcing the device RX controller to idle after the first instance of an error during a transfer. This fix is enabled with
LINESTATE_TUNING.DEV_RX_ERR_QUIESCE.
• Added SIE_RX_CHATTER_SE0_FIX: the existing error recovery implementation waits for 8 FS idle bit-times before
signalling a framing error and returning to idle. This works OK for random bus errors, but when a hub terminates a
downstream packet, the hub forces a bit-stuff error followed by EOP. A valid token from the host may immediately
follow this, but the device controller may ignore it due to the enforced delay. Optionally waits for either a valid EOP
or 8 idle bit times before signalling a framing error. To enable the fix, use
LINESTATE_TUNING.SIE_RX_CHATTER_SE0_FIX.
• Fix RP2040-E15: the receive state machine doesnt always handle cases where the bitstream deserialiser can abort
a transfer. If decoding terminates due to bitstuff errors during the middle phases of a packet, the device controller
can lock up. Unconditionally disables RX if the deserialiser has flagged a bitstuff error and subsequently signalled
framing error after linestate returns to idle. To enable this fix, use LINESTATE_TUNING.SIE_RX_BITSTUFF_FIX.
• Device state machine watchdog: added a watchdog so that if the device state machine gets stuck for a certain
amount of time it can be forced to idle. This is to handle any other error cases not anticipated by the above fixes.
To enable the watchdog, use DEV_SM_WATCHDOG.
12.7.3. Architecture
12.7.3.1. Clock speed
This controller requires clk_usb to be running at 48MHz.
 NOTE
clk_sys must also be running at > 48MHz. See RP2350-E12.
12.7.3.2. Overview
RP2350 Datasheet
12.7. USB 1144
Figure 124. A
simplified overview of
the USB controller
architecture.
The USB controller is an area-efficient design that muxes a device controller or host controller onto a common set of
components. Each component is detailed below.
12.7.3.3. USB PHY
The USB PHY provides the electrical interface between the USB DP and DM pins and the digital logic of the controller. The
DP and DM pins are a differential pair, meaning the values are always the inverse of each other, except to encode a
specific line state (e.g. SE0). The USB PHY drives the DP and DM pins to transmit data and performs a differential receive
of any incoming data. The USB PHY provides both single-ended and differential receive data to the line state detection
module.
The USB PHY has built in pull-up and pull-down resistors. When the controller acts as a Full Speed device, the DP pin is
pulled up to indicate to the host that a Full Speed device has been connected. In host mode, a weak pull-down is applied
to DP and DM so that the lines are pulled to a logical zero until the device pulls up DP for Full Speed or DM for Low Speed.
12.7.3.4. Line state detection
The USB 2.0 Specification defines several line states (Bus Reset, Connected, Suspend, Resume, Data 1, Data 0, etc.) that
need to be detected. The line state detection module has several state machines to detect these states and signal
events to the other hardware components. There is no shared clock signal in USB, so the RX data must be sampled by
an internal clock. The maximum data rate of USB Full Speed is 12 Mb/s. The RX data is sampled at 48MHz, giving 4
clock cycles to capture and filter the bus state. The line state detection module distributes the filtered RX data to the
Serial RX Engine.
12.7.3.5. Serial RX engine
The serial receive (RX) engine decodes receive data captured by the line state detection module. It produces the
following information:
• The PID of the incoming data packet
• The device address for the incoming data
• The device endpoint for the incoming data
• Data bytes
The serial receive engine also detects errors in RX data by performing a CRC check on the incoming data. Any errors are
signalled to the other hardware blocks and can raise an interrupt.
RP2350 Datasheet
12.7. USB 1145
 NOTE
If you disconnect the USB cable during packet transfer in either host or device mode, the hardware will raise errors.
Software must account for this scenario if you enable error interrupts.
12.7.3.6. Serial TX engine
The serial transmit (TX) engine is a mirror of the serial receive engine. It is connected to the currently active controller
(either device or host). It creates TOKEN and DATA packets, calculates the CRC, and transmits them on the bus.
12.7.3.7. DPSRAM
The USB controller uses 4 kB (4096 bytes) of Dual Port SRAM (DPSRAM) to store control registers and data buffers. The
DPSRAM is accessible as a 32-bit wide memory at address 0 of the USB controller (0x50100000).
The DPSRAM has the following characteristics, which differ from most registers on RP2350:
• Supports 8-bit, 16-bit, and 32-bit accesses (typically, RP2350 registers only support 32-bit accesses)
• Does not support set/clear aliases. (typically, RP2350 registers support these)
Data Buffers are typically 64 bytes long, as this is the maximum normal packet size for most Full Speed packets.
Isochronous endpoints support a maximum buffer size of 1023 bytes. For other packet types, the maximum size is 64
bytes per buffer.
12.7.3.7.1. Concurrent access
The DPSRAM in the USB controller is asynchronous. The dual port part of the name indicates that both the processor
and the USB controller have ports to read and write, and these two ports are in different clock domains. As a result, the
processor and USB controller can access the same memory address at the same time. One could write and one could
read simultaneously. This could result in inconsistent data reads. You can avoid this scenario by following the rules
outlined in this section.
The AVAILABLE bit in the buffer control register indicates who has ownership of a buffer. Set this bit to 1 from the
processor to give the controller ownership of the buffer. When it has finished using the buffer, the controller sets the bit
back to 0. Set the AVAILABLE bit separately from the rest of the data in the buffer control register so that the rest of the
data in the buffer control register is accurate when the AVAILABLE bit is set.
This is necessary because the processor clock clk_sys can run several times faster than the clk_usb clock. Therefore
clk_sys can update the data during a USB controller read on a slower clock. The correct process is:
1. Write buffer information (length, etc.) to the buffer control register.
2. nop for some clk_sys cycles to ensure that at least one clk_usb cycle passes. Consider a scenario where clk_sys runs
at 125MHz and clk_usb runs at 48MHz. Because , you should issue 3 nop instructions between the writes
to guarantee that at least one clk_usb cycle has passed.
3. Set the AVAILABLE bit.
If clk_sys and clk_usb run at the same frequency, then it is not necessary to set the AVAILABLE bit separately.
RP2350 Datasheet
12.7. USB 1146
 NOTE
When the USB controller writes the status back to the DPSRAM, it does a 16-bit write to the lower 2 bytes for buffer 0
and the upper 2 bytes for buffer 1. When using double-buffered mode, always treat the buffer control register as two
16-bit registers when updating it in software.
12.7.3.7.2. Layout
Addresses 0x0 → 0xff are used for control registers containing configuration data. The remaining space, addresses
0x100 → 0xfff (3840 bytes) can be used for data buffers. The controller has control registers that start at address
0x10000.
The memory layout depends on the USB controller mode:
• In Device mode, the host can access multiple endpoints, so each endpoint must have endpoint control and buffer
control registers.
• In Host mode, the host software running on the processor decides which endpoints and devices to access. This
only requires one set of endpoint control and buffer control registers. As well as software-driven transfers, the host
controller can poll up to 15 interrupt endpoints and has a register for each of these interrupt endpoints.
Table 1192. DPSRAM
layout
Offset Device Function Host Function
0x0 Setup packet (8 bytes)
0x8 EP1 in control Interrupt endpoint control 1
0xc EP1 out control Spare
0x10 EP2 in control Interrupt endpoint control 2
0x14 EP2 out control Spare
0x18 EP3 in control Interrupt endpoint control 3
0x1c EP3 out control Spare
0x20 EP4 in control Interrupt endpoint control 4
0x24 EP4 out control Spare
0x28 EP5 in control Interrupt endpoint control 5
0x2c EP5 out control Spare
0x30 EP6 in control Interrupt endpoint control 6
0x34 EP6 out control Spare
0x38 EP7 in control Interrupt endpoint control 7
0x3c EP7 out control Spare
0x40 EP8 in control Interrupt endpoint control 8
0x44 EP8 out control Spare
0x48 EP9 in control Interrupt endpoint control 9
0x4c EP9 out control Spare
0x50 EP10 in control Interrupt endpoint control 10
0x54 EP10 out control Spare
0x58 EP11 in control Interrupt endpoint control 11
RP2350 Datasheet
12.7. USB 1147
Offset Device Function Host Function
0x5c EP11 out control Spare
0x60 EP12 in control Interrupt endpoint control 12
0x64 EP12 out control Spare
0x68 EP13 in control Interrupt endpoint control 13
0x6c EP13 out control Spare
0x70 EP14 in control Interrupt endpoint control 14
0x74 EP14 out control Spare
0x78 EP15 in control Interrupt endpoint control 15
0x7c EP15 out control Spare
0x80 EP0 in buffer control EPx buffer control
0x84 EP0 out buffer control Spare
0x88 EP1 in buffer control Interrupt endpoint buffer control 1
0x8c EP1 out buffer control Spare
0x90 EP2 in buffer control Interrupt endpoint buffer control 2
0x94 EP2 out buffer control Spare
0x98 EP3 in buffer control Interrupt endpoint buffer control 3
0x9c EP3 out buffer control Spare
0xa0 EP4 in buffer control Interrupt endpoint buffer control 4
0xa4 EP4 out buffer control Spare
0xa8 EP5 in buffer control Interrupt endpoint buffer control 5
0xac EP5 out buffer control Spare
0xb0 EP6 in buffer control Interrupt endpoint buffer control 6
0xb4 EP6 out buffer control Spare
0xb8 EP7 in buffer control Interrupt endpoint buffer control 7
0xbc EP7 out buffer control Spare
0xc0 EP8 in buffer control Interrupt endpoint buffer control 8
0xc4 EP8 out buffer control Spare
0xc8 EP9 in buffer control Interrupt endpoint buffer control 9
0xcc EP9 out buffer control Spare
0xd0 EP10 in buffer control Interrupt endpoint buffer control 10
0xd4 EP10 out buffer control Spare
0xd8 EP11 in buffer control Interrupt endpoint buffer control 11
0xdc EP11 out buffer control Spare
0xe0 EP12 in buffer control Interrupt endpoint buffer control 12
0xe4 EP12 out buffer control Spare
0xe8 EP13 in buffer control Interrupt endpoint buffer control 13
RP2350 Datasheet
12.7. USB 1148
Offset Device Function Host Function
0xec EP13 out buffer control Spare
0xf0 EP14 in buffer control Interrupt endpoint buffer control 14
0xf4 EP14 out buffer control Spare
0xf8 EP15 in buffer control Interrupt endpoint buffer control 15
0xfc EP15 out buffer control Spare
0x100 EP0 buffer 0 (shared between in and
out)
EPx control
0x140 Optional EP0 buffer 1 Spare
0x180 Data buffers
12.7.3.7.3. Endpoint control register
The endpoint control register is used to configure an endpoint. It defines:
• The endpoint type
• The base address of the endpoints data buffer (or data buffers if double-buffered)
• Which endpoint events trigger the controller interrupt output
A device must support Endpoint 0 so that it can reply to SETUP packets and be enumerated. As a result, there is no
endpoint control register for EP0. Its buffers begin at 0x100. All other endpoints can have either single or dual buffers and
are mapped at the base address programmed. As EP0 has no endpoint control register, the interrupt enable controls for
EP0 come from SIE_CTRL.
Table 1193. Endpoint
control register layout
Bit(s) Device Function Host Function
31 Endpoint enable
30 Single buffered (64 bytes) = 0, Double buffered (64 bytes × 2) = 1
29 Enable interrupt for every transferred buffer
28 Enable interrupt for every 2 transferred buffers (valid for double-buffered only)
27:26 Endpoint Type: Control = 0, Isochronous = 1, Bulk = 2, Interrupt = 3
25:18 N/A The interval the host controller should poll this
endpoint. Only applicable for interrupt
endpoints. Specified in ms - 1. For example: a
value of 9 would poll the endpoint every 10ms.
17 Interrupt on STALL
16 Interrupt on NAK
15:6 Address base offset in DPSRAM of data buffer(s)
 NOTE
The data buffer base address must be 64-byte aligned, since bits 0 through 5 are ignored.
12.7.3.7.4. Buffer control register
The buffer control register contains information about the state of the data buffers for that endpoint. It is shared
between the processor and the controller. If the endpoint is configured to be single-buffered, only the first half (bits 0
through 15) of the buffer are used.
If double buffering, the buffer select starts at buffer 0. From then on, the buffer select flips between buffer 0 and 1
RP2350 Datasheet
12.7. USB 1149
unless the reset buffer select bit is set (which resets the buffer select to buffer 0). The value of the buffer select is
internal to the controller and not accessible by the processor.
For host interrupt and isochronous packets on EPx, the buffer full bit will be set on completion even if the transfer was
unsuccessful. To determine the error, read the error bits in the SIE_STATUS register.
Table 1194. Buffer
control register layout
Bit(s) Function
31 Buffer 1 full. Should be set to 1 by the processor for an IN transaction and 0 for an OUT
transaction. The controller sets this to 1 for an OUT transaction because it has filled the buffer.
The controller sets it to 0 for an IN transaction because it has emptied the buffer. Only valid
when double buffering.
30 Last buffer of transfer for buffer 1. Only valid when double buffering.
29 Data PID for buffer 1 - DATA0 = 0, DATA1 = 1. Only valid when double buffering.
27:28 Double buffer offset for isochronous mode (0 = 128, 1 = 256, 2 = 512, 3 = 1024).
26 Buffer 1 available. Whether the buffer can be used by the controller for a transfer. The
processor sets this to 1 when the buffer is configured. The controller sets this to 0 after it has
sent the data to the host for an IN transaction, or filled the buffer with data from the host for an
OUT transaction. Only valid when double buffering.
25:16 Buffer 1 transfer length. Only valid when double buffering.
15 Buffer 0 full. Should be set to 1 by the processor for an IN transaction and 0 for an OUT
transaction. The controller sets this to 1 for an OUT transaction because it has filled the buffer.
The controller sets it to 0 for an IN transaction because it has emptied the buffer.
14 Last buffer of transfer for buffer 0.
13 Data PID for buffer 0 - DATA0 = 0, DATA1 = 1.
12 Reset buffer select to buffer 0 - cleared at end of transfer. For device only.
11 Send STALL for device, STALL received for host.
10 Buffer 0 available. Indicates whether the buffer can be used by the controller for a transfer.
The processor sets this to 1 when the buffer is configured. The controller sets this to 0 after it
has sent the data to the host for an IN transaction or filled the buffer with data from the host
for an OUT transaction.
9:0 Buffer 0 transfer length.
 WARNING
If you run clk_sys and clk_usb at different speeds, set the available and stall bits after the other data in the buffer
control register. Otherwise, the controller may initiate a transaction with data from a previous packet. The controller
could see the available bit set, but get the data PID or length from the previous packet.
12.7.3.8. Device controller
This section details how the device controller operates when it receives various packet types from the host.
12.7.3.8.1. SETUP
The device controller MUST always accept a SETUP packet from the host. DPSRAM dedicates its first 8 bytes to the setup
packet.
The USB 2.0 Specification states that receiving a setup packet also clears any stall bits on EP0. For this reason, the stall
RP2350 Datasheet
12.7. USB 1150
bits for EP0 are gated with two bits in the EP_STALL_ARM register. These bits are cleared when a setup packet is
received. This means that to send a stall on EP0, you must set both the stall bit in the buffer control register and the
appropriate bit in EP_STALL_ARM.
Barring any errors, the setup packet will be put into the setup packet buffer at DPSRAM offset 0x0. The device controller
will then reply with an ACK.
Finally, SIE_STATUS.SETUP_REC is set to indicate that a setup packet has been received. This will trigger an interrupt if
the programmer has enabled the SETUP_REC interrupt (see INTE).
12.7.3.8.2. IN
From the devices point of view, an IN transfer means transferring data into the host. When an IN token is received from
the host, the request is handled as follows:
TOKEN phase:
1. If STALL is set in the buffer control register (and if EP0, the appropriate EP_STALL_ARM bit is set), send a STALL
response and go to idle.
2. If AVAILABLE and FULL bits are set in buffer control, go to the DATA phase.
3. If this is an isochronous endpoint, go to idle.
Otherwise, send NAK and go to the DATA phase.
DATA phase:
1. Send data.
2. If this is an isochronous endpoint, go to idle.
Otherwise, go to the ACK phase.
ACK phase:
1. Wait for ACK packet from host.
2. If there is a timeout, raise a timeout error.
3. If ACK is received, the packet is done, so go to STATUS phase.
STATUS phase:
1. If this was the last buffer in the transfer (i.e. if the LAST_BUFFER bit in the buffer control register was set), set
SIE_STATUS.TRANS_COMPLETE.
2. If the endpoint is double buffered, flip the buffer select to the other buffer.
3. Set a bit in BUFF_STATUS to indicate the buffer is done. When handling this event, the programmer should read
BUFF_CPU_SHOULD_HANDLE to see if it is buffer 0 or buffer 1 that is finished. If the endpoint is double-buffered,
both buffers could be done. The cleared BUFF_STATUS bit will be set again, and BUFF_CPU_SHOULD_HANDLE will
change in this instance.
4. Update status in the appropriate half of the buffer control register: length, pid, and last_buff are set. Everything else
is written to zero.
If the host receives a NAK, the host will retry again later.
12.7.3.8.3. OUT
When an OUT token is received from the host, the request is handled as follows:
TOKEN phase:
1. If this is not an Isochronous endpoint and the data PID does not match the buffer control register, raise
RP2350 Datasheet
12.7. USB 1151
SIE_STATUS.DATA_SEQ_ERROR (isochronous data is always sent with a DATA0 pid).
2. If the AVAILABLE bit is set and the FULL bit is clear, go to the DATA phase, unless the STALL bit is set in which case the
device controller will reply with a STALL.
DATA phase:
1. Store received data in buffer. If this is an isochronous endpoint, go to the STATUS phase. Otherwise, go to the ACK
phase.
ACK phase:
1. Send ACK. Go to the STATUS phase.
STATUS phase:
See IN STATUS phase: [usb-device-in-status-phase]. There is one difference: the FULL bit is set in the buffer control register
to indicate that data has been received. In the IN phase, the FULL bit is cleared to indicate that data has been sent.
12.7.3.8.4. Suspend and resume
The USB device controller supports suspend, resume, and device-initiated remote resume (triggered with
SIE_CTRL.RESUME). There is an interrupt / status bit in SIE_STATUS. It is not necessary to enable the suspend and
resume interrupts, since suspend and resume are irrelevant to most devices.
The device goes into suspend when it does not see any start of frame packets (transmitted every 1ms) from the host.
 NOTE
If you enable the suspend interrupt, it is likely you will see a suspend interrupt when the device first connects, but the
bus is idle. The bus can be idle for a few milliseconds before the host begins sending start of frame packets. If you
do not have a VBUS detect circuit connected, you will also see a suspend interrupt when the device disconnects.
Without VBUS detection, it is impossible to tell the difference between being disconnected and suspended.
12.7.3.9. Host controller
The host controller design is similar to the device controller. The host starts all transactions, so the host always deals
with transactions it has started. For this reason, there is only one set of endpoint control and endpoint buffer control
registers. The host controller also contains additional hardware to poll interrupt endpoints in the background when there
are no software controlled transactions taking place.
The host needs to send keep-alive packets to the device every 1ms to keep the device from suspending. Full Speed
mode uses a SOF (start of frame) packet. Low Speed mode uses an EOP (end of packet) instead. Set
SIE_CTRL.KEEP_ALIVE_EN and SIE_CTRL.SOF_EN to enable these packets.
Several bits in SIE_CTRL are used to begin a host transaction:
• SEND_SETUP - Send a setup packet. Typically used with RECEIVE_TRANS, so the setup packet will be sent followed by the
additional data transaction expected from the device.
• SEND_TRANS - This transfer is OUT from the host.
• RECEIVE_TRANS - This transfer is IN to the host.
• START_TRANS - Start the transfer (non-latching).
• STOP_TRANS - Stop the current transfer (non-latching).
• PREAMBLE_ENABLE - Used to send a packet to a Low Speed device on a Full Speed hub. Sends a PRE token packet
before every packet the host sends (i.e. PRE, TOKEN, PRE, DATA, pre, ACK).
• SOF_SYNC - Used to delay the transaction until after the next SOF. Useful for interrupt and isochronous endpoints. The
host controller prevents a transaction of 64 bytes from clashing with the SOF packets. For longer isochronous
RP2350 Datasheet
12.7. USB 1152
packets, software is responsible for preventing collisions. To prevent collisions in software, use SOF_SYNC and limit
the number of packets sent in one frame. If a transaction is set up with multiple packets, SOF_SYNC only applies to
the first packet.
The START_TRANS bit is synchronised separately from other control bits in the SIE_CTRL register because the processor
clock clk_sys can be asynchronous to the clk_usb clock. Always set the START_TRANS bit separately from the rest of the
data in the SIE_CTRL register. Always ensure that at least two clk_usb cycles pass between writing to START_TRANS and other
bits in SIE_CTRL. This ensures that the register contents are stable when the controller is prompted to start a transfer.
Consider a scenario where clk_sys runs at 125MHz and clk_usb runs at 48MHz. Because , you should
issue 6 nop instructions between the writes to guarantee that at least two clk_usb cycles have passed.
12.7.3.9.1. SETUP
The SETUP packet sent from the host always comes from the dedicated 8 bytes of space at offset 0x0 of the DPSRAM.
Like the device controller, there are no control registers associated with the setup packet. The parameters are hardcoded and loaded into the hardware when you write to START_TRANS with the SEND_SETUP bit set. Once the setup packet has
been sent, the host state machine waits for an ACK from the device. If there is a timeout, an RX_TIMEOUT error will be raised.
If the SEND_TRANS bit is set, the host state machine will move to the OUT phase. Typically, the SEND_SETUP packet is used with
the RECEIVE_TRANS bit, so the controller moves to the IN phase after sending a setup packet.
12.7.3.9.2. IN
An IN transfer is triggered with the RECEIVE_TRANS bit set when the START_TRANS bit is set. If the SEND_SETUP bit was set, this
may be preceded by a SETUP packet.
CONTROL phase:
1. Read the EPx control register located at 0x80 to get the following endpoint information:
Is it double buffered?
◦ What interrupts are enabled?
Base address of the data buffer (data buffers if in double-buffered mode)
◦ What is the endpoint type?
2. Read the EPx buffer control register at 0x100 to get endpoint buffer information, such as transfer length and data
PID.
3. Set the AVAILABLE bit (the host state machine checks for it).
4. Clear the FULL bit.
TOKEN phase:
1. Send the IN token packet to the device. The target device address and endpoint come from the ADDR_ENDP
register.
DATA phase:
1. Receive the first data packet from the device.
2. Raise RX timeout error if the device doesnt reply.
3. If this is not an Isochronous endpoint and the data PID does not match the buffer control register, raise
SIE_STATUS.DATA_SEQ_ERROR (isochronous data is always sent with a DATA0 pid).
ACK phase:
1. Send ACK to device.
STATUS phase:
RP2350 Datasheet
12.7. USB 1153
1. Set the BUFF_STATUS bit and update the buffer control register.
2. Set FULL, DATA_PID, WR_LEN, and LAST_BUFF if applicable.
3. If this is the last buffer in the transfer, set TRANS_COMPLETE.
CONTROL phase (continued):
The host state machine performs IN transactions until LAST_BUFF is seen in the buffer_control register.
If the host is in double buffered mode, the host controller toggles between the BUF0 and BUF1 sections of the buffer
control register.
Otherwise, the controller reads the buffer control register for buffer 0, then waits for FULL to be clear and AVAILABLE to be
set before starting the next IN transaction, waiting in the CONTROL phase.
If the host receives a zero length packet, the device has no more data. The host state machine stops listening for more
data regardless of if the LAST_BUFF flag was set or not. To detect this from host software, check BUFF_DONE for a data
length of 0 in the buffer control register.
12.7.3.9.3. OUT
An OUT transfer is triggered with the SEND_TRANS bit set when the START_TRANS bit is set. This may be preceded by a SETUP
packet if the SEND_SETUP bit was set.
CONTROL phase:
1. Read the EPx control register to get endpoint information (same as Section 12.7.3.9.2).
2. Read the EPx buffer control register to get the transfer length and data PID. AVAILABLE and FULL must be set before
the transfer can start.
TOKEN phase
1. Send an OUT packet to the device. The target device address and endpoint come from the ADDR_ENDP register.
DATA phase:
1. Send the first data packet to the device. If the endpoint type is isochronous, there is no ACK phase, so the host
controller goes straight to status phase. If ACK is received, go to status phase. Otherwise:
If the host receives no reply, raise SIE_STATUS.RX_TIMEOUT.
If the host receives NAK, raise SIE_STATUS.NAK_REC and send the data packet again.
If the host receives STALL, raise SIE_STATUS.STALL_REC and go to idle.
STATUS phase:
1. Set the BUFF_STATUS bit and update the buffer control register. FULL will be set to 0. TRANS_COMPLETE will be set if
this is the last buffer in the transfer.
CONTROL phase (continued):
1. If this isnt the last buffer in the transfer, wait for FULL and AVAILABLE to be set in the EPx buffer control register again.
12.7.3.9.4. Interrupt endpoints
The host controller can poll interrupt endpoints on a maximum of 15 endpoints. To enable interrupt endpoints, the
programmer must:
• Pick the next free interrupt endpoint slot on the host controller (starting at 1, to a maximum of 15).
• Program the appropriate endpoint control register and buffer control register like you would with a normal IN or OUT
transfer. Because interrupt endpoints are single-buffered, the BUF1 part of the buffer control register is invalid.
• Set the address and endpoint of the device in the appropriate ADDR_ENDP register (ADDR_ENDP1 to ADDR_ENDP15).
RP2350 Datasheet
12.7. USB 1154
If the device is Low Speed but attached to a Full Speed hub, the preamble bit should be set. The endpoint direction
bit should also be set.
• Set the corresponding interrupt endpoint active bit (one of bits 1 through 15) in INT_EP_CTRL.
Typically, interrupt endpoints use an IN transfer. The host might poll a USB hub to see if the state of any of its ports have
changed. If there is no change, the hub replies with a NAK to the controller, and nothing happens. Similarly, a mouse
replies with a NAK unless the mouse has been moved since the last time the interrupt endpoint was polled.
Interrupt endpoints are polled by the controller once a SOF packet has been sent by the host controller.
The controller loops from 1 to 15 and attempts to poll any interrupt endpoint with the EP_ACTIVE bit set to 1 in
INT_EP_CTRL. The controller will then read the endpoint control register and the buffer control register to see if there is
an available buffer (i.e. FULL + AVAILABLE if an OUT transfer and NOT FULL + AVAILABLE for an IN transfer). If not, the controller
will move onto the next interrupt endpoint slot.
If there is an available buffer, the transfer is dealt with the same as a normal IN or OUT transfer and the BUFF_DONE flag in
BUFF_STATUS will be set when the interrupt endpoint has a valid buffer.
12.7.3.10. VBUS control
The USB controller can be connected to GPIO pins (see Chapter 9) for the following VBUS controls:
• VBUS enable, used to enable VBUS in host mode. Set in SIE_CTRL.
• VBUS detect, used to detect that VBUS is present in device mode. Set via a bit in SIE_STATUS. Can also raise a
VBUS_DETECT interrupt enabled in INTE.
• VBUS overcurrent, used to detect an overcurrent event. Applicable to both device and host. VBUS overcurrent is a
bit in SIE_STATUS.
It is not necessary to connect up any of these pins to GPIO. The host can permanently supply VBUS and detect a device
being connected when either the DP or DM pin is pulled high. VBUS detect can be forced in USB_PWR.
12.7.4. Programmers model
12.7.4.1. TinyUSB
The RP2350 TinyUSB port is the reference implementation for this USB controller. This port can be found in the
following files of the pico-sdk GitHub repository:
dcd_rp2040.c
hcd_rp2040.c
rp2040_usb.h
12.7.4.2. Standalone device example
A standalone USB device example, dev_lowlevel, makes it easier to understand how to interact with the USB controller
without needing to understand the TinyUSB abstractions. In addition to endpoint 0, the standalone device has two bulk
endpoints: EP1 OUT and EP2 IN. The device is designed to send whatever data it receives on EP1 to EP2. The example comes
with a small Python script that writes "Hello World" into EP1 and checks that it is correctly received on EP2.
The code included in this section explains setting up the USB device controller to receive. It also shows how software
responds to a setup packet received from the host.
RP2350 Datasheet
12.7. USB 1155
Figure 125. USB
analyser trace of the
dev_lowlevel USB
device example. The
control transfers are
the device
enumeration. The first
bulk OUT (out from the
host) transfer,
highlighted in blue, is
the host sending
"Hello World" to the
device. The second
bulk transfer IN (in to
the host), is the device
returning "Hello World"
to the host.
12.7.4.2.1. Device controller initialisation
The following code initialises the USB device:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 183 - 217
183 void usb_device_init() {
184 // Reset usb controller
185 reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
186
187 // Clear any previous state in dpram just in case
188 memset(usb_dpram, 0, sizeof(*usb_dpram)); ①
189
190 // Enable USB interrupt at processor
191 irq_set_enabled(USBCTRL_IRQ, true);
192
193 // Mux the controller to the onboard usb phy
194 usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
195
196 // Force VBUS detect so the device thinks it is plugged into a host
197 usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
198
199 // Enable the USB controller in device mode.
200 usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS;
201
202 // Enable an interrupt per EP0 transaction
203 usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; ②
204
205 // Enable interrupts for when a buffer is done, when the bus is reset,
206 // and when a setup packet is received
207 usb_hw->inte = USB_INTS_BUFF_STATUS_BITS |
208 USB_INTS_BUS_RESET_BITS |
209 USB_INTS_SETUP_REQ_BITS;
210
211 // Set up endpoints (endpoint control registers)
212 // described by device configuration
213 usb_setup_endpoints();
214
215 // Present full speed device by enabling pull up on DP
RP2350 Datasheet
12.7. USB 1156
216 usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
217 }
12.7.4.2.2. Configuring the endpoint control registers for EP1 and EP2
The function usb_configure_endpoints loops through each endpoint defined in the device configuration (including EP0 in
and EP0 out, which dont have an endpoint control register defined) and calls the usb_configure_endpoint function. This
sets up the endpoint control register for that endpoint:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 149 - 164
149 void usb_setup_endpoint(const struct usb_endpoint_configuration *ep) {
150 printf("Set up endpoint 0x%x with buffer address 0x%p\n", ep->descriptor-
>bEndpointAddress, ep->data_buffer);
151
152 // EP0 doesn't have one so return if that is the case
153 if (!ep->endpoint_control) {
154 return;
155 }
156
157 // Get the data buffer as an offset of the USB controller's DPRAM
158 uint32_t dpram_offset = usb_buffer_offset(ep->data_buffer);
159 uint32_t reg = EP_CTRL_ENABLE_BITS
160 | EP_CTRL_INTERRUPT_PER_BUFFER
161 | (ep->descriptor->bmAttributes << EP_CTRL_BUFFER_TYPE_LSB)
162 | dpram_offset;
163 *ep->endpoint_control = reg;
164 }
12.7.4.2.3. Receiving a setup packet
An interrupt is raised when a setup packet is received, so the interrupt handler must handle this event:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 494 - 504
494 void isr_usbctrl(void) {
495 // USB interrupt handler
496 uint32_t status = usb_hw->ints;
497 uint32_t handled = 0;
498
499 // Setup packet received
500 if (status & USB_INTS_SETUP_REQ_BITS) {
501 handled |= USB_INTS_SETUP_REQ_BITS;
502 usb_hw_clear->sie_status = USB_SIE_STATUS_SETUP_REC_BITS;
503 usb_handle_setup_packet();
504 }
The controller writes the SETUP packet to the first 8 bytes of the DPSRAM, so the setup packet handler casts that area of
memory to struct usb_setup_packet *:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 383 - 427
383 void usb_handle_setup_packet(void) {
384 volatile struct usb_setup_packet *pkt = (volatile struct usb_setup_packet *) &usb_dpram
->setup_packet;
385 uint8_t req_direction = pkt->bmRequestType;
RP2350 Datasheet
12.7. USB 1157
386 uint8_t req = pkt->bRequest;
387
388 // Reset PID to 1 for EP0 IN
389 usb_get_endpoint_configuration(EP0_IN_ADDR)->next_pid = 1u;
390
391 if (req_direction == USB_DIR_OUT) {
392 if (req == USB_REQUEST_SET_ADDRESS) {
393 usb_set_device_address(pkt);
394 } else if (req == USB_REQUEST_SET_CONFIGURATION) {
395 usb_set_device_configuration(pkt);
396 } else {
397 usb_acknowledge_out_request();
398 printf("Other OUT request (0x%x)\r\n", pkt->bRequest);
399 }
400 } else if (req_direction == USB_DIR_IN) {
401 if (req == USB_REQUEST_GET_DESCRIPTOR) {
402 uint16_t descriptor_type = pkt->wValue >> 8;
403
404 switch (descriptor_type) {
405 case USB_DT_DEVICE:
406 usb_handle_device_descriptor(pkt);
407 printf("GET DEVICE DESCRIPTOR\r\n");
408 break;
409
410 case USB_DT_CONFIG:
411 usb_handle_config_descriptor(pkt);
412 printf("GET CONFIG DESCRIPTOR\r\n");
413 break;
414
415 case USB_DT_STRING:
416 usb_handle_string_descriptor(pkt);
417 printf("GET STRING DESCRIPTOR\r\n");
418 break;
419
420 default:
421 printf("Unhandled GET_DESCRIPTOR type 0x%x\r\n", descriptor_type);
422 }
423 } else {
424 printf("Other IN request (0x%x)\r\n", pkt->bRequest);
425 }
426 }
427 }
12.7.4.2.4. Replying to a setup packet on EP0 IN
The host first requests the device descriptor. The following code handles that setup request:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 266 - 273
266 void usb_handle_device_descriptor(volatile struct usb_setup_packet *pkt) {
267 const struct usb_device_descriptor *d = dev_config.device_descriptor;
268 // EP0 in
269 struct usb_endpoint_configuration *ep = usb_get_endpoint_configuration(EP0_IN_ADDR);
270 // Always respond with pid 1
271 ep->next_pid = 1;
272 usb_start_transfer(ep, (uint8_t *) d, MIN(sizeof(struct usb_device_descriptor), pkt-
>wLength));
273 }
The usb_start_transfer function copies data to be sent into the appropriate hardware buffer and configures the buffer
RP2350 Datasheet
12.7. USB 1158
control register. Once the buffer control register has been written to, the device controller responds to the host with the
data. Before this point, the device replies with a NAK:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/usb/device/dev_lowlevel/dev_lowlevel.c Lines 238 - 260
238 void usb_start_transfer(struct usb_endpoint_configuration *ep, uint8_t *buf, uint16_t len) {
239 // We are asserting that the length is <= 64 bytes for simplicity of the example.
240 // For multi packet transfers see the tinyusb port.
241 assert(len <= 64);
242
243 printf("Start transfer of len %d on ep addr 0x%x\n", len, ep->descriptor-
>bEndpointAddress);
244
245 // Prepare buffer control register value
246 uint32_t val = len | USB_BUF_CTRL_AVAIL;
247
248 if (ep_is_tx(ep)) {
249 // Need to copy the data from the user buffer to the usb memory
250 memcpy((void *) ep->data_buffer, (void *) buf, len);
251 // Mark as full
252 val |= USB_BUF_CTRL_FULL;
253 }
254
255 // Set pid and flip for next transfer
256 val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
257 ep->next_pid ^= 1u;
258
259 *ep->buffer_control = val;
260 }
12.7.5. List of registers
The USB registers start at a base address of 0x50110000 (defined as USBCTRL_REGS_BASE in SDK).
Table 1195. List of
USB registers
Offset Name Info
0x000 ADDR_ENDP Device address and endpoint control
0x004 ADDR_ENDP1 Interrupt endpoint 1. Only valid for HOST mode.
0x008 ADDR_ENDP2 Interrupt endpoint 2. Only valid for HOST mode.
0x00c ADDR_ENDP3 Interrupt endpoint 3. Only valid for HOST mode.
0x010 ADDR_ENDP4 Interrupt endpoint 4. Only valid for HOST mode.
0x014 ADDR_ENDP5 Interrupt endpoint 5. Only valid for HOST mode.
0x018 ADDR_ENDP6 Interrupt endpoint 6. Only valid for HOST mode.
0x01c ADDR_ENDP7 Interrupt endpoint 7. Only valid for HOST mode.
0x020 ADDR_ENDP8 Interrupt endpoint 8. Only valid for HOST mode.
0x024 ADDR_ENDP9 Interrupt endpoint 9. Only valid for HOST mode.
0x028 ADDR_ENDP10 Interrupt endpoint 10. Only valid for HOST mode.
0x02c ADDR_ENDP11 Interrupt endpoint 11. Only valid for HOST mode.
0x030 ADDR_ENDP12 Interrupt endpoint 12. Only valid for HOST mode.
0x034 ADDR_ENDP13 Interrupt endpoint 13. Only valid for HOST mode.
RP2350 Datasheet
12.7. USB 1159
Offset Name Info
0x038 ADDR_ENDP14 Interrupt endpoint 14. Only valid for HOST mode.
0x03c ADDR_ENDP15 Interrupt endpoint 15. Only valid for HOST mode.
0x040 MAIN_CTRL Main control register
0x044 SOF_WR Set the SOF (Start of Frame) frame number in the host controller.
The SOF packet is sent every 1ms and the host will increment the
frame number by 1 each time.
0x048 SOF_RD Read the last SOF (Start of Frame) frame number seen. In device
mode the last SOF received from the host. In host mode the last
SOF sent by the host.
0x04c SIE_CTRL SIE control register
0x050 SIE_STATUS SIE status register
0x054 INT_EP_CTRL interrupt endpoint control register
0x058 BUFF_STATUS Buffer status register. A bit set here indicates that a buffer has
completed on the endpoint (if the buffer interrupt is enabled). It
is possible for 2 buffers to be completed, so clearing the buffer
status bit may instantly re set it on the next clock cycle.
0x05c BUFF_CPU_SHOULD_HANDLE Which of the double buffers should be handled. Only valid if
using an interrupt per buffer (i.e. not per 2 buffers). Not valid for
host interrupt endpoint polling because they are only single
buffered.
0x060 EP_ABORT Device only: Can be set to ignore the buffer control register for
this endpoint in case you would like to revoke a buffer. A NAK
will be sent for every access to the endpoint until this bit is
cleared. A corresponding bit in EP_ABORT_DONE is set when it is safe
to modify the buffer control register.
0x064 EP_ABORT_DONE Device only: Used in conjunction with EP_ABORT. Set once an
endpoint is idle so the programmer knows it is safe to modify the
buffer control register.
0x068 EP_STALL_ARM Device: this bit must be set in conjunction with the STALL bit in the
buffer control register to send a STALL on EP0. The device
controller clears these bits when a SETUP packet is received
because the USB spec requires that a STALL condition is cleared
when a SETUP packet is received.
0x06c NAK_POLL Used by the host controller. Sets the wait time in microseconds
before trying again if the device replies with a NAK.
0x070 EP_STATUS_STALL_NAK Device: bits are set when the IRQ_ON_NAK or IRQ_ON_STALL bits are
set. For EP0 this comes from SIE_CTRL. For all other endpoints it
comes from the endpoint control register.
0x074 USB_MUXING Where to connect the USB controller. Should be to_phy by
default.
0x078 USB_PWR Overrides for the power signals in the event that the VBUS
signals are not hooked up to GPIO. Set the value of the override
and then the override enable to switch over to the override value.
RP2350 Datasheet
12.7. USB 1160
Offset Name Info
0x07c USBPHY_DIRECT This register allows for direct control of the USB phy. Use in
conjunction with usbphy_direct_override register to enable each
override bit.
0x080 USBPHY_DIRECT_OVERRIDE Override enable for each control in usbphy_direct
0x084 USBPHY_TRIM Used to adjust trim values of USB phy pull down resistors.
0x088 LINESTATE_TUNING Used for debug only.
0x08c INTR Raw Interrupts
0x090 INTE Interrupt Enable
0x094 INTF Interrupt Force
0x098 INTS Interrupt status after masking & forcing
0x100 SOF_TIMESTAMP_RAW Device only. Raw value of free-running PHY clock counter
@48MHz. Used to calculate time between SOF events.
0x104 SOF_TIMESTAMP_LAST Device only. Value of free-running PHY clock counter @48MHz
when last SOF event occured.
0x108 SM_STATE
0x10c EP_TX_ERROR TX error count for each endpoint. Write to each field to reset the
counter to 0.
0x110 EP_RX_ERROR RX error count for each endpoint. Write to each field to reset the
counter to 0.
0x114 DEV_SM_WATCHDOG Watchdog that forces the device state machine to idle and raises
an interrupt if the device stays in a state that isnt idle for the
configured limit. The counter is reset on every state transition.
Set limit while enable is low and then set the enable.
12.1. UART
Arm documentation
Excerpted from the PrimeCell UART (PL011) Technical Reference Manual. Used with permission.
RP2350 has 2 identical instances of a UART peripheral, based on the Arm Primecell UART (PL011) (Revision r1p5).
Each instance supports the following features:
• Separate 32×8 TX and 32×12 RX FIFOs
• Programmable baud rate generator, clocked by clk_peri (see Figure 33)
• Standard asynchronous communication bits (start, stop, parity) added on transmit and removed on receive
• Line break detection
• Programmable serial interface (5, 6, 7, or 8 bits)
• 1 or 2 stop bits
• Programmable hardware flow control
Each UART can be connected to a number of GPIO pins as defined in the GPIO muxing table in Section 9.4. Connections
to the GPIO muxing use a prefix including the UART instance name uart0_ or uart1_, and include the following:
• Transmit data tx (referred to as UARTTXD in the following sections)
• Received data rx (referred to as UARTRXD in the following sections)
• Output flow control rts (referred to as nUARTRTS in the following sections)
• Input flow control cts (referred to as nUARTCTS in the following sections)
The modem mode and IrDA mode of the PL011 are not supported.
The UARTCLK is driven from clk_peri, and PCLK is driven from the system clock clk_sys (see Figure 33).
12.1.1. Overview
The UART performs:
• Serial-to-parallel conversion on data received from a peripheral device
• Parallel-to-serial conversion on data transmitted to the peripheral device
The CPU reads and writes data and control/status information through the AMBA APB interface. The transmit and
receive paths are buffered with internal FIFO memories that store up to 32 bytes independently in both transmit and
receive modes.
The UART:
• Includes a programmable baud rate generator that generates a common transmit and receive internal clock from
the UART internal reference clock input, UARTCLK
• Offers similar functionality to the industry-standard 16C650 UART device
• Supports a maximum baud rate of UARTCLK / 16 in UART mode (7.8 Mbaud at 125MHz)
RP2350 Datasheet
12.1. UART 961
The UART operation and baud rate values are controlled by the Line Control Register (UARTLCR_H) and the baud rate
divisor registers: Integer Baud Rate Register (UARTIBRD), and Fractional Baud Rate Register (UARTFBRD).
The UART can generate:
• Individually maskable interrupts from the receive (including timeout), transmit, modem status and error conditions
• A single combined interrupt so that the output is asserted if any of the individual interrupts are asserted and
unmasked
• DMA request signals for interfacing with a Direct Memory Access (DMA) controller
If a framing, parity, or break error occurs during reception, the appropriate error bit is set and stored in the FIFO. If an
overrun condition occurs, the overrun register bit is set immediately and FIFO data is prevented from being overwritten.
You can program the FIFOs to be 1-byte deep providing a conventional double-buffered UART interface.
There is a programmable hardware flow control feature that uses the nUARTCTS input and the nUARTRTS output to
automatically control the serial data flow.
12.1.2. Functional description
Figure 63. UART block
diagram. Test logic is
not shown for clarity.
12.1.2.1. AMBA APB interface
The AMBA APB interface generates read and write decodes for accesses to status/control registers, and the transmit
and receive FIFOs.
12.1.2.2. Register block
The register block stores data written, or to be read across the AMBA APB interface.
RP2350 Datasheet
12.1. UART 962
12.1.2.3. Baud rate generator
The baud rate generator contains free-running counters that generate the internal clocks: Baud16 and IrLPBaud16
signals. Baud16 provides timing information for UART transmit and receive control. Baud16 is a stream of pulses with a
width of one UARTCLK clock period and a frequency of 16 times the baud rate.
12.1.2.4. Transmit FIFO
The transmit FIFO is an 8-bit wide, 32 location deep, FIFO memory buffer. CPU data written across the APB interface is
stored in the FIFO until read out by the transmit logic. When disabled, the transmit FIFO acts like a one byte holding
register.
12.1.2.5. Receive FIFO
The receive FIFO is a 12-bit wide, 32 location deep, FIFO memory buffer. Received data and corresponding error bits are
stored in the receive FIFO by the receive logic until read out by the CPU across the APB interface. When disabled, the
receive FIFO acts like a one byte holding register.
12.1.2.6. Transmit logic
The transmit logic performs parallel-to-serial conversion on the data read from the transmit FIFO. Control logic outputs
the serial bit stream in the following order:
1. Start bit
2. Data bits (Least Significant Bit (LSB) first)
3. Parity bit
4. Stop bits according to the programmed configuration in control registers
12.1.2.7. Receive logic
The receive logic performs serial-to-parallel conversion on the received bit stream after a valid start pulse has been
detected. Receive logic includes overrun, parity, frame error checking, and line break detection; you can find the output
of these checks in the status that accompanies the data written to the receive FIFO.
12.1.2.8. Interrupt generation logic
The UART generates individual maskable active HIGH interrupts to the processor interrupt controllers. To generate
combined interrupts, the UART outputs an OR function of the individual interrupt requests.
For more information, see Section 12.1.6.
12.1.2.9. DMA interface
The UART provides an interface to connect to the DMA controller as a UART DMA; for more information, see Section
12.1.5.
RP2350 Datasheet
12.1. UART 963
12.1.2.10. Synchronizing registers and logic
The UART supports both asynchronous and synchronous operation of the clocks, PCLK and UARTCLK. The UART
implements always-on synchronisation registers and handshaking logic. This has a minimal impact on performance and
area. The UART performs control signal synchronisation on both directions of data flow (from the PCLK to the UARTCLK
domain, and from the UARTCLK to the PCLK domain).
12.1.3. Operation
12.1.3.1. Clock signals
The frequency selected for UARTCLK must accommodate the required range of baud rates:
• FUARTCLK (min) ≥ 16 × baud_rate (max)
• FUARTCLK (max) ≤ 16 × 65535 × baud_rate (min)
For example, for a range of baud rates from 110 baud to 460800 baud the UARTCLK frequency must be between
7.3728MHz to 115.34MHz.
To use all baud rates, the UARTCLK frequency must fall within the required error limits.
There is also a constraint on the ratio of clock frequencies for PCLK to UARTCLK. The frequency of UARTCLK must be no more
than 5/3 times faster than the frequency of PCLK:
• FUARTCLK ≤ 5/3 × FPCLK
For example, in UART mode, to generate 921600 baud when UARTCLK is 14.7456MHz, PCLK must be greater than or equal
to 8.85276MHz. This ensures that the UART has sufficient time to write the received data to the receive FIFO.
12.1.3.2. UART operation
Control data is written to the UART Line Control Register, UARTLCR. This register is 30 bits wide internally, but provides
external access through the APB interface by writes to the following registers:
• UARTLCR_H, which defines the following:
transmission parameters
word length
buffer mode
number of transmitted stop bits
parity mode
break generation
• UARTIBRD, which defines the integer baud rate divider
• UARTFBRD, which defines the fractional baud rate divider
12.1.3.2.1. Fractional baud rate divider
The baud rate divisor is a 22-bit number consisting of a 16-bit integer and a 6-bit fractional part. The baud rate generator
uses the baud rate divisor to determine the bit period. The fractional baud rate divider enables the use of any clock with
a frequency greater than 3.6864MHz to act as UARTCLK, while it is still possible to generate all the standard baud rates.
The 16-bit integer is written to the Integer Baud Rate Register, UARTIBRD. The 6-bit fractional part is written to the
Fractional Baud Rate Register, UARTFBRD. The Baud Rate Divisor has the following relationship to UARTCLK:
RP2350 Datasheet
12.1. UART 964
Baud Rate Divisor = UARTCLK/(16×Baud Rate) = where is the integer part and is the
fractional part separated by a decimal point as shown in Figure 64.
Figure 64. Baud rate
divisor.
To calculate the 6-bit number ( ), multiply the fractional part of the required baud rate divisor by 64 ( , where is the
width of the UARTFBRD register) and add 0.5 to account for rounding errors:
The UART generates an internal clock enable signal, Baud16. This is a stream of UARTCLK-wide pulses with an average
frequency of 16 times the required baud rate. Divide this signal by 16 to give the transmit clock. A low number in the
baud rate divisor produces a short bit period, and a high number in the baud rate divisor produces a long bit period.
12.1.3.2.2. Data transmission or reception
The UART uses two 32-byte FIFOs to store data received and transmitted. The receive FIFO has an extra four bits per
character for status information. For transmission, data is written into the transmit FIFO. If the UART is enabled, it
causes a data frame to start transmitting with the parameters indicated in the Line Control Register, UARTLCR_H. Data
continues to be transmitted until there is no data left in the transmit FIFO. The BUSY signal goes HIGH immediately after
data writes to the transmit FIFO (that is, the FIFO is non-empty) and remains asserted HIGH while data transmits. BUSY
is negated only when the transmit FIFO is empty, and the last character has been transmitted from the shift register,
including the stop bits. BUSY can be asserted HIGH even though the UART might no longer be enabled.
For each sample of data, three readings are taken and the majority value is kept. In the following paragraphs, the middle
sampling point is defined, and one sample is taken either side of it.
When the receiver is idle (UARTRXD continuously 1, in the marking state) and a LOW is detected on the data input (a start
bit has been received), the receive counter, with the clock enabled by Baud16, begins running and data is sampled on
the eighth cycle of that counter in UART mode, or the fourth cycle of the counter in SIR mode to allow for the shorter
logic 0 pulses (half way through a bit period).
The start bit is valid if UARTRXD is still LOW on the eighth cycle of Baud16, otherwise a false start bit is detected and it is
ignored.
If the start bit was valid, successive data bits are sampled on every 16th cycle of Baud16 (that is, one bit period later)
according to the programmed length of the data characters. The parity bit is then checked if parity mode was enabled.
Lastly, a valid stop bit is confirmed if UARTRXD is HIGH, otherwise a framing error has occurred. When a full word is
received, the data is stored in the receive FIFO, with any error bits associated with that word
12.1.3.2.3. Error bits
The receive FIFO stores three error bits in bits 8 (framing), 9 (parity), and 10 (break), each associated with a particular
character. An additional error bit, stored in bit 11 of the receive FIFO, indicates an overrun error.
12.1.3.2.4. Overrun bit
The overrun bit is not associated with the character in the receive FIFO. The overrun error is set when the FIFO is full and
the next character is completely received in the shift register. The data in the shift register is overwritten, but it is not
written into the FIFO. When an empty location becomes available in the FIFO, another character is received and the state
of the overrun bit is copied into the receive FIFO along with the received character. The overrun state is then cleared.
Table 1025 lists the bit functions of the receive FIFO.
RP2350 Datasheet
12.1. UART 965
Table 1025. Receive
FIFO bit functions
FIFO bit Function
11 Overrun indicator
10 Break error
9 Parity error
8 Framing error
7:0 Received data
12.1.3.2.5. Disabling the FIFOs
The bottom entry of the transmit and receive sides of the UART both have the equivalent of a 1-byte holding register.
You can manipulate flags to disable the FIFOs, allowing you to use the bottom entry of the FIFOs as a 1-byte register.
However, this doesnt physically disable the FIFOs. When using the FIFOs as a 1-byte register, a write to the data register
bypasses the holding register unless the transmit shift register is already in use.
12.1.3.2.6. System and diagnostic loopback testing
To perform loopback testing for UART data, set the Loop Back Enable (LBE) bit to 1 in the Control Register, UARTCR.
Data transmitted on UARTTXD is received on the UARTRXD input.
12.1.3.3. UART character frame
Figure 65. UART
character frame.
12.1.4. UART hardware flow control
The fully-selectable hardware flow control feature enables you to control the serial data flow with the nUARTRTS output
and nUARTCTS input signals. Figure 66 shows how to communicate between two devices using hardware flow control:
Figure 66. Hardware
flow control between
two similar devices.
When the RTS flow control is enabled, nUARTRTS is asserted until the receive FIFO is filled up to the programmed
watermark level. When the CTS flow control is enabled, the transmitter can only transmit data when nUARTCTS is asserted.
The hardware flow control is selectable using the RTSEn and CTSEn bits in the Control Register, UARTCR. Table 1026 shows
how to configure UARTCR register bits to enable RTS and/or CTS.
RP2350 Datasheet
12.1. UART 966
Table 1026. Control
bits to enable and
disable hardware flow
control.
UARTCR register bits
CTSEn RTSEn Description
1 1 Both RTS and CTS flow control
enabled
1 0 Only CTS flow control enabled
0 1 Only RTS flow control enabled
0 0 Both RTS and CTS flow control
disabled
 NOTE
When RTS flow control is enabled, the software cannot use the RTSEn bit in the Control Register (UARTCR) to control
the status of nUARTRTS.
12.1.4.1. RTS flow control
The RTS flow control logic is linked to the programmable receive FIFO watermark levels.
When RTS flow control is disabled, the receive FIFO receives data until full, or no more data is transmitted to it.
When RTS flow control is enabled, the nUARTRTS is asserted until the receive FIFO fills up to the watermark level. When the
receive FIFO reaches the watermark level, the nUARTRTS signal is de-asserted. This indicates that the FIFO has no more
room to receive data. The transmission of data is expected to cease after the current character has been transmitted.
When the receive FIFO drains below the watermark level, the nUARTRTS signal is reasserted.
12.1.4.2. CTS flow control
The CTS flow control logic is linked to the nUARTCTS signal.
When CTS flow control is disabled, the transmitter transmits data until the transmit FIFO is empty.
When CTS flow control is enabled, the transmitter checks the nUARTCTS signal before transmitting each byte. It only
transmits the byte if the nUARTCTS signal is asserted. As long as the transmit FIFO is not empty and nUARTCTS is asserted,
data continues to transmit. If the transmit FIFO is empty and the nUARTCTS signal is asserted, no data is transmitted. If the
nUARTCTS signal is de-asserted during transmission, the transmitter finishes transmitting the current character before
stopping.
12.1.5. UART DMA interface
The UART provides an interface to connect to a DMA controller. The DMA operation of the UART is controlled using the
DMA Control Register, UARTDMACR. The DMA interface includes the following signals:
For receive:
UARTRXDMASREQ
Single character DMA transfer request, asserted by the UART. For receive, one character consists of up to 12 bits.
This signal is asserted when the receive FIFO contains at least one character.
UARTRXDMABREQ
Burst DMA transfer request, asserted by the UART. This signal is asserted when the receive FIFO contains more
characters than the programmed watermark level. You can program the watermark level for each FIFO using the
Interrupt FIFO Level Select Register (UARTIFLS).
RP2350 Datasheet
12.1. UART 967
UARTRXDMACLR
DMA request clear, asserted by a DMA controller to clear the receive request signals. If DMA burst transfer is
requested, the clear signal is asserted during the transfer of the last data in the burst.
For transmit:
UARTTXDMASREQ
Single character DMA transfer request, asserted by the UART. For transmit, one character consists of up to eight
bits. This signal is asserted when there is at least one empty location in the transmit FIFO.
UARTTXDMABREQ
Burst DMA transfer request, asserted by the UART. This signal is asserted when the transmit FIFO contains less
characters than the watermark level. You can program the watermark level for each FIFO using the Interrupt FIFO
Level Select Register (UARTIFLS).
UARTTXDMACLR
DMA request clear, asserted by a DMA controller to clear the transmit request signals. If DMA burst transfer is
requested, the clear signal is asserted during the transfer of the last data in the burst.
The burst transfer and single transfer request signals are not mutually exclusive: they can both be asserted at the same
time. When the receive FIFO exceeds the watermark level, the burst transfer request and the single transfer request
signals are both asserted. When the receive FIFO is below than the watermark level, only the single transfer request
signal is asserted. This is useful in situations where the number of characters left to be received in the stream is less
than a burst.
Consider a scenario where the watermark level is set to four, but 19 characters are left to be received. The DMA
controller then transfers four bursts of four characters and three single transfers to complete the stream.
 NOTE
For the remaining three characters, the UART cannot assert the burst request.
Each request signal remains asserted until the relevant DMACLR signal is asserted. After the request clear signal is deasserted, a request signal can become active again, depending on the conditions described previously. All request
signals are de-asserted if the UART is disabled or the relevant DMA enable bit, TXDMAE or RXDMAE, in the DMA Control
Register, UARTDMACR, is cleared.
If you disable the FIFOs in the UART, it operates in character mode. Character mode limits FIFO transfers to a single
character at a time, so only the DMA single transfer mode can operate. In character mode, only the UARTRXDMASREQ and
UARTTXDMASREQ request signals can be asserted. For information about disabling the FIFOs, see the Line Control Register,
UARTLCR_H.
When the UART is in the FIFO enabled mode, data transfers can use either single or burst transfers depending on the
programmed watermark level and the amount of data in the FIFO. Table 1027 lists the trigger points for UARTRXDMABREQ
and UARTTXDMABREQ, depending on the watermark level, for the transmit and receive FIFOs.
Table 1027. DMA
trigger points for the
transmit and receive
FIFOs.
Watermark level Burst length
Transmit (number of empty
locations)
Receive (number of filled locations)
1/8 28 4
1/4 24 8
1/2 16 16
3/4 8 24
7/8 4 28
In addition, the DMAONERR bit in the DMA Control Register, UARTDMACR, supports the use of the receive error interrupt,
RP2350 Datasheet
12.1. UART 968
UARTEINTR. It enables the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, to be masked out when the UART
error interrupt, UARTEINTR, is asserted. The DMA receive request outputs remain inactive until the UARTEINTR is cleared. The
DMA transmit request outputs are unaffected.
Figure 67. DMA
transfer waveforms.
Figure 67 shows the timing diagram for both a single transfer request and a burst transfer request with the appropriate
DMACLR signal. The signals are all synchronous to PCLK. For the sake of clarity it is assumed that there is no
synchronization of the request signals in the DMA controller.
12.1.6. Interrupts
There are eleven maskable interrupts generated in the UART. On RP2350, only the combined interrupt output, UARTINTR, is
connected.
To enable or disable individual interrupts, change the mask bits in the Interrupt Mask Set/Clear Register, UARTIMSC. Set
the appropriate mask bit HIGH to enable the interrupt.
The transmit and receive dataflow interrupts UARTRXINTR and UARTTXINTR have been separated from the status interrupts.
This enables you to use UARTRXINTR and UARTTXINTR to read or write data in response to FIFO trigger levels.
The error interrupt, UARTEINTR, can be triggered when there is an error in the reception of data. A number of error
conditions are possible.
The modem status interrupt, UARTMSINTR, is a combined interrupt of all the individual modem status signals.
The status of the individual interrupt sources can be read either from the Raw Interrupt Status Register, UARTRIS, or from
the Masked Interrupt Status Register, UARTMIS.
12.1.6.1. UARTMSINTR
The modem status interrupt is asserted if any of the modem status signals (nUARTCTS, nUARTDCD, nUARTDSR, and nUARTRI)
change. To clear the modem status interrupt, write a 1 to the bits corresponding to the modem status signals that
generated the interrupt in the Interrupt Clear Register (UARTICR).
12.1.6.2. UARTRXINTR
The receive interrupt changes state when one of the following events occurs:
• The FIFOs are enabled and the receive FIFO reaches the programmed trigger level. This asserts the receive
interrupt HIGH. To clear the receive interrupt, read data from the receive FIFO until it drops below the trigger level.
• The FIFOs are disabled (have a depth of one location) and data is received, thereby filling the receive FIFO. This
asserts the receive interrupt HIGH. To clear the receive interrupt, perform a single read from the receive FIFO.
In both cases, you can also clear the interrupt manually.
12.1.6.3. UARTTXINTR
The transmit interrupt changes state when one of the following events occurs:
• The FIFOs are enabled and the transmit FIFO is equal to or lower than the programmed trigger level. This asserts
the transmit interrupt HIGH. To clear the transmit interrupt, write data to the transmit FIFO until it exceeds the
RP2350 Datasheet
12.1. UART 969
trigger level.
• The FIFOs are disabled (have a depth of one location) and there is no data present in the transmit FIFO. This
asserts the transmit interrupt HIGH. To clear the transmit interrupt, perform a single write to the transmit FIFO.
In both cases, you can also clear the interrupt manually.
To update the transmit FIFO, write data to the transmit FIFO before or after enabling the UART and the interrupts.
 NOTE
The transmit interrupt is based on a transition through a level, rather than on the level itself. When the interrupt and
the UART is enabled before any data is written to the transmit FIFO, the interrupt is not set. The interrupt is only set
after written data leaves the single location of the transmit FIFO and it becomes empty.
12.1.6.4. UARTRTINTR
The receive timeout interrupt is asserted when the receive FIFO is not empty and no more data is received during a 32-
bit period.
The receive timeout interrupt is cleared in the following scenarios:
• the FIFO becomes empty through reading all the data or by reading the holding register
• a 1 is written to the corresponding bit of the Interrupt Clear Register, UARTICR
12.1.6.5. UARTEINTR
The error interrupt is asserted when an error occurs in the reception of data by the UART. The interrupt can be caused
by a number of different error conditions:
• framing
• parity
• break
• overrun
To determine the cause of the interrupt, read the Raw Interrupt Status Register (UARTRIS) or the Masked Interrupt Status
Register (UARTMIS). To clear the interrupt, write to the relevant bits of the Interrupt Clear Register, UARTICR (bits 7 to 10 are
the error clear bits).
12.1.6.6. UARTINTR
The interrupts are also combined into a single output, that is an OR function of the individual masked sources. You can
connect this output to a system interrupt controller to provide another level of masking on a individual peripheral basis.
The combined UART interrupt is asserted if any of the individual interrupts are asserted and enabled.
12.1.7. Programmers model
The SDK provides a uart_init function to configure the UART with a particular baud rate. Once the UART is initialised,
the user must configure a GPIO pin as UART_TX and UART_RX. See Section 9.10.1 for more information on selecting a GPIO
function.
To initialise the UART, the uart_init function takes the following steps:
1. De-asserts the reset
RP2350 Datasheet
12.1. UART 970
2. Enables clk_peri
3. Sets enable bits in the control register
4. Enables the FIFOs
5. Sets the baud rate divisors
6. Sets the format
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c Lines 42 - 92
42 uint uart_init(uart_inst_t *uart, uint baudrate) {
43 invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
44
45 if (uart_clock_get_hz(uart) == 0) {
46 return 0;
47 }
48
49 uart_reset(uart);
50 uart_unreset(uart);
51
52 uart_set_translate_crlf(uart, PICO_UART_DEFAULT_CRLF);
53
54 // Any LCR writes need to take place before enabling the UART
55 uint baud = uart_set_baudrate(uart, baudrate);
56
57 // inline the uart_set_format() call, as we don't need the CR disable/re-enable
58 // protection, and also many people will never call it again, so having
59 // the generic function is not useful, and much bigger than this inlined
60 // code which is only a handful of instructions.
61 //
62 // The UART_UARTLCR_H_FEN_BITS setting is combined as well as it is the same register
63 #ifdef 0
64 uart_set_format(uart, 8, 1, UART_PARITY_NONE);
65 // Enable FIFOs (must be before setting UARTEN, as this is an LCR access)
66 hw_set_bits(&uart_get_hw(uart)->lcr_h, UART_UARTLCR_H_FEN_BITS);
67 #else
68 uint data_bits = 8;
69 uint stop_bits = 1;
70 uint parity = UART_PARITY_NONE;
71 hw_write_masked(&uart_get_hw(uart)->lcr_h,
72 ((data_bits - 5u) << UART_UARTLCR_H_WLEN_LSB) |
73 ((stop_bits - 1u) << UART_UARTLCR_H_STP2_LSB) |
74 (bool_to_bit(parity != UART_PARITY_NONE) << UART_UARTLCR_H_PEN_LSB) |
75 (bool_to_bit(parity == UART_PARITY_EVEN) << UART_UARTLCR_H_EPS_LSB) |
76 UART_UARTLCR_H_FEN_BITS,
77 UART_UARTLCR_H_WLEN_BITS | UART_UARTLCR_H_STP2_BITS |
78 UART_UARTLCR_H_PEN_BITS | UART_UARTLCR_H_EPS_BITS |
79 UART_UARTLCR_H_FEN_BITS);
80 #endif
81
82 // Enable the UART, both TX and RX
83 uart_get_hw(uart)->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS |
UART_UARTCR_RXE_BITS;
84 // Always enable DREQ signals -- no harm in this if DMA is not listening
85 uart_get_hw(uart)->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS;
86
87 return baud;
88 }
RP2350 Datasheet
12.1. UART 971
12.1.7.1. Baud rate calculation
The UART baud rate is derived from dividing clk_peri.
If the required baud rate is 115200 and UARTCLK = 125MHz then:
Baud Rate Divisor = (125 × 106
)/(16 × 115200) ~= 67.817
Therefore, BRDI = 67 and BRDF = 0.817,
Therefore, fractional part, m = integer((0.817 × 64) + 0.5) = 52
Generated baud rate divider = 67 + 52/64 = 67.8125
Generated baud rate = (125 × 106
)/(16 × 67.8125) ~= 115207
Error = (abs(115200 - 115207) / 115200) × 100 ~= 0.006%
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c Lines 155 - 180
155 uint uart_set_baudrate(uart_inst_t *uart, uint baudrate) {
156 invalid_params_if(HARDWARE_UART, baudrate == 0);
157 uint32_t baud_rate_div = (8 * uart_clock_get_hz(uart) / baudrate) + 1;
158 uint32_t baud_ibrd = baud_rate_div >> 7;
159 uint32_t baud_fbrd;
160
161 if (baud_ibrd == 0) {
162 baud_ibrd = 1;
163 baud_fbrd = 0;
164 } else if (baud_ibrd >= 65535) {
165 baud_ibrd = 65535;
166 baud_fbrd = 0;
167 } else {
168 baud_fbrd = (baud_rate_div & 0x7f) >> 1;
169 }
170
171 uart_get_hw(uart)->ibrd = baud_ibrd;
172 uart_get_hw(uart)->fbrd = baud_fbrd;
173
174 // PL011 needs a (dummy) LCR_H write to latch in the divisors.
175 // We don't want to actually change LCR_H contents here.
176 uart_write_lcr_bits_masked(uart, 0, 0);
177
178 // See datasheet
179 return (4 * uart_clock_get_hz(uart)) / (64 * baud_ibrd + baud_fbrd);
180 }
12.1.8. List of registers
The UART0 and UART1 registers start at base addresses of 0x40070000 and 0x40078000 respectively (defined as
UART0_BASE and UART1_BASE in SDK).
Table 1028. List of
UART registers
Offset Name Info
0x000 UARTDR Data Register, UARTDR
0x004 UARTRSR Receive Status Register/Error Clear Register,
UARTRSR/UARTECR
0x018 UARTFR Flag Register, UARTFR
0x020 UARTILPR IrDA Low-Power Counter Register, UARTILPR
RP2350 Datasheet
12.1. UART 972
Offset Name Info
0x024 UARTIBRD Integer Baud Rate Register, UARTIBRD
0x028 UARTFBRD Fractional Baud Rate Register, UARTFBRD
0x02c UARTLCR_H Line Control Register, UARTLCR_H
0x030 UARTCR Control Register, UARTCR
0x034 UARTIFLS Interrupt FIFO Level Select Register, UARTIFLS
0x038 UARTIMSC Interrupt Mask Set/Clear Register, UARTIMSC
0x03c UARTRIS Raw Interrupt Status Register, UARTRIS
0x040 UARTMIS Masked Interrupt Status Register, UARTMIS
0x044 UARTICR Interrupt Clear Register, UARTICR
0x048 UARTDMACR DMA Control Register, UARTDMACR
0xfe0 UARTPERIPHID0 UARTPeriphID0 Register
0xfe4 UARTPERIPHID1 UARTPeriphID1 Register
0xfe8 UARTPERIPHID2 UARTPeriphID2 Register
0xfec UARTPERIPHID3 UARTPeriphID3 Register
0xff0 UARTPCELLID0 UARTPCellID0 Register
0xff4 UARTPCELLID1 UARTPCellID1 Register
0xff8 UARTPCELLID2 UARTPCellID2 Register
0xffc UARTPCELLID3 UARTPCellID3 Register
UART: UARTDR Register
Offset: 0x000
Description
Data Register, UARTDR
Table 1029. UARTDR
Register
Bits Description Type Reset
31:12 Reserved. - -
11 OE: Overrun error. This bit is set to 1 if data is received and the receive FIFO is
already full. This is cleared to 0 once there is an empty space in the FIFO and a
new character can be written to it.
RO -
10 BE: Break error. This bit is set to 1 if a break condition was detected, indicating
that the received data input was held LOW for longer than a full-word
transmission time (defined as start, data, parity and stop bits). In FIFO mode,
this error is associated with the character at the top of the FIFO. When a break
occurs, only one 0 character is loaded into the FIFO. The next character is only
enabled after the receive data input goes to a 1 (marking state), and the next
valid start bit is received.
RO -
9 PE: Parity error. When set to 1, it indicates that the parity of the received data
character does not match the parity that the EPS and SPS bits in the Line
Control Register, UARTLCR_H. In FIFO mode, this error is associated with the
character at the top of the FIFO.
RO -
RP2350 Datasheet
12.1. UART 973
Bits Description Type Reset
8 FE: Framing error. When set to 1, it indicates that the received character did
not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is
associated with the character at the top of the FIFO.
RO -
7:0 DATA: Receive (read) data character. Transmit (write) data character. RWF -
UART: UARTRSR Register
Offset: 0x004
Description
Receive Status Register/Error Clear Register, UARTRSR/UARTECR
Table 1030. UARTRSR
Register
Bits Description Type Reset
31:4 Reserved. - -
3 OE: Overrun error. This bit is set to 1 if data is received and the FIFO is already
full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain
valid because no more data is written when the FIFO is full, only the contents
of the shift register are overwritten. The CPU must now read the data, to
empty the FIFO.
WC 0x0
2 BE: Break error. This bit is set to 1 if a break condition was detected, indicating
that the received data input was held LOW for longer than a full-word
transmission time (defined as start, data, parity, and stop bits). This bit is
cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated
with the character at the top of the FIFO. When a break occurs, only one 0
character is loaded into the FIFO. The next character is only enabled after the
receive data input goes to a 1 (marking state) and the next valid start bit is
received.
WC 0x0
1 PE: Parity error. When set to 1, it indicates that the parity of the received data
character does not match the parity that the EPS and SPS bits in the Line
Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR.
In FIFO mode, this error is associated with the character at the top of the FIFO.
WC 0x0
0 FE: Framing error. When set to 1, it indicates that the received character did
not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write
to UARTECR. In FIFO mode, this error is associated with the character at the
top of the FIFO.
WC 0x0
UART: UARTFR Register
Offset: 0x018
Description
Flag Register, UARTFR
Table 1031. UARTFR
Register
Bits Description Type Reset
31:9 Reserved. - -
8 RI: Ring indicator. This bit is the complement of the UART ring indicator,
nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW.
RO -
RP2350 Datasheet
12.1. UART 974
Bits Description Type Reset
7 TXFE: Transmit FIFO empty. The meaning of this bit depends on the state of
the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled,
this bit is set when the transmit holding register is empty. If the FIFO is
enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not
indicate if there is data in the transmit shift register.
RO 0x1
6 RXFF: Receive FIFO full. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the receive holding register is full. If the FIFO is enabled, the RXFF bit is set
when the receive FIFO is full.
RO 0x0
5 TXFF: Transmit FIFO full. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set
when the transmit FIFO is full.
RO 0x0
4 RXFE: Receive FIFO empty. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set
when the receive FIFO is empty.
RO 0x1
3 BUSY: UART busy. If this bit is set to 1, the UART is busy transmitting data.
This bit remains set until the complete byte, including all the stop bits, has
been sent from the shift register. This bit is set as soon as the transmit FIFO
becomes non-empty, regardless of whether the UART is enabled or not.
RO 0x0
2 DCD: Data carrier detect. This bit is the complement of the UART data carrier
detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD
is LOW.
RO -
1 DSR: Data set ready. This bit is the complement of the UART data set ready,
nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW.
RO -
0 CTS: Clear to send. This bit is the complement of the UART clear to send,
nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW.
RO -
UART: UARTILPR Register
Offset: 0x020
Description
IrDA Low-Power Counter Register, UARTILPR
Table 1032. UARTILPR
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 ILPDVSR: 8-bit low-power divisor value. These bits are cleared to 0 at reset. RW 0x00
UART: UARTIBRD Register
Offset: 0x024
Description
Integer Baud Rate Register, UARTIBRD
Table 1033. UARTIBRD
Register
Bits Description Type Reset
31:16 Reserved. - -
RP2350 Datasheet
12.1. UART 975
Bits Description Type Reset
15:0 BAUD_DIVINT: The integer baud rate divisor. These bits are cleared to 0 on
reset.
RW 0x0000
UART: UARTFBRD Register
Offset: 0x028
Description
Fractional Baud Rate Register, UARTFBRD
Table 1034.
UARTFBRD Register
Bits Description Type Reset
31:6 Reserved. - -
5:0 BAUD_DIVFRAC: The fractional baud rate divisor. These bits are cleared to 0
on reset.
RW 0x00
UART: UARTLCR_H Register
Offset: 0x02c
Description
Line Control Register, UARTLCR_H
Table 1035.
UARTLCR_H Register
Bits Description Type Reset
31:8 Reserved. - -
7 SPS: Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is
0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then
the parity bit is transmitted and checked as a 0. This bit has no effect when
the PEN bit disables parity checking and generation.
RW 0x0
6:5 WLEN: Word length. These bits indicate the number of data bits transmitted or
received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5
bits.
RW 0x0
4 FEN: Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs
become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers
are enabled (FIFO mode).
RW 0x0
3 STP2: Two stop bits select. If this bit is set to 1, two stop bits are transmitted
at the end of the frame. The receive logic does not check for two stop bits
being received.
RW 0x0
2 EPS: Even parity select. Controls the type of parity the UART uses during
transmission and reception: 0 = odd parity. The UART generates or checks for
an odd number of 1s in the data and parity bits. 1 = even parity. The UART
generates or checks for an even number of 1s in the data and parity bits. This
bit has no effect when the PEN bit disables parity checking and generation.
RW 0x0
1 PEN: Parity enable: 0 = parity is disabled and no parity bit added to the data
frame 1 = parity checking and generation is enabled.
RW 0x0
0 BRK: Send break. If this bit is set to 1, a low-level is continually output on the
UARTTXD output, after completing transmission of the current character. For
the proper execution of the break command, the software must set this bit for
at least two complete frames. For normal use, this bit must be cleared to 0.
RW 0x0
UART: UARTCR Register
RP2350 Datasheet
12.1. UART 976
Offset: 0x030
Description
Control Register, UARTCR
Table 1036. UARTCR
Register
Bits Description Type Reset
31:16 Reserved. - -
15 CTSEN: CTS hardware flow control enable. If this bit is set to 1, CTS hardware
flow control is enabled. Data is only transmitted when the nUARTCTS signal is
asserted.
RW 0x0
14 RTSEN: RTS hardware flow control enable. If this bit is set to 1, RTS hardware
flow control is enabled. Data is only requested when there is space in the
receive FIFO for it to be received.
RW 0x0
13 OUT2: This bit is the complement of the UART Out2 (nUARTOut2) modem
status output. That is, when the bit is programmed to a 1, the output is 0. For
DTE this can be used as Ring Indicator (RI).
RW 0x0
12 OUT1: This bit is the complement of the UART Out1 (nUARTOut1) modem
status output. That is, when the bit is programmed to a 1 the output is 0. For
DTE this can be used as Data Carrier Detect (DCD).
RW 0x0
11 RTS: Request to send. This bit is the complement of the UART request to
send, nUARTRTS, modem status output. That is, when the bit is programmed
to a 1 then nUARTRTS is LOW.
RW 0x0
10 DTR: Data transmit ready. This bit is the complement of the UART data
transmit ready, nUARTDTR, modem status output. That is, when the bit is
programmed to a 1 then nUARTDTR is LOW.
RW 0x0
9 RXE: Receive enable. If this bit is set to 1, the receive section of the UART is
enabled. Data reception occurs for either UART signals or SIR signals
depending on the setting of the SIREN bit. When the UART is disabled in the
middle of reception, it completes the current character before stopping.
RW 0x1
8 TXE: Transmit enable. If this bit is set to 1, the transmit section of the UART is
enabled. Data transmission occurs for either UART signals, or SIR signals
depending on the setting of the SIREN bit. When the UART is disabled in the
middle of transmission, it completes the current character before stopping.
RW 0x1
7 LBE: Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and
the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the
nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit
in the test register must be set to 1 to override the normal half-duplex SIR
operation. This must be the requirement for accessing the test registers
during normal operation, and SIRTEST must be cleared to 0 when loopback
testing is finished. This feature reduces the amount of external coupling
required during system test. If this bit is set to 1, and the SIRTEST bit is set to
0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode
or UART mode, when this bit is set, the modem outputs are also fed through to
the modem inputs. This bit is cleared to 0 on reset, to disable loopback.
RW 0x0
6:3 Reserved. - -
RP2350 Datasheet
12.1. UART 977
Bits Description Type Reset
2 SIRLP: SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If
this bit is cleared to 0, low-level bits are transmitted as an active high pulse
with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are
transmitted with a pulse width that is 3 times the period of the IrLPBaud16
input signal, regardless of the selected bit rate. Setting this bit uses less
power, but might reduce transmission distances.
RW 0x0
1 SIREN: SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no
light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA
SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and
SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on
UARTRXD or modem status inputs have no effect. This bit has no effect if the
UARTEN bit disables the UART.
RW 0x0
0 UARTEN: UART enable: 0 = UART is disabled. If the UART is disabled in the
middle of transmission or reception, it completes the current character before
stopping. 1 = the UART is enabled. Data transmission and reception occurs for
either UART signals or SIR signals depending on the setting of the SIREN bit.
RW 0x0
UART: UARTIFLS Register
Offset: 0x034
Description
Interrupt FIFO Level Select Register, UARTIFLS
Table 1037. UARTIFLS
Register
Bits Description Type Reset
31:6 Reserved. - -
5:3 RXIFLSEL: Receive interrupt FIFO level select. The trigger points for the receive
interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 =
Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full
b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7
/ 8 full b101-b111 = reserved.
RW 0x2
2:0 TXIFLSEL: Transmit interrupt FIFO level select. The trigger points for the
transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full
b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <=
1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO
becomes <= 7 / 8 full b101-b111 = reserved.
RW 0x2
UART: UARTIMSC Register
Offset: 0x038
Description
Interrupt Mask Set/Clear Register, UARTIMSC
Table 1038.
UARTIMSC Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEIM: Overrun error interrupt mask. A read returns the current mask for the
UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
RP2350 Datasheet
12.1. UART 978
Bits Description Type Reset
9 BEIM: Break error interrupt mask. A read returns the current mask for the
UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
8 PEIM: Parity error interrupt mask. A read returns the current mask for the
UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
7 FEIM: Framing error interrupt mask. A read returns the current mask for the
UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
6 RTIM: Receive timeout interrupt mask. A read returns the current mask for the
UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
5 TXIM: Transmit interrupt mask. A read returns the current mask for the
UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
4 RXIM: Receive interrupt mask. A read returns the current mask for the
UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
3 DSRMIM: nUARTDSR modem interrupt mask. A read returns the current mask
for the UARTDSRINTR interrupt. On a write of 1, the mask of the
UARTDSRINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
2 DCDMIM: nUARTDCD modem interrupt mask. A read returns the current mask
for the UARTDCDINTR interrupt. On a write of 1, the mask of the
UARTDCDINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
1 CTSMIM: nUARTCTS modem interrupt mask. A read returns the current mask
for the UARTCTSINTR interrupt. On a write of 1, the mask of the
UARTCTSINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
0 RIMIM: nUARTRI modem interrupt mask. A read returns the current mask for
the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR
interrupt is set. A write of 0 clears the mask.
RW 0x0
UART: UARTRIS Register
Offset: 0x03c
Description
Raw Interrupt Status Register, UARTRIS
Table 1039. UARTRIS
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OERIS: Overrun error interrupt status. Returns the raw interrupt state of the
UARTOEINTR interrupt.
RO 0x0
9 BERIS: Break error interrupt status. Returns the raw interrupt state of the
UARTBEINTR interrupt.
RO 0x0
8 PERIS: Parity error interrupt status. Returns the raw interrupt state of the
UARTPEINTR interrupt.
RO 0x0
RP2350 Datasheet
12.1. UART 979
Bits Description Type Reset
7 FERIS: Framing error interrupt status. Returns the raw interrupt state of the
UARTFEINTR interrupt.
RO 0x0
6 RTRIS: Receive timeout interrupt status. Returns the raw interrupt state of the
UARTRTINTR interrupt. a
RO 0x0
5 TXRIS: Transmit interrupt status. Returns the raw interrupt state of the
UARTTXINTR interrupt.
RO 0x0
4 RXRIS: Receive interrupt status. Returns the raw interrupt state of the
UARTRXINTR interrupt.
RO 0x0
3 DSRRMIS: nUARTDSR modem interrupt status. Returns the raw interrupt state
of the UARTDSRINTR interrupt.
RO -
2 DCDRMIS: nUARTDCD modem interrupt status. Returns the raw interrupt state
of the UARTDCDINTR interrupt.
RO -
1 CTSRMIS: nUARTCTS modem interrupt status. Returns the raw interrupt state
of the UARTCTSINTR interrupt.
RO -
0 RIRMIS: nUARTRI modem interrupt status. Returns the raw interrupt state of
the UARTRIINTR interrupt.
RO -
UART: UARTMIS Register
Offset: 0x040
Description
Masked Interrupt Status Register, UARTMIS
Table 1040. UARTMIS
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEMIS: Overrun error masked interrupt status. Returns the masked interrupt
state of the UARTOEINTR interrupt.
RO 0x0
9 BEMIS: Break error masked interrupt status. Returns the masked interrupt
state of the UARTBEINTR interrupt.
RO 0x0
8 PEMIS: Parity error masked interrupt status. Returns the masked interrupt
state of the UARTPEINTR interrupt.
RO 0x0
7 FEMIS: Framing error masked interrupt status. Returns the masked interrupt
state of the UARTFEINTR interrupt.
RO 0x0
6 RTMIS: Receive timeout masked interrupt status. Returns the masked
interrupt state of the UARTRTINTR interrupt.
RO 0x0
5 TXMIS: Transmit masked interrupt status. Returns the masked interrupt state
of the UARTTXINTR interrupt.
RO 0x0
4 RXMIS: Receive masked interrupt status. Returns the masked interrupt state
of the UARTRXINTR interrupt.
RO 0x0
3 DSRMMIS: nUARTDSR modem masked interrupt status. Returns the masked
interrupt state of the UARTDSRINTR interrupt.
RO -
2 DCDMMIS: nUARTDCD modem masked interrupt status. Returns the masked
interrupt state of the UARTDCDINTR interrupt.
RO -
RP2350 Datasheet
12.1. UART 980
Bits Description Type Reset
1 CTSMMIS: nUARTCTS modem masked interrupt status. Returns the masked
interrupt state of the UARTCTSINTR interrupt.
RO -
0 RIMMIS: nUARTRI modem masked interrupt status. Returns the masked
interrupt state of the UARTRIINTR interrupt.
RO -
UART: UARTICR Register
Offset: 0x044
Description
Interrupt Clear Register, UARTICR
Table 1041. UARTICR
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEIC: Overrun error interrupt clear. Clears the UARTOEINTR interrupt. WC -
9 BEIC: Break error interrupt clear. Clears the UARTBEINTR interrupt. WC -
8 PEIC: Parity error interrupt clear. Clears the UARTPEINTR interrupt. WC -
7 FEIC: Framing error interrupt clear. Clears the UARTFEINTR interrupt. WC -
6 RTIC: Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. WC -
5 TXIC: Transmit interrupt clear. Clears the UARTTXINTR interrupt. WC -
4 RXIC: Receive interrupt clear. Clears the UARTRXINTR interrupt. WC -
3 DSRMIC: nUARTDSR modem interrupt clear. Clears the UARTDSRINTR
interrupt.
WC -
2 DCDMIC: nUARTDCD modem interrupt clear. Clears the UARTDCDINTR
interrupt.
WC -
1 CTSMIC: nUARTCTS modem interrupt clear. Clears the UARTCTSINTR
interrupt.
WC -
0 RIMIC: nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. WC -
UART: UARTDMACR Register
Offset: 0x048
Description
DMA Control Register, UARTDMACR
Table 1042.
UARTDMACR Register
Bits Description Type Reset
31:3 Reserved. - -
2 DMAONERR: DMA on error. If this bit is set to 1, the DMA receive request
outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the
UART error interrupt is asserted.
RW 0x0
1 TXDMAE: Transmit DMA enable. If this bit is set to 1, DMA for the transmit
FIFO is enabled.
RW 0x0
0 RXDMAE: Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO
is enabled.
RW 0x0
RP2350 Datasheet
12.1. UART 981
UART: UARTPERIPHID0 Register
Offset: 0xfe0
Description
UARTPeriphID0 Register
Table 1043.
UARTPERIPHID0
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 PARTNUMBER0: These bits read back as 0x11 RO 0x11
UART: UARTPERIPHID1 Register
Offset: 0xfe4
Description
UARTPeriphID1 Register
Table 1044.
UARTPERIPHID1
Register
Bits Description Type Reset
31:8 Reserved. - -
7:4 DESIGNER0: These bits read back as 0x1 RO 0x1
3:0 PARTNUMBER1: These bits read back as 0x0 RO 0x0
UART: UARTPERIPHID2 Register
Offset: 0xfe8
Description
UARTPeriphID2 Register
Table 1045.
UARTPERIPHID2
Register
Bits Description Type Reset
31:8 Reserved. - -
7:4 REVISION: This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1
r1p3 0x2 r1p4 0x2 r1p5 0x3
RO 0x3
3:0 DESIGNER1: These bits read back as 0x4 RO 0x4
UART: UARTPERIPHID3 Register
Offset: 0xfec
Description
UARTPeriphID3 Register
Table 1046.
UARTPERIPHID3
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 CONFIGURATION: These bits read back as 0x00 RO 0x00
UART: UARTPCELLID0 Register
Offset: 0xff0
Description
UARTPCellID0 Register
RP2350 Datasheet
12.1. UART 982
Table 1047.
UARTPCELLID0
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID0: These bits read back as 0x0D RO 0x0d
UART: UARTPCELLID1 Register
Offset: 0xff4
Description
UARTPCellID1 Register
Table 1048.
UARTPCELLID1
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID1: These bits read back as 0xF0 RO 0xf0
UART: UARTPCELLID2 Register
Offset: 0xff8
Description
UARTPCellID2 Register
Table 1049.
UARTPCELLID2
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID2: These bits read back as 0x05 RO 0x05
UART: UARTPCELLID3 Register
Offset: 0xffc
Description
UARTPCellID3 Register
Table 1050.
UARTPCELLID3
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID3: These bits read back as 0xB1 RO 0xb112.1. UART
Arm documentation
Excerpted from the PrimeCell UART (PL011) Technical Reference Manual. Used with permission.
RP2350 has 2 identical instances of a UART peripheral, based on the Arm Primecell UART (PL011) (Revision r1p5).
Each instance supports the following features:
• Separate 32×8 TX and 32×12 RX FIFOs
• Programmable baud rate generator, clocked by clk_peri (see Figure 33)
• Standard asynchronous communication bits (start, stop, parity) added on transmit and removed on receive
• Line break detection
• Programmable serial interface (5, 6, 7, or 8 bits)
• 1 or 2 stop bits
• Programmable hardware flow control
Each UART can be connected to a number of GPIO pins as defined in the GPIO muxing table in Section 9.4. Connections
to the GPIO muxing use a prefix including the UART instance name uart0_ or uart1_, and include the following:
• Transmit data tx (referred to as UARTTXD in the following sections)
• Received data rx (referred to as UARTRXD in the following sections)
• Output flow control rts (referred to as nUARTRTS in the following sections)
• Input flow control cts (referred to as nUARTCTS in the following sections)
The modem mode and IrDA mode of the PL011 are not supported.
The UARTCLK is driven from clk_peri, and PCLK is driven from the system clock clk_sys (see Figure 33).
12.1.1. Overview
The UART performs:
• Serial-to-parallel conversion on data received from a peripheral device
• Parallel-to-serial conversion on data transmitted to the peripheral device
The CPU reads and writes data and control/status information through the AMBA APB interface. The transmit and
receive paths are buffered with internal FIFO memories that store up to 32 bytes independently in both transmit and
receive modes.
The UART:
• Includes a programmable baud rate generator that generates a common transmit and receive internal clock from
the UART internal reference clock input, UARTCLK
• Offers similar functionality to the industry-standard 16C650 UART device
• Supports a maximum baud rate of UARTCLK / 16 in UART mode (7.8 Mbaud at 125MHz)
RP2350 Datasheet
12.1. UART 961
The UART operation and baud rate values are controlled by the Line Control Register (UARTLCR_H) and the baud rate
divisor registers: Integer Baud Rate Register (UARTIBRD), and Fractional Baud Rate Register (UARTFBRD).
The UART can generate:
• Individually maskable interrupts from the receive (including timeout), transmit, modem status and error conditions
• A single combined interrupt so that the output is asserted if any of the individual interrupts are asserted and
unmasked
• DMA request signals for interfacing with a Direct Memory Access (DMA) controller
If a framing, parity, or break error occurs during reception, the appropriate error bit is set and stored in the FIFO. If an
overrun condition occurs, the overrun register bit is set immediately and FIFO data is prevented from being overwritten.
You can program the FIFOs to be 1-byte deep providing a conventional double-buffered UART interface.
There is a programmable hardware flow control feature that uses the nUARTCTS input and the nUARTRTS output to
automatically control the serial data flow.
12.1.2. Functional description
Figure 63. UART block
diagram. Test logic is
not shown for clarity.
12.1.2.1. AMBA APB interface
The AMBA APB interface generates read and write decodes for accesses to status/control registers, and the transmit
and receive FIFOs.
12.1.2.2. Register block
The register block stores data written, or to be read across the AMBA APB interface.
RP2350 Datasheet
12.1. UART 962
12.1.2.3. Baud rate generator
The baud rate generator contains free-running counters that generate the internal clocks: Baud16 and IrLPBaud16
signals. Baud16 provides timing information for UART transmit and receive control. Baud16 is a stream of pulses with a
width of one UARTCLK clock period and a frequency of 16 times the baud rate.
12.1.2.4. Transmit FIFO
The transmit FIFO is an 8-bit wide, 32 location deep, FIFO memory buffer. CPU data written across the APB interface is
stored in the FIFO until read out by the transmit logic. When disabled, the transmit FIFO acts like a one byte holding
register.
12.1.2.5. Receive FIFO
The receive FIFO is a 12-bit wide, 32 location deep, FIFO memory buffer. Received data and corresponding error bits are
stored in the receive FIFO by the receive logic until read out by the CPU across the APB interface. When disabled, the
receive FIFO acts like a one byte holding register.
12.1.2.6. Transmit logic
The transmit logic performs parallel-to-serial conversion on the data read from the transmit FIFO. Control logic outputs
the serial bit stream in the following order:
1. Start bit
2. Data bits (Least Significant Bit (LSB) first)
3. Parity bit
4. Stop bits according to the programmed configuration in control registers
12.1.2.7. Receive logic
The receive logic performs serial-to-parallel conversion on the received bit stream after a valid start pulse has been
detected. Receive logic includes overrun, parity, frame error checking, and line break detection; you can find the output
of these checks in the status that accompanies the data written to the receive FIFO.
12.1.2.8. Interrupt generation logic
The UART generates individual maskable active HIGH interrupts to the processor interrupt controllers. To generate
combined interrupts, the UART outputs an OR function of the individual interrupt requests.
For more information, see Section 12.1.6.
12.1.2.9. DMA interface
The UART provides an interface to connect to the DMA controller as a UART DMA; for more information, see Section
12.1.5.
RP2350 Datasheet
12.1. UART 963
12.1.2.10. Synchronizing registers and logic
The UART supports both asynchronous and synchronous operation of the clocks, PCLK and UARTCLK. The UART
implements always-on synchronisation registers and handshaking logic. This has a minimal impact on performance and
area. The UART performs control signal synchronisation on both directions of data flow (from the PCLK to the UARTCLK
domain, and from the UARTCLK to the PCLK domain).
12.1.3. Operation
12.1.3.1. Clock signals
The frequency selected for UARTCLK must accommodate the required range of baud rates:
• FUARTCLK (min) ≥ 16 × baud_rate (max)
• FUARTCLK (max) ≤ 16 × 65535 × baud_rate (min)
For example, for a range of baud rates from 110 baud to 460800 baud the UARTCLK frequency must be between
7.3728MHz to 115.34MHz.
To use all baud rates, the UARTCLK frequency must fall within the required error limits.
There is also a constraint on the ratio of clock frequencies for PCLK to UARTCLK. The frequency of UARTCLK must be no more
than 5/3 times faster than the frequency of PCLK:
• FUARTCLK ≤ 5/3 × FPCLK
For example, in UART mode, to generate 921600 baud when UARTCLK is 14.7456MHz, PCLK must be greater than or equal
to 8.85276MHz. This ensures that the UART has sufficient time to write the received data to the receive FIFO.
12.1.3.2. UART operation
Control data is written to the UART Line Control Register, UARTLCR. This register is 30 bits wide internally, but provides
external access through the APB interface by writes to the following registers:
• UARTLCR_H, which defines the following:
transmission parameters
word length
buffer mode
number of transmitted stop bits
parity mode
break generation
• UARTIBRD, which defines the integer baud rate divider
• UARTFBRD, which defines the fractional baud rate divider
12.1.3.2.1. Fractional baud rate divider
The baud rate divisor is a 22-bit number consisting of a 16-bit integer and a 6-bit fractional part. The baud rate generator
uses the baud rate divisor to determine the bit period. The fractional baud rate divider enables the use of any clock with
a frequency greater than 3.6864MHz to act as UARTCLK, while it is still possible to generate all the standard baud rates.
The 16-bit integer is written to the Integer Baud Rate Register, UARTIBRD. The 6-bit fractional part is written to the
Fractional Baud Rate Register, UARTFBRD. The Baud Rate Divisor has the following relationship to UARTCLK:
RP2350 Datasheet
12.1. UART 964
Baud Rate Divisor = UARTCLK/(16×Baud Rate) = where is the integer part and is the
fractional part separated by a decimal point as shown in Figure 64.
Figure 64. Baud rate
divisor.
To calculate the 6-bit number ( ), multiply the fractional part of the required baud rate divisor by 64 ( , where is the
width of the UARTFBRD register) and add 0.5 to account for rounding errors:
The UART generates an internal clock enable signal, Baud16. This is a stream of UARTCLK-wide pulses with an average
frequency of 16 times the required baud rate. Divide this signal by 16 to give the transmit clock. A low number in the
baud rate divisor produces a short bit period, and a high number in the baud rate divisor produces a long bit period.
12.1.3.2.2. Data transmission or reception
The UART uses two 32-byte FIFOs to store data received and transmitted. The receive FIFO has an extra four bits per
character for status information. For transmission, data is written into the transmit FIFO. If the UART is enabled, it
causes a data frame to start transmitting with the parameters indicated in the Line Control Register, UARTLCR_H. Data
continues to be transmitted until there is no data left in the transmit FIFO. The BUSY signal goes HIGH immediately after
data writes to the transmit FIFO (that is, the FIFO is non-empty) and remains asserted HIGH while data transmits. BUSY
is negated only when the transmit FIFO is empty, and the last character has been transmitted from the shift register,
including the stop bits. BUSY can be asserted HIGH even though the UART might no longer be enabled.
For each sample of data, three readings are taken and the majority value is kept. In the following paragraphs, the middle
sampling point is defined, and one sample is taken either side of it.
When the receiver is idle (UARTRXD continuously 1, in the marking state) and a LOW is detected on the data input (a start
bit has been received), the receive counter, with the clock enabled by Baud16, begins running and data is sampled on
the eighth cycle of that counter in UART mode, or the fourth cycle of the counter in SIR mode to allow for the shorter
logic 0 pulses (half way through a bit period).
The start bit is valid if UARTRXD is still LOW on the eighth cycle of Baud16, otherwise a false start bit is detected and it is
ignored.
If the start bit was valid, successive data bits are sampled on every 16th cycle of Baud16 (that is, one bit period later)
according to the programmed length of the data characters. The parity bit is then checked if parity mode was enabled.
Lastly, a valid stop bit is confirmed if UARTRXD is HIGH, otherwise a framing error has occurred. When a full word is
received, the data is stored in the receive FIFO, with any error bits associated with that word
12.1.3.2.3. Error bits
The receive FIFO stores three error bits in bits 8 (framing), 9 (parity), and 10 (break), each associated with a particular
character. An additional error bit, stored in bit 11 of the receive FIFO, indicates an overrun error.
12.1.3.2.4. Overrun bit
The overrun bit is not associated with the character in the receive FIFO. The overrun error is set when the FIFO is full and
the next character is completely received in the shift register. The data in the shift register is overwritten, but it is not
written into the FIFO. When an empty location becomes available in the FIFO, another character is received and the state
of the overrun bit is copied into the receive FIFO along with the received character. The overrun state is then cleared.
Table 1025 lists the bit functions of the receive FIFO.
RP2350 Datasheet
12.1. UART 965
Table 1025. Receive
FIFO bit functions
FIFO bit Function
11 Overrun indicator
10 Break error
9 Parity error
8 Framing error
7:0 Received data
12.1.3.2.5. Disabling the FIFOs
The bottom entry of the transmit and receive sides of the UART both have the equivalent of a 1-byte holding register.
You can manipulate flags to disable the FIFOs, allowing you to use the bottom entry of the FIFOs as a 1-byte register.
However, this doesnt physically disable the FIFOs. When using the FIFOs as a 1-byte register, a write to the data register
bypasses the holding register unless the transmit shift register is already in use.
12.1.3.2.6. System and diagnostic loopback testing
To perform loopback testing for UART data, set the Loop Back Enable (LBE) bit to 1 in the Control Register, UARTCR.
Data transmitted on UARTTXD is received on the UARTRXD input.
12.1.3.3. UART character frame
Figure 65. UART
character frame.
12.1.4. UART hardware flow control
The fully-selectable hardware flow control feature enables you to control the serial data flow with the nUARTRTS output
and nUARTCTS input signals. Figure 66 shows how to communicate between two devices using hardware flow control:
Figure 66. Hardware
flow control between
two similar devices.
When the RTS flow control is enabled, nUARTRTS is asserted until the receive FIFO is filled up to the programmed
watermark level. When the CTS flow control is enabled, the transmitter can only transmit data when nUARTCTS is asserted.
The hardware flow control is selectable using the RTSEn and CTSEn bits in the Control Register, UARTCR. Table 1026 shows
how to configure UARTCR register bits to enable RTS and/or CTS.
RP2350 Datasheet
12.1. UART 966
Table 1026. Control
bits to enable and
disable hardware flow
control.
UARTCR register bits
CTSEn RTSEn Description
1 1 Both RTS and CTS flow control
enabled
1 0 Only CTS flow control enabled
0 1 Only RTS flow control enabled
0 0 Both RTS and CTS flow control
disabled
 NOTE
When RTS flow control is enabled, the software cannot use the RTSEn bit in the Control Register (UARTCR) to control
the status of nUARTRTS.
12.1.4.1. RTS flow control
The RTS flow control logic is linked to the programmable receive FIFO watermark levels.
When RTS flow control is disabled, the receive FIFO receives data until full, or no more data is transmitted to it.
When RTS flow control is enabled, the nUARTRTS is asserted until the receive FIFO fills up to the watermark level. When the
receive FIFO reaches the watermark level, the nUARTRTS signal is de-asserted. This indicates that the FIFO has no more
room to receive data. The transmission of data is expected to cease after the current character has been transmitted.
When the receive FIFO drains below the watermark level, the nUARTRTS signal is reasserted.
12.1.4.2. CTS flow control
The CTS flow control logic is linked to the nUARTCTS signal.
When CTS flow control is disabled, the transmitter transmits data until the transmit FIFO is empty.
When CTS flow control is enabled, the transmitter checks the nUARTCTS signal before transmitting each byte. It only
transmits the byte if the nUARTCTS signal is asserted. As long as the transmit FIFO is not empty and nUARTCTS is asserted,
data continues to transmit. If the transmit FIFO is empty and the nUARTCTS signal is asserted, no data is transmitted. If the
nUARTCTS signal is de-asserted during transmission, the transmitter finishes transmitting the current character before
stopping.
12.1.5. UART DMA interface
The UART provides an interface to connect to a DMA controller. The DMA operation of the UART is controlled using the
DMA Control Register, UARTDMACR. The DMA interface includes the following signals:
For receive:
UARTRXDMASREQ
Single character DMA transfer request, asserted by the UART. For receive, one character consists of up to 12 bits.
This signal is asserted when the receive FIFO contains at least one character.
UARTRXDMABREQ
Burst DMA transfer request, asserted by the UART. This signal is asserted when the receive FIFO contains more
characters than the programmed watermark level. You can program the watermark level for each FIFO using the
Interrupt FIFO Level Select Register (UARTIFLS).
RP2350 Datasheet
12.1. UART 967
UARTRXDMACLR
DMA request clear, asserted by a DMA controller to clear the receive request signals. If DMA burst transfer is
requested, the clear signal is asserted during the transfer of the last data in the burst.
For transmit:
UARTTXDMASREQ
Single character DMA transfer request, asserted by the UART. For transmit, one character consists of up to eight
bits. This signal is asserted when there is at least one empty location in the transmit FIFO.
UARTTXDMABREQ
Burst DMA transfer request, asserted by the UART. This signal is asserted when the transmit FIFO contains less
characters than the watermark level. You can program the watermark level for each FIFO using the Interrupt FIFO
Level Select Register (UARTIFLS).
UARTTXDMACLR
DMA request clear, asserted by a DMA controller to clear the transmit request signals. If DMA burst transfer is
requested, the clear signal is asserted during the transfer of the last data in the burst.
The burst transfer and single transfer request signals are not mutually exclusive: they can both be asserted at the same
time. When the receive FIFO exceeds the watermark level, the burst transfer request and the single transfer request
signals are both asserted. When the receive FIFO is below than the watermark level, only the single transfer request
signal is asserted. This is useful in situations where the number of characters left to be received in the stream is less
than a burst.
Consider a scenario where the watermark level is set to four, but 19 characters are left to be received. The DMA
controller then transfers four bursts of four characters and three single transfers to complete the stream.
 NOTE
For the remaining three characters, the UART cannot assert the burst request.
Each request signal remains asserted until the relevant DMACLR signal is asserted. After the request clear signal is deasserted, a request signal can become active again, depending on the conditions described previously. All request
signals are de-asserted if the UART is disabled or the relevant DMA enable bit, TXDMAE or RXDMAE, in the DMA Control
Register, UARTDMACR, is cleared.
If you disable the FIFOs in the UART, it operates in character mode. Character mode limits FIFO transfers to a single
character at a time, so only the DMA single transfer mode can operate. In character mode, only the UARTRXDMASREQ and
UARTTXDMASREQ request signals can be asserted. For information about disabling the FIFOs, see the Line Control Register,
UARTLCR_H.
When the UART is in the FIFO enabled mode, data transfers can use either single or burst transfers depending on the
programmed watermark level and the amount of data in the FIFO. Table 1027 lists the trigger points for UARTRXDMABREQ
and UARTTXDMABREQ, depending on the watermark level, for the transmit and receive FIFOs.
Table 1027. DMA
trigger points for the
transmit and receive
FIFOs.
Watermark level Burst length
Transmit (number of empty
locations)
Receive (number of filled locations)
1/8 28 4
1/4 24 8
1/2 16 16
3/4 8 24
7/8 4 28
In addition, the DMAONERR bit in the DMA Control Register, UARTDMACR, supports the use of the receive error interrupt,
RP2350 Datasheet
12.1. UART 968
UARTEINTR. It enables the DMA receive request outputs, UARTRXDMASREQ or UARTRXDMABREQ, to be masked out when the UART
error interrupt, UARTEINTR, is asserted. The DMA receive request outputs remain inactive until the UARTEINTR is cleared. The
DMA transmit request outputs are unaffected.
Figure 67. DMA
transfer waveforms.
Figure 67 shows the timing diagram for both a single transfer request and a burst transfer request with the appropriate
DMACLR signal. The signals are all synchronous to PCLK. For the sake of clarity it is assumed that there is no
synchronization of the request signals in the DMA controller.
12.1.6. Interrupts
There are eleven maskable interrupts generated in the UART. On RP2350, only the combined interrupt output, UARTINTR, is
connected.
To enable or disable individual interrupts, change the mask bits in the Interrupt Mask Set/Clear Register, UARTIMSC. Set
the appropriate mask bit HIGH to enable the interrupt.
The transmit and receive dataflow interrupts UARTRXINTR and UARTTXINTR have been separated from the status interrupts.
This enables you to use UARTRXINTR and UARTTXINTR to read or write data in response to FIFO trigger levels.
The error interrupt, UARTEINTR, can be triggered when there is an error in the reception of data. A number of error
conditions are possible.
The modem status interrupt, UARTMSINTR, is a combined interrupt of all the individual modem status signals.
The status of the individual interrupt sources can be read either from the Raw Interrupt Status Register, UARTRIS, or from
the Masked Interrupt Status Register, UARTMIS.
12.1.6.1. UARTMSINTR
The modem status interrupt is asserted if any of the modem status signals (nUARTCTS, nUARTDCD, nUARTDSR, and nUARTRI)
change. To clear the modem status interrupt, write a 1 to the bits corresponding to the modem status signals that
generated the interrupt in the Interrupt Clear Register (UARTICR).
12.1.6.2. UARTRXINTR
The receive interrupt changes state when one of the following events occurs:
• The FIFOs are enabled and the receive FIFO reaches the programmed trigger level. This asserts the receive
interrupt HIGH. To clear the receive interrupt, read data from the receive FIFO until it drops below the trigger level.
• The FIFOs are disabled (have a depth of one location) and data is received, thereby filling the receive FIFO. This
asserts the receive interrupt HIGH. To clear the receive interrupt, perform a single read from the receive FIFO.
In both cases, you can also clear the interrupt manually.
12.1.6.3. UARTTXINTR
The transmit interrupt changes state when one of the following events occurs:
• The FIFOs are enabled and the transmit FIFO is equal to or lower than the programmed trigger level. This asserts
the transmit interrupt HIGH. To clear the transmit interrupt, write data to the transmit FIFO until it exceeds the
RP2350 Datasheet
12.1. UART 969
trigger level.
• The FIFOs are disabled (have a depth of one location) and there is no data present in the transmit FIFO. This
asserts the transmit interrupt HIGH. To clear the transmit interrupt, perform a single write to the transmit FIFO.
In both cases, you can also clear the interrupt manually.
To update the transmit FIFO, write data to the transmit FIFO before or after enabling the UART and the interrupts.
 NOTE
The transmit interrupt is based on a transition through a level, rather than on the level itself. When the interrupt and
the UART is enabled before any data is written to the transmit FIFO, the interrupt is not set. The interrupt is only set
after written data leaves the single location of the transmit FIFO and it becomes empty.
12.1.6.4. UARTRTINTR
The receive timeout interrupt is asserted when the receive FIFO is not empty and no more data is received during a 32-
bit period.
The receive timeout interrupt is cleared in the following scenarios:
• the FIFO becomes empty through reading all the data or by reading the holding register
• a 1 is written to the corresponding bit of the Interrupt Clear Register, UARTICR
12.1.6.5. UARTEINTR
The error interrupt is asserted when an error occurs in the reception of data by the UART. The interrupt can be caused
by a number of different error conditions:
• framing
• parity
• break
• overrun
To determine the cause of the interrupt, read the Raw Interrupt Status Register (UARTRIS) or the Masked Interrupt Status
Register (UARTMIS). To clear the interrupt, write to the relevant bits of the Interrupt Clear Register, UARTICR (bits 7 to 10 are
the error clear bits).
12.1.6.6. UARTINTR
The interrupts are also combined into a single output, that is an OR function of the individual masked sources. You can
connect this output to a system interrupt controller to provide another level of masking on a individual peripheral basis.
The combined UART interrupt is asserted if any of the individual interrupts are asserted and enabled.
12.1.7. Programmers model
The SDK provides a uart_init function to configure the UART with a particular baud rate. Once the UART is initialised,
the user must configure a GPIO pin as UART_TX and UART_RX. See Section 9.10.1 for more information on selecting a GPIO
function.
To initialise the UART, the uart_init function takes the following steps:
1. De-asserts the reset
RP2350 Datasheet
12.1. UART 970
2. Enables clk_peri
3. Sets enable bits in the control register
4. Enables the FIFOs
5. Sets the baud rate divisors
6. Sets the format
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c Lines 42 - 92
42 uint uart_init(uart_inst_t *uart, uint baudrate) {
43 invalid_params_if(HARDWARE_UART, uart != uart0 && uart != uart1);
44
45 if (uart_clock_get_hz(uart) == 0) {
46 return 0;
47 }
48
49 uart_reset(uart);
50 uart_unreset(uart);
51
52 uart_set_translate_crlf(uart, PICO_UART_DEFAULT_CRLF);
53
54 // Any LCR writes need to take place before enabling the UART
55 uint baud = uart_set_baudrate(uart, baudrate);
56
57 // inline the uart_set_format() call, as we don't need the CR disable/re-enable
58 // protection, and also many people will never call it again, so having
59 // the generic function is not useful, and much bigger than this inlined
60 // code which is only a handful of instructions.
61 //
62 // The UART_UARTLCR_H_FEN_BITS setting is combined as well as it is the same register
63 #ifdef 0
64 uart_set_format(uart, 8, 1, UART_PARITY_NONE);
65 // Enable FIFOs (must be before setting UARTEN, as this is an LCR access)
66 hw_set_bits(&uart_get_hw(uart)->lcr_h, UART_UARTLCR_H_FEN_BITS);
67 #else
68 uint data_bits = 8;
69 uint stop_bits = 1;
70 uint parity = UART_PARITY_NONE;
71 hw_write_masked(&uart_get_hw(uart)->lcr_h,
72 ((data_bits - 5u) << UART_UARTLCR_H_WLEN_LSB) |
73 ((stop_bits - 1u) << UART_UARTLCR_H_STP2_LSB) |
74 (bool_to_bit(parity != UART_PARITY_NONE) << UART_UARTLCR_H_PEN_LSB) |
75 (bool_to_bit(parity == UART_PARITY_EVEN) << UART_UARTLCR_H_EPS_LSB) |
76 UART_UARTLCR_H_FEN_BITS,
77 UART_UARTLCR_H_WLEN_BITS | UART_UARTLCR_H_STP2_BITS |
78 UART_UARTLCR_H_PEN_BITS | UART_UARTLCR_H_EPS_BITS |
79 UART_UARTLCR_H_FEN_BITS);
80 #endif
81
82 // Enable the UART, both TX and RX
83 uart_get_hw(uart)->cr = UART_UARTCR_UARTEN_BITS | UART_UARTCR_TXE_BITS |
UART_UARTCR_RXE_BITS;
84 // Always enable DREQ signals -- no harm in this if DMA is not listening
85 uart_get_hw(uart)->dmacr = UART_UARTDMACR_TXDMAE_BITS | UART_UARTDMACR_RXDMAE_BITS;
86
87 return baud;
88 }
RP2350 Datasheet
12.1. UART 971
12.1.7.1. Baud rate calculation
The UART baud rate is derived from dividing clk_peri.
If the required baud rate is 115200 and UARTCLK = 125MHz then:
Baud Rate Divisor = (125 × 106
)/(16 × 115200) ~= 67.817
Therefore, BRDI = 67 and BRDF = 0.817,
Therefore, fractional part, m = integer((0.817 × 64) + 0.5) = 52
Generated baud rate divider = 67 + 52/64 = 67.8125
Generated baud rate = (125 × 106
)/(16 × 67.8125) ~= 115207
Error = (abs(115200 - 115207) / 115200) × 100 ~= 0.006%
SDK: https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_uart/uart.c Lines 155 - 180
155 uint uart_set_baudrate(uart_inst_t *uart, uint baudrate) {
156 invalid_params_if(HARDWARE_UART, baudrate == 0);
157 uint32_t baud_rate_div = (8 * uart_clock_get_hz(uart) / baudrate) + 1;
158 uint32_t baud_ibrd = baud_rate_div >> 7;
159 uint32_t baud_fbrd;
160
161 if (baud_ibrd == 0) {
162 baud_ibrd = 1;
163 baud_fbrd = 0;
164 } else if (baud_ibrd >= 65535) {
165 baud_ibrd = 65535;
166 baud_fbrd = 0;
167 } else {
168 baud_fbrd = (baud_rate_div & 0x7f) >> 1;
169 }
170
171 uart_get_hw(uart)->ibrd = baud_ibrd;
172 uart_get_hw(uart)->fbrd = baud_fbrd;
173
174 // PL011 needs a (dummy) LCR_H write to latch in the divisors.
175 // We don't want to actually change LCR_H contents here.
176 uart_write_lcr_bits_masked(uart, 0, 0);
177
178 // See datasheet
179 return (4 * uart_clock_get_hz(uart)) / (64 * baud_ibrd + baud_fbrd);
180 }
12.1.8. List of registers
The UART0 and UART1 registers start at base addresses of 0x40070000 and 0x40078000 respectively (defined as
UART0_BASE and UART1_BASE in SDK).
Table 1028. List of
UART registers
Offset Name Info
0x000 UARTDR Data Register, UARTDR
0x004 UARTRSR Receive Status Register/Error Clear Register,
UARTRSR/UARTECR
0x018 UARTFR Flag Register, UARTFR
0x020 UARTILPR IrDA Low-Power Counter Register, UARTILPR
RP2350 Datasheet
12.1. UART 972
Offset Name Info
0x024 UARTIBRD Integer Baud Rate Register, UARTIBRD
0x028 UARTFBRD Fractional Baud Rate Register, UARTFBRD
0x02c UARTLCR_H Line Control Register, UARTLCR_H
0x030 UARTCR Control Register, UARTCR
0x034 UARTIFLS Interrupt FIFO Level Select Register, UARTIFLS
0x038 UARTIMSC Interrupt Mask Set/Clear Register, UARTIMSC
0x03c UARTRIS Raw Interrupt Status Register, UARTRIS
0x040 UARTMIS Masked Interrupt Status Register, UARTMIS
0x044 UARTICR Interrupt Clear Register, UARTICR
0x048 UARTDMACR DMA Control Register, UARTDMACR
0xfe0 UARTPERIPHID0 UARTPeriphID0 Register
0xfe4 UARTPERIPHID1 UARTPeriphID1 Register
0xfe8 UARTPERIPHID2 UARTPeriphID2 Register
0xfec UARTPERIPHID3 UARTPeriphID3 Register
0xff0 UARTPCELLID0 UARTPCellID0 Register
0xff4 UARTPCELLID1 UARTPCellID1 Register
0xff8 UARTPCELLID2 UARTPCellID2 Register
0xffc UARTPCELLID3 UARTPCellID3 Register
UART: UARTDR Register
Offset: 0x000
Description
Data Register, UARTDR
Table 1029. UARTDR
Register
Bits Description Type Reset
31:12 Reserved. - -
11 OE: Overrun error. This bit is set to 1 if data is received and the receive FIFO is
already full. This is cleared to 0 once there is an empty space in the FIFO and a
new character can be written to it.
RO -
10 BE: Break error. This bit is set to 1 if a break condition was detected, indicating
that the received data input was held LOW for longer than a full-word
transmission time (defined as start, data, parity and stop bits). In FIFO mode,
this error is associated with the character at the top of the FIFO. When a break
occurs, only one 0 character is loaded into the FIFO. The next character is only
enabled after the receive data input goes to a 1 (marking state), and the next
valid start bit is received.
RO -
9 PE: Parity error. When set to 1, it indicates that the parity of the received data
character does not match the parity that the EPS and SPS bits in the Line
Control Register, UARTLCR_H. In FIFO mode, this error is associated with the
character at the top of the FIFO.
RO -
RP2350 Datasheet
12.1. UART 973
Bits Description Type Reset
8 FE: Framing error. When set to 1, it indicates that the received character did
not have a valid stop bit (a valid stop bit is 1). In FIFO mode, this error is
associated with the character at the top of the FIFO.
RO -
7:0 DATA: Receive (read) data character. Transmit (write) data character. RWF -
UART: UARTRSR Register
Offset: 0x004
Description
Receive Status Register/Error Clear Register, UARTRSR/UARTECR
Table 1030. UARTRSR
Register
Bits Description Type Reset
31:4 Reserved. - -
3 OE: Overrun error. This bit is set to 1 if data is received and the FIFO is already
full. This bit is cleared to 0 by a write to UARTECR. The FIFO contents remain
valid because no more data is written when the FIFO is full, only the contents
of the shift register are overwritten. The CPU must now read the data, to
empty the FIFO.
WC 0x0
2 BE: Break error. This bit is set to 1 if a break condition was detected, indicating
that the received data input was held LOW for longer than a full-word
transmission time (defined as start, data, parity, and stop bits). This bit is
cleared to 0 after a write to UARTECR. In FIFO mode, this error is associated
with the character at the top of the FIFO. When a break occurs, only one 0
character is loaded into the FIFO. The next character is only enabled after the
receive data input goes to a 1 (marking state) and the next valid start bit is
received.
WC 0x0
1 PE: Parity error. When set to 1, it indicates that the parity of the received data
character does not match the parity that the EPS and SPS bits in the Line
Control Register, UARTLCR_H. This bit is cleared to 0 by a write to UARTECR.
In FIFO mode, this error is associated with the character at the top of the FIFO.
WC 0x0
0 FE: Framing error. When set to 1, it indicates that the received character did
not have a valid stop bit (a valid stop bit is 1). This bit is cleared to 0 by a write
to UARTECR. In FIFO mode, this error is associated with the character at the
top of the FIFO.
WC 0x0
UART: UARTFR Register
Offset: 0x018
Description
Flag Register, UARTFR
Table 1031. UARTFR
Register
Bits Description Type Reset
31:9 Reserved. - -
8 RI: Ring indicator. This bit is the complement of the UART ring indicator,
nUARTRI, modem status input. That is, the bit is 1 when nUARTRI is LOW.
RO -
RP2350 Datasheet
12.1. UART 974
Bits Description Type Reset
7 TXFE: Transmit FIFO empty. The meaning of this bit depends on the state of
the FEN bit in the Line Control Register, UARTLCR_H. If the FIFO is disabled,
this bit is set when the transmit holding register is empty. If the FIFO is
enabled, the TXFE bit is set when the transmit FIFO is empty. This bit does not
indicate if there is data in the transmit shift register.
RO 0x1
6 RXFF: Receive FIFO full. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the receive holding register is full. If the FIFO is enabled, the RXFF bit is set
when the receive FIFO is full.
RO 0x0
5 TXFF: Transmit FIFO full. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the transmit holding register is full. If the FIFO is enabled, the TXFF bit is set
when the transmit FIFO is full.
RO 0x0
4 RXFE: Receive FIFO empty. The meaning of this bit depends on the state of the
FEN bit in the UARTLCR_H Register. If the FIFO is disabled, this bit is set when
the receive holding register is empty. If the FIFO is enabled, the RXFE bit is set
when the receive FIFO is empty.
RO 0x1
3 BUSY: UART busy. If this bit is set to 1, the UART is busy transmitting data.
This bit remains set until the complete byte, including all the stop bits, has
been sent from the shift register. This bit is set as soon as the transmit FIFO
becomes non-empty, regardless of whether the UART is enabled or not.
RO 0x0
2 DCD: Data carrier detect. This bit is the complement of the UART data carrier
detect, nUARTDCD, modem status input. That is, the bit is 1 when nUARTDCD
is LOW.
RO -
1 DSR: Data set ready. This bit is the complement of the UART data set ready,
nUARTDSR, modem status input. That is, the bit is 1 when nUARTDSR is LOW.
RO -
0 CTS: Clear to send. This bit is the complement of the UART clear to send,
nUARTCTS, modem status input. That is, the bit is 1 when nUARTCTS is LOW.
RO -
UART: UARTILPR Register
Offset: 0x020
Description
IrDA Low-Power Counter Register, UARTILPR
Table 1032. UARTILPR
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 ILPDVSR: 8-bit low-power divisor value. These bits are cleared to 0 at reset. RW 0x00
UART: UARTIBRD Register
Offset: 0x024
Description
Integer Baud Rate Register, UARTIBRD
Table 1033. UARTIBRD
Register
Bits Description Type Reset
31:16 Reserved. - -
RP2350 Datasheet
12.1. UART 975
Bits Description Type Reset
15:0 BAUD_DIVINT: The integer baud rate divisor. These bits are cleared to 0 on
reset.
RW 0x0000
UART: UARTFBRD Register
Offset: 0x028
Description
Fractional Baud Rate Register, UARTFBRD
Table 1034.
UARTFBRD Register
Bits Description Type Reset
31:6 Reserved. - -
5:0 BAUD_DIVFRAC: The fractional baud rate divisor. These bits are cleared to 0
on reset.
RW 0x00
UART: UARTLCR_H Register
Offset: 0x02c
Description
Line Control Register, UARTLCR_H
Table 1035.
UARTLCR_H Register
Bits Description Type Reset
31:8 Reserved. - -
7 SPS: Stick parity select. 0 = stick parity is disabled 1 = either: * if the EPS bit is
0 then the parity bit is transmitted and checked as a 1 * if the EPS bit is 1 then
the parity bit is transmitted and checked as a 0. This bit has no effect when
the PEN bit disables parity checking and generation.
RW 0x0
6:5 WLEN: Word length. These bits indicate the number of data bits transmitted or
received in a frame as follows: b11 = 8 bits b10 = 7 bits b01 = 6 bits b00 = 5
bits.
RW 0x0
4 FEN: Enable FIFOs: 0 = FIFOs are disabled (character mode) that is, the FIFOs
become 1-byte-deep holding registers 1 = transmit and receive FIFO buffers
are enabled (FIFO mode).
RW 0x0
3 STP2: Two stop bits select. If this bit is set to 1, two stop bits are transmitted
at the end of the frame. The receive logic does not check for two stop bits
being received.
RW 0x0
2 EPS: Even parity select. Controls the type of parity the UART uses during
transmission and reception: 0 = odd parity. The UART generates or checks for
an odd number of 1s in the data and parity bits. 1 = even parity. The UART
generates or checks for an even number of 1s in the data and parity bits. This
bit has no effect when the PEN bit disables parity checking and generation.
RW 0x0
1 PEN: Parity enable: 0 = parity is disabled and no parity bit added to the data
frame 1 = parity checking and generation is enabled.
RW 0x0
0 BRK: Send break. If this bit is set to 1, a low-level is continually output on the
UARTTXD output, after completing transmission of the current character. For
the proper execution of the break command, the software must set this bit for
at least two complete frames. For normal use, this bit must be cleared to 0.
RW 0x0
UART: UARTCR Register
RP2350 Datasheet
12.1. UART 976
Offset: 0x030
Description
Control Register, UARTCR
Table 1036. UARTCR
Register
Bits Description Type Reset
31:16 Reserved. - -
15 CTSEN: CTS hardware flow control enable. If this bit is set to 1, CTS hardware
flow control is enabled. Data is only transmitted when the nUARTCTS signal is
asserted.
RW 0x0
14 RTSEN: RTS hardware flow control enable. If this bit is set to 1, RTS hardware
flow control is enabled. Data is only requested when there is space in the
receive FIFO for it to be received.
RW 0x0
13 OUT2: This bit is the complement of the UART Out2 (nUARTOut2) modem
status output. That is, when the bit is programmed to a 1, the output is 0. For
DTE this can be used as Ring Indicator (RI).
RW 0x0
12 OUT1: This bit is the complement of the UART Out1 (nUARTOut1) modem
status output. That is, when the bit is programmed to a 1 the output is 0. For
DTE this can be used as Data Carrier Detect (DCD).
RW 0x0
11 RTS: Request to send. This bit is the complement of the UART request to
send, nUARTRTS, modem status output. That is, when the bit is programmed
to a 1 then nUARTRTS is LOW.
RW 0x0
10 DTR: Data transmit ready. This bit is the complement of the UART data
transmit ready, nUARTDTR, modem status output. That is, when the bit is
programmed to a 1 then nUARTDTR is LOW.
RW 0x0
9 RXE: Receive enable. If this bit is set to 1, the receive section of the UART is
enabled. Data reception occurs for either UART signals or SIR signals
depending on the setting of the SIREN bit. When the UART is disabled in the
middle of reception, it completes the current character before stopping.
RW 0x1
8 TXE: Transmit enable. If this bit is set to 1, the transmit section of the UART is
enabled. Data transmission occurs for either UART signals, or SIR signals
depending on the setting of the SIREN bit. When the UART is disabled in the
middle of transmission, it completes the current character before stopping.
RW 0x1
7 LBE: Loopback enable. If this bit is set to 1 and the SIREN bit is set to 1 and
the SIRTEST bit in the Test Control Register, UARTTCR is set to 1, then the
nSIROUT path is inverted, and fed through to the SIRIN path. The SIRTEST bit
in the test register must be set to 1 to override the normal half-duplex SIR
operation. This must be the requirement for accessing the test registers
during normal operation, and SIRTEST must be cleared to 0 when loopback
testing is finished. This feature reduces the amount of external coupling
required during system test. If this bit is set to 1, and the SIRTEST bit is set to
0, the UARTTXD path is fed through to the UARTRXD path. In either SIR mode
or UART mode, when this bit is set, the modem outputs are also fed through to
the modem inputs. This bit is cleared to 0 on reset, to disable loopback.
RW 0x0
6:3 Reserved. - -
RP2350 Datasheet
12.1. UART 977
Bits Description Type Reset
2 SIRLP: SIR low-power IrDA mode. This bit selects the IrDA encoding mode. If
this bit is cleared to 0, low-level bits are transmitted as an active high pulse
with a width of 3 / 16th of the bit period. If this bit is set to 1, low-level bits are
transmitted with a pulse width that is 3 times the period of the IrLPBaud16
input signal, regardless of the selected bit rate. Setting this bit uses less
power, but might reduce transmission distances.
RW 0x0
1 SIREN: SIR enable: 0 = IrDA SIR ENDEC is disabled. nSIROUT remains LOW (no
light pulse generated), and signal transitions on SIRIN have no effect. 1 = IrDA
SIR ENDEC is enabled. Data is transmitted and received on nSIROUT and
SIRIN. UARTTXD remains HIGH, in the marking state. Signal transitions on
UARTRXD or modem status inputs have no effect. This bit has no effect if the
UARTEN bit disables the UART.
RW 0x0
0 UARTEN: UART enable: 0 = UART is disabled. If the UART is disabled in the
middle of transmission or reception, it completes the current character before
stopping. 1 = the UART is enabled. Data transmission and reception occurs for
either UART signals or SIR signals depending on the setting of the SIREN bit.
RW 0x0
UART: UARTIFLS Register
Offset: 0x034
Description
Interrupt FIFO Level Select Register, UARTIFLS
Table 1037. UARTIFLS
Register
Bits Description Type Reset
31:6 Reserved. - -
5:3 RXIFLSEL: Receive interrupt FIFO level select. The trigger points for the receive
interrupt are as follows: b000 = Receive FIFO becomes >= 1 / 8 full b001 =
Receive FIFO becomes >= 1 / 4 full b010 = Receive FIFO becomes >= 1 / 2 full
b011 = Receive FIFO becomes >= 3 / 4 full b100 = Receive FIFO becomes >= 7
/ 8 full b101-b111 = reserved.
RW 0x2
2:0 TXIFLSEL: Transmit interrupt FIFO level select. The trigger points for the
transmit interrupt are as follows: b000 = Transmit FIFO becomes <= 1 / 8 full
b001 = Transmit FIFO becomes <= 1 / 4 full b010 = Transmit FIFO becomes <=
1 / 2 full b011 = Transmit FIFO becomes <= 3 / 4 full b100 = Transmit FIFO
becomes <= 7 / 8 full b101-b111 = reserved.
RW 0x2
UART: UARTIMSC Register
Offset: 0x038
Description
Interrupt Mask Set/Clear Register, UARTIMSC
Table 1038.
UARTIMSC Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEIM: Overrun error interrupt mask. A read returns the current mask for the
UARTOEINTR interrupt. On a write of 1, the mask of the UARTOEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
RP2350 Datasheet
12.1. UART 978
Bits Description Type Reset
9 BEIM: Break error interrupt mask. A read returns the current mask for the
UARTBEINTR interrupt. On a write of 1, the mask of the UARTBEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
8 PEIM: Parity error interrupt mask. A read returns the current mask for the
UARTPEINTR interrupt. On a write of 1, the mask of the UARTPEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
7 FEIM: Framing error interrupt mask. A read returns the current mask for the
UARTFEINTR interrupt. On a write of 1, the mask of the UARTFEINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
6 RTIM: Receive timeout interrupt mask. A read returns the current mask for the
UARTRTINTR interrupt. On a write of 1, the mask of the UARTRTINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
5 TXIM: Transmit interrupt mask. A read returns the current mask for the
UARTTXINTR interrupt. On a write of 1, the mask of the UARTTXINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
4 RXIM: Receive interrupt mask. A read returns the current mask for the
UARTRXINTR interrupt. On a write of 1, the mask of the UARTRXINTR interrupt
is set. A write of 0 clears the mask.
RW 0x0
3 DSRMIM: nUARTDSR modem interrupt mask. A read returns the current mask
for the UARTDSRINTR interrupt. On a write of 1, the mask of the
UARTDSRINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
2 DCDMIM: nUARTDCD modem interrupt mask. A read returns the current mask
for the UARTDCDINTR interrupt. On a write of 1, the mask of the
UARTDCDINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
1 CTSMIM: nUARTCTS modem interrupt mask. A read returns the current mask
for the UARTCTSINTR interrupt. On a write of 1, the mask of the
UARTCTSINTR interrupt is set. A write of 0 clears the mask.
RW 0x0
0 RIMIM: nUARTRI modem interrupt mask. A read returns the current mask for
the UARTRIINTR interrupt. On a write of 1, the mask of the UARTRIINTR
interrupt is set. A write of 0 clears the mask.
RW 0x0
UART: UARTRIS Register
Offset: 0x03c
Description
Raw Interrupt Status Register, UARTRIS
Table 1039. UARTRIS
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OERIS: Overrun error interrupt status. Returns the raw interrupt state of the
UARTOEINTR interrupt.
RO 0x0
9 BERIS: Break error interrupt status. Returns the raw interrupt state of the
UARTBEINTR interrupt.
RO 0x0
8 PERIS: Parity error interrupt status. Returns the raw interrupt state of the
UARTPEINTR interrupt.
RO 0x0
RP2350 Datasheet
12.1. UART 979
Bits Description Type Reset
7 FERIS: Framing error interrupt status. Returns the raw interrupt state of the
UARTFEINTR interrupt.
RO 0x0
6 RTRIS: Receive timeout interrupt status. Returns the raw interrupt state of the
UARTRTINTR interrupt. a
RO 0x0
5 TXRIS: Transmit interrupt status. Returns the raw interrupt state of the
UARTTXINTR interrupt.
RO 0x0
4 RXRIS: Receive interrupt status. Returns the raw interrupt state of the
UARTRXINTR interrupt.
RO 0x0
3 DSRRMIS: nUARTDSR modem interrupt status. Returns the raw interrupt state
of the UARTDSRINTR interrupt.
RO -
2 DCDRMIS: nUARTDCD modem interrupt status. Returns the raw interrupt state
of the UARTDCDINTR interrupt.
RO -
1 CTSRMIS: nUARTCTS modem interrupt status. Returns the raw interrupt state
of the UARTCTSINTR interrupt.
RO -
0 RIRMIS: nUARTRI modem interrupt status. Returns the raw interrupt state of
the UARTRIINTR interrupt.
RO -
UART: UARTMIS Register
Offset: 0x040
Description
Masked Interrupt Status Register, UARTMIS
Table 1040. UARTMIS
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEMIS: Overrun error masked interrupt status. Returns the masked interrupt
state of the UARTOEINTR interrupt.
RO 0x0
9 BEMIS: Break error masked interrupt status. Returns the masked interrupt
state of the UARTBEINTR interrupt.
RO 0x0
8 PEMIS: Parity error masked interrupt status. Returns the masked interrupt
state of the UARTPEINTR interrupt.
RO 0x0
7 FEMIS: Framing error masked interrupt status. Returns the masked interrupt
state of the UARTFEINTR interrupt.
RO 0x0
6 RTMIS: Receive timeout masked interrupt status. Returns the masked
interrupt state of the UARTRTINTR interrupt.
RO 0x0
5 TXMIS: Transmit masked interrupt status. Returns the masked interrupt state
of the UARTTXINTR interrupt.
RO 0x0
4 RXMIS: Receive masked interrupt status. Returns the masked interrupt state
of the UARTRXINTR interrupt.
RO 0x0
3 DSRMMIS: nUARTDSR modem masked interrupt status. Returns the masked
interrupt state of the UARTDSRINTR interrupt.
RO -
2 DCDMMIS: nUARTDCD modem masked interrupt status. Returns the masked
interrupt state of the UARTDCDINTR interrupt.
RO -
RP2350 Datasheet
12.1. UART 980
Bits Description Type Reset
1 CTSMMIS: nUARTCTS modem masked interrupt status. Returns the masked
interrupt state of the UARTCTSINTR interrupt.
RO -
0 RIMMIS: nUARTRI modem masked interrupt status. Returns the masked
interrupt state of the UARTRIINTR interrupt.
RO -
UART: UARTICR Register
Offset: 0x044
Description
Interrupt Clear Register, UARTICR
Table 1041. UARTICR
Register
Bits Description Type Reset
31:11 Reserved. - -
10 OEIC: Overrun error interrupt clear. Clears the UARTOEINTR interrupt. WC -
9 BEIC: Break error interrupt clear. Clears the UARTBEINTR interrupt. WC -
8 PEIC: Parity error interrupt clear. Clears the UARTPEINTR interrupt. WC -
7 FEIC: Framing error interrupt clear. Clears the UARTFEINTR interrupt. WC -
6 RTIC: Receive timeout interrupt clear. Clears the UARTRTINTR interrupt. WC -
5 TXIC: Transmit interrupt clear. Clears the UARTTXINTR interrupt. WC -
4 RXIC: Receive interrupt clear. Clears the UARTRXINTR interrupt. WC -
3 DSRMIC: nUARTDSR modem interrupt clear. Clears the UARTDSRINTR
interrupt.
WC -
2 DCDMIC: nUARTDCD modem interrupt clear. Clears the UARTDCDINTR
interrupt.
WC -
1 CTSMIC: nUARTCTS modem interrupt clear. Clears the UARTCTSINTR
interrupt.
WC -
0 RIMIC: nUARTRI modem interrupt clear. Clears the UARTRIINTR interrupt. WC -
UART: UARTDMACR Register
Offset: 0x048
Description
DMA Control Register, UARTDMACR
Table 1042.
UARTDMACR Register
Bits Description Type Reset
31:3 Reserved. - -
2 DMAONERR: DMA on error. If this bit is set to 1, the DMA receive request
outputs, UARTRXDMASREQ or UARTRXDMABREQ, are disabled when the
UART error interrupt is asserted.
RW 0x0
1 TXDMAE: Transmit DMA enable. If this bit is set to 1, DMA for the transmit
FIFO is enabled.
RW 0x0
0 RXDMAE: Receive DMA enable. If this bit is set to 1, DMA for the receive FIFO
is enabled.
RW 0x0
RP2350 Datasheet
12.1. UART 981
UART: UARTPERIPHID0 Register
Offset: 0xfe0
Description
UARTPeriphID0 Register
Table 1043.
UARTPERIPHID0
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 PARTNUMBER0: These bits read back as 0x11 RO 0x11
UART: UARTPERIPHID1 Register
Offset: 0xfe4
Description
UARTPeriphID1 Register
Table 1044.
UARTPERIPHID1
Register
Bits Description Type Reset
31:8 Reserved. - -
7:4 DESIGNER0: These bits read back as 0x1 RO 0x1
3:0 PARTNUMBER1: These bits read back as 0x0 RO 0x0
UART: UARTPERIPHID2 Register
Offset: 0xfe8
Description
UARTPeriphID2 Register
Table 1045.
UARTPERIPHID2
Register
Bits Description Type Reset
31:8 Reserved. - -
7:4 REVISION: This field depends on the revision of the UART: r1p0 0x0 r1p1 0x1
r1p3 0x2 r1p4 0x2 r1p5 0x3
RO 0x3
3:0 DESIGNER1: These bits read back as 0x4 RO 0x4
UART: UARTPERIPHID3 Register
Offset: 0xfec
Description
UARTPeriphID3 Register
Table 1046.
UARTPERIPHID3
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 CONFIGURATION: These bits read back as 0x00 RO 0x00
UART: UARTPCELLID0 Register
Offset: 0xff0
Description
UARTPCellID0 Register
RP2350 Datasheet
12.1. UART 982
Table 1047.
UARTPCELLID0
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID0: These bits read back as 0x0D RO 0x0d
UART: UARTPCELLID1 Register
Offset: 0xff4
Description
UARTPCellID1 Register
Table 1048.
UARTPCELLID1
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID1: These bits read back as 0xF0 RO 0xf0
UART: UARTPCELLID2 Register
Offset: 0xff8
Description
UARTPCellID2 Register
Table 1049.
UARTPCELLID2
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID2: These bits read back as 0x05 RO 0x05
UART: UARTPCELLID3 Register
Offset: 0xffc
Description
UARTPCellID3 Register
Table 1050.
UARTPCELLID3
Register
Bits Description Type Reset
31:8 Reserved. - -
7:0 UARTPCELLID3: These bits read back as 0xB1 RO 0xb1
12.6. DMA
The RP2350 Direct Memory Access (DMA) controller performs bulk data transfers on a processors behalf. This leaves
processors free to attend to other tasks or enter low-power sleep states. The DMA dual bus manager ports can issue
one read and one write access per cycle. The data throughput is therefore far greater than one of RP2350s processors.
RP2350 Datasheet
12.6. DMA 1094
Control/Status
Registers
Read Address FIFO
Write Address FIFO
Address Generator
AHB5
Read Manager
From
System
Transfer Data FIFO
AHB5
Write Manager
To
System
AHB5
Subordinate
Interface
Figure 122. DMA
Architecture Overview.
The read manager can
read data from some
address every clock
cycle. Likewise, the
write manager can
write to another
address. The address
generator produces
matched pairs of read
and write addresses,
which the managers
consume through the
address FIFOs. The
DMA can run up to 16
transfer sequences
simultaneously,
supervised by
software via the
control and status
registers.
The DMA can perform one read access and one write access, up to 32 bits in size, every clock cycle. There are 16
independent channels, each of which supervises a sequence of bus transfers in one of the following scenarios:
Memory-to-peripheral
a peripheral signals the DMA when it needs more data to transmit. The DMA reads data from an array in RAM or
flash, and writes to the peripherals data FIFO.
Peripheral-to-memory
a peripheral signals the DMA when it has received data. The DMA reads this data from the peripherals data FIFO,
and writes it to an array in RAM.
Memory-to-memory
the DMA transfers data between two buffers in RAM, as fast as possible.
Each channel has its own control and status registers (CSRs) that software can use to program and monitor the
channels progress. When multiple channels are active at the same time, the DMA shares bandwidth evenly between the
channels, with round-robin over all channels that are currently requesting data transfers.
The transfer size can be either 32, 16, or 8 bits. This is configured once for each channel: source transfer size and
destination transfer size are the same. The DMA performs byte lane replication on narrow writes, so byte data is
available in all 4 bytes of the databus, and halfword data in both halfwords.
Channels can be combined in varied ways for more sophisticated behaviour and greater autonomy. For example, one
channel can configure another, loading configuration data from a sequence of control blocks in memory, and the
second can then call back to the first via the CHAIN_TO option when it needs to be reconfigured.
Making the DMA more autonomous means that much less processor supervision is required: overall this allows the
system to do more at once, or to dissipate less power.
12.6.1. Changes from RP2040
The following new features have been added:
• Increased the number of DMA channels from 12 to 16.
• Increased the number of shared IRQ outputs from 2 to 4.
• Channels can be assigned to security domains using SECCFG_CH0 through SECCFG_CH15.
• The DMA now filters bus accesses using the built-in memory protection unit (Section 12.6.6.3).
• Interrupts can be assigned to security domains using SECCFG_IRQ0 through SECCFG_IRQ3.
• Pacing timers and the CRC sniffer can be assigned to security domains using the SECCFG_MISC register.
• The four most-significant bits of TRANS_COUNT (CH0_TRANS_COUNT) are redefined as the MODE field, which defines
what happens when TRANS_COUNT reaches zero:
RP2350 Datasheet
12.6. DMA 1095
This backward-incompatible change reduces the maximum transfers in one sequence from 232-1 to 228-1.
◦ Mode 0x0 has the same behaviour as RP2040, so there is no need to modify software that performs less than
256 million transfers at a time.
◦ Mode 0x1, "trigger self", allows a channel to automatically restart itself after finishing a transfer sequence, in
addition to the usual end-of-sequence actions like raising an interrupt or triggering other channels. This can
be used for example to get periodic interrupts from streaming ring buffer transfers.
◦ Mode 0xf, "endless", allows a channel to run forever: TRANS_COUNT does not decrement.
• New CH0_CTRL_TRIG.INCR_READ_REV and CH0_CTRL_TRIG.INCR_WRITE_REV fields allow addresses to
decrement rather than increment, or to increment by two.
Some existing fields in the CTRL registers, such as CH0_CTRL_TRIG.BUSY, have moved to accommodate the
new fields.
Some existing behaviour has been refined:
• The logic that adjusts values read from WRITE_ADDR and READ_ADDR according to the number of in-flight transfers is
disabled for address-wrapping and non-incrementing transfers (erratum RP2040-E12).
• You can now poll the ABORT register to wait for completion of an aborted channel (erratum RP2040-E13).
• DMA completion actions such as CHAIN_TO are now strictly ordered against the last write completion, so a CHAIN_TO
on a channel whose registers you write to is a well-defined operation.
This enables the use of control blocks that dont include one of the four trigger register aliases.
Previously, a channel was considered to complete on the first cycle of its last writes data phase. Now, a
channel is considered to complete on the last cycle of its last writes data phase. This is usually the same
cycle, but it can be later when the DMA encounters a write data-phase bus stall.
• Previously, the DMAs internal arbitration logic inserted an idle cycle after completing a round of active high-priority
channels (CH0_CTRL_TRIG.HIGH_PRIORITY), even if there were no active low-priority requests. This reduced DMA
throughput when lightly loaded. This idle cycle has been removed, eliminating lost throughput.
• IRQ assertion latency has been reduced by one cycle.
12.6.2. Configuring channels
Each channel has four control/status registers:
• READ_ADDR (CH0_READ_ADDR) is the address of the next memory location to read.
• WRITE_ADDR (CH0_WRITE_ADDR) is the address of the next memory location to write.
• TRANS_COUNT (CH0_TRANS_COUNT) shows the number of transfers remaining in the current transfer sequence and
programs the number of transfers in the next transfer sequence (see Section 12.6.2.2).
• CTRL (CH0_CTRL_TRIG) configures all other aspects of the channels behaviour, enables/disables the channel, and
provides completion status.
To directly instruct the DMA channel to perform a data transfer, software writes to these four registers, and then
triggers the channel (Section 12.6.3). To make the DMA more autonomous, you can also program one DMA channel to
write to another channels configuration registers, queueing up many transfer sequences in advance.
All four are live registers; they update their status continuously as the channel progresses.
12.6.2.1. Read and write addresses
READ_ADDR and WRITE_ADDR contain the address the channel will next read from, and write to, respectively. These registers
update automatically after each read/write access, incrementing to the next read/write address as required. The size of
the increment varies according to:
RP2350 Datasheet
12.6. DMA 1096
• the transfer size: 1, 2 or 4 byte bus accesses as per CH0_CTRL_TRIG.DATA_SIZE
• the increment enable for each address register: CH0_CTRL_TRIG.INCR_READ and CH0_CTRL_TRIG.INCR_WRITE
• the increment direction: CH0_CTRL_TRIG.INCR_READ_REV and CH0_CTRL_TRIG.INCR_WRITE_REV
Software should generally program these registers with new start addresses each time a new transfer sequence starts.
If READ_ADDR and WRITE_ADDR are not reprogrammed, the DMA will use the current values as start addresses for the next
transfer. For example:
• If the address does not increment (e.g. it is the address of a peripheral FIFO), and the next transfer sequence is
to/from that same address, there is no need to write to the register again.
• When transferring to/from a consecutive series of buffers in memory (e.g. scattering and gathering), an address
register will already have incremented to the start of the next buffer at the completion of a transfer.
By not programming all four CSRs for each transfer sequence, software can use shorter interrupt handlers, and more
compact control block formats when used with channel chaining (see register aliases in Section 12.6.3.1, chaining in
Section 12.6.3.2).
12.6.2.1.1. Address alignment
READ_ADDR and WRITE_ADDR must be aligned to the transfer size, specified in CH0_CTRL_TRIG.DATA_SIZE. For 32-bit
transfers, the address must be a multiple of four, and for 16-bit transfers, the address must be a multiple of two.
Software is responsible for correctly aligning addresses written to READ_ADDR and WRITE_ADDR: the DMA does not enforce
alignment.
If software initially writes a correctly aligned address, the address will remain correctly aligned throughout the transfer
sequence, because the DMA always increments READ_ADDR and WRITE_ADDR by a multiple of the transfer size. Specifically, it
increments by transfer size times -1, 0, 1 or 2, depending on the values of CH0_CTRL_TRIG.INCR_READ,
CH0_CTRL_TRIG.INCR_WRITE, CH0_CTRL_TRIG.INCR_READ_REV and CH0_CTRL_TRIG.INCR_WRITE_REV.
The DMA MPU and system-level bus security filters perform protection checks on the lowest byte address of all bytes
transferred on a given cycle (i.e. to the present value of READ_ADDR/WRITE_ADDR). RP2350 memory hardware ensures
unaligned bus accesses do not cause data to be read/written from the other side of a protection boundary. This means
that unaligned access can not be used to violate the memory protection model. Other than this, the result of an
unaligned access is unspecified.
12.6.2.2. Transfer count
Reading TRANS_COUNT (CH0_TRANS_COUNT) returns the number of transfers remaining in the current transfer sequence.
This value updates continuously as the channel progresses. Writing to TRANS_COUNT sets the length of the next transfer
sequence. Up to 228-1 transfers can be performed in one sequence (0x0fffffff, approximately 256 million).
Each time the channel starts a new transfer sequence, the most recent value written to TRANS_COUNT is copied to the live
transfer counter, which will then start to decrement again as the new transfer sequence makes progress. For debugging
purposes, the DBG_TCR (TRANS_COUNT reload value) registers display the last value written to each channels TRANS_COUNT.
If the channel is triggered multiple times without intervening writes to TRANS_COUNT, it performs the same number of
transfers each time. For example, when chained to, one channel might load a fixed-size control block into another
channels CSRs. TRANS_COUNT would be programmed once by software, and then reload automatically every time.
Alternatively, TRANS_COUNT can be written with a new value before starting each transfer sequence. If TRANS_COUNT is the
channel trigger (see Section 12.6.3.1), the channel will start immediately, and the value just written will be used, not the
value currently in the reload register.
RP2350 Datasheet
12.6. DMA 1097
 NOTE
The TRANS_COUNT is the number of transfers to be performed. The total number of bytes transferred is TRANS_COUNT
times the size of each transfer in bytes, given by CTRL.DATA_SIZE.
12.6.2.2.1. Count modes
The four most-significant bits of TRANS_COUNT contain the MODE field (CH0_TRANS_COUNT.MODE), which modifies the
counting behaviour of TRANS_COUNT. Mode 0x0 is the default: TRANS_COUNT decrements once for every bus transfer, and the
channel halts once TRANS_COUNT reaches zero and all in-flight transfers have finished. The value of 0x0 is chosen for
backward-compatibility with RP2040 software, which expects the TRANS_COUNT register to contain a 32-bit count rather
than a 4-bit mode and a 28-bit count. There are few use cases for a finite number of transfers greater than 228, which is
why the four most-significant bits have been reallocated for use with endless transfers.
Mode 0x1, TRIGGER_SELF, behaves the same as mode 0x0, except that rather than halting upon completion, the channel
immediately re-triggers itself. This is equivalent to a trigger performed by any other mechanism (Section 12.6.3):
TRANS_COUNT is reloaded, and the channel resumes from the current READ_ADDR and WRITE_ADDR addresses. A completion
interrupt is still raised (if CTRL.IRQ_QUIET is not set) and the specified CHAIN_TO operation is still performed. The main use
for this mode is streaming through SRAM ring buffers, where some action is required at regular intervals, for example
requesting the processor to refill an audio buffer once it is half-empty.
Mode 0xf, ENDLESS, disables the decrement of TRANS_COUNT. This means a channel will generally run indefinitely without
pause, though triggering a channel with a mode of 0xf and a count of 0x0 will result in the channel halting immediately.
All other values are reserved for future use and their effect is unspecified.
12.6.2.3. Control/Status
The CTRL register (CH0_CTRL_TRIG) has more, smaller fields than the other 3 registers. Among other things, CTRL is used
to:
• Configure the size of this channels data transfers through the DATA_SIZE field. Reads are always the same size as
writes.
• Configure if and how READ_ADDR and WRITE_ADDR increment after each read or write through the INCR_READ,
INCR_READ_REV, INCR_WRITE, INCR_WRITE_REV, RING_SEL, and RING_SIZE fields. Ring transfers are available, where one of the
address pointers wraps at some power-of-2 boundary.
• Select another channel (or none) to trigger when this channel completes through the CHAIN_TO field.
• Select a peripheral data request (DREQ) signal to pace this channels transfers, via the TREQ_SEL field.
• See when the channel is idle, using the BUSY flag.
• See if the channel has encountered a bus error in the READ_ERROR and WRITE_ERROR flags, or the combined error status
in the AHB_ERROR flag.
12.6.3. Triggering channels
After a channel has been correctly configured, you must trigger it. This instructs the channel to begin scheduling bus
accesses, either paced by a peripheral data request signal (DREQ) or as fast as possible. The following events can
trigger a channel:
• A write to a channel trigger register.
• Completion of another channel whose CHAIN_TO points to this channel.
• A write to the MULTI_CHAN_TRIGGER register (can trigger multiple channels at once).
Each trigger mechanism covers different use cases. For example, trigger registers are simple and efficient when
RP2350 Datasheet
12.6. DMA 1098
configuring and starting a channel in an interrupt service routine because the channel is triggered by the last
configuration write. CHAIN_TO allows one channel to callback to another channel, which can then reconfigure the first
channel. MULTI_CHAN_TRIGGER allows software to simply start a channel without touching any of its configuration
registers.
When triggered, the channel sets its CTRL.BUSY flag to indicate it is actively scheduling transfers. This remains set until
the transfer count reaches zero, or the channel is aborted via the CHAN_ABORT register (Section 12.6.8.3).
When a channel is already running, indicated by BUSY = 1, it ignores additional triggers. A channel that is disabled (CTRL.EN
is clear) also ignores triggers.
12.6.3.1. Aliases and triggers
Table 1145. Control
register aliases. Each
channel has four
control/status
registers. Each
register can be
accessed at multiple
different addresses. In
each naturally-aligned
group of four, all four
registers appear, in
different orders.
Offset +0x0 +0x4 +0x8 +0xc (Trigger)
0x00 (Alias 0) READ_ADDR WRITE_ADDR TRANS_COUNT CTRL_TRIG
0x10 (Alias 1) CTRL READ_ADDR WRITE_ADDR TRANS_COUNT_TRIG
0x20 (Alias 2) CTRL TRANS_COUNT READ_ADDR WRITE_ADDR_TRIG
0x30 (Alias 3) CTRL WRITE_ADDR TRANS_COUNT READ_ADD_TRIG
The four CSRs are aliased multiple times in memory. Each of the four aliases exposes the same four physical registers,
but in a different order. The final register in each alias (at offset +0xc, highlighted) is a trigger register. Writing to the
trigger register starts the channel.
Often, only alias 0 is used, and aliases 1 through 3 can be ignored. To configure and start the channel, write READ_ADDR,
WRITE_ADDR, TRANS_COUNT, and finally CTRL. Since CTRL is the trigger register in alias 0, this starts the channel.
The other aliases allow more compact control block lists when using one channel to configure another, and more
efficient reconfiguration and launch in interrupt handlers:
• Each CSR is a trigger register in one of the aliases:
◦ When gathering fixed-size buffers into a peripheral, the DMA channel can be configured and launched by
writing only READ_ADDR_TRIG.
◦ When scattering from a peripheral to fixed-size buffers, the channel can be configured and launched by
writing only WRITE_ADDR_TRIG.
• Useful combinations of registers appear as naturally-aligned tuples which contain a trigger register. In conjunction
with channel chaining and address wrapping, these implement compressed control block formats, e.g.:
(WRITE_ADDR, TRANS_COUNT_TRIG) for peripheral scatter operations
(TRANS_COUNT, READ_ADDR_TRIG) for peripheral gather operations, or calculating CRCs on a list of buffers
(READ_ADDR, WRITE_ADDR_TRIG) for manipulating fixed-size buffers in memory
Trigger registers do not start the channel if:
• The channel is disabled via CTRL.EN (if the trigger is CTRL, the just-written value of EN is used, not the value currently
in the CTRL register)
• The channel is already running
• The value 0 is written to the trigger register (useful for ending control block chains, see null triggers (Section
12.6.3.3))
• The bus access has a security level lower than the channels security level (Section 12.6.6.1)
RP2350 Datasheet
12.6. DMA 1099
12.6.3.2. Chaining
When a channel completes, it can name a different channel to immediately be triggered. This can be used as a callback
for the second channel to reconfigure and restart the first.
This feature is configured through the CHAIN_TO field in the channel CTRL register. This 4-bit value selects a channel that
will start when this one finishes. A channel cannot chain to itself. Setting CHAIN_TO to a channels own index prevents
chaining.
Chain triggers behave the same as triggers from other sources, such as trigger registers. For example, they cause
TRANS_COUNT to reload, and they are ignored if the targeted channel is already running.
One application for CHAIN_TO is for a channel to request reconfiguration by another channel from a sequence of control
blocks in memory. Channel A is configured to perform a wrapped transfer from memory to channel Bs control registers
(including a trigger register), and channel B is configured to chain back to channel A when it completes each transfer
sequence. This is shown explicitly in the DMA control blocks example (Section 12.6.9.2).
Use of the register aliases (Section 12.6.3.1) enables compact formats for DMA control blocks: as little as one word, in
some cases.
Another use of chaining is a ping-pong configuration, where two channels each trigger one another. The processor can
respond to the channel completion interrupts and reconfigure each channel after it completes. However, the chained
channel, which has already been configured, starts immediately. In other words, channel configuration and channel
operation are pipelined. This can improve performance dramatically when a usage pattern requires many short transfer
sequences.
The Section 12.6.9 goes into more detail on the possibilities of chain triggers in the real world.
12.6.3.3. Null triggers and chain interrupts
As mentioned in Section 12.6.3.1, writing all-zeroes to a trigger register does not start the channel. This is called a null
trigger, and it has two purposes:
• Cause a halt at the end of an array of control blocks, by appending an all-zeroes block.
• Reduce the number of interrupts generated when using control blocks.
By default, channels generate an interrupt each time they finish a transfer sequence, unless that channels IRQ is
masked in INTE0 through INTE3. The rate of interrupts can be excessive, particularly as processor attention is generally
not required while a sequence of control blocks are in progress. However, processor attention is required at the end of a
chain.
The channel CTRL register has a field called IRQ_QUIET. Its default value is 0. When this set to 1, channels generate an
interrupt when they receive a null trigger, but not on normal completion of a transfer sequence. The interrupt is
generated by the channel that receives the trigger.
12.6.4. Data request (DREQ)
Peripherals produce or consume data at their own pace. If the DMA transferred data as fast as possible, loss or
corruption of data would ensue. DREQs are a communication channel between peripherals and the DMA that enables
the DMA to pace transfers according to the needs of the peripheral.
The CTRL.TREQ_SEL (transfer request) field selects an external DREQ. It can also be used to select one of the internal
pacing timers, or select no TREQ at all (the transfer proceeds as fast as possible), e.g. for memory-to-memory transfers.
12.6.4.1. System DREQ table
DREQ numbers use the following global assignment to peripheral DREQ channels:
RP2350 Datasheet
12.6. DMA 1100
Table 1146. DREQs DREQ DREQ Channel DREQ DREQ Channel DREQ DREQ Channel DREQ DREQ Channel
0 DREQ_PIO0_TX0 14 DREQ_PIO1_RX2 28 DREQ_UART0_TX 42 DREQ_PWM_WRAP10
1 DREQ_PIO0_TX1 15 DREQ_PIO1_RX3 29 DREQ_UART0_RX 43 DREQ_PWM_WRAP11
2 DREQ_PIO0_TX2 16 DREQ_PIO2_TX0 30 DREQ_UART1_TX 44 DREQ_I2C0_TX
3 DREQ_PIO0_TX3 17 DREQ_PIO2_TX1 31 DREQ_UART1_RX 45 DREQ_I2C0_RX
4 DREQ_PIO0_RX0 18 DREQ_PIO2_TX2 32 DREQ_PWM_WRAP0 46 DREQ_I2C1_TX
5 DREQ_PIO0_RX1 19 DREQ_PIO2_TX3 33 DREQ_PWM_WRAP1 47 DREQ_I2C1_RX
6 DREQ_PIO0_RX2 20 DREQ_PIO2_RX0 34 DREQ_PWM_WRAP2 48 DREQ_ADC
7 DREQ_PIO0_RX3 21 DREQ_PIO2_RX1 35 DREQ_PWM_WRAP3 49 DREQ_XIP_STREAM
8 DREQ_PIO1_TX0 22 DREQ_PIO2_RX2 36 DREQ_PWM_WRAP4 50 DREQ_XIP_QMITX
9 DREQ_PIO1_TX1 23 DREQ_PIO2_RX3 37 DREQ_PWM_WRAP5 51 DREQ_XIP_QMIRX
10 DREQ_PIO1_TX2 24 DREQ_SPI0_TX 38 DREQ_PWM_WRAP6 52 DREQ_HSTX
11 DREQ_PIO1_TX3 25 DREQ_SPI0_RX 39 DREQ_PWM_WRAP7 53 DREQ_CORESIGHT
12 DREQ_PIO1_RX0 26 DREQ_SPI1_TX 40 DREQ_PWM_WRAP8 54 DREQ_SHA256
13 DREQ_PIO1_RX1 27 DREQ_SPI1_RX 41 DREQ_PWM_WRAP9
12.6.4.2. Credit-based DREQ Scheme
The RP2350 DMA is designed for systems where:
• The area and power cost of large peripheral data FIFOs is prohibitive.
• The bandwidth demands of individual peripherals can be high, for example, >50% bus injection rate for short
periods.
• Bus latency is low, but multiple managers can compete for bus access.
In addition, the DMAs transfer FIFOs and dual-manager-port structure permit multiple accesses to the same peripheral
to be in-flight at once to improve throughput. Choice of DREQ mechanism is therefore critical:
• The traditional "turn on the tap" method can cause overflow if multiple writes are backed up in the TDF. Some
systems solve this by over-provisioning peripheral FIFOs and setting the DREQ threshold below the full level at the
expense of precious area and power.
• The Arm-style single and burst handshake does not permit additional requests to be registered while the current
request is being served. This limits performance when FIFOs are very shallow.
The RP2350 DMA uses a credit-based DREQ mechanism. For each peripheral, the DMA attempts to keep as many
transfers in-flight as the peripheral has capacity for. This enables full bus throughput (1 word per clock) through an 8-
deep peripheral FIFO with no possibility of overflow or underflow in the absence of fabric latency or contention.
For each channel, the DMA maintains a counter. Each 1-clock pulse on the dreq signal increments this counter. When
non-zero, the channel requests a transfer from the DMAs internal arbiter. The counter decrements when the transfer is
issued to the address FIFOs. At this point the transfer is in flight, but has not yet necessarily completed.
The counter is saturating, and six bits in size. The counter ignores increments at the maximum value or decrements at
zero. The six-bit counter size supports counts up to the depth of any FIFO on RP2350.
RP2350 Datasheet
12.6. DMA 1101
clk
0 1 0 1 2
dreq
chan count
chan issue
1
Figure 123. DREQ
counting
The effect is to upper bound the number of in-flight transfers based on the amount of room or data available in the
peripheral FIFO. In the steady state, this gives maximum throughput, but cant underflow or underflow. This approach
has the following caveats:
• The user must not access a FIFO currently being serviced by the DMA. This causes the channel and peripheral to
become desynchronised, and can cause corruption or loss of data.
• Multiple channels must not be connected to the same DREQ.
12.6.5. Interrupts
Each channel can generate interrupts; these can be masked on a per-channel basis using one of the four identical
interrupt enable registers, INTE0 through INTE3. There are three circumstances where a channel raises an interrupt
request:
• On the completion of each transfer sequence, if CTRL.IRQ_QUIET is disabled
• On receiving a null trigger, if CTRL.IRQ_QUIET is enabled
• On a read or write bus error
The masked interrupt status is visible in the INTS registers; there is one bit for each channel. Interrupts are cleared by
writing a bit mask to INTS. One idiom for acknowledging interrupts is to read INTS, then write the same value back, so
only enabled interrupts are cleared.
The RP2350 DMA provides four system IRQs, with independent masking and status registers (e.g. INTE0, INTE1). Any
combination of channel interrupt requests can be routed to each system IRQ, though generally software only routes
each channel interrupt to a single system IRQ. For example:
• Some channels can be given a higher priority in the system interrupt controller, if they have particularly tight timing
requirements.
• In multiprocessor systems, different channel interrupts can be routed independently to different cores.
• When channels are assigned to a mixture of security domains, IRQs can also be assigned, so that software in each
security domain can get interrupts from its own channels.
For debugging purposes, the INTF registers can force any channel interrupt to be asserted, which will cause assertion of
any system IRQs that have that channel interrupts enable bit set in their respective INTE registers.
12.6.6. Security
RP2350s processors support partitioning of memory and peripherals into multiple security domains. This partitioning is
extended into the DMA, so that different security contexts can safely use their assigned channels without breaking any
of the security invariants laid out by the processor security model. For example, an Arm processor in the Non-secure
state must not be able to use the DMA to access memory or peripherals owned by Secure software.
The DMA defines four security levels that map onto Arm or RISC-V processor security states:
• 3: SP (secure and privileged)
Equivalent to Arm processors in the Secure, Privileged state
Equivalent to RISC-V processors in Machine mode
• 2: SU (secure and unprivileged)
RP2350 Datasheet
12.6. DMA 1102
Equivalent to Arm processors in the Secure, Normal state
• 1: NSP (nonsecure and privileged)
Equivalent to Arm processors in the Non-secure, Privileged state
Equivalent to RISC-V processors in Supervisor mode
• 0: NSU (nonsecure and unprivileged)
Equivalent to Arm processors in the Non-secure, Normal state
Equivalent to RISC-V processors in User mode
So that the DMA can compare different security levels in a consistent way, they are considered ordered, with SP > SU >
NSP > NSU. For example, when we say that a channel requires a minimum of SU to access its registers, this means that
SP and SU are acceptable, and NSP and NSU are not. As a rule, every action has a reaction that is at or below the
security level of the original action, and so the DMA can not be used to escalate accesses to a higher security level.
Software assigns internal DMA resources, like channels, interrupts, pacing timers and the CRC sniffer, to one of the four
possible security levels. These resources are then accessible only at and above that level. Channel assignment in
particular is discussed in Section 12.6.6.1.
The DMA memory protection unit (Section 12.6.6.3) defines the minimum security level required to access up to eight
programmable address ranges, so that channels of a given security level can not access memory beyond their means.
This MPU is intended to mirror the SRAM and XIP memory protection boundaries configured in the processor SAU or
PMP. In addition to the internal filtering performed by the DMA MPU, accesses are filtered by the system bus according
to the ACCESSCTRL filter rules described in Section 10.6.2.
The combination of these features allows the DMA to be safely shared by software running in different security
domains. If this is not desired, the entire DMA block can instead be assigned wholesale to a single security domain
using the ACCESSCTRL DMA register.
12.6.6.1. Channel security assignment
Channels are assigned to security domains using the channel SECCFG registers, SECCFG_CH0 through SECCFG_CH15.
There is one register per channel. Each register contains a 2-bit security level, and a lock bit that prevents that SECCFG
register from being changed once configured. At reset, all channels are assigned to the SP security level, which is the
highest.
The security level of a channel defines:
• The security level of bus transfers performed by this channel, which is checked against both the DMA memory
protection unit and the ACCESSCTRL bus-level filters described in Section 10.6.2.
• The minimum security level required to read or write this channels registers; access from a lower level returns a
bus fault.
• The minimum security level that must be defined on a shared IRQ line for that IRQ to be able to observe this
channels interrupts (Section 12.6.6.2), or for this channels interrupt to be set/cleared through that IRQs registers.
• The minimum bus security level required to clear this channels interrupts through the INTR register.
• Which DREQs a channel can observe: channels assigned to the NSP or NSU security levels can not observe DREQs
of Secure-only peripherals (as defined by the ACCESSCTRL peripheral configuration).
• Which pacing timer TREQs can be observed; pacing timer security levels are configured by SECCFG_MISC and
must be no higher than the channel security level for the channel in order to observe the TREQ.
• Whether the channel is visible to the CRC sniffer; the sniffers security level is configured by SECCFG_MISC and
must be no lower than the observed channels security level.
• Which channels this channel can trigger with a CHAIN_TO; chaining from lower to higher security levels is not
permitted.
RP2350 Datasheet
12.6. DMA 1103
• The minimum bus security level required to trigger this channel with a write to MULTI_CHAN_TRIGGER.
The channel SECCFG registers require privileged writes (SP/NSP), and will generate a bus fault on an attempted
unprivileged write (SU/NSU). Additionally, the S bit (MSB of the security level) and the LOCK bit are writable only by SP,
whilst the P bit (LSB of the security level) is also writable by NSP, if and only if the S bit is clear. Reads are always
allowed: it is always possible to query which channels are assigned to you by reading the channel SECCFG registers.
Each channel SECCFG register can be locked manually by writing a one to the LOCK bit in that register, and will also lock
automatically upon a successful write to one of the channels control registers such as CH0_CTRL_TRIG. This
automatic locking avoids any race conditions that can arise from a channels security level changing after it has already
started making transfers, or from leaking secure pointers that have been written to its control registers. After a channel
SECCFG register has been locked, it becomes read-only. LOCK bits can be cleared only by a full reset of the DMA block.
SECCFG registers can be written multiple times before being locked, so the full assignment does not have to be known up
front: for example, Secure Arm software can set spare channels to NSP before launching the Non-secure software
context, and Non-secure, Privileged software can then set the remaining channels it does not need to NSU before
returning to the Non-secure, Normal context.
12.6.6.2. Interrupt Security Assignment
The RP2350 DMA has four system-level interrupt request lines (IRQs), each of which can be asserted on any
combination of channel interrupts, as defined by the channel masks in the interrupt enable registers INTE0 through
INTE3. Because the timing of interrupts can leak information, and because it is possible to cause software to
malfunction by deliberately manipulating its interrupts, access to the channel interrupt flags must be controlled.
The interrupt security configuration registers, SECCFG_IRQ0 through SECCFG_IRQ3, define the security level for each
interrupt. This is one of the four security levels laid out in Section 12.6.6. The security level of an IRQ defines:
• Which channels are visible in this IRQs status registers; channels of a level higher than the IRQs will read back as
zero.
• Whether a bus access to this IRQs control and status registers is permitted; bus accesses below this IRQs
security level will return bus faults and have no effect on the DMA.
• Which channels will assert this IRQ; channels of a level higher than this IRQs level will not cause the interrupt to
assert, even if relevant INTE bit is set.
• Whether a channels interrupt can be cleared through this IRQs INTS register, or set through this channels INTF
register; the interrupt flags of channels of higher security level than the IRQ can not be set or cleared.
The INTR register is shared between all IRQs, so it does not respect any of the IRQ security levels. Instead, it follows the
security level of the bus access: reads of INTR will return the interrupt flags of all channels at or below the security level
of the bus access (with higher-level channels reading back as zeroes), and writes to INTR have write-one-clear behaviour
on channels which are at or below the security level of the bus access.
12.6.6.3. Memory protection unit
The DMA memory protection unit (MPU) monitors the addresses of all read/write transfers performed by the DMA, and
notes the security level of the originating channel. The MPU is configured in advance with a user-defined security
address map, which specifies the minimum security level required to access up to eight dynamically configured regions.
This is one of the four security levels defined in Section 12.6.6.
Transfers that fail to meet the minimum security level for their address are shot down before reaching the system bus,
and a bus error is returned to the originating channel. This will be reported as either a read or write bus error in the
channels CTRL register, depending on whether it was a read or write address that failed the security check.
The intended use for the DMA MPU is to mirror the security definitions of SRAM and XIP memory from the processor
SAU or PMP. The number of DMA MPU regions is not sufficient for assigning individual peripherals, so the
ACCESSCTRL bus access registers (Section 10.6.2) are provided for this purpose.
RP2350 Datasheet
12.6. DMA 1104
Each of the eight MPU regions is configured with a base address, MPU_BAR0 through MPU_BAR7 for each region, and a
limit address, MPU_LAR0 through MPU_LAR7.
MPU regions have a granularity of 32 bytes, so the base/limit addresses are configured by the 27 most-significant bits
of each BAR/LAR register (bits 31:5). Addresses match MPU regions when the 27 most-significant bits of the address are
greater than or equal to the BAR address bits, and less than or equal to the LAR address bits. For example, when
MPU_BAR0 and MPU_LAR0 both have the value 0x10000000, MPU region 0 matches on a 32-byte region extending from
byte address 0x10000000 to 0x1000001f (inclusive). Regions can be enabled or disabled using the LAR.EN bits — if a region is
disabled, it matches no addresses.
The minimum security level required to access each region is defined by the S and P bits in the LSBs of that regions LAR
register. When an address matches multiple regions, the lowest-numbered region applies. This matches the tie-break
rules for the RISC-V PMP, but is different from the Arm SAU tie-break rules, so care must be taken when mirroring SAU
mappings with overlapping regions. When none of the MPU regions are matched, the security level is defined by the
global MPU_CTRL.S and MPU_CTRL.P bits.
The MPU configuration registers (MPU_CTRL, MPU_BAR0 through MPU_BAR7 and MPU_LAR0 through MPU_LAR7) do
not permit unprivileged access. Bus accesses at the SU and NSU security levels will return a bus fault and have no other
effect.
The MPU registers are also mostly read-only to NSP accesses, with the sole exception being the region P bits which are
NSP-writable if and only if the corresponding regions S bit is clear. This delegates to Privileged, Non-secure software
the decision of whether Non-secure regions are NSU-accessible.
12.6.7. Bus error handling
A bus error is an error condition flagged to one of the DMAs manager ports in response to an attempted read or write
transfer, indicating the transfer was rejected for one of the following reasons:
• The DMA MPU forbids access to this address at the originating channels security level (Section 12.6.6.3).
• The bus fabric failed to decode the address; the address did not match any known memory location (for example
SIO is not visible from the DMA bus ports as it is tightly coupled to the processors).
• ACCESSCTRL forbids access to the addressed region at the originating channels privilege level (Section 10.6.2).
• ACCESSCTRL forbids DMA access to the addressed region, irrespective of privilege.
• The APB bridge returned a timeout fault for a transfer exceeding 65535 cycles (e.g. accessed ADC whilst clk_adc
was stopped).
• The downstream bus port returned an error response for any other device-specific reason, e.g. attempting to
access configuration registers for a DMA channel with higher security level (Section 12.6.6.1).
12.6.7.1. Response to bus errors
Upon encountering a bus error, the DMA halts the offending channel and reports the error through the channels
CH0_CTRL_TRIG.READ_ERROR and WRITE_ERROR flags. The channel stops scheduling bus accesses.
Bus errors are exceptional events which usually indicate misconfiguration of the DMA or some other system hardware.
Therefore the DMA refuses to restart the offending channel until its error status is cleared by writing 1 to the relevant
error flag. Other channels are not affected, and continue their transfer sequences uninterrupted.
A channel which encounters a bus error does not CHAIN_TO other channels.
Bus errors always cause the channels interrupt request to be asserted. Whether or not this causes a system-level IRQ
depends on the channel masks configured in interrupt enable registers INTE0 through INTE3.
RP2350 Datasheet
12.6. DMA 1105
12.6.7.2. Recovery after bus errors
If an error is reported through READ_ERR/WRITE_ERR then, before restarting the channel, software must:
1. Poll for a low BUSY status to ensure that all in-flight transfers for this channel have been flushed from the DMAs bus
pipeline.
2. Clear the error flags by writing 1 to each flag.
Generally the BUSY flag will already be low long before the processor enters its interrupt handler and checks the error
status, but it is possible for these events to overlap when the DMA is accessing a slow device such as XIP with a high
SCK divisor and processors are executing from SRAM.
READ_ADDR and WRITE_ADDR contain the approximate address where the bus error was encountered. This can be useful for
the programmer to understand why the bus error occurred, and fix the software to avoid it in future.
Since the DMA performs reads and writes in parallel, it is possible for a channel to encounter both a read and write error
simultaneously, and in this case the DMA sets both READ_ERR and WRITE_ERR. You must clear both.
12.6.7.3. Halt timing
The DMA halts the channel as soon as possible following a bus error. This suppresses future reads and writes. Because
the request to access the bus is masked, the bus access has no side effects on the system. The timing relationships are
not straightforward due to the DMAs pipelining and buffering. The DMA provides the following ordering guarantees
between transfers originating from one channel:
• Read error → read suppression: Any reads scheduled to occur after a faulting read will be suppressed, but can still
increment READ_ADDR up to two times total
• Write error → write suppression: Any writes scheduled to occur after a faulting write will be suppressed, but can
still increment WRITE_ADDR up to four times total
• Read error → write suppression:
Any write paired with a faulting read will be suppressed, but will increment WRITE_ADDR
Any write following the first write paired with a faulting read will be suppressed, but can increment WRITE_ADDR
up to three times total
Up to three writes immediately preceding the first write paired with a faulting read can be suppressed, but will
increment WRITE_ADDR
• Write error → read suppression:
Reads paired with writes before the first faulting write will not be suppressed, and will increment READ_ADDR.
Up to two read transfers paired with writes after the first faulting write can be suppressed, and can increment
READ_ADDR
"Paired with" in the above paragraph refers to the write access which writes data originating from a particular read
transfer, or vice versa. The DMA always schedules read and write accesses in matched pairs.
Slight variability in halt behaviour is due to the buffering of in-flight transfers, and the parallel operation of the read and
write bus ports. The values of READ_ADDR/WRITE_ADDR following a bus error can be slightly beyond the address that
experienced the first error, but the difference is bounded, and usually this is still sufficient to diagnose the reason for the
fault. Additionally, READ_ADDR and WRITE_ADDR are guaranteed to over-increment by the same amount, since reads and
writes are always scheduled in pairs.
In addition to the increments mentioned above, READ_ADDR/WRITE_ADDR always point to the next address to be written, so
always point slightly past the faulting address if address increment is enabled.
RP2350 Datasheet
12.6. DMA 1106
12.6.8. Additional features
12.6.8.1. Pacing timers
These allow transfer of data roughly once every n clk_sys clocks instead of using external peripheral DREQ to trigger
transfers. A fractional (X/Y) divider is used, and will generate a maximum of 1 request per clk_sys cycle.
There are 4 timers available in RP2350. Each DMA channel is able to select any of these in CTRL.TREQ_SEL. There is one
register used to configure the pacing coefficients for each timer, TIMER0 through TIMER3.
Each timers security level is defined by a register field in SECCFG_MISC. This defines the minimum bus security level
required to configure that timer (lower levels will get a bus fault), and the minimum channel security level required to
observe that timers TREQ.
12.6.8.2. CRC calculation
The DMA can watch data from a given channel passing through the data FIFO, and calculate checksums based on this
data. This a purely passive affair: the data is not altered by this hardware, only observed.
The feature is controlled via the SNIFF_CTRL and SNIFF_DATA registers, and can be enabled/disabled per DMA transfer via
the CTRL.SNIFF_EN field.
As this hardware cannot place back-pressure on the FIFO, it must keep up with the DMAs maximum transfer rate of 32
bits per clock.
The supported checksums are:
• CRC-32, MSB-first and LSB-first
• CRC-16-CCITT, MSB-first and LSB-first
• Simple summation (add to 32-bit accumulator)
• Even parity
The result register is both readable and writable, so that the initial seed value can be set.
Bit/byte manipulations are available on the result, which can aid specific use cases:
• Bit inversion
• Bit reversal
• Byte swap
These manipulations do not affect the CRC calculation, just how the data is presented in the result register.
The sniffers security level is configured by the SECCFG_MISC.SNIFF_S and SECCFG_MISC.SNIFF_P bits. This
determines the minimum bus security level required to access the sniffers control registers, as well as the maximum
channel security level that the sniffer can observe.
12.6.8.3. Channel abort
It is possible for a channel to get into an irrecoverable state. If commanded to transfer more data than a peripheral will
ever request, the channel will never complete. Clearing the CTRL.EN bit pauses the channel, but does not solve the
problem. This should not occur under normal circumstances, but it is important that there is a mechanism to recover
without simply hard-resetting the entire DMA block.
In such a situation, use the CHAN_ABORT register to force the channel to complete early. There is one bit for each
channel. Writing a 1 to the corresponding bit terminates the channel. This clears the transfer counter and forces the
channel into an inactive state.
RP2350 Datasheet
12.6. DMA 1107
At the time an abort is triggered, a channel might have bus transfers currently in flight between the read and write
manager. These transfers cannot be revoked. The CTRL.BUSY flag stays high until these transfers complete, and the
channel reaches a safe state. This generally takes only a few cycles. The channel must not be restarted until its
CTRL.BUSY flag de-asserts. Starting a new sequence of transfers whilst transfers from an old sequence are still in flight
will cause unpredictable behaviour.
The sequence to abort one or more channels in an unknown state (also accounting for the behaviour described in
RP2350-E5 is:
1. Clear the EN bit and disable CHAIN_TO for all channels to be aborted.
2. Write the CHAN_ABORT register with a bitmap of those same channels.
3. Poll the ABORT register until all bits set by the previous write are clear.
When aborting a channel involved in a CHAIN_TO, it is recommended to simultaneously abort all other channels involved in
the chain.
12.6.8.4. Debug
Debug registers are available for each DMA channel to show the dreq counter DBG_CTDREQ and next transfer count DBG_TCR.
These can also be used to reset a DMA channel if required.
12.6.9. Example use cases
12.6.9.1. Using interrupts to reconfigure a channel
When a channel finishes a block of transfers, it becomes available for making more transfers. Software detects that the
channel is no longer busy, and reconfigures and restarts the channel. One approach is to poll the CTRL_BUSY bit until the
channel is done, but this loses one of the key advantages of the DMA, namely that it does not have to operate in
lockstep with a processor. By setting the correct bit in INTE0 through INTE3, you can instruct the DMA to raise one of its
four interrupt request lines when a given channel completes. Rather than repeatedly asking if a channel is done, you are
told.
 NOTE
Having four system interrupt lines allows different channel completion interrupts to be routed to different cores, or
to pre-empt one another on the same core if one channel is more time-critical. It also allows channel interrupts to
target different security domains.
When the interrupt is asserted, the processor can be configured to drop whatever it is doing and call a user-specified
handler function. The handler can reconfigure and restart the channel. When the handler exits, the processor returns to
the interrupted code running in the foreground.
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/dma/channel_irq/channel_irq.c Lines 35 - 52
35 void dma_handler() {
36 static int pwm_level = 0;
37 static uint32_t wavetable[N_PWM_LEVELS];
38 static bool first_run = true;
39 // Entry number `i` has `i` one bits and `(32 - i)` zero bits.
40 if (first_run) {
41 first_run = false;
42 for (int i = 0; i < N_PWM_LEVELS; ++i)
43 wavetable[i] = ~(~0u << i);
44 }
45
RP2350 Datasheet
12.6. DMA 1108
46 // Clear the interrupt request.
47 dma_hw->ints0 = 1u << dma_chan;
48 // Give the channel a new wave table entry to read from, and re-trigger it
49 dma_channel_set_read_addr(dma_chan, &wavetable[pwm_level], true);
50
51 pwm_level = (pwm_level + 1) % N_PWM_LEVELS;
52 }
In many cases, most of the configuration can be done the first time the channel starts. This way, only addresses and
transfer lengths need reprogramming in the interrupt handler.
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/dma/channel_irq/channel_irq.c Lines 54 - 94
54 int main() {
55 #ifndef PICO_DEFAULT_LED_PIN
56 #warning dma/channel_irq example requires a board with a regular LED
57 #else
58 // Set up a PIO state machine to serialise our bits
59 uint offset = pio_add_program(pio0, &pio_serialiser_program);
60 pio_serialiser_program_init(pio0, 0, offset, PICO_DEFAULT_LED_PIN, PIO_SERIAL_CLKDIV);
61
62 // Configure a channel to write the same word (32 bits) repeatedly to PIO0
63 // SM0's TX FIFO, paced by the data request signal from that peripheral.
64 dma_chan = dma_claim_unused_channel(true);
65 dma_channel_config c = dma_channel_get_default_config(dma_chan);
66 channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
67 channel_config_set_read_increment(&c, false);
68 channel_config_set_dreq(&c, DREQ_PIO0_TX0);
69
70 dma_channel_configure(
71 dma_chan,
72 &c,
73 &pio0_hw->txf[0], // Write address (only need to set this once)
74 NULL, // Don't provide a read address yet
75 PWM_REPEAT_COUNT, // Write the same value many times, then halt and interrupt
76 false // Don't start yet
77 );
78
79 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
80 dma_channel_set_irq0_enabled(dma_chan, true);
81
82 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
83 irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
84 irq_set_enabled(DMA_IRQ_0, true);
85
86 // Manually call the handler once, to trigger the first transfer
87 dma_handler();
88
89 // Everything else from this point is interrupt-driven. The processor has
90 // time to sit and think about its early retirement -- maybe open a bakery?
91 while (true)
92 tight_loop_contents();
93 #endif
94 }
One disadvantage of this technique is that you dont start to reconfigure the channel until some time after the channel
makes its last transfer. If there is heavy interrupt activity on the processor, this can be quite a long time, and quite a
large gap in transfers. This makes it difficult to sustain a high data throughput.
This is solved by using two channels, with their CHAIN_TO fields crossed over, so that channel A triggers channel B when it
completes, and vice versa. At any point in time, one of the channels is transferring data. The other is either already
RP2350 Datasheet
12.6. DMA 1109
configured to start the next transfer immediately when the current one finishes, or it is in the process of being
reconfigured. When channel A completes, it immediately starts the cued-up transfer on channel B. At the same time, the
interrupt is fired, and the handler reconfigures channel A so that it is ready when channel B completes.
12.6.9.2. DMA control blocks
Frequently, multiple smaller buffers must be gathered together and sent to the same peripheral. To address this use
case, the RP2350 DMA can execute a long and complex sequence of transfers without processor control. One channel
repeatedly reconfigures a second channel, and the second channel restarts the first each time it completes block of
transfers.
Because the first DMA channel transfers data directly from memory to the second channels control registers, the
format of the control blocks in memory must match those registers. Each time, the last register written to will be one of
the trigger registers (Section 12.6.3.1), which will start the second channel on its programmed block of transfers. The
register aliases (Section 12.6.3.1) give some flexibility for the block layout, and more importantly allow some registers
to be omitted from the blocks, so they occupy less memory and can be loaded more quickly.
This example shows how multiple buffers can be gathered and transferred to the UART, by reprogramming TRANS_COUNT
and READ_ADDR_TRIG:
Pico Examples: https://github.com/raspberrypi/pico-examples/blob/master/dma/control_blocks/control_blocks.c
1 /**
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 // Use two DMA channels to make a programmed sequence of data transfers to the
8 // UART (a data gather operation). One channel is responsible for transferring
9 // the actual data, the other repeatedly reprograms that channel.
10
11 #include <stdio.h>
12 #include "pico/stdlib.h"
13 #include "hardware/dma.h"
14 #include "hardware/structs/uart.h"
15
16 // These buffers will be DMA'd to the UART, one after the other.
17
18 const char word0[] = "Transferring ";
19 const char word1[] = "one ";
20 const char word2[] = "word ";
21 const char word3[] = "at ";
22 const char word4[] = "a ";
23 const char word5[] = "time.\n";
24
25 // Note the order of the fields here: it's important that the length is before
26 // the read address, because the control channel is going to write to the last
27 // two registers in alias 3 on the data channel:
28 // +0x0 +0x4 +0x8 +0xC (Trigger)
29 // Alias 0: READ_ADDR WRITE_ADDR TRANS_COUNT CTRL
30 // Alias 1: CTRL READ_ADDR WRITE_ADDR TRANS_COUNT
31 // Alias 2: CTRL TRANS_COUNT READ_ADDR WRITE_ADDR
32 // Alias 3: CTRL WRITE_ADDR TRANS_COUNT READ_ADDR
33 //
34 // This will program the transfer count and read address of the data channel,
35 // and trigger it. Once the data channel completes, it will restart the
36 // control channel (via CHAIN_TO) to load the next two words into its control
37 // registers.
38
39 const struct {uint32_t len; const char *data;} control_blocks[] = {
RP2350 Datasheet
12.6. DMA 1110
40 {count_of(word0) - 1, word0}, // Skip null terminator
41 {count_of(word1) - 1, word1},
42 {count_of(word2) - 1, word2},
43 {count_of(word3) - 1, word3},
44 {count_of(word4) - 1, word4},
45 {count_of(word5) - 1, word5},
46 {0, NULL} // Null trigger to end chain.
47 };
48
49 int main() {
50 #ifndef uart_default
51 #warning dma/control_blocks example requires a UART
52 #else
53 stdio_init_all();
54 puts("DMA control block example:");
55
56 // ctrl_chan loads control blocks into data_chan, which executes them.
57 int ctrl_chan = dma_claim_unused_channel(true);
58 int data_chan = dma_claim_unused_channel(true);
59
60 // The control channel transfers two words into the data channel's control
61 // registers, then halts. The write address wraps on a two-word
62 // (eight-byte) boundary, so that the control channel writes the same two
63 // registers when it is next triggered.
64
65 dma_channel_config c = dma_channel_get_default_config(ctrl_chan);
66 channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
67 channel_config_set_read_increment(&c, true);
68 channel_config_set_write_increment(&c, true);
69 channel_config_set_ring(&c, true, 3); // 1 << 3 byte boundary on write ptr
70
71 dma_channel_configure(
72 ctrl_chan,
73 &c,
74 &dma_hw->ch[data_chan].al3_transfer_count, // Initial write address
75 &control_blocks[0], // Initial read address
76 2, // Halt after each control block
77 false // Don't start yet
78 );
79
80 // The data channel is set up to write to the UART FIFO (paced by the
81 // UART's TX data request signal) and then chain to the control channel
82 // once it completes. The control channel programs a new read address and
83 // data length, and retriggers the data channel.
84
85 c = dma_channel_get_default_config(data_chan);
86 channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
87 channel_config_set_dreq(&c, uart_get_dreq(uart_default, true));
88 // Trigger ctrl_chan when data_chan completes
89 channel_config_set_chain_to(&c, ctrl_chan);
90 // Raise the IRQ flag when 0 is written to a trigger register (end of chain):
91 channel_config_set_irq_quiet(&c, true);
92
93 dma_channel_configure(
94 data_chan,
95 &c,
96 &uart_get_hw(uart_default)->dr,
97 NULL, // Initial read address and transfer count are unimportant;
98 0, // the control channel will reprogram them each time.
99 false // Don't start yet.
100 );
101
102 // Everything is ready to go. Tell the control channel to load the first
103 // control block. Everything is automatic from here.
RP2350 Datasheet
12.6. DMA 1111
104 dma_start_channel_mask(1u << ctrl_chan);
105
106 // The data channel will assert its IRQ flag when it gets a null trigger,
107 // indicating the end of the control block list. We're just going to wait
108 // for the IRQ flag instead of setting up an interrupt handler.
109 while (!(dma_hw->intr & 1u << data_chan))
110 tight_loop_contents();
111 dma_hw->ints0 = 1u << data_chan;
112
113 puts("DMA finished.");
114 #endif
115 }
12.6.10. List of Registers
The DMA registers start at a base address of 0x50000000 (defined as DMA_BASE in SDK).
Table 1147. List of
DMA registers
Offset Name Info
0x000 CH0_READ_ADDR DMA Channel 0 Read Address pointer
0x004 CH0_WRITE_ADDR DMA Channel 0 Write Address pointer
0x008 CH0_TRANS_COUNT DMA Channel 0 Transfer Count
0x00c CH0_CTRL_TRIG DMA Channel 0 Control and Status
0x010 CH0_AL1_CTRL Alias for channel 0 CTRL register
0x014 CH0_AL1_READ_ADDR Alias for channel 0 READ_ADDR register
0x018 CH0_AL1_WRITE_ADDR Alias for channel 0 WRITE_ADDR register
0x01c CH0_AL1_TRANS_COUNT_TRIG Alias for channel 0 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x020 CH0_AL2_CTRL Alias for channel 0 CTRL register
0x024 CH0_AL2_TRANS_COUNT Alias for channel 0 TRANS_COUNT register
0x028 CH0_AL2_READ_ADDR Alias for channel 0 READ_ADDR register
0x02c CH0_AL2_WRITE_ADDR_TRIG Alias for channel 0 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x030 CH0_AL3_CTRL Alias for channel 0 CTRL register
0x034 CH0_AL3_WRITE_ADDR Alias for channel 0 WRITE_ADDR register
0x038 CH0_AL3_TRANS_COUNT Alias for channel 0 TRANS_COUNT register
0x03c CH0_AL3_READ_ADDR_TRIG Alias for channel 0 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x040 CH1_READ_ADDR DMA Channel 1 Read Address pointer
0x044 CH1_WRITE_ADDR DMA Channel 1 Write Address pointer
0x048 CH1_TRANS_COUNT DMA Channel 1 Transfer Count
0x04c CH1_CTRL_TRIG DMA Channel 1 Control and Status
RP2350 Datasheet
12.6. DMA 1112
Offset Name Info
0x050 CH1_AL1_CTRL Alias for channel 1 CTRL register
0x054 CH1_AL1_READ_ADDR Alias for channel 1 READ_ADDR register
0x058 CH1_AL1_WRITE_ADDR Alias for channel 1 WRITE_ADDR register
0x05c CH1_AL1_TRANS_COUNT_TRIG Alias for channel 1 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x060 CH1_AL2_CTRL Alias for channel 1 CTRL register
0x064 CH1_AL2_TRANS_COUNT Alias for channel 1 TRANS_COUNT register
0x068 CH1_AL2_READ_ADDR Alias for channel 1 READ_ADDR register
0x06c CH1_AL2_WRITE_ADDR_TRIG Alias for channel 1 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x070 CH1_AL3_CTRL Alias for channel 1 CTRL register
0x074 CH1_AL3_WRITE_ADDR Alias for channel 1 WRITE_ADDR register
0x078 CH1_AL3_TRANS_COUNT Alias for channel 1 TRANS_COUNT register
0x07c CH1_AL3_READ_ADDR_TRIG Alias for channel 1 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x080 CH2_READ_ADDR DMA Channel 2 Read Address pointer
0x084 CH2_WRITE_ADDR DMA Channel 2 Write Address pointer
0x088 CH2_TRANS_COUNT DMA Channel 2 Transfer Count
0x08c CH2_CTRL_TRIG DMA Channel 2 Control and Status
0x090 CH2_AL1_CTRL Alias for channel 2 CTRL register
0x094 CH2_AL1_READ_ADDR Alias for channel 2 READ_ADDR register
0x098 CH2_AL1_WRITE_ADDR Alias for channel 2 WRITE_ADDR register
0x09c CH2_AL1_TRANS_COUNT_TRIG Alias for channel 2 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x0a0 CH2_AL2_CTRL Alias for channel 2 CTRL register
0x0a4 CH2_AL2_TRANS_COUNT Alias for channel 2 TRANS_COUNT register
0x0a8 CH2_AL2_READ_ADDR Alias for channel 2 READ_ADDR register
0x0ac CH2_AL2_WRITE_ADDR_TRIG Alias for channel 2 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x0b0 CH2_AL3_CTRL Alias for channel 2 CTRL register
0x0b4 CH2_AL3_WRITE_ADDR Alias for channel 2 WRITE_ADDR register
0x0b8 CH2_AL3_TRANS_COUNT Alias for channel 2 TRANS_COUNT register
0x0bc CH2_AL3_READ_ADDR_TRIG Alias for channel 2 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
RP2350 Datasheet
12.6. DMA 1113
Offset Name Info
0x0c0 CH3_READ_ADDR DMA Channel 3 Read Address pointer
0x0c4 CH3_WRITE_ADDR DMA Channel 3 Write Address pointer
0x0c8 CH3_TRANS_COUNT DMA Channel 3 Transfer Count
0x0cc CH3_CTRL_TRIG DMA Channel 3 Control and Status
0x0d0 CH3_AL1_CTRL Alias for channel 3 CTRL register
0x0d4 CH3_AL1_READ_ADDR Alias for channel 3 READ_ADDR register
0x0d8 CH3_AL1_WRITE_ADDR Alias for channel 3 WRITE_ADDR register
0x0dc CH3_AL1_TRANS_COUNT_TRIG Alias for channel 3 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x0e0 CH3_AL2_CTRL Alias for channel 3 CTRL register
0x0e4 CH3_AL2_TRANS_COUNT Alias for channel 3 TRANS_COUNT register
0x0e8 CH3_AL2_READ_ADDR Alias for channel 3 READ_ADDR register
0x0ec CH3_AL2_WRITE_ADDR_TRIG Alias for channel 3 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x0f0 CH3_AL3_CTRL Alias for channel 3 CTRL register
0x0f4 CH3_AL3_WRITE_ADDR Alias for channel 3 WRITE_ADDR register
0x0f8 CH3_AL3_TRANS_COUNT Alias for channel 3 TRANS_COUNT register
0x0fc CH3_AL3_READ_ADDR_TRIG Alias for channel 3 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x100 CH4_READ_ADDR DMA Channel 4 Read Address pointer
0x104 CH4_WRITE_ADDR DMA Channel 4 Write Address pointer
0x108 CH4_TRANS_COUNT DMA Channel 4 Transfer Count
0x10c CH4_CTRL_TRIG DMA Channel 4 Control and Status
0x110 CH4_AL1_CTRL Alias for channel 4 CTRL register
0x114 CH4_AL1_READ_ADDR Alias for channel 4 READ_ADDR register
0x118 CH4_AL1_WRITE_ADDR Alias for channel 4 WRITE_ADDR register
0x11c CH4_AL1_TRANS_COUNT_TRIG Alias for channel 4 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x120 CH4_AL2_CTRL Alias for channel 4 CTRL register
0x124 CH4_AL2_TRANS_COUNT Alias for channel 4 TRANS_COUNT register
0x128 CH4_AL2_READ_ADDR Alias for channel 4 READ_ADDR register
0x12c CH4_AL2_WRITE_ADDR_TRIG Alias for channel 4 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x130 CH4_AL3_CTRL Alias for channel 4 CTRL register
RP2350 Datasheet
12.6. DMA 1114
Offset Name Info
0x134 CH4_AL3_WRITE_ADDR Alias for channel 4 WRITE_ADDR register
0x138 CH4_AL3_TRANS_COUNT Alias for channel 4 TRANS_COUNT register
0x13c CH4_AL3_READ_ADDR_TRIG Alias for channel 4 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x140 CH5_READ_ADDR DMA Channel 5 Read Address pointer
0x144 CH5_WRITE_ADDR DMA Channel 5 Write Address pointer
0x148 CH5_TRANS_COUNT DMA Channel 5 Transfer Count
0x14c CH5_CTRL_TRIG DMA Channel 5 Control and Status
0x150 CH5_AL1_CTRL Alias for channel 5 CTRL register
0x154 CH5_AL1_READ_ADDR Alias for channel 5 READ_ADDR register
0x158 CH5_AL1_WRITE_ADDR Alias for channel 5 WRITE_ADDR register
0x15c CH5_AL1_TRANS_COUNT_TRIG Alias for channel 5 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x160 CH5_AL2_CTRL Alias for channel 5 CTRL register
0x164 CH5_AL2_TRANS_COUNT Alias for channel 5 TRANS_COUNT register
0x168 CH5_AL2_READ_ADDR Alias for channel 5 READ_ADDR register
0x16c CH5_AL2_WRITE_ADDR_TRIG Alias for channel 5 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x170 CH5_AL3_CTRL Alias for channel 5 CTRL register
0x174 CH5_AL3_WRITE_ADDR Alias for channel 5 WRITE_ADDR register
0x178 CH5_AL3_TRANS_COUNT Alias for channel 5 TRANS_COUNT register
0x17c CH5_AL3_READ_ADDR_TRIG Alias for channel 5 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x180 CH6_READ_ADDR DMA Channel 6 Read Address pointer
0x184 CH6_WRITE_ADDR DMA Channel 6 Write Address pointer
0x188 CH6_TRANS_COUNT DMA Channel 6 Transfer Count
0x18c CH6_CTRL_TRIG DMA Channel 6 Control and Status
0x190 CH6_AL1_CTRL Alias for channel 6 CTRL register
0x194 CH6_AL1_READ_ADDR Alias for channel 6 READ_ADDR register
0x198 CH6_AL1_WRITE_ADDR Alias for channel 6 WRITE_ADDR register
0x19c CH6_AL1_TRANS_COUNT_TRIG Alias for channel 6 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x1a0 CH6_AL2_CTRL Alias for channel 6 CTRL register
0x1a4 CH6_AL2_TRANS_COUNT Alias for channel 6 TRANS_COUNT register
RP2350 Datasheet
12.6. DMA 1115
Offset Name Info
0x1a8 CH6_AL2_READ_ADDR Alias for channel 6 READ_ADDR register
0x1ac CH6_AL2_WRITE_ADDR_TRIG Alias for channel 6 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x1b0 CH6_AL3_CTRL Alias for channel 6 CTRL register
0x1b4 CH6_AL3_WRITE_ADDR Alias for channel 6 WRITE_ADDR register
0x1b8 CH6_AL3_TRANS_COUNT Alias for channel 6 TRANS_COUNT register
0x1bc CH6_AL3_READ_ADDR_TRIG Alias for channel 6 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x1c0 CH7_READ_ADDR DMA Channel 7 Read Address pointer
0x1c4 CH7_WRITE_ADDR DMA Channel 7 Write Address pointer
0x1c8 CH7_TRANS_COUNT DMA Channel 7 Transfer Count
0x1cc CH7_CTRL_TRIG DMA Channel 7 Control and Status
0x1d0 CH7_AL1_CTRL Alias for channel 7 CTRL register
0x1d4 CH7_AL1_READ_ADDR Alias for channel 7 READ_ADDR register
0x1d8 CH7_AL1_WRITE_ADDR Alias for channel 7 WRITE_ADDR register
0x1dc CH7_AL1_TRANS_COUNT_TRIG Alias for channel 7 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x1e0 CH7_AL2_CTRL Alias for channel 7 CTRL register
0x1e4 CH7_AL2_TRANS_COUNT Alias for channel 7 TRANS_COUNT register
0x1e8 CH7_AL2_READ_ADDR Alias for channel 7 READ_ADDR register
0x1ec CH7_AL2_WRITE_ADDR_TRIG Alias for channel 7 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x1f0 CH7_AL3_CTRL Alias for channel 7 CTRL register
0x1f4 CH7_AL3_WRITE_ADDR Alias for channel 7 WRITE_ADDR register
0x1f8 CH7_AL3_TRANS_COUNT Alias for channel 7 TRANS_COUNT register
0x1fc CH7_AL3_READ_ADDR_TRIG Alias for channel 7 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x200 CH8_READ_ADDR DMA Channel 8 Read Address pointer
0x204 CH8_WRITE_ADDR DMA Channel 8 Write Address pointer
0x208 CH8_TRANS_COUNT DMA Channel 8 Transfer Count
0x20c CH8_CTRL_TRIG DMA Channel 8 Control and Status
0x210 CH8_AL1_CTRL Alias for channel 8 CTRL register
0x214 CH8_AL1_READ_ADDR Alias for channel 8 READ_ADDR register
0x218 CH8_AL1_WRITE_ADDR Alias for channel 8 WRITE_ADDR register
RP2350 Datasheet
12.6. DMA 1116
Offset Name Info
0x21c CH8_AL1_TRANS_COUNT_TRIG Alias for channel 8 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x220 CH8_AL2_CTRL Alias for channel 8 CTRL register
0x224 CH8_AL2_TRANS_COUNT Alias for channel 8 TRANS_COUNT register
0x228 CH8_AL2_READ_ADDR Alias for channel 8 READ_ADDR register
0x22c CH8_AL2_WRITE_ADDR_TRIG Alias for channel 8 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x230 CH8_AL3_CTRL Alias for channel 8 CTRL register
0x234 CH8_AL3_WRITE_ADDR Alias for channel 8 WRITE_ADDR register
0x238 CH8_AL3_TRANS_COUNT Alias for channel 8 TRANS_COUNT register
0x23c CH8_AL3_READ_ADDR_TRIG Alias for channel 8 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x240 CH9_READ_ADDR DMA Channel 9 Read Address pointer
0x244 CH9_WRITE_ADDR DMA Channel 9 Write Address pointer
0x248 CH9_TRANS_COUNT DMA Channel 9 Transfer Count
0x24c CH9_CTRL_TRIG DMA Channel 9 Control and Status
0x250 CH9_AL1_CTRL Alias for channel 9 CTRL register
0x254 CH9_AL1_READ_ADDR Alias for channel 9 READ_ADDR register
0x258 CH9_AL1_WRITE_ADDR Alias for channel 9 WRITE_ADDR register
0x25c CH9_AL1_TRANS_COUNT_TRIG Alias for channel 9 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x260 CH9_AL2_CTRL Alias for channel 9 CTRL register
0x264 CH9_AL2_TRANS_COUNT Alias for channel 9 TRANS_COUNT register
0x268 CH9_AL2_READ_ADDR Alias for channel 9 READ_ADDR register
0x26c CH9_AL2_WRITE_ADDR_TRIG Alias for channel 9 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x270 CH9_AL3_CTRL Alias for channel 9 CTRL register
0x274 CH9_AL3_WRITE_ADDR Alias for channel 9 WRITE_ADDR register
0x278 CH9_AL3_TRANS_COUNT Alias for channel 9 TRANS_COUNT register
0x27c CH9_AL3_READ_ADDR_TRIG Alias for channel 9 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x280 CH10_READ_ADDR DMA Channel 10 Read Address pointer
0x284 CH10_WRITE_ADDR DMA Channel 10 Write Address pointer
0x288 CH10_TRANS_COUNT DMA Channel 10 Transfer Count
RP2350 Datasheet
12.6. DMA 1117
Offset Name Info
0x28c CH10_CTRL_TRIG DMA Channel 10 Control and Status
0x290 CH10_AL1_CTRL Alias for channel 10 CTRL register
0x294 CH10_AL1_READ_ADDR Alias for channel 10 READ_ADDR register
0x298 CH10_AL1_WRITE_ADDR Alias for channel 10 WRITE_ADDR register
0x29c CH10_AL1_TRANS_COUNT_TRIG Alias for channel 10 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x2a0 CH10_AL2_CTRL Alias for channel 10 CTRL register
0x2a4 CH10_AL2_TRANS_COUNT Alias for channel 10 TRANS_COUNT register
0x2a8 CH10_AL2_READ_ADDR Alias for channel 10 READ_ADDR register
0x2ac CH10_AL2_WRITE_ADDR_TRIG Alias for channel 10 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x2b0 CH10_AL3_CTRL Alias for channel 10 CTRL register
0x2b4 CH10_AL3_WRITE_ADDR Alias for channel 10 WRITE_ADDR register
0x2b8 CH10_AL3_TRANS_COUNT Alias for channel 10 TRANS_COUNT register
0x2bc CH10_AL3_READ_ADDR_TRIG Alias for channel 10 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x2c0 CH11_READ_ADDR DMA Channel 11 Read Address pointer
0x2c4 CH11_WRITE_ADDR DMA Channel 11 Write Address pointer
0x2c8 CH11_TRANS_COUNT DMA Channel 11 Transfer Count
0x2cc CH11_CTRL_TRIG DMA Channel 11 Control and Status
0x2d0 CH11_AL1_CTRL Alias for channel 11 CTRL register
0x2d4 CH11_AL1_READ_ADDR Alias for channel 11 READ_ADDR register
0x2d8 CH11_AL1_WRITE_ADDR Alias for channel 11 WRITE_ADDR register
0x2dc CH11_AL1_TRANS_COUNT_TRIG Alias for channel 11 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x2e0 CH11_AL2_CTRL Alias for channel 11 CTRL register
0x2e4 CH11_AL2_TRANS_COUNT Alias for channel 11 TRANS_COUNT register
0x2e8 CH11_AL2_READ_ADDR Alias for channel 11 READ_ADDR register
0x2ec CH11_AL2_WRITE_ADDR_TRIG Alias for channel 11 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x2f0 CH11_AL3_CTRL Alias for channel 11 CTRL register
0x2f4 CH11_AL3_WRITE_ADDR Alias for channel 11 WRITE_ADDR register
0x2f8 CH11_AL3_TRANS_COUNT Alias for channel 11 TRANS_COUNT register
RP2350 Datasheet
12.6. DMA 1118
Offset Name Info
0x2fc CH11_AL3_READ_ADDR_TRIG Alias for channel 11 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x300 CH12_READ_ADDR DMA Channel 12 Read Address pointer
0x304 CH12_WRITE_ADDR DMA Channel 12 Write Address pointer
0x308 CH12_TRANS_COUNT DMA Channel 12 Transfer Count
0x30c CH12_CTRL_TRIG DMA Channel 12 Control and Status
0x310 CH12_AL1_CTRL Alias for channel 12 CTRL register
0x314 CH12_AL1_READ_ADDR Alias for channel 12 READ_ADDR register
0x318 CH12_AL1_WRITE_ADDR Alias for channel 12 WRITE_ADDR register
0x31c CH12_AL1_TRANS_COUNT_TRIG Alias for channel 12 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x320 CH12_AL2_CTRL Alias for channel 12 CTRL register
0x324 CH12_AL2_TRANS_COUNT Alias for channel 12 TRANS_COUNT register
0x328 CH12_AL2_READ_ADDR Alias for channel 12 READ_ADDR register
0x32c CH12_AL2_WRITE_ADDR_TRIG Alias for channel 12 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x330 CH12_AL3_CTRL Alias for channel 12 CTRL register
0x334 CH12_AL3_WRITE_ADDR Alias for channel 12 WRITE_ADDR register
0x338 CH12_AL3_TRANS_COUNT Alias for channel 12 TRANS_COUNT register
0x33c CH12_AL3_READ_ADDR_TRIG Alias for channel 12 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x340 CH13_READ_ADDR DMA Channel 13 Read Address pointer
0x344 CH13_WRITE_ADDR DMA Channel 13 Write Address pointer
0x348 CH13_TRANS_COUNT DMA Channel 13 Transfer Count
0x34c CH13_CTRL_TRIG DMA Channel 13 Control and Status
0x350 CH13_AL1_CTRL Alias for channel 13 CTRL register
0x354 CH13_AL1_READ_ADDR Alias for channel 13 READ_ADDR register
0x358 CH13_AL1_WRITE_ADDR Alias for channel 13 WRITE_ADDR register
0x35c CH13_AL1_TRANS_COUNT_TRIG Alias for channel 13 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x360 CH13_AL2_CTRL Alias for channel 13 CTRL register
0x364 CH13_AL2_TRANS_COUNT Alias for channel 13 TRANS_COUNT register
0x368 CH13_AL2_READ_ADDR Alias for channel 13 READ_ADDR register
RP2350 Datasheet
12.6. DMA 1119
Offset Name Info
0x36c CH13_AL2_WRITE_ADDR_TRIG Alias for channel 13 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x370 CH13_AL3_CTRL Alias for channel 13 CTRL register
0x374 CH13_AL3_WRITE_ADDR Alias for channel 13 WRITE_ADDR register
0x378 CH13_AL3_TRANS_COUNT Alias for channel 13 TRANS_COUNT register
0x37c CH13_AL3_READ_ADDR_TRIG Alias for channel 13 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x380 CH14_READ_ADDR DMA Channel 14 Read Address pointer
0x384 CH14_WRITE_ADDR DMA Channel 14 Write Address pointer
0x388 CH14_TRANS_COUNT DMA Channel 14 Transfer Count
0x38c CH14_CTRL_TRIG DMA Channel 14 Control and Status
0x390 CH14_AL1_CTRL Alias for channel 14 CTRL register
0x394 CH14_AL1_READ_ADDR Alias for channel 14 READ_ADDR register
0x398 CH14_AL1_WRITE_ADDR Alias for channel 14 WRITE_ADDR register
0x39c CH14_AL1_TRANS_COUNT_TRIG Alias for channel 14 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x3a0 CH14_AL2_CTRL Alias for channel 14 CTRL register
0x3a4 CH14_AL2_TRANS_COUNT Alias for channel 14 TRANS_COUNT register
0x3a8 CH14_AL2_READ_ADDR Alias for channel 14 READ_ADDR register
0x3ac CH14_AL2_WRITE_ADDR_TRIG Alias for channel 14 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x3b0 CH14_AL3_CTRL Alias for channel 14 CTRL register
0x3b4 CH14_AL3_WRITE_ADDR Alias for channel 14 WRITE_ADDR register
0x3b8 CH14_AL3_TRANS_COUNT Alias for channel 14 TRANS_COUNT register
0x3bc CH14_AL3_READ_ADDR_TRIG Alias for channel 14 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x3c0 CH15_READ_ADDR DMA Channel 15 Read Address pointer
0x3c4 CH15_WRITE_ADDR DMA Channel 15 Write Address pointer
0x3c8 CH15_TRANS_COUNT DMA Channel 15 Transfer Count
0x3cc CH15_CTRL_TRIG DMA Channel 15 Control and Status
0x3d0 CH15_AL1_CTRL Alias for channel 15 CTRL register
0x3d4 CH15_AL1_READ_ADDR Alias for channel 15 READ_ADDR register
0x3d8 CH15_AL1_WRITE_ADDR Alias for channel 15 WRITE_ADDR register
RP2350 Datasheet
12.6. DMA 1120
Offset Name Info
0x3dc CH15_AL1_TRANS_COUNT_TRIG Alias for channel 15 TRANS_COUNT register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x3e0 CH15_AL2_CTRL Alias for channel 15 CTRL register
0x3e4 CH15_AL2_TRANS_COUNT Alias for channel 15 TRANS_COUNT register
0x3e8 CH15_AL2_READ_ADDR Alias for channel 15 READ_ADDR register
0x3ec CH15_AL2_WRITE_ADDR_TRIG Alias for channel 15 WRITE_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x3f0 CH15_AL3_CTRL Alias for channel 15 CTRL register
0x3f4 CH15_AL3_WRITE_ADDR Alias for channel 15 WRITE_ADDR register
0x3f8 CH15_AL3_TRANS_COUNT Alias for channel 15 TRANS_COUNT register
0x3fc CH15_AL3_READ_ADDR_TRIG Alias for channel 15 READ_ADDR register
This is a trigger register (0xc). Writing a nonzero value will
reload the channel counter and start the channel.
0x400 INTR Interrupt Status (raw)
0x404 INTE0 Interrupt Enables for IRQ 0
0x408 INTF0 Force Interrupts
0x40c INTS0 Interrupt Status for IRQ 0
0x414 INTE1 Interrupt Enables for IRQ 1
0x418 INTF1 Force Interrupts
0x41c INTS1 Interrupt Status for IRQ 1
0x424 INTE2 Interrupt Enables for IRQ 2
0x428 INTF2 Force Interrupts
0x42c INTS2 Interrupt Status for IRQ 2
0x434 INTE3 Interrupt Enables for IRQ 3
0x438 INTF3 Force Interrupts
0x43c INTS3 Interrupt Status for IRQ 3
0x440 TIMER0 Pacing timer (generate periodic TREQs)
0x444 TIMER1 Pacing timer (generate periodic TREQs)
0x448 TIMER2 Pacing timer (generate periodic TREQs)
0x44c TIMER3 Pacing timer (generate periodic TREQs)
0x450 MULTI_CHAN_TRIGGER Trigger one or more channels simultaneously
0x454 SNIFF_CTRL Sniffer Control
0x458 SNIFF_DATA Data accumulator for sniff hardware
0x460 FIFO_LEVELS Debug RAF, WAF, TDF levels
0x464 CHAN_ABORT Abort an in-progress transfer sequence on one or more channels
RP2350 Datasheet
12.6. DMA 1121
Offset Name Info
0x468 N_CHANNELS The number of channels this DMA instance is equipped with.
This DMA supports up to 16 hardware channels, but can be
configured with as few as one, to minimise silicon area.
0x480 SECCFG_CH0 Security level configuration for channel 0.
0x484 SECCFG_CH1 Security level configuration for channel 1.
0x488 SECCFG_CH2 Security level configuration for channel 2.
0x48c SECCFG_CH3 Security level configuration for channel 3.
0x490 SECCFG_CH4 Security level configuration for channel 4.
0x494 SECCFG_CH5 Security level configuration for channel 5.
0x498 SECCFG_CH6 Security level configuration for channel 6.
0x49c SECCFG_CH7 Security level configuration for channel 7.
0x4a0 SECCFG_CH8 Security level configuration for channel 8.
0x4a4 SECCFG_CH9 Security level configuration for channel 9.
0x4a8 SECCFG_CH10 Security level configuration for channel 10.
0x4ac SECCFG_CH11 Security level configuration for channel 11.
0x4b0 SECCFG_CH12 Security level configuration for channel 12.
0x4b4 SECCFG_CH13 Security level configuration for channel 13.
0x4b8 SECCFG_CH14 Security level configuration for channel 14.
0x4bc SECCFG_CH15 Security level configuration for channel 15.
0x4c0 SECCFG_IRQ0 Security configuration for IRQ 0. Control whether the IRQ permits
configuration by Non-secure/Unprivileged contexts, and whether
it can observe Secure/Privileged channel interrupt flags.
0x4c4 SECCFG_IRQ1 Security configuration for IRQ 1. Control whether the IRQ permits
configuration by Non-secure/Unprivileged contexts, and whether
it can observe Secure/Privileged channel interrupt flags.
0x4c8 SECCFG_IRQ2 Security configuration for IRQ 2. Control whether the IRQ permits
configuration by Non-secure/Unprivileged contexts, and whether
it can observe Secure/Privileged channel interrupt flags.
0x4cc SECCFG_IRQ3 Security configuration for IRQ 3. Control whether the IRQ permits
configuration by Non-secure/Unprivileged contexts, and whether
it can observe Secure/Privileged channel interrupt flags.
0x4d0 SECCFG_MISC Miscellaneous security configuration
0x500 MPU_CTRL Control register for DMA MPU. Accessible only from a Privileged
context.
0x504 MPU_BAR0 Base address register for MPU region 0. Writable only from a
Secure, Privileged context.
0x508 MPU_LAR0 Limit address register for MPU region 0. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x50c MPU_BAR1 Base address register for MPU region 1. Writable only from a
Secure, Privileged context.
RP2350 Datasheet
12.6. DMA 1122
Offset Name Info
0x510 MPU_LAR1 Limit address register for MPU region 1. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x514 MPU_BAR2 Base address register for MPU region 2. Writable only from a
Secure, Privileged context.
0x518 MPU_LAR2 Limit address register for MPU region 2. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x51c MPU_BAR3 Base address register for MPU region 3. Writable only from a
Secure, Privileged context.
0x520 MPU_LAR3 Limit address register for MPU region 3. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x524 MPU_BAR4 Base address register for MPU region 4. Writable only from a
Secure, Privileged context.
0x528 MPU_LAR4 Limit address register for MPU region 4. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x52c MPU_BAR5 Base address register for MPU region 5. Writable only from a
Secure, Privileged context.
0x530 MPU_LAR5 Limit address register for MPU region 5. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x534 MPU_BAR6 Base address register for MPU region 6. Writable only from a
Secure, Privileged context.
0x538 MPU_LAR6 Limit address register for MPU region 6. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x53c MPU_BAR7 Base address register for MPU region 7. Writable only from a
Secure, Privileged context.
0x540 MPU_LAR7 Limit address register for MPU region 7. Writable only from a
Secure, Privileged context, with the exception of the P bit.
0x800 CH0_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x804 CH0_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x840 CH1_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x844 CH1_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x880 CH2_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x884 CH2_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
RP2350 Datasheet
12.6. DMA 1123
Offset Name Info
0x8c0 CH3_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x8c4 CH3_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x900 CH4_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x904 CH4_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x940 CH5_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x944 CH5_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x980 CH6_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x984 CH6_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0x9c0 CH7_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0x9c4 CH7_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xa00 CH8_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xa04 CH8_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xa40 CH9_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xa44 CH9_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xa80 CH10_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
RP2350 Datasheet
12.6. DMA 1124
Offset Name Info
0xa84 CH10_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xac0 CH11_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xac4 CH11_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xb00 CH12_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xb04 CH12_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xb40 CH13_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xb44 CH13_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xb80 CH14_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xb84 CH14_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer
0xbc0 CH15_DBG_CTDREQ Read: get channel DREQ counter (i.e. how many accesses the
DMA expects it can perform on the peripheral without
overflow/underflow. Write any value: clears the counter, and
cause channel to re-initiate DREQ handshake.
0xbc4 CH15_DBG_TCR Read to get channel TRANS_COUNT reload value, i.e. the length
of the next transfer