Lesson 10: Introduction to the GPIO Port Control Register (GPIOPCTL)

What the GPIOPCTL Register Is

Every GPIO port on the TM4C123G and TM4C1294 owns one 32-bit GPIOPCTL register, located at offset 0x52C inside that port's register block. Its job is simple to state but easy to get wrong: it decides which peripheral signal a pin carries when the pin is switched out of plain-GPIO mode.

GPIOPCTL never works alone. It is the second half of a two-step handshake with the GPIOAFSEL (Alternate Function Select) register:

  • GPIOAFSEL answers the yes/no question: "Is this pin a plain GPIO, or an alternate function?" (0 = GPIO, 1 = alternate function).
  • GPIOPCTL answers the follow-up: "If it's an alternate function, then which one?"

A pin like PA6 can physically be routed to I2C1SCL, M1PWM2, and several other blocks. AFSEL only opens the door to "not-GPIO"; GPIOPCTL is what actually selects I2C1SCL versus M1PWM2. On both chips the reset value is 0x0000.0000, and because AFSEL also resets to 0, every ordinary pin comes up as a plain GPIO.

Note — both CPUs share the same structure. The register layout, the 0x52C offset, and the PMC0–PMC7 fields are identical on TM4C123G and TM4C1294. The only differences are: (1) the TM4C1294 has more ports (A through Q) and only AHB base addresses, while the TM4C123G offers both APB and AHB; and (2) the encoding values in the mux table differ between the two chips, so always read the table that belongs to your specific MCU.

When Do You Use It?

Use GPIOPCTL only when a pin must act as a digital peripheral signal — for example:

  • UART: U0Rx / U0Tx
  • SSI / SPI: SSI0Clk, SSI0Rx, SSI0Tx
  • I2C: I2C0SCL, I2C0SDA
  • PWM: M0PWM0, M1PWM5 …
  • Timer capture/compare: T0CCP0, WT2CCP1 …
  • CAN, QEI (PhA/PhB/IDX), etc.

You do not touch GPIOPCTL when:

  • The pin is a normal digital input or output (button, LED) — the default GPIO mode is already correct.
  • The pin is used as an analog input (ADC AINx) — analog routing is handled by GPIOAMSEL/GPIODEN, not by the PCTL mux. PCTL only selects digital peripheral functions.

The 4-bit-per-pin Idea

A GPIO port has 8 pins (0–7), and the register is 32 bits wide. Divide it up: 32 ÷ 8 = 4 bits per pin. So each pin gets its own 4-bit field, named PMCn (Port Mux Control n), where n is the pin number:

gpiopctl

FieldControls pinBit rangeShift (= pin × 4)
PMC0 0 3:0 0
PMC1 1 7:4 4
PMC2 2 11:8 8
PMC3 3 15:12 12
PMC4 4 19:16 16
PMC5 5 23:20 20
PMC6 6 27:24 24
PMC7 7 31:28 28

Four bits give 16 possible codes (0x0 – 0xF), which is exactly why the mux table has sixteen columns. Each pin can therefore choose from up to 16 signal options (most rows only fill a handful; the rest are reserved and shown as "—"). This is the register-level reason our projects define _PCTL_PINx as pin × 4 — that value is precisely how far you must shift a 4-bit code to land it in the right PMCn field.

How to Read and Search the PCTL Table

The mux table is a lookup grid. To find the value you need to write, follow four steps:

  1. Find the row for your pin (e.g., PA0).
  2. Scan across that row until you find the peripheral signal you want (e.g., U0Rx).
  3. Look up to the column header above that entry — the header is the 4-bit encoding (shown as 0x1, binary 0001).
  4. That header value is the number you write into the pin's PMCn field.

Worked Example — Route PA1 to UART0 TX (U0Tx)

  • In the PA1 row, U0Tx sits under the 0x1 column → the encoding is 0x1.
  • PA1 is pin 1 → field PMC1 → bits 7:4 → shift = 4 (_PCTL_PIN1).
  • Enable the alternate function, write the mux code into PMC1, then enable digital I/O:
// Route PA1 -> U0Tx (encoding 0x1)
GPIOA->AFSEL = _PIN1;                  // pin 1 = alternate function
GPIOA->PCTL  = (0x1 << _PCTL_PIN1);    // PMC1 = 0x1
GPIOA->DEN   = _PIN1;                  // enable digital I/O

