What is DMA?
Direct Memory Access (DMA) is a feature that allows peripherals to transfer data directly to or from memory without involving the main processor (MCU).
DMA Streams and UART Ports:
DMA can be used in conjunction with UART ports to establish what are known as DMA streams—high-speed data designed for efficient communication across modules. Once a DMA stream is configured, it transfers data independently of the MCUs, meaning there is no parsing or routing of messages by the microcontrollers involved.
By default, module ports operate in backend messaging mode after startup. However, these ports can be reconfigured to use DMA streams through various APIs,
When these ports are enabled in the DMA stream, we are unable to send messages or CLI commands by these ports because the backend messaging task does not process them.
A DMA stream automatically stops after transferring a specified number of bytes or when a timeout occurs—whichever happens first. Once the stream ends, all involved module ports revert to their default messaging mode.
There are functions used to transfer raw data across modules:
1) Stream raw data from UART port in source module to UART port in destination module and vice versa:
BOS_Status StreamPortToPort(uint8_t srcP, uint8_t srcM, uint8_t dstP, uint8_t dstM, uint8_t direction, uint32_t size, uint32_t timeout, bool stored);
where:
- srcP, srcM: Source port and module id.
- dstP, dstM: Destination port and module id.
- direction: flow data direction (FORWARD, BACKWARD, BIDIRECTIONAL).
- size: Maximum number of bytes to transfer.
- timeout: Max time to wait before stopping the stream.
- stored: storing the physical data flow path in EEPROM memory (TRUE, FALSE).
Example:
uint8_t srcM = 1, dstM = 3 , srcP = P1, dstP = P6, direction = FORWARD;
uint32_t size = 100, timeout = 0xffff;
bool stored = FALSE;
StreamPortToPort(srcP, srcM, dstP, dstM, direction, size, timeout, stored);
Where we send data from port1 from module1 to port6 in module3.
2) Stream raw data from RAM memory in source module to UART port in destination module:
BOS_Status StreamMemoryToPort(uint8_t dstP, uint8_t dstM, uint8_t *pBuffer, uint32_t size, uint32_t timeout, bool stored);
Where:
- dstP: Destination port.
- dstM: Destination module id.
- pBuffer: Pointer to memory buffer to send.
- size: Number of bytes to send.
- timeout: Time limit for the transmission.
- stored: storing the physical data flow path in EEPROM memory (TRUE, FALSE).
Example:
uint8_t dstP = P2, dstM = 2;
uint8_t *pBuffer = "hello";
uint32_t size = 100, timeout = 0xffff;
bool stored = FALSE;
StreamMemoryToPort(dstP, dstM, pBuffer, size, timeout, stored);
Where we send data from pBuffer array in module1 to port6 in module3.
3) Stream raw data from UART port in source module to RAM memory in destination module:
BOS_Status StreamPortToMemory(uint8_t srcP, uint8_t dstM, uint32_t size, uint32_t timeout, bool stored);
Where:
- srcP: Source port.
- dstM: Destination module id where memory is located.
- size: Number of bytes to receive.
- timeout: Time limit for data reception.
- stored: storing the physical data flow path in EEPROM memory (TRUE, FALSE).
Example:
uint8_t srcP = P1, dstM = 2;
uint32_t size = 100, timeout = 0xffff;
bool stored = false;
StreamPortToMemory(srcP, dstM, size, timeout, stored);
Where we send data from port1 from module1 to StreamBuffer array in module2.
Note: uint8_t StreamBuffer[512] is a circular DMA buffer that receives raw data from the master module and temporarily stores it in memory for later processing. When the buffer becomes full, DMA resumes writing at the beginning.
4) Stream raw data from RAM memory in source module to RAM memory in destination module:
BOS_Status StreamMemoryToMemory(uint8_t dstM, uint8_t *pBuffer, uint32_t size, uint32_t timeout, bool stored);
Where:
- dstM: Destination module id.
- pBuffer: Pointer to memory buffer to send.
- size: Number of bytes to copy.
- timeout: Time limit for the operation.
- stored: storing the physical data flow path in EEPROM memory (TRUE, FALSE).
Example:
uint8_t dstM = 2;
uint8_t *pBuffer = "hello";
uint32_t size = 100, timeout = 0xffff;
bool stored = FALSE;
StreamMemoryToMemory(dstM, pBuffer, size, timeout, stored);
Where we send data from pBuffer array from module1 to StreamBuffer array in module3.
Note: uint8_t StreamBuffer[512] is a circular DMA buffer that receives raw data from the master module and temporarily stores it in memory for later processing. When the buffer becomes full, DMA resumes writing at the beginning.