Direct Memory Access#

Introduction#

Direct Memory Access (DMA) is a process of transferring data from one memory location to another without the direct involvement of the processor (CPU). The main benefit of using DMA is more efficient data movement in the embedded system.

Here are some common applications of DMA in micro-controller systems:

  • Data Transfer: One of the primary uses of DMA is to facilitate data transfer between peripherals and memory

  • Memory-to-Memory Transfer: DMA can also be utilized for moving data between different memory locations, providing fast and efficient memory operations without CPU intervention. This is particularly useful for tasks like memory copying, memory clearing, or memory initialization.

  • Peripheral Initialization: DMA can assist in initializing peripheral registers or buffers by transferring predefined data patterns or configurations directly from memory to the peripheral registers, speeding up the initialization process.

  • Data Processing: DMA can be employed for offloading data processing tasks from the CPU to dedicated hardware peripherals.

  • Real-Time Systems: DMA is essential in real-time systems where predictable and deterministic data transfer is crucial. By minimizing CPU involvement in data transfer operations, DMA helps meet strict timing requirements and reduces the likelihood of missed deadlines in time-critical applications.

  • Power Management: DMA can contribute to power efficiency by reducing CPU wake-up times and allowing the CPU to enter low-power modes more frequently. By handling data transfer tasks autonomously, DMA can help optimize power consumption in battery-operated or energy-constrained systems.

Configuration#

  • Configuring DMA has three parameters that can be configured in such, if DAM instance configuration to configured through and call th API sl_si91x_dma_init(), DAM Channel can be configured in the range of 1-32 by passing the instance and channel in the API sl_si91x_dma_allocate_channel(), and transfer size also can be configured in the range of (1-10000).

  • For more information on configuring available parameters refer to the respective peripheral example readme document.

Usage#

The common DMA functions can be used after the DMA Structures are specified, passing an instance of sl_dma_init_t. These functions will initiate and configure the DMA below, which is the flow for implementation.

  1. sl_si91x_dma_init

  2. sl_si91x_dma_allocate_channel

  3. sl_si91x_dma_register_callbacks

  4. sl_si91x_dma_simple_transfer or

  5. sl_si91x_dma_transfer

  6. sl_si91x_dma_deinit

Modules#

sl_dma_callback_t

sl_dma_init_t

sl_channel_data_t

sl_dma_xfer_t

Enumerations#

enum
SL_DMA_MEMORY_TO_MEMORY
SL_DMA_MEMORY_TO_PERIPHERAL
SL_DMA_PERIPHERAL_TO_MEMORY
}

Enumeration holds transfer types of DMA.

enum
SL_DMA_BASIC_MODE = UDMA_MODE_BASIC
SL_DMA_PINGPONG_MODE = UDMA_MODE_PINGPONG
}

Enumeration holds transfer modes of DMA.

enum
SL_USART0_ACK = 0x01
SL_UART1_ACK = 0x02
SL_UART3_ACK = 0x03
SL_SSI_SLAVE_ACK = 0x04
SL_SSI_MASTER_ACK = 0x05
SL_SSI1_SLAVE_ACK = 0x06
SL_I2C_ACK = 0x07
}

Enumeration holds peripheral ACK signals to DMA.

enum
SL_TRANSFER_SIZE_32 = SRC_SIZE_32
SL_TRANSFER_SIZE_16 = SRC_SIZE_16
SL_TRANSFER_SIZE_8 = SRC_SIZE_8
}

Enumeration holds DMA transfer sizes.

enum
SL_TRANSFER_SRC_INC_32 = SRC_INC_32
SL_TRANSFER_SRC_INC_16 = SRC_INC_16
SL_TRANSFER_SRC_INC_8 = SRC_INC_8
SL_TRANSFER_SRC_INC_NONE = SRC_INC_NONE
SL_TRANSFER_DST_INC_32 = DST_INC_32
SL_TRANSFER_DST_INC_16 = DST_INC_16
SL_TRANSFER_DST_INC_8 = DST_INC_8
SL_TRANSFER_DST_INC_NONE = DST_INC_NONE
}

Enumeration holds DMA transfer address increment for source and destination.

