01/11/2026
🔥 ARE YOU EXPOSING HARDWARE RECORDS TO HEADER FILE?
In large embedded C projects, a classic mistake many engineers make is to define the entire MMIO register struct or driver state directly in the header (`.h`) file.
Consequences:
❌ Any module that includes headers can arbitrarily interfere with internal registers.
❌ Every time we resize a struct or edit a register, the entire project must be recompiled from the beginning.
❌ Breaking the encapsulation of MISRA C safety standards.
💡 SOLUTION: OPAQUE POINTER (pImpl Pattern in pure C)
By declaring only `typedef struct uart_dev uart_dev_t;` in the header and hiding the entire actual structure inside the `.c` file, you create an absolute hardware "firewall".
Visual diagram:
┌─────────────────┐ ┌──────────────────────┐
│ user_app.c │ │ uart_driver.h │
│ (Just saw │──────>│ typedef struct dev │
│ hidden cursor) │ │ uart_dev_t; │
└─────────────────┘ └──────────┬───────────┘
│ (Point to)
▼
┌──────────────────────┐
│ uart_driver.c │
│ struct dev { │
│ volatile reg_t*; │
│ uint32_t baud; │
│ }; │
└──────────────────────┘
Illustrative code snippet:
```c
// uart_driver.h - Public interface
typedef struct uart_dev uart_dev_t;
uart_dev_t *uart_create(uint32_t base_addr);
void uart_send(uart_dev_t *dev, uint8_t byte);
// uart_driver.c - Internal sealed implementation
struct uart_dev {
volatile uint32_t *CR1;
volatile uint32_t *DR;
uint32_t baudrate;
};
```
🎯 GOLDEN RULES:
If the external module does not need to know the size (sizeof) of the struct when statically allocated, USE OPAQUE POINTER to protect the driver architecture.
---
👉 Are you guys on the team using Opaque Pointer or exposing the entire struct in the header? Let's discuss below!
📖 Read a comprehensive analysis with in-depth source code at DevStack:
https://devstack.it.com/en/article/advanced-memory-systems-zero-copy-dma-descriptor-rings
*(Note: Detailed link is pinned in the first comment 👇)*