#include // Macro for register access (volatile pointer dereferencing, not used here) #define REG32(addr) (*(volatile uint32_t *)(addr)) #define REG16(addr) (*(volatile uint16_t *)(addr)) #define REG8(addr) (*(volatile uint8_t *)(addr)) typedef struct MMIO_device { volatile uint16_t hello; volatile uint8_t __RESERVED1[2]; volatile uint16_t status; volatile uint8_t __RESERVED2[8]; volatile uint32_t control; // ...and so on } __attribute__((aligned(4))) MMIO_device; /* A base address pointing to the start of the 'peripherals' memory region */ #define MEM_PERIPH_BASE 0xDEADBEEF /* Specific device, often defined as an offset from a base */ #define MY_MMIO (MEM_PERIPH_BASE + 0x10) #define DVC_CTLR_ENA (0x3 << 1) /* Device Control Register Enable */ #define DVC_CTLR_WRITE (0x1) /* Device Control Register Write */ volatile MMIO_device *mmio1 = (volatile MMIO_device *)MY_MMIO; void configure_peripheral() { mmio1->hello = 0x1234; // Raw write mmio1->control |= DVC_CTLR_ENA | DVC_CTLR_WRITE; // Set mmio1->control &= ~(DVC_CTLR_ENA | DVC_CTLR_WRITE); // Clear }