Summary of Methods for Implementing Multithreading in Single Chip Microcontrollers

ampheoampheo
3 min read

Multithreading enables microcontrollers to handle concurrent tasks efficiently. Here are the primary implementation approaches:

1. Real-Time Operating Systems (RTOS)

RTOSLicenseKey FeaturesBest For
FreeRTOSMITLightweight, portableGeneral-purpose
ZephyrApache 2.0Modular, IoT-focusedConnected devices
ThreadXProprietaryHard real-timeAutomotive/medical
RT-ThreadApache 2.0Middleware-richComplex IoT systems

Implementation Example (FreeRTOS):

c

void vTask1(void *pvParameters) {
  while(1) {
    HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
    vTaskDelay(500 / portTICK_PERIOD_MS);
  }
}

void main() {
  xTaskCreate(vTask1, "LED_Task", 128, NULL, 1, NULL);
  vTaskStartScheduler();
}

2. Bare-Metal Multitasking

A. Cooperative Scheduling

c

typedef struct {
  void (*task)(void);
  uint32_t interval;
  uint32_t last_run;
} Task;

Task tasks[] = {
  {LED_Update, 100},  // Runs every 100ms
  {Sensor_Read, 500}
};

void Scheduler_Run() {
  uint32_t now = HAL_GetTick();
  for(int i=0; i<2; i++) {
    if(now - tasks[i].last_run >= tasks[i].interval) {
      tasks[i].task();
      tasks[i].last_run = now;
    }
  }
}

B. Time-Triggered Architecture

  • Uses hardware timers to invoke tasks at precise intervals

  • Benefits:

    • Predictable timing

    • No stack overflows

    • Minimal CPU overhead

3. Interrupt-Driven Concurrency

c

volatile uint8_t adc_ready = 0;

void ADC_IRQHandler() {
  adc_ready = 1;  // Set flag
}

void main() {
  while(1) {
    if(adc_ready) {
      Process_ADC_Data();
      adc_ready = 0;
    }
    // Other non-blocking code
  }
}

4. Hybrid Approaches

RTOS + Interrupts

  • Critical tasks: Handled by ISRs

  • Background tasks: Managed by RTOS

Coroutines

c

void coroutine1() {
  static int state = 0;
  switch(state) {
    case 0: /* Initialization */ state++; break;
    case 1: /* Task step 1 */ state++; break;
    // ...
  }
}

Comparison Table

MethodRAM UsageTiming PrecisionComplexityBest Use Case
RTOSMedium-HighHighMediumComplex systems
CooperativeLowLowSimpleResource-constrained
Time-TriggeredLowVery HighMediumTiming-critical
InterruptsLowVery HighMediumEvent-driven

Key Considerations

  1. Stack Management

    • RTOS: Each thread needs dedicated stack

    • Bare-metal: Shared stack (risk of overflow)

  2. Synchronization

    • Use mutexes/semaphores in RTOS

    • Disable interrupts for critical sections in bare-metal

  3. Debugging Tools

    • FreeRTOS: Tracealyzer

    • Bare-metal: Logic analyzer for task timing

Advanced Techniques

  • Memory Protection Units (MPU): Isolate task memory (Cortex-M)

  • Dynamic Priority Adjustment: Change task priorities at runtime

  • Task Watchdogs: Monitor for stuck tasks

For most modern 32-bit MCUs (STM32, ESP32), an RTOS provides the best balance of features and maintainability. 8-bit systems often benefit from simpler cooperative schedulers.

0
Subscribe to my newsletter

Read articles from ampheo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

ampheo
ampheo