This is the documentation for the latest (main) development branch. If you are looking for the documentation of previous releases, use the drop-down menu on the left and select the desired version.

DMA

Introduction

DMA (Direct Memory Access) is a method of data transfer that provides high-speed data transfer between peripherals and memory or between memory and memory without CPU intervention. Data can be moved quickly through DMA, bypassing the need for CPU registers in traditional data transfer methods.

Function List

  1. Initialize DMA — Initialize the DMA device.

  2. Request DMA Channel — Request a DMA channel.

  3. Release DMA Channel — Release a DMA channel.

  4. Register DMA Callback — Register a DMA callback function.

  5. Unregister DMA Callback — Unregister a DMA callback function.

  6. Configure DMA Transfer — Configure DMA transfer parameters.

  7. Start DMA Transfer — Start a DMA transfer.

  8. Stop DMA Transfer — Stop a DMA transfer.

  9. Get DMA Status — Get the DMA transfer status.

  10. DMA Transfer — Configure and start a DMA transfer.

Function Overview

Parameter Configuration Supports configuring parameters such as source address, destination address, transfer length, transfer mode, etc.

Support for Multiple Transfer Modes DMA supports various transfer modes such as single transfer, burst transfer, etc., to meet different application needs.

Bus Control The DMA controller responds to peripheral requests and sends bus request signals to the CPU. When the CPU relinquishes control of the bus, the DMA controller takes over bus control. After gaining bus control, the DMA controller sends address signals to the address bus and issues read/write control signals during DMA transfers.

Transfer Management The DMA controller determines the number of bytes to be transferred and checks whether the current DMA transfer is complete. After the transfer is complete, the DMA controller returns bus control to the CPU.

Events Supports events such as transfer completion and transfer errors, which can be handled by registering callback functions.

Key Features

Initialize DMA

Call the function wm_drv_dma_init() to initialize the DMA device. The initialization process includes configuring the hardware parameters of the DMA and initializing necessary data structures to ensure the DMA device works correctly. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

Here, dma is the name of the DMA device, used to identify the device, and needs to be configured in the device table. The type is const char *.

Warning

After DMA initialization, if wm_drv_dma_deinit is not called, invoking wm_drv_dma_init again will return NULL.

Request DMA Channel

Call the function wm_drv_dma_request_ch() to request a DMA channel for the specified DMA transfer source and destination addresses and their related configurations. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;
wm_drv_dma_request_ch(dma_dev, &ch, DRV_DMA_M2M_EXAMPLE_TO_US);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is used to store the allocated DMA channel number, of type uint8_t *.

The third parameter is the timeout period for waiting for channel allocation, in milliseconds, set here as DRV_DMA_M2M_EXAMPLE_TO_US, which has a value of 0xffffffffUL, of type uint32_t.

Release DMA Channel

Call the function wm_drv_dma_release_ch() to release a DMA channel, used to terminate a DMA transfer and free the allocated DMA resources. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;
wm_drv_dma_release_ch(dma_dev, ch, DRV_DMA_M2M_EXAMPLE_TO_US);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number to be released, of type uint8_t *.

The third parameter is the timeout period for waiting to release the channel, in milliseconds, set here as DRV_DMA_M2M_EXAMPLE_TO_US, which has a value of 0xffffffffUL, of type uint32_t.

Register DMA Completion Callback

Call the function wm_drv_dma_register_callback() to register a DMA completion callback function, which is called when the DMA transfer is completed, to handle operations after the DMA transfer ends. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;
void dma_callback(wm_dma_ch_t ch, uint32_t sts, void *user_data) {
}
wm_drv_dma_register_callback(dma_dev, dma_ch, dma_callback, NULL);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number, of type uint8_t *.

The third parameter is the callback function that is called when the DMA transfer is completed, used to handle operations after the transfer ends, of type wm_drv_dma_ch_callback_t.

The fourth parameter is a user data pointer, which can pass additional information. In this example, no information is passed, of type void *.

Unregister DMA Completion Callback

Call the function wm_drv_dma_unregister_callback() to unregister the DMA completion callback function. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;

wm_drv_dma_unregister_callback(dma_dev, dma_ch);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number, of type uint8_t *.

Configure DMA Transfer

