Skip to content

Infineon/async-transfer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Async Transfer Utility Library - Non-blocking Background Data Transfer for Communication Peripherals

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):

mtb_async_transfer_interface_t interface = {0};
interface.inst_ref               = UART_HW;
interface.rx_addr                = (uint32_t*)&(UART_HW->RX_FIFO_RD);
interface.tx_addr                = (uint32_t*)&(UART_HW->TX_FIFO_WR);
interface.get_num_rx_fifo        = (mtb_async_transfer_get_num_fifo_t)Cy_SCB_UART_GetNumInRxFifo;
interface.get_num_tx_fifo        = uart_get_num_tx_fifo;
interface.set_rx_fifo_level      = (mtb_async_transfer_set_fifo_level_t)Cy_SCB_SetRxFifoLevel;
interface.set_tx_fifo_level      = (mtb_async_transfer_set_fifo_level_t)Cy_SCB_SetTxFifoLevel;
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;

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

mtb_async_transfer_context_t async_context;
cy_rslt_t result = mtb_async_transfer_init(&async_context, &interface);

Step 3 - Register a Completion Callback (optional)

result = mtb_async_transfer_register_callback(&async_context,
                                              my_transfer_callback,
                                              callback_arg);

Step 4 - Start Transfers

/* Initiate a background read */
result = mtb_async_transfer_read(&async_context, rx_buffer, sizeof(rx_buffer));

/* Initiate a background write */
result = mtb_async_transfer_write(&async_context, tx_buffer, sizeof(tx_buffer));

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)
{
    mtb_async_transfer_direction_t direction = (mtb_async_transfer_direction_t)0;
    uint32_t rxMasked = Cy_SCB_GetRxInterruptStatusMasked(UART_HW);
    uint32_t txMasked = Cy_SCB_GetTxInterruptStatusMasked(UART_HW);
    if (0u != (CY_SCB_UART_RX_TRIGGER & rxMasked))
        direction = MTB_ASYNC_TRANSFER_DIRECTION_READ;
    if (0u != (CY_SCB_UART_TX_TRIGGER & txMasked))
        direction |= MTB_ASYNC_TRANSFER_DIRECTION_WRITE;
    if (direction)
        mtb_async_transfer_process_fifo_level_event(&async_context, direction);
}

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)
        mtb_async_transfer_process_dma_complete(&async_context,
                                                MTB_ASYNC_TRANSFER_DIRECTION_READ);
}

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:

  1. 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));
  2. 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.

About

No description, website, or topics provided.

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages