DMA Driver
Overview
DMA (Direct Memory Access) driver provides high-speed data transfer between memory and peripherals without CPU intervention.
Functional Description
Multiple DMA channels for concurrent operations
Memory-to-memory transfers
Peripheral-to-memory transfers
Memory-to-peripheral transfers
Interrupt support for transfer completion
Channel allocation and management
Configurable transfer parameters
Status monitoring
Low power mode support
Development Guide
Initialization - Call bk_dma_driver_init() before any DMA operations - Allocate channel: bk_dma_alloc(user_id) - Configure transfer: source, destination, length
Basic Operations - Set addresses: bk_dma_set_src_addr(), bk_dma_set_dest_addr() - Set length: bk_dma_set_transfer_len() - Start transfer: bk_dma_start() - Wait completion: bk_dma_wait_finish()
Channel Management - Allocate: bk_dma_alloc() - Free: bk_dma_free() - Check remaining: bk_dma_get_remain_len()
Interrupt Handling - Register ISR: bk_dma_register_isr() - Enable interrupt: bk_dma_enable_interrupt() - Handle completion in ISR
Notes
Channel allocation must be in task context
Ensure memory alignment for transfers
Consider cache consistency
Use proper interrupt priorities
API Reference
bk_dma_driver_init/deinit() - Driver management
bk_dma_alloc/free() - Channel management
bk_dma_set_src_addr/dest_addr() - Address configuration
bk_dma_set_transfer_len() - Length configuration
bk_dma_start/stop() - Transfer control
bk_dma_get_remain_len() - Status monitoring
bk_dma_register_isr() - Interrupt handling
bk_dma_wait_finish() - Synchronous wait
Examples
Basic memory-to-memory transfer:
bk_dma_driver_init();
dma_id_t chan = bk_dma_alloc(0x1000);
if (chan >= DMA_ID_MAX) {
printf("DMA allocation failed\n");
return;
}
uint8_t src[1024], dst[1024];
bk_dma_set_src_addr(chan, (uint32_t)src);
bk_dma_set_dest_addr(chan, (uint32_t)dst);
bk_dma_set_transfer_len(chan, 1024);
bk_dma_start(chan);
bk_dma_wait_finish(chan);
bk_dma_free(0x1000, chan);
Interrupt-based transfer:
static void dma_isr(dma_id_t id, void *param) {
printf("DMA channel %d complete\n", id);
bk_dma_clear_interrupt(id);
}
dma_id_t chan = bk_dma_alloc(0x1001);
bk_dma_register_isr(chan, dma_isr, NULL);
bk_dma_enable_interrupt(chan);
uint8_t src[512], dst[512];
bk_dma_set_src_addr(chan, (uint32_t)src);
bk_dma_set_dest_addr(chan, (uint32_t)dst);
bk_dma_set_transfer_len(chan, 512);
bk_dma_start(chan);
Peripheral-to-memory transfer:
dma_id_t chan = bk_dma_alloc(0x1002);
uint8_t buffer[256];
bk_dma_set_src_addr(chan, UART0_RX_ADDR);
bk_dma_set_dest_addr(chan, (uint32_t)buffer);
bk_dma_set_transfer_len(chan, 256);
bk_dma_start(chan);
while (bk_dma_get_remain_len(chan) > 0) {
// Wait for completion
}
printf("Received %d bytes\n", 256);
bk_dma_free(0x1002, chan);
Status monitoring:
dma_id_t chan = bk_dma_alloc(0x1003);
uint8_t src[1024], dst[1024];
bk_dma_set_src_addr(chan, (uint32_t)src);
bk_dma_set_dest_addr(chan, (uint32_t)dst);
bk_dma_set_transfer_len(chan, 1024);
bk_dma_start(chan);
while (1) {
uint32_t remain = bk_dma_get_remain_len(chan);
dma_status_t status = bk_dma_get_status(chan);
printf("Remain: %d, Status: %d\n", remain, status);
if (remain == 0) {
printf("Transfer complete\n");
break;
}
rtos_delay_milliseconds(10);
}
bk_dma_free(0x1003, chan);
FAQs
Channel allocation failed: Check available channels and user ID
Transfer failure: Verify address alignment and validity
Interrupt not triggered: Confirm ISR registration and enable
Error Codes
BK_ERR_DMA_NOT_INIT: Driver not initialized
BK_ERR_DMA_INVALID_ID: Invalid DMA channel ID
BK_ERR_DMA_CHANNEL_BUSY: Channel busy
BK_ERR_DMA_TRANSFER_FAIL: Transfer failed