0% found this document useful (0 votes)
129 views5 pages

Pointers in Embedded C With Examples

The document outlines various types of pointers in Embedded C, including basic pointers, constant pointers, volatile pointers, function pointers, and more, with examples for each type. It emphasizes the importance of pointer safety in embedded systems, recommending practices such as initialization, validation, and avoiding pointer arithmetic with hardware registers. Additionally, it discusses specific use cases like memory-mapped I/O and DMA buffer handling.

Uploaded by

Tarun Gupta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
129 views5 pages

Pointers in Embedded C With Examples

The document outlines various types of pointers in Embedded C, including basic pointers, constant pointers, volatile pointers, function pointers, and more, with examples for each type. It emphasizes the importance of pointer safety in embedded systems, recommending practices such as initialization, validation, and avoiding pointer arithmetic with hardware registers. Additionally, it discusses specific use cases like memory-mapped I/O and DMA buffer handling.

Uploaded by

Tarun Gupta
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

All Types of Pointers in Embedded C with

Examples

1. Basic Pointer to Variable

int sensor_value = 25;


int *ptr = &sensor_value; // Pointer to integer

// Access
*ptr = 30; // sensor_value now = 30

2. Pointer to Constant Data

const uint8_t ROM_DATA[] = {0xAA, 0xBB}; // Stored in Flash


const uint8_t *rom_ptr = ROM_DATA; // Read-only pointer

// Access
uint8_t first_byte = rom_ptr[0]; // OK: 0xAA
// rom_ptr[0] = 0xCC; // ERROR: Const violation

3. Constant Pointer (Fixed Address)

uint8_t buffer[64];
uint8_t *const buf_ptr = buffer; // Pointer can't change

// Access
buf_ptr[0] = 0xFF; // OK: Modify data
// buf_ptr = &other_buffer; // ERROR: Pointer const

4. Volatile Pointer (Hardware Access)

volatile uint32_t *const GPIOA_ODR = (volatile uint32_t*)0x40020014;

// Toggle output
*GPIOA_ODR ^= (1 << 5); // Atomic PA5 toggle

5. Pointer to Function

void led_on(void) { /* ... */ }


void led_off(void) { /* ... */ }

// Function pointer type


typedef void (*led_func_t)(void);

// Usage
led_func_t led_operation = led_on;
led_operation(); // Calls led_on()

6. Pointer to Array
uint8_t frame[8] = {0};
uint8_t (*frame_ptr)[8] = &frame; // Pointer to array

// Access
(*frame_ptr)[0] = 0x01; // frame[0] = 0x01

7. Array of Pointers

const char *error_messages[] = {


"Sensor Fail",
"Comm Error",
"Low Voltage"
};

// Access
uart_send(error_messages[1]); // Sends "Comm Error"

8. Pointer to Structure

typedef struct {
uint32_t cr;
uint32_t sr;
} UART_Regs;

UART_Regs *const UART1 = (UART_Regs*)0x40011000;


UART1->cr |= UART_ENABLE; // Set enable bit

9. Void Pointer (Generic)

uint32_t sensor = 25;


void *generic_ptr = &sensor;

// Must cast before use


uint32_t value = *(uint32_t*)generic_ptr;

10. Double Pointer (Pointer-to-Pointer)

uint8_t *dma_buffer;
uint8_t **dma_ptr = &dma_buffer; // Pointer to pointer

// Configure DMA
* DMA_CMAR = (uint32_t)*dma_ptr; // Set buffer address

11. Far Pointer (Segmented Architectures)

__far uint8_t *ext_mem_ptr = (__far uint8_t*)0x80000000; // Extended memory

12. Near Pointer (Local Memory)

__near uint8_t *ram_ptr = (__near uint8_t*)0x0000; // On-chip RAM

13. Null Pointer


uint32_t *ptr = NULL; // Explicit null pointer

if(ptr == NULL) {
// Handle uninitialized pointer
}

14. Wild Pointer (Uninitialized)

uint32_t *wild_ptr; // Dangerous uninitialized pointer


// *wild_ptr = 10; // UNDEFINED BEHAVIOR!

15. Dangling Pointer (Invalid Memory)

uint32_t *create_dangling() {
uint32_t local = 42;
return &local; // Returns stack address
} // 'local' destroyed here

uint32_t *dangler = create_dangling();


// *dangler = 10; // CORRUPTS MEMORY

16. Function Pointer with Parameters

int32_t (*sensor_read)(uint8_t sensor_id); // Function pointer

// Assign implementation
sensor_read = &read_temperature_sensor;
int32_t temp = sensor_read(SENSOR1); // Call function

17. Const Volatile Pointer

const volatile uint32_t *const RTC_COUNTER =


(const volatile uint32_t*)0x40002800; // Read-only hardware counter

uint32_t timestamp = *RTC_COUNTER; // Always reads actual value

Embedded-Specific Use Cases


1. Memory-Mapped I/O

// GPIO port definition


#define GPIOB_BASE 0x40020400
volatile GPIO_TypeDef *const GPIOB = (volatile GPIO_TypeDef*)GPIOB_BASE;

// Set PB7 high


GPIOB->ODR |= (1 << 7);

2. DMA Buffer Handling


__attribute__((aligned(4))) uint8_t dma_buf[128];
uint8_t *dma_ptr = dma_buf;

// Configure DMA source


DMA1->CMAR = (uint32_t)dma_ptr;

3. ISR Callback Table

// Array of function pointers


void (*isr_handlers[8])(void) = {0};

// Register UART1 handler


isr_handlers[USART1_IRQn] = &uart1_isr;

// Dispatch in vector table


void USART1_IRQHandler() {
if(isr_handlers[USART1_IRQn])
isr_handlers[USART1_IRQn]();
}

4. Command Parser

typedef struct {
const char *cmd;
void (*handler)(void);
} CmdEntry;

const CmdEntry cmd_table[] = {


{"LED_ON", &led_on},
{"READ", &read_sensor}
};

void parse_command(const char *cmd) {


for(int i=0; i<sizeof(cmd_table)/sizeof(CmdEntry); i++) {
if(strcmp(cmd, cmd_table[i].cmd) == 0) {
cmd_table[i].handler();
return;
}
}
}

Pointer Safety in Embedded Systems


1. Always initialize pointers

uint32_t *ptr = NULL; // Safe initialization

2. Use const for hardware registers

volatile const uint32_t *ADC_DATA = ...; // Read-only

3. Validate pointers before use


if(ptr >= MEM_START && ptr < MEM_END) {
*ptr = value;
}

4. Avoid pointer arithmetic with hardware registers

// BAD: TIM1_CR1 + 0x04 (risky)


// GOOD: Use structure access
TIM1->CCR1 = value;

5. Use compiler attributes for alignment

__attribute__((aligned(4))) uint32_t buffer[64];

Pointers in embedded C enable direct hardware access and efficient memory manipulation
but require careful management to avoid crashes and security vulnerabilities.

You might also like