Part 5 — Chapter 22

Chapter 22: Registers and Memory Mapping in C

Introduction

In embedded systems, software communicates directly with hardware peripherals such as GPIO pins, timers, UART modules, ADCs, and communication interfaces. These peripherals are controlled using hardware registers, which are special memory locations mapped to fixed addresses.

Most microcontrollers use memory-mapped I/O, where hardware registers are accessed like normal memory using pointers in C.

What is a Register?

A register is a small hardware-controlled memory location used to configure, control, or monitor peripherals.

Registers are commonly used to:

  • enable or disable peripherals
  • configure hardware settings
  • store status information
  • transfer hardware data

Each register is assigned a unique memory address inside the system memory map.

Memory-Mapped I/O

In memory-mapped systems, specific memory addresses are reserved for hardware peripherals.

Address        Peripheral Register
0x40000000 → GPIO Register
0x40000004 → UART Register
0x40000008 → Timer Register

Reading or writing to these addresses directly affects the associated hardware.

Accessing Registers Using Pointers

Pointers are used to access hardware registers through their memory addresses.

Example

unsigned int *GPIO =
    (unsigned int *)0x40000000;

Here:

  • 0x40000000 is the register address
  • the pointer stores this address
  • dereferencing the pointer accesses the actual hardware register
Writing to a Register
*GPIO = 0x01;

This writes data directly into the hardware register.

Reading from a Register
unsigned int value = *GPIO;

This reads the current register value from hardware.

Register Bit Manipulation

Bitwise operators are commonly used to control specific register bits.

*GPIO |= (1 << 3);

This sets bit 3 while keeping other bits unchanged.

Example Program
main.c
C
#include <stdio.h>

int main()
{
    unsigned int *GPIO =
        (unsigned int *)0x40000000;

    *GPIO = 0x01;

    return 0;
}
How It Works

The pointer stores the hardware register address. When the pointer is dereferenced using *, the program directly accesses that physical hardware location. The processor then performs a real hardware read or write operation on the peripheral register.

Important Points

  • Hardware peripherals are controlled through registers
  • Registers are mapped to fixed memory addresses
  • Pointers allow direct hardware access
  • Register operations commonly use bitwise operators
  • Reading and writing register values directly affects hardware behavior

Why This Matters in Embedded Systems

Register-level programming is one of the core foundations of embedded development. Almost all embedded firmware interacts directly with memory-mapped registers to configure peripherals, handle interrupts, control communication interfaces, and manage hardware behavior.

UART_CTRL |= (1 << 0);

Understanding registers and memory mapping is essential for low-level firmware development and microcontroller programming.

← Chapter 21: Bitwise Operators Chapter 23: volatile Keyword →