A Brief Summary of Core Differences
- FIFO: A hardware buffer queue that primarily addresses the minor, short-term mismatches between MCU response speed and SPI communication speed, aiming to reduce the number of interrupts and improve the efficiency of each interrupt.
- PDMA: A data transfer engine that mainly solves the problem of freeing the CPU during the transfer of large volumes of data, with the goal of achieving “zero CPU intervention” in data handling.
1. FIFO Mechanism
1. Concept: What is FIFO?
FIFO stands for “First In, First Out” buffer. You can think of it as a short conveyor belt or a section of a water pipe that stores water.
- At the SPI transmitter (TX), when you write data to the data register, it is actually first placed into the TX FIFO. The SPI controller sends out the data from the FIFO in the order it was placed.
- At the receiver (RX), the data received by the SPI controller is first stored in the RX FIFO, and when you read from the data register, you are actually retrieving data from the RX FIFO in order.
2. Function and Problems Addressed
Without FIFO, each time SPI sends/receives a byte, an interrupt is generated or the CPU needs to poll the status and handle it immediately. This can lead to:
- Frequent CPU interrupts, preventing it from handling other tasks, resulting in inefficiency.
- If the CPU response is slightly slow and the next data arrives, it can lead to data overflow or overwrite.
The introduction of FIFO brings two core benefits:
- Buffering: Allows the CPU to write multiple data items to be sent at once (for example, writing 8 bytes to the TX FIFO at once), and then the SPI controller automatically sends them in order. Similarly, during reception, the SPI controller can continuously receive multiple data items into the RX FIFO, waiting for the CPU to read them all at once. This provides the CPU with a more relaxed response time.
- Adjustable Interrupt Thresholds: You can set the trigger threshold for the FIFO. For example, generate an interrupt only when the TX FIFO is empty (to notify the CPU to fill data), or generate an interrupt only when there are 4 items in the RX FIFO (to notify the CPU to read in bulk). This greatly reduces the number of interrupts.
3. Usage Instructions and Precautions
- Configure Thresholds: Set FIFO thresholds according to your application scenario. For sending, if you want to minimize CPU intervention, you can set a lower threshold (like 1/4 empty) to request filling; for receiving, if real-time data is required, you can set a lower threshold (like generating an interrupt upon receiving 1 byte), or if efficiency is pursued, wait until the FIFO is nearly full before interrupting.
- Check Status: When operating the FIFO, always check the FIFO status through the SPI status register to see if it is full (before sending) or empty (before receiving) to avoid write failures or reading invalid data.
- Data Alignment: Ensure that your data operations (usually 8-bit or 16-bit) match the width of the FIFO.
- Clear FIFO: Remember to clear the TX/RX FIFO during initialization or when communication errors occur to avoid residual data interference.
2. PDMA Mechanism
1. Concept: What is PDMA?
PDMA is a hardware controller that allows peripherals (such as SPI, UART) to directly transfer data between memory (such as SRAM) without CPU core involvement. The CPU only needs to “set up the bridge” and can then go do other tasks while PDMA automatically completes the data transfer.
2. Function and Problems Addressed
Without DMA, the CPU needs to act like a “porter” to move each piece of data from memory to the SPI transmit register or from the SPI receive register to memory. For large amounts of data (like transferring an image or a segment of audio), most of the CPU’s time is wasted on this simple repetitive moving task.
The core goal of introducing PDMA is to free the CPU:
- Freeing the CPU: During PDMA data transfer, the CPU can perform other tasks, such as complex algorithms, responding to other interrupts, or entering low-power modes, greatly improving system efficiency and real-time performance.
- High Throughput: PDMA is optimized for transferring large volumes of data and can efficiently handle continuous, bulk data transfers.
- Reduced Latency: For high-speed data streams, PDMA’s response speed is faster than that of software interrupts, ensuring that data is not lost.
3. Usage Instructions and Precautions
Configuring PDMA is relatively complex and typically involves the following steps:
- Configure DMA Channels: Allocate a DMA channel for SPI TX and another for SPI RX.
- Set Source and Destination Addresses:
- For Sending (SPI TX DMA): The source address is the address of the sending array in memory, and the destination address is the address of the SPI data register.
- For Receiving (SPI RX DMA): The source address is the address of the SPI data register, and the destination address is the address of the receiving buffer in memory.
⚠️ Important Precautions:
- Memory Management: The memory buffer used for DMA typically needs to be non-cached, or manual cache consistency operations (like
<span>Cache Clean</span>and<span>Cache Invalidate</span>) are required; otherwise, the CPU and DMA may see different versions of the data. - Data Race: The CPU must absolutely not access or modify the buffer being used by DMA before the DMA transfer is complete.
- Interrupt Handling: The DMA transfer complete interrupt service routine must be correctly written to handle subsequent tasks (like parsing received data, preparing for the next send, etc.) and clear the interrupt flag.
- Error Handling: DMA transfer error interrupts, such as bus errors and configuration errors, need to be handled.
3. Comparative Summary and Combined Use
| Feature | FIFO | PDMA |
|---|---|---|
| Nature | Hardware buffer/queue | Data transfer engine |
| Core Goal | Reduce interrupts, smooth data flow | Free CPU, achieve bulk data transfer |
| Data Mover | Still the CPU | PDMA controller |
| Applicable Scenarios | Medium to small data volumes, low to medium speed | Large volumes of data, high-speed communication |
| CPU Usage | Moderate (still needs to handle interrupts) | Very low (only involved at the start and end) |
| Configuration Complexity | Simple (mainly setting thresholds) | Complex (needs to configure addresses, lengths, modes, etc.) |
Combined Use: Best Practices
In modern high-performance MCUs, FIFO and PDMA typically work in tandem to achieve optimal performance.
Example Workflow (SPI Receiving Large Data):
- The CPU configures the PDMA for SPI RX: the source address is the SPI data register, the destination address is a large memory buffer, and the transfer amount is 1000 bytes.
- The SPI controller is set to automatically trigger a PDMA request when the RX FIFO receives data.
- The SPI begins to receive data. Each time a data item/group is received (depending on the FIFO threshold), the non-empty RX FIFO will trigger the PDMA.
- The PDMA controller responds to the request, transferring data directly from the SPI RX FIFO to the designated memory buffer. During this process, the CPU does not need to intervene at all.
- When the PDMA completes the transfer of 1000 bytes, it generates a transfer complete interrupt.
- The CPU responds to this interrupt, learns that all data has been received, and then begins processing the 1000 bytes of data.
In this mode:
- FIFO acts as a traffic regulator between the high-speed SPI port and the relatively slower PDMA controller/memory bus.
- PDMA is responsible for the most labor-intensive bulk data transfer tasks.
Conclusion
- If your SPI communication only occasionally sends a few bytes of commands, using polling or basic interrupt mode (even without deep FIFO usage) is sufficient.
- If the communication data volume increases and the frequency rises, the first step is to enable and configure FIFO, which can immediately enhance stability and reduce CPU load.
- When faced with continuous large data streams (such as displays, audio codecs, high-speed ADC/DAC via SPI), PDMA (or PDMA+FIFO) is an essential solution, being key to achieving efficient, stable, and real-time processing.