The General Procedure to Enable Any Alternate Function

  1. Turn on the GPIO port clock (RCGCGPIO) and the peripheral clock (e.g., RCGCUART).
  2. Set the pin's bit in GPIOAFSEL.
  3. Write the correct 4-bit code into the matching PMCn field of GPIOPCTL.
  4. Set GPIODEN (digital enable) for the pin.
  5. For the special-consideration pins — PC0–PC3 (JTAG/SWD) and PD7 on both chips, plus PF0 on TM4C123G / PE7 on TM4C1294 — you must first unlock them via GPIOLOCK and un-commit via GPIOCR before any of the above will take effect.

Implementing It in Setup_GPIO()

In our labs the port initialization lives in a Setup_GPIO() function built from a fixed 8-step comment scaffold. Step 4 writes the PCTL mux code you looked up, and Step 5 raises AFSEL to hand the pin to the peripheral. The example below routes PA0 and PA1 to UART0 (U0Rx / U0Tx), mux code 0x1.

void Setup_GPIO(void)
{
    // Configure GPIOs
    // 1. Enable Clock to the GPIO Modules (SYSCTL->RCGCGPIO |= (_PORTs);)
    SYSCTL->RCGCGPIO |= (_PORTA);
    // allow time for clock to stabilize (SYSCTL->PRGPIO & (_PORTs))
    while ((SYSCTL->PRGPIO & (_PORTA)) != (_PORTA)) {};

    // 2. Unlock GPIO only PD7, PF0 on TM4C123G; PD7, PE7 on TM4C1294 (GPIOx->LOCK = 0x4C4F434B; and GPIOx->CR = _PINs;)
    //    -> PA0 / PA1 are ordinary pins: no unlock needed here.

    // 3. Set Analog Mode Select bits for each Port (GPIOx->AMSEL = _PINs;)
    //    -> UART is a DIGITAL function: leave AMSEL cleared (do nothing).

    // 4. Set Port Control Register for each Port (GPIOx->PCTL = PMCn << _PCTL_PINn, check the PCTL table)
    GPIOA->PCTL = (0x1 << _PCTL_PIN0)    // PA0 -> U0Rx
                | (0x1 << _PCTL_PIN1);   // PA1 -> U0Tx

    // 5. Set Alternate Function Select bits for each Port (GPIOx->AFSEL = _PINs;)
    GPIOA->AFSEL = _PIN0 | _PIN1;

    // 6. Set the output pins for each port only (Direction of the Pins: GPIOx->DIR = _PINs;)
    //    -> Not needed: once AFSEL routes the pins to UART0, the peripheral owns their direction.

    // 7. Set PUR bits (internal Pull-Up Resistor), PDR (Pull-Down Resistor), ODR (Open Drain) for each Port
    //    -> Not needed for a push-pull UART. (I2C would set ODR on its SDA pin here.)

    // 8. Set Digital ENable register on all digital port.pins (GPIOx->DEN = _PINs;)
    GPIOA->DEN = _PIN0 | _PIN1;
}
Tip — PCTL before AFSEL. Filling in PCTL first (step 4) and only then raising AFSEL (step 5) means the pin is never left in alternate-function mode with an undefined mux selection. Set the destination, then throw the switch.

Do Peripheral Pins Need DIR, PUR, PDR, ODR — and DEN?

Once a pin is handed to a peripheral through PCTL (step 4) and AFSEL (step 5), most of the "GPIO personality" registers stop mattering — but one still does. Here is the rule for each:

  • Step 6 — DIR (direction): Not needed. When AFSEL = 1, the peripheral hardware drives the pin's direction internally. GPIODIR only applies to plain-GPIO pins; setting it on an alternate-function pin has no effect. So skip step 6 for peripheral pins — use it only for the GPIO output pins in the same port.
  • Step 7 — PUR / PDR (pull-up / pull-down): Usually not needed. Digital peripherals such as UART, SSI/SPI, PWM, and Timer are push-pull — they actively drive the line, so no pull resistor is required. You would only add one to give a defined idle level to a floating input line, which is an electrical choice, not a mux requirement.
  • Step 7 — ODR (open drain): Only for open-drain buses. The classic case is I2C: you set ODR on the SDA pin (SCL stays standard/push-pull) and rely on pull-ups, usually external. For UART/SSI/PWM you leave ODR cleared.
  • Step 8 — DEN (digital enable): Always needed. DEN switches on the pin's digital I/O pad. Without it the pin carries nothing — not a GPIO signal and not the peripheral signal you just muxed in. Every digital peripheral pin must have its DEN bit set. The only time you leave DEN cleared is for an analog function (ADC input, analog comparator), where you set AMSEL in step 3 instead.