enum
SL_DMA_TRANSFER_DONE_CB = 1
SL_DMA_ERROR_CB = 2
}

Enumeration holds 8-bit codes which are used by callback_type in sl_si91x_dma_unregister_callbacks function.

Typedefs#

typedef void(*
sl_dma_transfer_complete)(uint32_t channel, void *data)

Typedef for user-supplied callback function which is called when a DMA transfer completes.

typedef void(*
sl_dma_error)(uint32_t channel, void *data)

Typedef for user-supplied callback function which is called when a DMA error occurs.

Variables#

DMA driver channel allocator.

Functions#

sl_status_t
sl_si91x_dma_init(sl_dma_init_t *dma_init)

This API initializes the DMA peripheral.

sl_status_t
sl_si91x_dma_deinit(uint32_t dma_number)

This function de-initializes the DMA peripheral.

sl_status_t
sl_si91x_dma_allocate_channel(uint32_t dma_number, uint32_t *channel_no, uint32_t priority)

This API allocates DMA channel for the transfer.

sl_status_t
sl_si91x_dma_deallocate_channel(uint32_t dma_number, uint32_t channel_no)

This API deallocates the DMA channel.

sl_status_t
sl_si91x_dma_register_callbacks(uint32_t dma_number, uint32_t channel_no, sl_dma_callback_t *callback_t)

This API registers the DMA callbacks (transfer complete & error).

sl_status_t
sl_si91x_dma_unregister_callbacks(uint32_t dma_number, uint32_t channel_no, uint8_t callback_type)

This API unregisters the DMA callbacks (transfer complete & error).

sl_status_t
sl_si91x_dma_transfer(uint32_t dma_number, uint32_t channel_no, sl_dma_xfer_t *dma_transfer_t)

This API starts the DMA transfer.

sl_status_t
sl_si91x_dma_simple_transfer(uint32_t dma_number, uint32_t channel_no, void *src_addr, void *dst_addr, uint32_t data_size)

This API starts a simple memory to memory DMA transfer.

sl_status_t
sl_si91x_dma_stop_transfer(uint32_t dma_number, uint32_t channel_no)

This API stops DMA transfer.

sl_status_t
sl_si91x_dma_channel_status_get(uint32_t dma_number, uint32_t channel_no)

This API returns the DMA channel status.

sl_status_t
sl_si91x_dma_channel_enable(uint32_t dma_number, uint32_t channel_no)

This API enables the DMA channel.

sl_status_t
sl_si91x_dma_channel_disable(uint32_t dma_number, uint32_t channel_no)

This API disables the DMA channel.

sl_status_t
sl_si91x_dma_enable(uint32_t dma_number)

This API enables DMA peripheral.

Macros#

#define
SL_STATUS_DMA_CHANNEL_ALLOCATED (sl_status_t)0x45
#define
SL_STATUS_DMA_NO_CHANNEL_AVAILABLE (sl_status_t)0x46
#define
SL_STATUS_DMA_CHANNEL_ALREADY_UNALLOCATED (sl_status_t)0X47
#define
SL_STATUS_DMA_CHANNEL_UNALLOCATED (sl_status_t)0X48
#define
SL_CHANNEL_COUNT 32
#define
ALTERNATE_DESCRIPTOR_DISABLE 0
#define
ALTERNATE_DESCRIPTOR_ENABLE 1
#define
BURST_REQUEST_ENABLE 1
#define
BURST_REQUEST_DISABLE 0
#define
CHANNEL_PRIO_DISABLE 0
#define
CHANNEL_PRIO_ENABLE 1
#define
PERIPHERAL_ACK_DISABLE 0
#define
PERIPHERAL_REQUEST_DISABLE 0
#define
PERIPHERAL_REQUEST_ENABLE 1
#define
REQUEST_MASK_DISABLE 0
#define
NEXT_BURST_ENABLE undefined
#define
NEXT_BURST_DISABLE 0
#define
SOURCE_PROTECT_CONTROL_DISABLE 0x000
#define
DESTINATION_PROTECT_CONTROL_DISABLE 0x000

