UNIT 07 · LESSON 1 OF 6

Pin Modes and Alternate Functions

Who decides which peripheral owns a pin, and how do you tell the chip?

INTERACTIVEOne pin, many possible owners
The functions available on one RP2040 pin with the selected one highlightedGPIO0: what each FUNCSEL value connectsF1SPI0_RXF2UART0_TXF3I2C0_SDAF4PWM_A_0F5SIO_0F6PIO0_0F7PIO1_0F9USB_OVCUR_DETIO_BANK0 GPIO0_CTRL = 0x00000002: the pad now follows UART0_TXgpio_set_function(0, GPIO_FUNC_UART) writes exactly this, and also turns the pad’sinput on and its output-disable off
The functions available on one RP2040 pin with the selected one highlightedGPIO0: what each FUNCSEL value connectsF1SPI0_RXF2UART0_TXF3I2C0_SDAF4PWM_A_0F5SIO_0F6PIO0_0F7PIO1_0F9USB_OVCUR_DETIO_BANK0 GPIO0_CTRL = 0x00000002: the pad nowfollows UART0_TXgpio_set_function(0, GPIO_FUNC_UART) writes exactlythis, and also turns the pad’s input on and itsoutput-disable off

Try this

Pin
GPIO0 FUNCSEL 2: UART0_TX.

Each RP2040 GPIO has a multiplexer: the FUNCSEL field of its IO_BANK0 GPIOn_CTRL register chooses which peripheral signal drives the pad. The table is the real one for GPIO0–5 (pico-sdk io_bank0.h, USB signal names shortened); FUNCSEL resets to 0x1F, no function. The same signal often appears on several pins, and each pin offers a different subset.

What you will be able to do
  • Describe the path from a peripheral or software register through the pin multiplexer and pad to the physical pin.
  • Select a pin function on the RP2040 from its FUNCSEL table and explain why not every function is available on every pin.
  • Compute the STM32F4 MODER, OTYPER, PUPDR and AFR field values and bit positions for a given pin.
  • Name the pad controls (input enable, pulls, Schmitt trigger, drive strength, slew rate) and their RP2040 reset values.
  • Plan a pin assignment that avoids conflicts between peripherals.
Before you start
  • Bit fields and read-modify-write (unit 2, lessons 1 and 6).
  • Pull-up and pull-down resistors (unit 1, lesson 3).
Steps in this lesson
  1. A pin is a multiplexer and a pad
  2. The pad’s own settings
  3. The STM32F4 way: several registers per port
  4. Worked example: USART2 on pin 2 of a port
  5. Planning pins
  6. Common misconceptions

The puzzle

You want a UART on your board. The datasheet’s pin table lists its transmit signal in three places, the I²C you also need shares one of those pins, and the pin you soldered the LED to can only be a PWM output on one particular channel. Who decides which peripheral owns a pin, and how do you tell the chip?

STEP 1

A pin is a multiplexer and a pad

Inside the chip, each package pin connects to a pad: the output driver, the input buffer, the pull resistors and the protection diodes. In front of the pad sits a multiplexer that chooses which internal signal drives it: the software-controlled GPIO block, or one of several peripherals (UART, SPI, I²C, PWM, timers). Configuring a pin means choosing both: who owns it and how the pad behaves.

↑ This step uses the figure at the top of the page.

On the RP2040 the choice is one field per pin, FUNCSEL in IO_BANK0 GPIOn_CTRL: 1 for SPI, 2 for UART, 3 for I²C, 5 for software GPIO (SIO) and so on. The table differs pin by pin: GPIO0 with FUNCSEL 2 is UART0 TX, GPIO4 with the same value is UART1 TX. After reset FUNCSEL is 0x1F, “no function”, and the SDK’s gpio_set_function() writes the chosen value and turns the pad’s input on.

STEP 2

The pad’s own settings

The pad has controls that apply whatever the owner:

