Overview
Async Transfer Utility Library enables non-blocking data transfers on communication peripherals – the application initiates a transfer and continues execution while data moves in the background via CPU copy or DMA.
Features
- Both read and write transfers via CPU copy or DMA.
- One pending transfer per direction (read and write) at a time.
- Callback notification on transfer completion.
- Abort an in-progress transfer or query availability at any time.
- Multiple independent instances managing different communication interfaces simultaneously.
- DCACHE coherency handling for DMA-based transfers.
When to Use
Use this library when you need to:
- Perform UART, SPI, or I2C data transfers without blocking the application.
- Overlap communication with processing by offloading transfers to DMA.
- Manage asynchronous data flow across multiple communication interfaces simultaneously.
- Build protocol stacks or communication middleware on top of PDL or HAL peripheral drivers.
How to Use
Step 1 - Set Up the Interface
This library is peripheral-agnostic. Populate mtb_async_transfer_interface_t with function pointers and addresses matching your communication peripheral (example using a PDL UART SCB):
interface.rx_addr = (uint32_t*)&(UART_HW->RX_FIFO_RD);
interface.tx_addr = (uint32_t*)&(UART_HW->TX_FIFO_WR);
interface.get_num_tx_fifo = uart_get_num_tx_fifo;
interface.enable_rx_event = uart_enable_rx_event;
interface.enable_tx_event = uart_enable_tx_event;
interface.get_rx_transfer_len = uart_get_rx_transfer_len;
interface.get_tx_transfer_len = uart_get_tx_transfer_len;
interface.transfer_width = uart_get_transfer_width(UART_HW);
interface.enter_critical_section = Cy_SysLib_EnterCriticalSection;
interface.exit_critical_section = Cy_SysLib_ExitCriticalSection;
void(* mtb_async_transfer_set_fifo_level_t)(void *inst_ref, uint32_t level)
Function pointer to set the fifo level for triggering an interrupt when the number of elements in the...
Definition mtb_async_transfer.h:136
uint32_t(* mtb_async_transfer_get_num_fifo_t)(void *inst_ref)
Function pointer for returning the number of elements that can be read from the FIFO in case of rx or...
Definition mtb_async_transfer.h:127
void * inst_ref
The opaque pointer that is passed as the first argument to all non-DMA functions.
Definition mtb_async_transfer.h:219
Async Transfer interface data structure.
Definition mtb_async_transfer.h:215
For DMA mode, additionally populate the DMA-specific fields:
interface.dma_rx_ref = &dma_Descriptor_0;
interface.dma_set_length = uart_dma_set_len;
interface.dma_set_src = uart_dma_set_src_addr;
interface.dma_set_dest = uart_dma_set_dest_addr;
interface.dma_enable_rx = uart_dma_enable_rx;
Step 2 - Initialize
Async Transfer context data structure.
Definition mtb_async_transfer.h:288
cy_rslt_t mtb_async_transfer_init(mtb_async_transfer_context_t *context, const mtb_async_transfer_interface_t *iface)
Initializes an async transfer library instance.
Definition mtb_async_transfer.c:436
Step 3 - Register a Completion Callback (optional)
my_transfer_callback,
callback_arg);
cy_rslt_t mtb_async_transfer_register_callback(mtb_async_transfer_context_t *context, mtb_async_transfer_event_callback_t callback, void *arg)
Register a callback to be invoked when a transfer is complete.
Definition mtb_async_transfer.c:624
Step 4 - Start Transfers
cy_rslt_t mtb_async_transfer_write(mtb_async_transfer_context_t *context, void *source, uint32_t length)
Writes data from memory to the peripheral in the background.
Definition mtb_async_transfer.c:502
cy_rslt_t mtb_async_transfer_read(mtb_async_transfer_context_t *context, void *dest, size_t length)
Reads data from the peripheral to the memory in the background.
Definition mtb_async_transfer.c:454
Transfer completion is driven by interrupts. Wire up the appropriate handler depending on the transfer mode:
CPU mode – call mtb_async_transfer_process_fifo_level_event from the peripheral FIFO-level interrupt:
void uart_interrupt_handler(void)
{
uint32_t rxMasked = Cy_SCB_GetRxInterruptStatusMasked(UART_HW);
uint32_t txMasked = Cy_SCB_GetTxInterruptStatusMasked(UART_HW);
if (0u != (CY_SCB_UART_RX_TRIGGER & rxMasked))
if (0u != (CY_SCB_UART_TX_TRIGGER & txMasked))
if (direction)
}
mtb_async_transfer_direction_t
Async Transfer direction.
Definition mtb_async_transfer.h:104
@ MTB_ASYNC_TRANSFER_DIRECTION_WRITE
Write Transfer.
Definition mtb_async_transfer.h:106
@ MTB_ASYNC_TRANSFER_DIRECTION_READ
Read Transfer.
Definition mtb_async_transfer.h:105
cy_rslt_t mtb_async_transfer_process_fifo_level_event(mtb_async_transfer_context_t *context, mtb_async_transfer_direction_t direction)
Handler for when the FIFO in the peripheral reaches the trigger level.
Definition mtb_async_transfer.c:645
DMA mode – call mtb_async_transfer_process_dma_complete from the DMA completion interrupt:
void dma_interrupt_handler(void)
{
cy_en_dma_intr_cause_t cause = Cy_DMA_Channel_GetStatus(DMA_HW, DMA_CHANNEL);
Cy_DMA_Channel_ClearInterrupt(DMA_HW, DMA_CHANNEL);
if (cause == CY_DMA_INTR_CAUSE_COMPLETION)
}
cy_rslt_t mtb_async_transfer_process_dma_complete(mtb_async_transfer_context_t *context, mtb_async_transfer_direction_t direction)
Handler for when a DMA transfer is complete.
Definition mtb_async_transfer.c:675
DCACHE Management
When using DMA on devices with a data cache (DCACHE), cache coherency must be maintained for the buffers passed to mtb_async_transfer_read and mtb_async_transfer_write.
The library assumes the following cache configuration:
- Write-back with read and write allocate: WB-RWA
- Cache line size: 32 bytes
- All application memory is cacheable
Two scenarios require explicit cache maintenance by the application:
- CPU writes, DMA reads (TX path) – the CPU write updates only the cache, not SRAM. Clean the cache after writing the TX buffer so the DMA sees the correct data:
SCB_CleanDCache_by_Addr(tx_buffer, sizeof(tx_buffer));
- DMA writes, CPU reads (RX path) – the DMA writes directly to SRAM. Invalidate the cache before reading the RX buffer so the CPU fetches fresh data from SRAM:
SCB_InvalidateDCache_by_Addr(rx_buffer, sizeof(rx_buffer));
Cache operations work at 32-byte cache-line granularity. All DMA data buffers must be aligned to 32 bytes and padded to a multiple of 32 bytes. Without this, adjacent data can be corrupted. Buffer alignment and padding is the responsibility of the application.
Release Notes and Changelog
- RELEASE.md - Detailed release notes for all versions
License
Licensed under the Apache License, Version 2.0. You may not use this file except in compliance with the License. A copy of the License is available at http://www.apache.org/licenses/LICENSE-2.0.
- LICENSE - Apache License 2.0
Copyright
(c) (2025-2026), Infineon Technologies AG, or an affiliate of Infineon Technologies AG. All rights reserved.