Enumeration Documentation#

sl_dma_transfer_type_t#

sl_dma_transfer_type_t

Enumeration holds transfer types of DMA.

Enumerator
SL_DMA_MEMORY_TO_MEMORY

Memory to memory transfer.

SL_DMA_MEMORY_TO_PERIPHERAL

Memory to peripheral transfer.

SL_DMA_PERIPHERAL_TO_MEMORY

Peripheral to memory transfer.


sl_dma_transfer_mode_t#

sl_dma_transfer_mode_t

Enumeration holds transfer modes of DMA.

Enumerator
SL_DMA_BASIC_MODE

Basic DMA mode.

SL_DMA_PINGPONG_MODE

Ping pong mode.


sl_dma_peripheral_ack_t#

sl_dma_peripheral_ack_t

Enumeration holds peripheral ACK signals to DMA.

Enumerator
SL_USART0_ACK

ACK code for USART0.

SL_UART1_ACK

ACK code for UART1.

SL_UART3_ACK

ACK code for UART3.

SL_SSI_SLAVE_ACK

ACK code for SSI slave.

SL_SSI_MASTER_ACK

ACK code for SSI master.

SL_SSI1_SLAVE_ACK

ACK code for SSI1.

SL_I2C_ACK

ACK code for I2C.


sl_dma_transfer_size_t#

sl_dma_transfer_size_t

Enumeration holds DMA transfer sizes.

Enumerator
SL_TRANSFER_SIZE_32

4 bytes transfer size

SL_TRANSFER_SIZE_16

2 bytes transfer size

SL_TRANSFER_SIZE_8

1 bytes transfer size


sl_dma_transfer_inc_t#

sl_dma_transfer_inc_t

Enumeration holds DMA transfer address increment for source and destination.

Enumerator
SL_TRANSFER_SRC_INC_32

4 bytes source address increment

SL_TRANSFER_SRC_INC_16

2 bytes source address increment

SL_TRANSFER_SRC_INC_8

1 byte source address increment

SL_TRANSFER_SRC_INC_NONE

No source address increment.

SL_TRANSFER_DST_INC_32

4 bytes destination address increment

SL_TRANSFER_DST_INC_16

2 bytes destination address increment

SL_TRANSFER_DST_INC_8

1 byte destination address increment

SL_TRANSFER_DST_INC_NONE

No destination address increment.


sl_dma_callback_code_t#

sl_dma_callback_code_t

Enumeration holds 8-bit codes which are used by callback_type in sl_si91x_dma_unregister_callbacks function.

Enumerator
SL_DMA_TRANSFER_DONE_CB

8-bit code for transfer complete callback

SL_DMA_ERROR_CB

8-bit code for error callback


Typedef Documentation#

sl_dma_transfer_complete#

typedef void(* sl_dma_transfer_complete) (uint32_t channel, void *data) )(uint32_t channel, void *data)

Typedef for user-supplied callback function which is called when a DMA transfer completes.

Parameters
TypeDirectionArgument NameDescription
[in]channel_no

DMA channel number

[in]*data

An extra parameter for user application


sl_dma_error#

typedef void(* sl_dma_error) (uint32_t channel, void *data) )(uint32_t channel, void *data)

Typedef for user-supplied callback function which is called when a DMA error occurs.

Parameters
TypeDirectionArgument NameDescription
[in]channel_no

DMA channel number

[in]*data

An extra parameter for user application


Variable Documentation#

sl_channel_allocation_data_t#

sl_channel_data_t sl_channel_allocation_data_t[2][SL_CHANNEL_COUNT]

DMA driver channel allocator.


Function Documentation#

sl_si91x_dma_init#

sl_status_t sl_si91x_dma_init (sl_dma_init_t * dma_init)

This API initializes the DMA peripheral.

Parameters
TypeDirectionArgument NameDescription
sl_dma_init_t *[in]dma_init

DMA initialization structure, dma_init->dma_number - 0->UDMA0, 1->UDMA1

This API enables DMA clock and clears DMA interrupts. Configure dma_init->dma_number to 0 for initializing UDMA0 and 1 for initializing UDMA1

  • Pre-condition:

    • none