controlwhat it doesRP2040 reset value
input enableconnects the input bufferon
pull-up / pull-downweak resistor to a rail (unit 1, lesson 3); both = bus keeper on the RP2040pull-down on
Schmitt triggerhysteresis on the input (unit 1, lesson 2)on
drive strengthhow hard the output drives: 2, 4, 8 or 12 mA settings4 mA
slew rateslow or fast edgesslow
output disableforces the driver off, whatever the owner wantsoff

That last row is a trap: the RP2040 bit called OD means output disable, not open-drain. Names are not portable; read the register description.

STEP 3

The STM32F4 way: several registers per port

An STM32F4 GPIO port splits the same decisions across registers, with a field per pin:

INTERACTIVEThe same choice on an STM32F4
The STM32F4 GPIO register fields for one pin and their valuesMODERbits 5:410alternate functionOTYPERbit 20push-pullPUPDRbits 5:400no pullAFR[0]bits 11:80111AF7to change only pin 2: MODER = (MODER & ~(3u << 4)) | (2u << 4)Alternate: the chosen peripheral drives the pin; OTYPER and the pulls still apply.
The STM32F4 GPIO register fields for one pin and their valuesMODERbits 5:410alternate functionOTYPERbit 20push-pullPUPDRbits 5:400no pullAFR[0]bits 11:80111AF7to change only pin 2: MODER = (MODER & ~(3u << 4)) |(2u << 4)Alternate: the chosen peripheral drives the pin;OTYPER and the pulls still apply.
MODER
PUPDR
Pin 2: MODER=10, OTYPER=0, PUPDR=00, AFR[0]=AF7.

An STM32F4 GPIO port spreads the choice over several registers: MODER picks input, output, alternate function or analog; OTYPER push-pull or open-drain; PUPDR the pulls; AFRL or AFRH which of 16 alternate functions (AF0–AF15). Register layout from ST’s stm32f407xx.h and HAL; which AF number reaches which peripheral on which pin is in the chip’s datasheet.

MODER (2 bits per pin) chooses input, output, alternate function or analog; OTYPER (1 bit) push-pull or open-drain; PUPDR (2 bits) the pulls; OSPEEDR the slew rate; and AFRL/AFRH (4 bits per pin) which alternate function, AF0 to AF15, the pin uses when MODER says “alternate”. The HAL names AF numbers after peripherals (GPIO_AF7_USART2); which pin offers which AF is in the chip’s datasheet, not the register header.

Because each field is a few bits of a shared word, changing one pin is a read-modify-write (unit 2, lesson 6): clear the pin’s field with a mask, OR in the new value, and do it where no interrupt handler changes the same register.

STEP 4

Worked example: USART2 on pin 2 of a port

Suppose the chip’s datasheet lists USART2 TX on pin PA2 as alternate function 7 (the HAL names USART2’s function AF7; the pin assignment itself must come from the datasheet of your exact part). The fields for pin 2:

MODER[5:4]=102,OTYPER[2]=0,PUPDR[5:4]=002,AFRL[11:8]=01112=7\text{MODER}[5{:}4] = 10_2,\quad \text{OTYPER}[2] = 0,\quad \text{PUPDR}[5{:}4] = 00_2,\quad \text{AFRL}[11{:}8] = 0111_2 = 7

The shifts come straight from the pin number: 2 bits per pin puts pin 2 at bits 5:4; 4 bits per pin in AFRL puts it at bits 11:8. In C:

RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;                           /* clock the port first */
GPIOA->AFR[0] = (GPIOA->AFR[0] & ~(0xFu << 8)) | (7u << 8);     /* AF7 = USART2 */
GPIOA->MODER = (GPIOA->MODER & ~(3u << 4)) | (2u << 4);        /* then alternate mode */

The order matters: writes to an unclocked port are ignored, and switching MODER before AFR holds 7 would briefly give the pin to AF0. ST’s HAL also writes AFR before MODER.

On the RP2040 the equivalent is one call, gpio_set_function(0, GPIO_FUNC_UART), which puts UART0 TX on GPIO0.

STEP 5

Planning pins

