Essential C Programming Concepts for Embedded Systems
Constants and Macros
Define a constant representing seconds in a year:
#define SECONDS_IN_YEAR (365UL * 24 * 60 * 60)
Standard minimum value macro:
#define MIN_VALUE(x,y) (((x) < (y)) ? (x) : (y))
Preprocessor Directives
The #error directive halts compilation and displays custom error messages.
Infinite Loops
Common patterns for endless loops in embedded applications:
// Method 1
for (;;) {
// loop body
}
// Method 2
while (1) {
// loop body
}
// Method 3
do {
// loop body
} while (1);
Variable Declarations
Various declarations using variable data:
- Integer:
int data; - Pointer to integer:
int *data; - Pointer to pointer to integer:
int **data; - Array of 10 integers:
int data[10]; - Array of 10 pointers to integers:
int *data[10]; - Pointer to array of 10 itnegers:
int (*data)[10]; - Function pointer taking int and returning int:
int (*data)(int);
Storage Class Specifiers
The static keyword:
- Limits variable scope to file level
- Preserves variable value between function calls
Type Qualifiers
const
Indicates that a variable's value should not be modified after initialization.
volatile
Tells the compiler that a variable's value may change unexpectedly, requiring fresh reads from memory rather than cached register values.
Example usage in embedded systems:
#define BIT_POSITION_3 (1U << 3)
static int register_value;
void activate_bit3(void) {
register_value |= BIT_POSITION_3;
}
void deactivate_bit3(void) {
register_value &= ~BIT_POSITION_3;
}
Memory-Mapped I/O
Direct memory access example:
unsigned int *memory_address = (unsigned int *)0x67a9;
*memory_address = 0xaa66;
Interrupt Handling
Interrupt Service Routines (ISRs) execute when hardware events occur, temporarily suspending main program flow.
Mixed-Type Arithmetic
void evaluate_expression(void) {
unsigned int positive_val = 6;
int negative_val = -20;
if ((positive_val + negative_val) > 6) {
printf("Result exceeds threshold\n");
} else {
printf("Result within limits\n");
}
}
In mixed signed/unsigned operations, operands convert to unsigned types. The negative value becomes a large positive number, making the sum exceed the threshold.
Dynamic Memory Management
int *dynamic_array = NULL;
dynamic_array = (int *)malloc(128 * sizeof(int));
if (dynamic_array != NULL) {
// use allocated memory
free(dynamic_array);
dynamic_array = NULL;
}
Type Definitions
Differance between #define and typedef:
#define POINTER_DEFINITION struct record *
typedef struct record *RecordPointer;
POINTER_DEFINITION ptr1, ptr2; // Only ptr1 is a pointer
RecordPointer ptr3, ptr4; // Both are pointers