Returns

  • Initialization status

    • SL_STATUS_OK - Initialization success

    • SL_STATUS_NOT_INITIALIZED - Initialization fail


sl_si91x_dma_deinit#

sl_status_t sl_si91x_dma_deinit (uint32_t dma_number)

This function de-initializes the DMA peripheral.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

0->UDMA0, 1->UDMA1

This API disables the DMA peripheral clock and interrupts. DMA will be deinitialized only if there is no ongoing transfer.

Returns

  • deinitialization status

    • SL_STATUS_OK - Deinit success

    • SL_STATUS_BUSY - Cannot deinit the peripheral due to an ongoing transfer

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized


sl_si91x_dma_allocate_channel#

sl_status_t sl_si91x_dma_allocate_channel (uint32_t dma_number, uint32_t * channel_no, uint32_t priority)

This API allocates DMA channel for the transfer.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t *[in]channel_no

0 -> Automatically allocates available channel for DMA transfer (1-32) -> Allocates given channel for UDMA0 transfer (1-12) -> Allocates given channel for UDMA1 transfer

uint32_t[in]priority

0 -> low priority 1 -> high priority

This API checks the available DMA channel and allocates the channel. This function also sets the priority of the allocated channel and assigns the channel number to the *channel_no variable. If no channel is available, it will return SL_DMA_NO_CHANNEL_AVAILABLE. Note: Users can also initialize the desired channel number and this API checks whether the desired channel is available and allocates the channel if available. If users want the driver to allocate the available channel, channel_no should be initialized to 0.

Returns

  • channel allocation status:

    • SL_STATUS_OK - Channel allocated

    • SL_STATUS_DMA_NO_CHANNEL_AVAILABLE - All DMA channels are allocated

    • SL_STATUS_DMA_CHANNEL_ALLOCATED - The desired channel is already allocated

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_deallocate_channel#

sl_status_t sl_si91x_dma_deallocate_channel (uint32_t dma_number, uint32_t channel_no)

This API deallocates the DMA channel.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

This API deallocates the DMA channel if there is no ongoing transfer on the channel. Deallocating the channel will also unregister the callbacks for transfer complete and error.

Returns

  • channel deallocation status:

    • SL_STATUS_OK - Channel deallocated

    • SL_STATUS_BUSY - Cannot deallocate channel due to an ongoing transfer

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_register_callbacks#

sl_status_t sl_si91x_dma_register_callbacks (uint32_t dma_number, uint32_t channel_no, sl_dma_callback_t * callback_t)

This API registers the DMA callbacks (transfer complete & error).

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

sl_dma_callback_t *[in]callback_t

structure containing callback functions

User must update the sl_dma_callback_t structure and pass its address to this function. A separate callback can be present for transfer complete and error for each channel.

Returns

  • channel deallocation status:

    • SL_STATUS_OK - Callback registered successfully

    • SL_STATUS_INVALID_PARAMETER - Invalid channel number

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized


sl_si91x_dma_unregister_callbacks#

sl_status_t sl_si91x_dma_unregister_callbacks (uint32_t dma_number, uint32_t channel_no, uint8_t callback_type)

This API unregisters the DMA callbacks (transfer complete & error).

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

uint8_t[in]callback_type

Unregister the DMA callbacks based on the callback type (bit-mapped to callbacks), (SL_DMA_TRANSFER_DONE_CB) -> unregister transfer complete callback (SL_DMA_ERROR_CB) -> unregister error callback (SL_DMA_TRANSFER_DONE_CB | SL_DMA_ERROR_CB) -> unregister both transfer complete and error callback

Users need to update the 8-bit variable callback_type and pass to the function Each bit is mapped to a specific callback.

Returns

  • channel de-allocation status:

    • SL_STATUS_OK - Callback unregistered successfully

    • SL_STATUS_INVALID_PARAMETER - Invalid channel number

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized


sl_si91x_dma_transfer#

sl_status_t sl_si91x_dma_transfer (uint32_t dma_number, uint32_t channel_no, sl_dma_xfer_t * dma_transfer_t)

This API starts the DMA transfer.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

