#define ARR_LEN 1024
char src[ARR_LEN] = "hello\0";
char dst[ARR_LEN] = {0};
将src这个数组的值,赋值到dst这个数组中,不可以采取直接赋值的方式,需要通过DMA将数据进行传递。
添加标准库中的gd32f4xx_dma.c
文件
/***************** DMA m2m *******************/
// 时钟
rcu_periph_clock_enable(RCU_DMA1);
// 重置dma
dma_deinit(DMA1, DMA_CH0);
dma 配置
dma_single_data_parameter_struct dsdps;
dma_single_data_para_struct_init(&dsdps);
// 方向
dsdps.direction = DMA_MEMORY_TO_MEMORY;
// 外设(作为内存到内存拷贝的源)
dsdps.periph_addr = (uint32_t)src;
dsdps.periph_inc = DMA_PERIPH_INCREASE_ENABLE;
// 内存
dsdps.memory0_addr = (uint32_t)dst;
dsdps.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
// 数据长度
dsdps.number = ARR_LEN;
// 数据宽度
dsdps.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
dma_single_data_mode_init(DMA1, DMA_CH0, &dsdps);
dma_channel_enable(DMA1, DMA_CH0);
while(RESET == dma_flag_get(DMA1, DMA_CH0, DMA_FLAG_FTF));
dma_flag_clear(DMA1, DMA_CH0, DMA_FLAG_FTF);
源地址和目标地址都是提前配置好的,当传输时,就会从源地址将数据传递给目标地址。
每传输一个字节数据,地址是否需要增长。这里包含了源地址是否需要增长,也包含了目标地址是否需要增长。
数据宽度表示一次传递多上个bit
传输了多少个数据宽度的数据。
这里主要指的是在配置DMA的源和目标的时候,我们无法给出一个具体的源地址和源的数据长度。
通常我们要解决的也是初始化和数据传输请求。
uint32_t dmax = DMA1;
uint32_t dmax_rcu = RCU_DMA1;
uint32_t dmax_ch = DMA_CH0;
uint32_t dmax_dirction = DMA_MEMORY_TO_MEMORY;
//uint32_t dmax_src = (uint32_t)src;
uint32_t dmax_src_inc = DMA_PERIPH_INCREASE_ENABLE;
uint32_t dmax_src_width = DMA_PERIPH_WIDTH_8BIT;
//uint32_t dmax_src_len = ARR_LEN;
uint32_t dmax_dst = (uint32_t)dst;
uint32_t dmax_dst_inc = DMA_MEMORY_INCREASE_ENABLE;
/***************** DMA m2m *******************/
// 时钟
rcu_periph_clock_enable(dmax_rcu);
// 重置dma
dma_deinit(dmax, dmax_ch);
dma 配置
dma_single_data_parameter_struct dsdps;
dma_single_data_para_struct_init(&dsdps);
// 方向
dsdps.direction = dmax_dirction;
// 内存
dsdps.memory0_addr = dmax_dst;
dsdps.memory_inc = dmax_dst_inc;
// 外设
//dsdps.periph_addr = dmax_src;
dsdps.periph_inc = dmax_src_inc;
// 数据长度
//dsdps.number = dmax_src_len;
// 数据宽度
dsdps.periph_memory_width = dmax_src_width;
dma_single_data_mode_init(dmax, dmax_ch, &dsdps);
初始化时,不再初始化源地址和要传输的长度。
dma_periph_address_config(DMA1, DMA_CH0,(uint32_t)data);
dma_transfer_number_config(DMA1, DMA_CH0, len);
dma_channel_enable(DMA1, DMA_CH0);
while(RESET == dma_flag_get(DMA1, DMA_CH0, DMA_FLAG_FTF));
dma_flag_clear(DMA1, DMA_CH0, DMA_FLAG_FTF);
请求数据传输前,进行动态配置:
通常,dma数据传输完成,我们也是可以知道的。可以通过中断的方式获取。
// 中断配置
nvic_irq_enable(DMA1_Channel0_IRQn, 2, 2);
// 中断使能
dma_interrupt_enable(DMA1, DMA_CH0, DMA_INT_FTF);
// 开启DMA通道
dma_channel_enable(DMA1, DMA_CH0);
void DMA1_Channel0_IRQHandler() {
// 判断中断标记
if(SET == dma_interrupt_flag_get(DMA1, DMA_CH0, DMA_INT_FLAG_FTF)) {
printf("INT dst: %s\n", dst);
// 清理标记位
dma_interrupt_flag_clear(DMA1, DMA_CH0, DMA_INT_FLAG_FTF);
}
}