Assign pins on paper before the board is drawn. List every peripheral signal, the pins that offer it, and pick a combination with no overlaps; check the pins the board already uses (the debug port, the crystal, the RP2040’s dedicated QSPI flash pins) and the pins whose reset state matters for what they drive (lesson 5).

MYTHS AND FACTS

Common misconceptions

Writing the GPIO output register drives the pin

Only while software GPIO owns the pin; once a peripheral does, the software output register is ignored.

Any peripheral can use any pin

Each pin offers a fixed subset, listed in the datasheet or the FUNCSEL table.

OD means open-drain

On the RP2040 it means output disable. Check each register’s description.

AF7 is the UART on every chip

AF numbers are family-specific, and whether a peripheral appears on a given pin at all is in that part’s datasheet.

Check yourself

Answer in your head, then open the card.

On the RP2040, which pin carries UART1 TX according to the table in the figure, and with which FUNCSEL value?

GPIO4, FUNCSEL 2.

On an STM32F4, which bits of MODER and AFRH belong to pin 10?

MODER bits 21:20 (2 × 10 and 2 × 10 + 1); pin 10 is in AFRH (pins 8–15) at bits 4 × (10 − 8) = 8 to 11.

The code writes GPIOA->MODER = 2u << 4; to put pin 2 in alternate-function mode. What else happened?

Every other pin of port A was set to input (00), including any that were outputs or alternate functions, the debug pins among them. Use a masked read-modify-write.

Why does gpio_set_function() on the RP2040 also turn on the pad's input enable?

Many peripherals read the pin as well as drive it (UART RX, I²C, SPI), and the input enable may have been turned off: the boot ROM and the SDK's runtime clear it on GPIO26–29, and user code can clear it on any pin. Setting it makes sure the chosen function can see the pin.

Sources (3)
  1. Raspberry Pi Ltd, pico-sdk 1.5.1, src/rp2040/hardware_regs/include/hardware/regs/io_bank0.h and pads_bank0.h — GPIOn_CTRL FUNCSEL values per pin (GPIO0: 0 JTAG_TCK, 1 SPI0_RX, 2 UART0_TX, 3 I2C0_SDA, 4 PWM_A_0, 5 SIO_0, 6 PIO0_0, 7 PIO1_0, 9 USB_MUXING_OVERCURR_DETECT; GPIO4: 1 SPI0_RX, 2 UART1_TX …), FUNCSEL reset 0x1F; pads_bank0.h: GPIOn reset 0x56 (IE 1, DRIVE 4 mA, PDE 1, SCHMITT 1, SLEWFAST 0, PUE 0), DRIVE values 2/4/8/12 mA, OD = “Output disable. Has priority over output enable from peripherals”
  2. Raspberry Pi Ltd, pico-sdk 1.5.1, src/rp2_common/hardware_gpio/gpio.h and gpio.c — enum gpio_function (SPI 1, UART 2, I2C 3, PWM 4, SIO 5, PIO0 6, PIO1 7, GPCK 8, USB 9, NULL 0x1F); gpio_set_function sets IE, clears OD and writes FUNCSEL; gpio_init = input, output value 0, function SIO; “setting both pulls enables a bus keep function”
  3. STMicroelectronics, cmsis-device-f4 stm32f407xx.h, and stm32f4xx-hal-driver stm32f4xx_hal_gpio.h / _gpio_ex.h — GPIO_TypeDef: MODER 0x00, OTYPER 0x04, OSPEEDR 0x08, PUPDR 0x0C, IDR 0x10, ODR 0x14, BSRR 0x18, LCKR 0x1C, AFR[2] 0x20–0x24; MODE_INPUT 0, MODE_OUTPUT 1, MODE_AF 2, MODE_ANALOG 3; OUTPUT_PP 0, OUTPUT_OD 1; GPIO_NOPULL 0, PULLUP 1, PULLDOWN 2; AF numbers per peripheral, e.g. GPIO_AF7_USART2, GPIO_AF4_I2C1