基于RT1052的DMA(内存到内存的实验)

注: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);	
		}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值