Eliminate all fragile LaTeX math syntax in WEEK05a.md and rebuild companion PDF for flawless Canvas rendering

This commit is contained in:
Kevin Thomas committed 2026-10-19 06:24:13 -04:00
1 parent 04a6a8e346
commit cffc47ce33
2 files changed
+41 -37

No files matched your search

+41 -37
View File
@@ -21,9 +21,9 @@ By using this repository and course, you acknowledge and agree that:
By the end of this tutorial, you will be able to:
- Master the physical silicon reality of General Purpose Input/Output (GPIO) on the RP2350 microcontroller from Chapter 9 of the datasheet.
- Understand why microcontroller pins are never simple wires, dissecting the split between the internal 1.1V digital core domain ($V_{\text{core}} / \text{DVDD}$) and the external 3.3V analog pad ring domain ($V_{\text{io}} / \text{IOVDD}$).
- Understand why microcontroller pins are never simple wires, dissecting the split between the internal 1.1V digital core domain (Vcore / DVDD) and the external 3.3V analog pad ring domain (Vio / IOVDD).
- Decouple the two independent hardware layers: electrical pad configuration (`PADS_BANK0` at `0x40038000`) versus digital crossbar multiplexing (`IO_BANK0` at `0x40028000`).
- Dissect every bitfield of `PADS_BANK0`: Output Disable (`OD`), Input Enable (`IE`), Pad Isolation (`ISO`), Drive Strength ($2/4/8/12\text{ mA}$), Pull-Up (`PUE`), Pull-Down (`PDE`), Schmitt Trigger (`SCHMITT`), and Slew Rate (`SLEWFAST`).
- Dissect every bitfield of `PADS_BANK0`: Output Disable (`OD`), Input Enable (`IE`), Pad Isolation (`ISO`), Drive Strength (2/4/8/12 mA), Pull-Up (`PUE`), Pull-Down (`PDE`), Schmitt Trigger (`SCHMITT`), and Slew Rate (`SLEWFAST`).
- Discover why unconfigured RP2350 pins are physically isolated by default (`ISO = 1`) and why digital input buffers are disconnected (`IE = 0`) to prevent catastrophic CMOS shoot-through leakage current.
- Master RP2350 **Bus Keeper Mode**, activated by setting both `PUE = 1` and `PDE = 1` to weakly latch floating line states without power dissipation.
- Navigate the digital crossbar switchboard in `IO_BANK0`: function selection (`FUNCSEL 0..31`), peripheral routing (UART, SPI, I2C, PWM, SIO, PIO), and signal overrides (`OUTOVER`, `OEOVER`, `INOVER`, `IRQOVER`).
@@ -44,11 +44,11 @@ In software, a developer writes `gpio_put(16, 1)` and visualizes a direct wire c
A modern microcontroller die like the RP2350 is divided into two radically distinct physical and electrical domains:
1. **The Internal Digital Core Domain ($1.1\text{ V}$ nominal $\text{DVDD}$):**
The central silicon die contains the dual ARM Cortex-M33 processors, the bus fabric, static RAM, cache controllers, and digital peripheral state machines (UART, SPI, PIO). These circuits are fabricated using ultra-thin, low-voltage nanoscale transistors designed exclusively for high switching speeds ($150\text{ MHz}$) and ultra-low power consumption. These microscopic gates cannot tolerate voltages above $1.21\text{ V}$. Connecting an external $3.3\text{ V}$ signal directly to a core gate would instantly cause dielectric oxide breakdown, permanently melting the transistor.
1. **The Internal Digital Core Domain (1.1V nominal DVDD):**
The central silicon die contains the dual ARM Cortex-M33 processors, the bus fabric, static RAM, cache controllers, and digital peripheral state machines (UART, SPI, PIO). These circuits are fabricated using ultra-thin, low-voltage nanoscale transistors designed exclusively for high switching speeds (150 MHz) and ultra-low power consumption. These microscopic gates cannot tolerate voltages above 1.21V. Connecting an external 3.3V signal directly to a core gate would instantly cause dielectric oxide breakdown, permanently melting the transistor.
2. **The External Pad Ring Domain ($1.8\text{ V} - 3.3\text{ V}$ nominal $\text{IOVDD}$):**
Surrounding the perimeter of the die is the **Pad Ring**. The pad ring consists of specialized, high-voltage analog and electrical interface cells ("pad cells") fabricated with thick-oxide transistors. These cells translate internal $1.1\text{ V}$ digital logic signals up to external $3.3\text{ V}$ board voltages, provide electrostatic discharge (ESD) protection diodes, supply high output drive currents (up to $12\text{ mA}$) to charge external capacitive PCB traces, and filter noisy incoming analog edges.
2. **The External Pad Ring Domain (1.8V - 3.3V nominal IOVDD):**
Surrounding the perimeter of the die is the **Pad Ring**. The pad ring consists of specialized, high-voltage analog and electrical interface cells ("pad cells") fabricated with thick-oxide transistors. These cells translate internal 1.1V digital logic signals up to external 3.3V board voltages, provide electrostatic discharge (ESD) protection diodes, supply high output drive currents (up to 12 mA) to charge external capacitive PCB traces, and filter noisy incoming analog edges.
```
+-----------------------------------------------------------------+
| RP2350 GPIO HARDWARE SUBSYSTEM ARCHITECTURE |
@@ -91,11 +91,11 @@ A modern microcontroller die like the RP2350 is divided into two radically disti
```
### The Physical Hazards of Uncontrolled I/O
Why can't a microcontroller provide a single "GPIO register" where bit $n$ directly drives pin $n$? Because every physical pin faces severe physical and electrical constraints:
Why can't a microcontroller provide a single "GPIO register" where bit n directly drives pin n? Because every physical pin faces severe physical and electrical constraints:
- **CMOS Shoot-Through Current:** When a CMOS digital input buffer encounters a voltage near mid-rail (e.g., $1.65\text{ V}$ on a $3.3\text{ V}$ rail), both the upper P-channel and lower N-channel MOSFETs turn partially ON simultaneously. This creates a low-resistance path directly from `IOVDD` to ground, dissipating substantial leakage current and generating heat. To prevent this on unused or analog pins (such as ADC inputs), the chip must provide a hardware switch to completely disconnect the input buffer (`IE = 0`).
- **CMOS Shoot-Through Current:** When a CMOS digital input buffer encounters a voltage near mid-rail (e.g., 1.65V on a 3.3V rail), both the upper P-channel and lower N-channel MOSFETs turn partially ON simultaneously. This creates a low-resistance path directly from `IOVDD` to ground, dissipating substantial leakage current and generating heat. To prevent this on unused or analog pins (such as ADC inputs), the chip must provide a hardware switch to completely disconnect the input buffer (`IE = 0`).
- **Electrostatic Discharge (ESD):** External human touch or inductive spikes can inject thousands of volts into a pin. Pad cells integrate dual clamping diodes to shunt overvoltage spikes safely into power and ground rails.
- **Power Domain Collapse during Deep Sleep:** When the RP2350 enters low-power dormant sleep, the $1.1\text{ V}$ core voltage can be completely powered down by the Power Manager (`POWMAN`). If the pad ring were directly connected to the core, the unpowered core outputs would float, causing external actuators, transceivers, or power supplies to turn on uncontrollably. The pad ring must therefore integrate **Pad Isolation Latches (`ISO`)** that freeze the external electrical state even when the CPU and digital core no longer exist!
- **Power Domain Collapse during Deep Sleep:** When the RP2350 enters low-power dormant sleep, the 1.1V core voltage can be completely powered down by the Power Manager (`POWMAN`). If the pad ring were directly connected to the core, the unpowered core outputs would float, causing external actuators, transceivers, or power supplies to turn on uncontrollably. The pad ring must therefore integrate **Pad Isolation Latches (`ISO`)** that freeze the external electrical state even when the CPU and digital core no longer exist!
To solve these orthogonal challenges, the RP2350 divides GPIO into a clean three-tier hardware hierarchy:
- **`PADS_BANK0` (`0x40038000`):** Governs the electrical pad cells along the silicon die perimeter.
@@ -200,14 +200,14 @@ Let us examine each bitfield with silicon-level precision:
- **The Input Gotcha:** If you want to read digital input from a button or serial line using SIO (`sio_hw->gpio_in`), you **must explicitly set `IE = 1`** in `PADS_BANK0`. If `IE = 0`, reading `GPIO_IN` will always return `0`, regardless of the voltage applied to the physical pin!
#### 4. DRIVE (Bits 5:4) - Output Drive Strength
- **Reset Value:** `0x1` ($4\text{ mA}$).
- **Reset Value:** `0x1` (4 mA).
- **Options:** `00 = 2mA`, `01 = 4mA`, `10 = 8mA`, `11 = 12mA`.
- **Silicon Implementation:** Inside the pad cell, the output push-pull stage consists of parallel arrays of PMOS (pull-up) and NMOS (pull-down) transistors. Selecting $2\text{ mA}$ enables a single transistor pair; selecting $12\text{ mA}$ switches on all parallel pairs, dramatically lowering the driver's output resistance ($R_{\text{on}}$).
- **Engineering Trade-off:** High drive strength ($12\text{ mA}$) charges external trace capacitance rapidly, enabling high-speed $50\text{ MHz}+$ SPI clocks. However, it generates sharp current transients ($dI/dt$), leading to ground bounce, ringing, and electromagnetic interference (EMI). Low drive strength ($2\text{ mA}$) softens transitions, producing clean, low-noise waveforms on sensitive sensor buses.
- **Silicon Implementation:** Inside the pad cell, the output push-pull stage consists of parallel arrays of PMOS (pull-up) and NMOS (pull-down) transistors. Selecting 2 mA enables a single transistor pair; selecting 12 mA switches on all parallel pairs, dramatically lowering the driver's output resistance (Ron).
- **Engineering Trade-off:** High drive strength (12 mA) charges external trace capacitance rapidly, enabling high-speed 50 MHz+ SPI clocks. However, it generates sharp current transients (dI/dt), leading to ground bounce, ringing, and electromagnetic interference (EMI). Low drive strength (2 mA) softens transitions, producing clean, low-noise waveforms on sensitive sensor buses.
#### 5. PUE (Bit 3) & PDE (Bit 2) - Pull-Up and Pull-Down Resistors
- **Reset Value:** `PUE = 0`, `PDE = 1` (Pads reset with weak pull-downs active!).
- **Electrical Specification:** Nominal internal resistance of approximately $50\text{ k}\Omega$ to `IOVDD` (PUE) or ground (PDE).
- **Electrical Specification:** Nominal internal resistance of approximately 50 kOhm to `IOVDD` (PUE) or ground (PDE).
- **Bus Keeper Mode (Section 9.6.1):** What happens if software sets both `PUE = 1` and `PDE = 1` simultaneously? On older microcontrollers, this would create an illegal cross-conduction voltage divider dissipating power. On the RP2350, setting both bits activates **Bus Keeper Mode**! In this mode:
- If the pad's voltage is High, the pad pulls weakly Up.
- If the pad's voltage is Low, the pad pulls weakly Down.
@@ -215,11 +215,11 @@ Let us examine each bitfield with silicon-level precision:
#### 6. SCHMITT (Bit 1) - Schmitt Trigger Enable
- **Reset Value:** `0x1` (Enabled).
- **Function:** Adds voltage hysteresis to the input comparator ($V_{\text{IH}} \approx 2.0\text{ V}$, $V_{\text{IL}} \approx 0.8\text{ V}$). If an incoming digital signal has a slow rise time or is corrupted by high-frequency noise, the Schmitt trigger prevents false multi-triggering and oscillation at the digital threshold.
- **Function:** Adds voltage hysteresis to the input comparator (VIH ~ 2.0V, VIL ~ 0.8V). If an incoming digital signal has a slow rise time or is corrupted by high-frequency noise, the Schmitt trigger prevents false multi-triggering and oscillation at the digital threshold.
#### 7. SLEWFAST (Bit 0) - Slew Rate Control
- **Reset Value:** `0x0` (Slow).
- **Function:** `0 = Slow`, `1 = Fast`. Slow slew rate actively limits the edge rate ($dV/dt$) of the output buffer, minimizing radiated emissions and transmission-line reflections on unterminated PCB traces. Fast slew rate is required for high-frequency interfaces like QSPI, HSTX, or high-speed UART.
- **Function:** `0 = Slow`, `1 = Fast`. Slow slew rate actively limits the edge rate (dV/dt) of the output buffer, minimizing radiated emissions and transmission-line reflections on unterminated PCB traces. Fast slew rate is required for high-frequency interfaces like QSPI, HSTX, or high-speed UART.
---
@@ -245,12 +245,16 @@ None of these peripherals own any dedicated physical pins! Instead, every periph
In `IO_BANK0`, every GPIO pin occupies an **8-byte stride** containing two 32-bit registers (Section 9.11.1, Table 649):
$$\text{GPIOx\_STATUS Offset} = 0\text{x}000 + (8 \times x)$$
$$\text{GPIOx\_CTRL Offset} = 0\text{x}004 + (8 \times x)$$
```text
GPIOx_STATUS Offset = 0x000 + (8 * x)
GPIOx_CTRL Offset = 0x004 + (8 * x)
```
For example, for GPIO 16:
$$\text{GPIO16\_CTRL Offset} = 0\text{x}004 + (8 \times 16) = 0\text{x}004 + 0\text{x}080 = 0\text{x}084$$
$$\text{Physical Address} = 0\text{x}40028000 + 0\text{x}084 = 0\text{x}40028084$$
```text
GPIO16_CTRL Offset = 0x004 + (8 * 16) = 0x004 + 0x080 = 0x084
Physical Address = 0x40028000 + 0x084 = 0x40028084
```
### The GPIOx_CTRL Register: Function Selection & Overrides
```
@@ -404,14 +408,14 @@ According to **Section 3.6.1**, the GPIOC instruction set provides instantaneous
#### 1. Single-Bit Output Enable (gpioc_bit_oe_put)
- **Opcode:** `mcrr p0, #4, Rt, Rt2, c4`
- `Rt`: General-purpose register holding the pin number ($0..47$).
- `Rt2`: General-purpose register holding the 1-bit value ($1 = \text{Output}, 0 = \text{Input}$).
- `Rt`: General-purpose register holding the pin number (0..47).
- `Rt2`: General-purpose register holding the 1-bit value (1 = Output, 0 = Input).
- **Operation:** Atomically sets or clears the output enable for pin `Rt` in **1 single clock cycle**! No 32-bit addresses, no bit-shifts (`1 << pin`), and zero bus traffic!
#### 2. Single-Bit Output Data (gpioc_bit_out_put)
- **Opcode:** `mcrr p0, #4, Rt, Rt2, c0`
- `Rt`: Pin number ($0..47$).
- `Rt2`: Value ($1 = \text{High}, 0 = \text{Low}$).
- `Rt`: Pin number (0..47).
- `Rt2`: Value (1 = High, 0 = Low).
- **Operation:** Atomically drives pin `Rt` High or Low in 1 clock cycle.
#### 3. Single-Pin Direct Toggling / Setting / Clearing
@@ -465,20 +469,20 @@ static void asm_init_gpio_range(void) {
1. **`ldr r3, =0x40038000`:** Loads `PADS_BANK0_BASE` into `r3`.
2. **`ldr r2, =0x40028004`:** Loads the address of `IO_BANK0: GPIO0_CTRL` into `r2`.
3. **`movs r0, #16`:** Sets loop counter starting at GPIO 16.
4. **`lsls r1, r0, #2`:** Multiplies pin number by 4 ($16 \times 4 = 64 = 0\text{x}40$).
5. **`adds r4, r3, r1`:** Calculates the pad register address ($0\text{x}40038000 + 0\text{x}40 = 0\text{x}40038040$).
4. **`lsls r1, r0, #2`:** Multiplies pin number by 4 (16 * 4 = 64 = 0x40).
5. **`adds r4, r3, r1`:** Calculates the pad register address (0x40038000 + 0x40 = 0x40038040).
6. **`ldr r5, [r4]`:** Reads current pad configuration.
7. **`bic r5, r5, #0x180`:** Clears bits 7 and 8 ($0\text{x}180 = 0001\,1000\,0000_2$):
- **Bit 7 (`OD`):** Cleared to `0` $\rightarrow$ Output driver enabled!
- **Bit 8 (`ISO`):** Cleared to `0` $\rightarrow$ Pad isolation latch de-asserted! The pad is connected to internal core logic!
8. **`orr r5, r5, #0x40`:** Sets bit 6 ($0\text{x}40 = 0100\,0000_2$):
- **Bit 6 (`IE`):** Set to `1` $\rightarrow$ Input buffer enabled!
7. **`bic r5, r5, #0x180`:** Clears bits 7 and 8 (0x180 = 0001 1000 0000b):
- **Bit 7 (`OD`):** Cleared to `0` -> Output driver enabled!
- **Bit 8 (`ISO`):** Cleared to `0` -> Pad isolation latch de-asserted! The pad is connected to internal core logic!
8. **`orr r5, r5, #0x40`:** Sets bit 6 (0x40 = 0100 0000b):
- **Bit 6 (`IE`):** Set to `1` -> Input buffer enabled!
9. **`str r5, [r4]`:** Writes new configuration back to `PADS_BANK0`. The physical pad cell is now electrically active!
10. **`lsls r1, r0, #3`:** Multiplies pin number by 8 ($16 \times 8 = 128 = 0\text{x}80$).
11. **`adds r4, r2, r1`:** Calculates `GPIO16_CTRL` address ($0\text{x}40028004 + 0\text{x}80 = 0\text{x}40028084$).
10. **`lsls r1, r0, #3`:** Multiplies pin number by 8 (16 * 8 = 128 = 0x80).
11. **`adds r4, r2, r1`:** Calculates `GPIO16_CTRL` address (0x40028004 + 0x80 = 0x40028084).
12. **`ldr r5, [r4]`:** Reads current control register.
13. **`bic r5, r5, #0x1f`:** Clears bits 4:0 (`FUNCSEL`), wiping out the reset value of `31` (NULL).
14. **`orr r5, r5, #5`:** Sets `FUNCSEL = 5` $\rightarrow$ Connects pin 16 to the SIO block!
14. **`orr r5, r5, #5`:** Sets `FUNCSEL = 5` -> Connects pin 16 to the SIO block!
15. **`str r5, [r4]`:** Writes back to `IO_BANK0`. The digital routing switchboard is now connected!
16. **`mcrr p0, #4, r4, r5, c4`:** Calls `gpioc_bit_oe_put(16, 1)`. The GPIO coprocessor on port `p0` sets the Output Enable bit in SIO in 1 single clock cycle!
@@ -504,7 +508,7 @@ static void asm_blink_pin(uint8_t pin) {
```
- When `mcrr p0, #4, r4, r5, c0` executes with `r5 = 1`, the coprocessor drives the output bit High in 1 cycle.
- The high signal flows from SIO $\rightarrow$ `IO_BANK0` multiplexer $\rightarrow$ Voltage Level Shifter ($1.1\text{V} \rightarrow 3.3\text{V}$) $\rightarrow$ `PADS_BANK0` push-pull MOSFET driver $\rightarrow$ Physical Pin 16 $\rightarrow$ LED illuminates!
- The high signal flows from SIO -> `IO_BANK0` multiplexer -> Voltage Level Shifter (1.1V -> 3.3V) -> `PADS_BANK0` push-pull MOSFET driver -> Physical Pin 16 -> LED illuminates!
- When `mcrr p0, #4, r4, r5, c0` executes with `r5 = 0`, the coprocessor drives the output bit Low in 1 cycle, turning off the LED.
---
@@ -582,8 +586,8 @@ io_bank0->GPIO[16].CTRL = (io_bank0->GPIO[16].CTRL & ~0x1f) | FUNCSEL_SIO;
### Architectural Summary
1. **Hardware Split:** RP2350 enforces a strict division between electrical physics (`PADS_BANK0`) and digital logic (`IO_BANK0`).
2. **PADS_BANK0 (`0x40038000`):** Manages analog pad cells. Controls `ISO` (isolation latch), `OD` (output disable), `IE` (input enable), `DRIVE` ($2/4/8/12\text{ mA}$), `PUE`/`PDE` (pulls and Bus Keeper), `SCHMITT`, and `SLEWFAST`.
3. **IO_BANK0 (`0x40028000`):** Manages digital crossbar routing. Controls `FUNCSEL` (functions 0..31; $5 = \text{SIO}$), logic overrides (`OUTOVER`, `OEOVER`, `INOVER`, `IRQOVER`), and edge/level interrupt generation.
2. **PADS_BANK0 (`0x40038000`):** Manages analog pad cells. Controls `ISO` (isolation latch), `OD` (output disable), `IE` (input enable), `DRIVE` (2/4/8/12 mA), `PUE`/`PDE` (pulls and Bus Keeper), `SCHMITT`, and `SLEWFAST`.
3. **IO_BANK0 (`0x40028000`):** Manages digital crossbar routing. Controls `FUNCSEL` (functions 0..31; 5 = SIO), logic overrides (`OUTOVER`, `OEOVER`, `INOVER`, `IRQOVER`), and edge/level interrupt generation.
4. **SIO (`0xd0000000`):** Single-Cycle I/O memory-mapped registers for 32-bit atomic bit set, clear, toggle, and read.
5. **GPIOC (Coprocessor Port `p0`):** Native ARMv8-M coprocessor hardware enabling 1-cycle single-bit output and output-enable manipulation (`mcrr p0, #4`), single-pin toggling (`mcr p0, #5`), and 64-bit sampling (`mrrc p0, #0`) with zero memory bus overhead.
@@ -599,7 +603,7 @@ io_bank0->GPIO[16].CTRL = (io_bank0->GPIO[16].CTRL & ~0x1f) | FUNCSEL_SIO;
| **SIO** | `0xd0000000` | `GPIO_OUT_SET` (`+0x14`) | Bits 31:0: Atomic bit set High |
| **SIO** | `0xd0000000` | `GPIO_OUT_CLR` (`+0x18`) | Bits 31:0: Atomic bit clear Low |
| **SIO** | `0xd0000000` | `GPIO_OUT_XOR` (`+0x1c`) | Bits 31:0: Atomic bit toggle |
| **SIO** | `0xd0000000` | `GPIO_OE` (`+0x20`) | Bits 31:0: Output enable ($1=\text{Out}, 0=\text{In}$) |
| **SIO** | `0xd0000000` | `GPIO_OE` (`+0x20`) | Bits 31:0: Output enable (`1 = Out, 0 = In`) |
| **SIO** | `0xd0000000` | `GPIO_IN` (`+0x04`) | Bits 31:0: Direct input sample (Requires `IE=1`) |
| **GPIOC** | Port `p0` | `mcrr p0, #4, Rt, Rt2, c4` | Single-pin atomic output enable write (`gpioc_bit_oe_put`) |
| **GPIOC** | Port `p0` | `mcrr p0, #4, Rt, Rt2, c0` | Single-pin atomic output data write (`gpioc_bit_out_put`) |
Binary file not shown.