Embedded systems design and programming
// Example: STM32 GPIO configuration
void GPIO_Init(GPIO_TypeDef *port, uint8_t pin, uint8_t mode) {
// Enable clock
if (port == GPIOA) RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// Configure pin mode
port->CRL &= ~(0xF << (pin * 4)); // Clear
port->CRL |= (mode << (pin * 4)); // Set
}
// Interrupt handler
void EXTI0_IRQHandler(void) {
if (EXTI->PR & EXTI_PR_PR0) {
// Handle interrupt
EXTI->PR = EXTI_PR_PR0; // Clear pending
}
}
// FreeRTOS task creation
void vTaskCode(void *pvParameters) {
while (1) {
// Task functionality
vTaskDelay(pdMS_TO_TICKS(100));
}
}
void create_tasks() {
xTaskCreate(vTaskCode, "Task1", configMINIMAL_STACK_SIZE,
NULL, 1, NULL);
xTaskCreate(vTaskCode, "Task2", configMINIMAL_STACK_SIZE,
NULL, 2, NULL);
}
// Queue communication
QueueHandle_t xQueue;
xQueue = xQueueCreate(10, sizeof(int32_t));
xQueueSend(xQueue, &value, 0);
xQueueReceive(xQueue, &received, portMAX_DELAY);
# I2C communication
class I2CDevice:
def __init__(self, address):
self.address = address
def read_register(self, reg):
"""Read from register"""
# I2C read sequence: START → ADDR+W → REG → START → ADDR+R → DATA → STOP
pass
def write_register(self, reg, value):
"""Write to register"""
# I2C write sequence: START → ADDR+W → REG → DATA → STOP
pass
# SPI communication
class SPIDevice:
def __init__(self, clk, mosi, miso, cs):
self.clk = clk
self.mosi = mosi
self.miso = miso
self.cs = cs
def transfer(self, data):
"""Full duplex SPI transfer"""
# Shift out data while shifting in response
pass
| Peripheral | Protocol | Use Case |
|---|---|---|
| UART/USART | Async serial | Debug, GPS, Bluetooth |
| SPI | Serial synchronous | Sensors, SD cards, displays |
| I2C | Two-wire serial | Sensors, EEPROMs, RTCs |
| ADC | N/A | Analog sensors |
| PWM | N/A | Motor control, LEDs |
| Timer | N/A | Timing, interrupts |
// Low power mode transitions
void enter_sleep_mode(uint8_t mode) {
// Save state
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
switch(mode) {
case SLEEP:
PWR->CR |= PWR_CR_LPDS;
break;
case STOP:
PWR->CR |= PWR_CR_LPDS;
PWR->CR |= PWR_CR_CSBF;
break;
case STANDBY:
PWR->CR |= PWR_CR_PDDS;
break;
}
__WFI(); // Wait for interrupt
}
// Clock gating for unused peripherals
void disable_unused_clocks() {
RCC->APB1ENR = 0; // Disable all APB1
RCC->APB2ENR = 0; // Disable all APB2
}
| Family | Architecture | Use Cases |
|---|---|---|
| STM32 | ARM Cortex-M | General purpose |
| ESP32 | Xtensa dual-core | WiFi, BLE, IoT |
| ATmega | AVR | Arduino, simple apps |
| PIC | PIC | Industrial, automotive |
| nRF52 | ARM Cortex-M | BLE, wearables |
// Assert macro for development
#ifdef DEBUG
#define ASSERT(condition) \
if (!(condition)) { \
while(1); // Break here \
}
#else
#define ASSERT(condition)
#endif
// Ring buffer implementation
typedef struct {
uint8_t *buffer;
uint16_t head;
uint16_t tail;
uint16_t size;
} RingBuffer;
uint8_t rb_put(RingBuffer *rb, uint8_t data) {
uint16_t next = (rb->head + 1) % rb->size;
if (next == rb->tail) return 0; // Full
rb->buffer[rb->head] = data;
rb->head = next;
return 1;
}