GPIO port-wide operations in Embedded C - Time & Space Complexity
When working with GPIO ports, we often perform operations on all pins at once. Understanding how the time to do this changes with the number of pins helps us write efficient code.
We want to know how the time needed grows as the port size changes.
Analyze the time complexity of the following code snippet.
// Set all pins of a GPIO port to high
void set_all_pins_high(volatile uint32_t *port, int pin_count) {
for (int i = 0; i < pin_count; i++) {
*port |= (1U << i); // Set pin i high
}
}
This code sets each pin of a GPIO port to high one by one using a loop.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The for-loop that sets each pin high.
- How many times: The loop runs once for each pin, so pin_count times.
As the number of pins increases, the loop runs more times, so the total work grows proportionally.
| Input Size (pin_count) | Approx. Operations |
|---|---|
| 10 | 10 operations |
| 100 | 100 operations |
| 1000 | 1000 operations |
Pattern observation: Doubling the number of pins roughly doubles the work done.
Time Complexity: O(n)
This means the time to set all pins grows linearly with the number of pins.
[X] Wrong: "Setting all pins at once is always constant time because it's one operation on the port register."
[OK] Correct: In this code, each pin is set individually in a loop, so the time depends on how many pins there are, not just one operation.
Understanding how loops over hardware registers affect performance shows you can think about real embedded system costs, a valuable skill for many programming tasks.
"What if we replaced the loop with a single write that sets all pins at once? How would the time complexity change?"
Practice
PORTB in embedded C typically do in GPIO port-wide operations?Solution
Step 1: Understand PORT register role
The PORT register controls the output voltage levels on the pins of a GPIO port.Step 2: Effect of writing to PORTB
Writing a value to PORTB sets the output state (high or low) of all pins in port B simultaneously.Final Answer:
Sets the output levels of all pins in port B at once -> Option BQuick Check:
PORTB write = set output levels [OK]
- Confusing PORT with DDR (direction register)
- Thinking PORT reads input levels
- Assuming PORT configures pull-ups
Solution
Step 1: Identify DDR register purpose
DDRx registers set pin directions: 1 for output, 0 for input.Step 2: Set all pins of port D as output
Writing 0xFF (all bits 1) to DDRD sets all pins as outputs.Final Answer:
DDRD = 0xFF; -> Option CQuick Check:
DDRD = 0xFF sets all outputs [OK]
- Using PORTD instead of DDRD to set direction
- Writing to PINB which is read-only
- Setting DDRB instead of DDRD
DDRC = 0x00;
PORTC = 0xFF;
uint8_t val = PINC;
What is the value of
val assuming all pins on port C are externally connected to ground?Solution
Step 1: Analyze DDRC and PORTC settings
DDRC = 0x00 sets all pins as inputs. PORTC = 0xFF enables pull-up resistors on all pins.Step 2: Effect of external ground on input pins
Even with pull-ups enabled, external ground forces pins low, so PINC reads 0x00.Final Answer:
0x00 -> Option AQuick Check:
Input pins grounded read 0x00 [OK]
- Assuming pull-ups force input high regardless
- Confusing PORTC write with output level
- Ignoring DDRC input configuration
DDRA = 0xFF;
PINA = 0xFF;
Solution
Step 1: Check register purpose
PINA reads input levels or toggles outputs, but does not directly set output levels.Step 2: Correct register to set output levels
To set output pins high, write to PORTA, not PINx.Final Answer:
PORTA should be used instead of PINA to set outputs -> Option AQuick Check:
Use PORTA to write outputs, not PINx [OK]
- Using PINx registers instead of PORTx for outputs
- Writing outputs to PIN register
- Confusing DDR and PORT registers
Solution
Step 1: Set pins 0-3 as outputs
Bits 0-3 set to 1 in DDRC means DDRC = 0x0F (00001111 binary).Step 2: Enable pull-ups on pins 4-7 inputs
Pins 4-7 inputs require DDRC bits 4-7 = 0, and PORTC bits 4-7 = 1 to enable pull-ups, so PORTC = 0xF0.Final Answer:
DDRC = 0x0F; PORTC = 0xF0; -> Option DQuick Check:
Outputs low nibble, pull-ups high nibble [OK]
- Mixing up which bits control direction vs pull-ups
- Setting pull-ups on output pins
- Using wrong hex values for bit masks
Ready to prove it?
Pass the test and this pattern moves unknown
