Course contentsShow
← Embedded Systems & Computer Architecture
Lesson 411 of 9365. Communication Protocols and Data TransferFree lesson

Handling Multi-Channel DMA Resource Contention

Develop strategies to prioritize critical DMA channels when multiple peripherals require simultaneous access to the system bus.

In this lesson, you will learn how to resolve resource conflicts when multiple peripherals compete for DMA bus access simultaneously.

When your microcontroller has multiple DMA channels active at once, they often reach the system bus at the same time. Since the bus acts as a shared highway, only one channel can transmit data at any given moment. This creates "resource contention," where lower-priority channels must wait for higher-priority ones to finish, potentially causing latency in time-sensitive peripherals like audio buffers or high-speed sensors.

Arbitration Strategies

To manage this contention, most DMA controllers use a fixed or programmable arbitration logic:

  1. Fixed Priority: Each DMA channel is assigned a hard-coded rank (e.g., Channel 0 is always higher than Channel 1). While predictable, this can cause "starvation," where lower-priority channels never get bus access if the high-priority channel is constantly active.
  2. Round-Robin Arbitration: The controller cycles through pending requests in a rotating order. This ensures fairness, as every peripheral eventually gets a turn, though it doesn't guarantee immediate access for mission-critical tasks.

Implementing Priority Logic

You should map your hardware requirements to these priority levels. For instance, if you are reading from an ADC and writing to a UART, the ADC is usually your priority because it faces a "hard" real-time deadline—if you don't empty the peripheral buffer, you will suffer a data overrun.

When configuring your DMA channels, prioritize them based on their frequency of service and the consequences of delay:

// Example: Setting priority in a configuration struct
dma_channel_config_t audio_stream = {
    .channel_id = 0,
    .priority = DMA_PRIORITY_HIGH, // Critical for real-time audio
    .mode = DMA_MODE_CIRCULAR
};

dma_channel_config_t logging_stream = {
    .channel_id = 1,
    .priority = DMA_PRIORITY_LOW,  // Data logging can wait
    .mode = DMA_MODE_NORMAL
};

By assigning DMA_PRIORITY_HIGH to your most sensitive task and DMA_PRIORITY_LOW to background tasks, you ensure that the system bus serves your most time-critical peripherals first, reducing the risk of data loss during high-load scenarios.

Key Takeaway: Effective contention management requires categorizing DMA tasks by their timing requirements and assigning priority levels to prevent critical peripheral starvation.