Call the function wm_drv_dma_config() to configure the DMA transfer parameters. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;
wm_drv_dma_desc_t dma_example_cfg = {
.src  = (uint32_t)&dma_src_data[0][0],
.dest = (uint32_t)&dma_dest_buf[0][0],
};
dma_example_cfg.ctrl.len           = DRV_DMA_M2M_EXAMPLE_XFER_LEN;
dma_example_cfg.ctrl.ch            = dma_ch;
dma_example_cfg.ctrl.dir           = WM_DRV_DMA_DIR_M2M;
dma_example_cfg.ctrl.burst_size    = WM_DRV_DMA_BURST_BYTE;
dma_example_cfg.ctrl.src_inc_mode  = WM_DRV_DMA_ADDR_INC;
dma_example_cfg.ctrl.dest_inc_mode = WM_DRV_DMA_ADDR_INC;
dma_example_cfg.ctrl.int_en        = WM_DRV_DMA_CH_INT_ENABLE;
dma_example_cfg.ctrl.auto_reload   = WM_DRV_DMA_RELOAD_DISABLE;
dma_example_cfg.ctrl.dma_mode      = WM_DRV_DMA_NORMAL_MODE;

wm_drv_dma_config(dma_dev, &dma_example_cfg);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the transfer descriptor, setting the source and destination addresses, where src is the starting address of the source data, pointing to the starting position of the dma_src_data array, and dest is the starting address of the destination buffer, pointing to the starting position of the dma_dest_buf array. The type is wm_drv_dma_desc_t *.

In this example, the transfer byte length, DMA channel number, data transfer direction, burst transfer size, source address increment mode, destination address increment mode, interrupt enable, auto-reload, and DMA mode are configured. Specific values can be referenced from the device table.

Start DMA Transfer

Call the function wm_drv_dma_start() to start the DMA transfer. The DMA controller will begin data transfer according to the configured parameters. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;

wm_drv_dma_start(dma_dev, dma_ch);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number to start the transfer, of type uint8_t *.

Stop DMA Transfer

Call the function wm_drv_dma_stop() to stop the DMA transfer. The DMA controller will stop the current transfer operation. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;

wm_drv_dma_stop(dma_dev, dma_ch);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number to stop the transfer, of type uint8_t *.

Get DMA Status

Call the function wm_drv_dma_get_status() to get the DMA transfer status. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;

wm_dma_sts_info_t dma_sts = {
.sts      = WM_DMA_RUNNING,
.xfer_cnt = 0,
};

wm_drv_dma_get_status(dma_dev, ch, &dma_sts);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the DMA channel number to query the status, of type uint8_t *.

The third parameter is a pointer to the wm_dma_sts_info_t structure, used to store the DMA status information.

In this example, the current status of the DMA is set during initialization, and the count of transferred data is set to zero.

DMA Transfer

Call the function wm_drv_dma_transfer() to configure and start the DMA transfer. In actual applications, you can adjust various parameters in dma_example_cfg to meet different transfer requirements according to specific needs. An example is as follows:

wm_device_t *dma_dev;
dma_dev = wm_drv_dma_init("dma");

uint8_t dma_ch = 0;
wm_drv_dma_desc_t dma_example_cfg = {
.src  = (uint32_t)&dma_src_data[0][0],
.dest = (uint32_t)&dma_dest_buf[0][0],
};
dma_example_cfg.ctrl.len           = DRV_DMA_M2M_EXAMPLE_XFER_LEN;
dma_example_cfg.ctrl.ch            = dma_ch;
dma_example_cfg.ctrl.dir           = WM_DRV_DMA_DIR_M2M;
dma_example_cfg.ctrl.burst_size    = WM_DRV_DMA_BURST_BYTE;
dma_example_cfg.ctrl.src_inc_mode  = WM_DRV_DMA_ADDR_INC;
dma_example_cfg.ctrl.dest_inc_mode = WM_DRV_DMA_ADDR_INC;
dma_example_cfg.ctrl.int_en        = WM_DRV_DMA_CH_INT_ENABLE;
dma_example_cfg.ctrl.auto_reload   = WM_DRV_DMA_RELOAD_DISABLE;
dma_example_cfg.ctrl.dma_mode      = WM_DRV_DMA_NORMAL_MODE;

wm_drv_dma_transfer(dma_dev, &dma_example_cfg);

The first parameter is the reference to the DMA device, of type wm_device_t *.

The second parameter is the transfer descriptor, setting the source and destination addresses, where src is the starting address of the source data, pointing to the starting position of the dma_src_data array, and dest is the starting address of the destination buffer, pointing to the starting position of the dma_dest_buf array. The type is wm_drv_dma_desc_t *.

In this example, the transfer byte length, DMA channel number, data transfer direction, burst transfer size, source address increment mode, destination address increment mode, interrupt enable, auto-reload, and DMA mode are configured. Specific values can be referenced from the device table.

Application Example

For basic examples of using DMA, please refer to: examples/peripheral/dma

API Reference