sl_dma_xfer_t *[in]dma_transfer_t

channel transfer data structure containing channel descriptor and other basic DMA parameters.

This API configures the DMA channel descriptor and initiates the DMA transfer DMA primary descriptor is updated in this function and based on transfer mode alternate descriptor is updated (only for ping pong mode). Also other DMA parameters like peripheral ACK signal (for peripheral memory transfers), DMA priority, etc. are updated in this function.

Returns

  • DMA transfer status:

    • SL_STATUS_OK - Transfer started successfully

    • SL_STATUS_SUSPENDED - Transfer initialization fails

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_simple_transfer#

sl_status_t sl_si91x_dma_simple_transfer (uint32_t dma_number, uint32_t channel_no, void * src_addr, void * dst_addr, uint32_t data_size)

This API starts a simple memory to memory DMA transfer.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

void *[in]src_addr

source address.

void *[in]dst_addr

destination address.

uint32_t[in]data_size

transfer size in bytes

This API configures the DMA channel descriptor and initiates simple memory-to-memory DMA transfer. Users need to pass the source address and destination address of the transfer along with transfer length in bytes.

Returns

  • DMA transfer status:

    • SL_STATUS_OK - Transfer success

    • SL_STATUS_SUSPENDED - Transfer initialization fails

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_stop_transfer#

sl_status_t sl_si91x_dma_stop_transfer (uint32_t dma_number, uint32_t channel_no)

This API stops DMA transfer.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

This API stops any active transfer on the channel by disabling the DMA channel. If there is no active transfer on the channel, this function returns SL_DMA_CHANNEL_IDLE

Returns

  • DMA transfer status:

    • SL_STATUS_OK - Transfer stopped successfully

    • SL_STATUS_IDLE - There is no active transfer on the channel

    • SL_STATUS_INVALID_PARAMETER - Invalid channel number

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized


sl_si91x_dma_channel_status_get#

sl_status_t sl_si91x_dma_channel_status_get (uint32_t dma_number, uint32_t channel_no)

This API returns the DMA channel status.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

This API returns the following channel status, SL_STATUS_DMA_CHANNEL_ALREADY_ALLOCATED - DMA channel allocated but no active transfer in progress SL_STATUS_BUSY - Channel is allocated and active transfer is in progress SL_STATUS_IDLE - Channel is not allocated.

Returns

  • channel status

    • SL_STATUS_IDLE - Channel is not allocated

    • SL_STATUS_DMA_CHANNEL_ALREADY_ALLOCATED - Channel is already allocated and idle

    • SL_STATUS_BUSY - Channel is allocated and busy

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_channel_enable#

sl_status_t sl_si91x_dma_channel_enable (uint32_t dma_number, uint32_t channel_no)

This API enables the DMA channel.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

Enabling channel will trigger DMA transfer if DMA is already enabled. Also, the channel should be allocated and transfer parameters should be configured before enabling the channel.

Returns

  • channel status

    • SL_STATUS_OK - Channel enables success

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_channel_disable#

sl_status_t sl_si91x_dma_channel_disable (uint32_t dma_number, uint32_t channel_no)

This API disables the DMA channel.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

uint32_t[in]channel_no

(1-32) -> UDMA0 (1-12) -> UDMA1

Disabling the DMA channel will abort any ongoing active transfers on the channel. Enabling the channel back will not resume the previous transfer.

Returns

  • channel status

    • SL_STATUS_OK - Channel disable success

    • SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized

    • SL_STATUS_INVALID_PARAMETER - Channel no is invalid


sl_si91x_dma_enable#

sl_status_t sl_si91x_dma_enable (uint32_t dma_number)

This API enables DMA peripheral.

Parameters
TypeDirectionArgument NameDescription
uint32_t[in]dma_number

dma_number 0->UDMA0, 1->UDMA1

Enabling the DMA will trigger transfer if the channel is already enabled. Also, the channel should be allocated and transfer parameters should be configured before enabling the DMA.

Returns

  • SL_STATUS_OK - Channel enable success SL_STATUS_NOT_INITIALIZED - DMA peripheral not initialized