注:1、需要注意配置edma_transfer_config_t时配置好源数据每个字节长度
2、需要注意DMA每次传输时需要间隔时间,防止DMA阻塞
/*
bsp_memtomem.c
*/
#include "bsp_memtomem.h"
edma_handle_t g_EDMA_Handle;//edma传输句柄
edma_transfer_config_t MEMtransferConfig;
volatile bool g_Transfer_Done = false;//定义传输完成标志
uint32_t srcAddr[MEM_BUFF_LENGTH]={0x01,0x02,0x03,0x04,0x58,0x76};
uint32_t destAddr[MEM_BUFF_LENGTH]={0x00};
void MEM_eDMA_Config(void)
{
// edma_transfer_config_t MEMtransferConfig;
edma_config_t MEMuserConfig;
//初始化DMAMUX外设 使能时钟
DMAMUX_Init(MEM_DMAMUX);
//设置DMA一直处于活动状态 验证始终运行模式 传输数据结束后需要重新申请才可以继续传输
DMAMUX_EnableAlwaysOn(MEM_DMAMUX,MEM_eDMA_Channel,true);
//使能DMA通道
DMAMUX_EnableChannel(MEM_DMAMUX,MEM_eDMA_Channel);
/*获得默认配置
* userConfig.enableRoundRobinArbitration = false; 使用固定优先级模式,
* userConfig.enableHaltOnError = true; 使能错误停止
* userConfig.enableContinuousLinkMode = false; 不使用次循环通道连接
* userConfig.enableDebugMode = false; 禁止DEBUG模式(在Debug 模式下DMA正常运行)
*/
EDMA_GetDefaultConfig(&MEMuserConfig);
EDMA_Init(MEM_DMA,&MEMuserConfig);
//初始化传输配置结构体
MEMtransferConfig.srcAddr = (uint32_t)srcAddr;//传输源地址
MEMtransferConfig.destAddr = (uint32_t)destAddr;//传输目的地址
MEMtransferConfig.srcTransferSize = kEDMA_TransferSize4Bytes;//源数据宽度 每一个数据字节数
MEMtransferConfig.destTransferSize = kEDMA_TransferSize4Bytes;//目的数据宽度
// MEMtransferConfig.srcTransferSize = kEDMA_TransferSize2Bytes;//源数据宽度 验证是一个数据是4个字节还是总的是4个字节
// MEMtransferConfig.destTransferSize = kEDMA_TransferSize2Bytes;//目的数据宽度
MEMtransferConfig.srcOffset = 4;//源地址偏移
MEMtransferConfig.destOffset = 4;//目的地址偏移
// MEMtransferConfig.minorLoopBytes = 16;//次循环传输字节数
MEMtransferConfig.minorLoopBytes = 24;//次循环传输字节数
MEMtransferConfig.majorLoopCounts = 1;//次循环执行次数
//创建eDMA传输句柄
EDMA_CreateHandle(&g_EDMA_Handle,MEM_DMA,MEM_eDMA_Channel);
//设置传输完成回调函数
EDMA_SetCallback(&g_EDMA_Handle, MEM_eDMA_Callback, NULL);
//提交eDMA传输请求
EDMA_SubmitTransfer(&g_EDMA_Handle, &MEMtransferConfig);
EDMA_StartTransfer(&g_EDMA_Handle);
}
void MEM_eDMA_Callback(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds)
{
if(transferDone)
g_Transfer_Done = true;
}
/*
bsp_memtomem.h
*/
#ifndef __BSP_MEMTOMEM_H__
#define __BSP_MEMTOMEM_H__
#include "fsl_common.h"
#include "fsl_edma.h"
#include "fsl_debug_console.h"
#include "fsl_dmamux.h"
#define MEM_DMAMUX DMAMUX//DMAMUX基地址
#define MEM_DMA DMA0//DMA基地址
#define MEM_eDMA_Channel 0 //DMA通道
#define MEM_BUFF_LENGTH 6U
extern edma_handle_t g_EDMA_Handle;//edma传输句柄
extern edma_transfer_config_t MEMtransferConfig;
//volatile使用场景
//中断服务程序中修改的供其他程序检测的变量
//多任务环境下,各任务之间共享的标志
//存储器映射的硬件寄存器
extern volatile bool g_Transfer_Done;//定义传输完成标志
extern uint32_t srcAddr[MEM_BUFF_LENGTH];
extern uint32_t destAddr[MEM_BUFF_LENGTH];
void MEM_eDMA_Config(void);
void MEM_eDMA_Callback(struct _edma_handle *handle, void *userData, bool transferDone, uint32_t tcds);
#endif
/*
main.c 测试代码
*/
...
uint8_t counter=0;
MEM_eDMA_Config();
while(1)
{
if(g_Transfer_Done){
PRINTF("%d %d %d %d %d %d\r\n",destAddr[0],destAddr[1],destAddr[2],destAddr[3],destAddr[4],destAddr[5]);
PRINTF("%d %d %d %d %d %d\r\n",srcAddr[0],srcAddr[1],srcAddr[2],srcAddr[3],srcAddr[4],srcAddr[5]);//搬运结束后源数据内容
g_Transfer_Done=false;
counter++;
}
if(counter<100){//改变数据查看是否还会传输
// Delay_nms(1000);
srcAddr[0] = counter;
srcAddr[1] = counter+1;
srcAddr[2] = counter+2;
srcAddr[3] = counter+3;
srcAddr[4] = counter+4;
srcAddr[5] = counter+5;
}else{
counter = 0;
}
while(EDMA_GetChannelStatusFlags(MEM_DMA,MEM_eDMA_Channel)!=kEDMA_DoneFlag);//等待传输完成,否则会阻塞
// Delay_nms(1);//延时防止DMA阻塞
EDMA_SubmitTransfer(&g_EDMA_Handle, &MEMtransferConfig);
EDMA_StartTransfer(&g_EDMA_Handle);
}