StepRegisterNeeded for a peripheral pin?
3 AMSEL No — leave cleared (digital function)
6 DIR No — the peripheral controls direction
7 PUR / PDR Usually no — only to set an idle level
7 ODR Only for open-drain buses (I2C SDA)
8 DEN Yes, always — enables the digital pad

Rule of thumb: for a digital peripheral pin you touch only PCTL (4), AFSEL (5), and DEN (8) — plus ODR (7) if, and only if, the peripheral is I2C.

Reminder. The encoding values shown above (e.g., U0Tx = 0x1) come from the TM4C123G mux table. When you target the TM4C1294, look the signal up again in its table — the same peripheral may sit under a different column.

 


TM4C123G MCU

EK TM4C123GXL s

I/O Analog
Function
Digital Function (GPIOx->PCTL PMCn Field Encoding)
0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
PA0 GPIO U0Rx CAN1Rx
PA1 GPIO U0Tx CAN1Tx
PA2 GPIO SSI0CLK
PA3 GPIO SSI0Fss
PA4 GPIO SSI0Rx
PA5 GPIO SSI0Tx
PA6 GPIO I2C1SCL M1PWM2
PA7 GPIO I2C1SDA M1PWM3
PB0 USB0ID GPIO U1Rx T2CCP0
PB1 USB0VBUS GPIO U1Tx T2CCP1
PB2 GPIO I2C0SCL T3CCP0
PB3 GPIO I2C0SDA T3CCP1
PB4 AIN10 GPIO SSI2Clk M0PWM2 T1CCP0 CAN0Rx
PB5 AIN11 GPIO SSI2Fss M0PWM3 T1CCP1 CAN0Tx
PB6 GPIO SSI2Rx M0PWM0 T0CCP0
PB7 GPIO SSI2Tx M0PWM1 T0CCP1
PC0 GPIO TCK
SWCLK
T4CCP0
PC1 GPIO TMS
SWDIO
T4CCP1
PC2 GPIO TDI T5CCP0
PC3 GPIO TDO
SWO
T5CCP1
PC4 C1- GPIO U4Rx U1Rx M0PWM6 IDX1 WT0CCP0 U1RTS
PC5 C1+ GPIO U4Tx U1Tx M0PWM7 PhA1 WT0CCP1 U1CTS
PC6 C0+ GPIO U3Rx PhB1 WT1CCP0 USB0EPEN
PC7 C0- GPIO U3Tx WT1CCP1 USB0PFLT
PD0 AIN7 GPIO SSI3Clk SSI1Clk I2C3SCL M0PWM6 M1PWM0 WT2CCP0
PD1 AIN6 GPIO SSI3Fss SSI1Fss I2C3SDA M0PWM7 M1PWM1 WT2CCP1
PD2 AIN5 GPIO SSI3Rx SSI1Rx M0FAILT0 WT3CCP0 USB0EPEN
PD3 AIN4 GPIO SSI3Tx SSI1Tx IDX0 WT3CCP1 USB0PFLT
PD4 USB0DM GPIO U6Rx WT4CCP0
PD5 USB0DP GPIO U6Tx WT4CCP1
PD6 GPIO U2Rx M0FAULT0 PhA0 WT5CCP0
PD7 GPIO U2Tx PhB0 WT5CCP1 NMI
PE0 AIN3 GPIO U7Rx
PE1 AIN2 GPIO U7Tx
PE2 AIN1 GPIO
PE3 AIN0 GPIO
PE4 AIN9 GPIO U5Rx I2C2SCL M0PWM4 M1PWM2 CAN0Rx
PE5 AIN8 GPIO U5Tx I2C3SDA M0PWM5 M1PWM3 CAN0TX
PF0 GPIO U1RTS SSI1Rx CAN0Rx M1PWM4 PhA0 T0CCP0 NMI C0o
PF1 GPIO U1CTS SSI1Tx M1PWM5 PhB0 T0CCP1 C1o TRD1
PF2 GPIO SSI1Clk M0FAULT0 M1PWM6 T1CCP0 TRD0
PF3 GPIO SSI1Fss CAN0Tx M1PWM7 T1CCP1 TRCLK
PF4 GPIO M1FAULT0 IDX0 T2CCP0 USB0EPEN
I/O Analog
Function
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
Digital Function (GPIOx->PCTL PMCn Field Encoding)

PD7 and PF0 are configured as GPIO by default but is locked and can only be reprogrammed by unlocking the pin in the GPIOLOCK register and uncommitting it by setting the GPIOCR register.

 

 

© 2026 Air Supply Information Center (Air Supply BBS)