0
0
Embedded Cprogramming~10 mins

Memory-mapped I/O concept in Embedded C - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - Memory-mapped I/O concept
CPU wants to read/write
Access address
Is address in RAM?
YesRead/Write RAM
No
Is address in I/O range?
YesAccess device register
No
Invalid address
CPU uses normal memory instructions to access RAM or device registers by address; addresses in I/O range connect to hardware devices.
Execution Sample
Embedded C
volatile unsigned int *LED = (volatile unsigned int *)0x40000000;
*LED = 0x1;
unsigned int val = *LED;
Write 1 to LED device register at address 0x40000000, then read back its value.
Execution Table
StepActionAddress AccessedValue Written/ReadResult
1Set pointer LED to address 0x400000000x40000000N/APointer LED points to device register
2Write value 0x1 to *LED0x400000000x1LED device register updated to 1 (turn on LED)
3Read value from *LED0x40000000N/AValue read is 0x1 (LED state)
💡 All memory accesses completed; device register at 0x40000000 used for I/O
Variable Tracker
VariableStartAfter Step 1After Step 2After Step 3
LED (pointer)undefined0x400000000x400000000x40000000
*LED (device register)unknownunknown0x10x1
valundefinedundefinedundefined0x1
Key Moments - 3 Insights
Why do we use a pointer to a fixed address for device access?
Because device registers are mapped to specific memory addresses, using a pointer lets CPU read/write them like normal memory (see execution_table step 1).
What does 'volatile' mean in the pointer declaration?
'volatile' tells the compiler not to optimize away reads/writes because device registers can change independently (see execution_table steps 2 and 3).
Why does reading from *LED return the value we wrote?
Because the device register at that address holds the current state, so reading it returns the last written value (see execution_table step 3).
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table, what value is written to the device register at step 2?
A0x1
B0x0
Cundefined
D0x40000000
💡 Hint
Check the 'Value Written/Read' column at step 2 in execution_table
At which step does the variable 'val' get assigned a value?
AStep 1
BStep 3
CStep 2
DNever
💡 Hint
Look at variable_tracker for 'val' changes and execution_table step 3
If the address 0x40000000 was not in the I/O range, what would happen?
ACPU ignores the access
BCPU reads/writes normal RAM
CCPU triggers invalid address error
DCPU writes to device anyway
💡 Hint
Refer to concept_flow: after No to 'Is address in RAM?', No to 'Is address in I/O range?' leads to [Invalid address]
Concept Snapshot
Memory-mapped I/O uses normal memory addresses to access device registers.
CPU reads/writes device by accessing special addresses.
Use pointers to fixed addresses for devices.
Declare pointers volatile to prevent optimization.
Reading/writing device registers uses normal memory instructions.
Full Transcript
Memory-mapped I/O means the CPU uses normal memory instructions to talk to devices by reading and writing special memory addresses. The CPU checks if the address is RAM or device. If device, it accesses hardware registers. In the example, a pointer LED points to address 0x40000000, which is a device register. Writing 0x1 to *LED turns on the LED. Reading from *LED gets the current LED state. The volatile keyword prevents compiler optimizations that could skip these important reads and writes. This way, device control looks like normal memory access but actually controls hardware.