您的位置:首页 > 财经 > 金融 > STM32H7的MDMA、DMA2D和通用DMA性能比较

STM32H7的MDMA、DMA2D和通用DMA性能比较

2024/12/23 3:31:22 来源:https://blog.csdn.net/yybyg/article/details/140682966  浏览:    关键词:STM32H7的MDMA、DMA2D和通用DMA性能比较

STM32H7的MDMA、DMA2D和通用DMA性能比较

  • MDMA测试
    • 初始化MDMA
    • 数据传输(DWT单位2.5n)
  • DMA2D
    • DMA2D初始化
    • 数据传输
  • DMA
  • 最终结论(参考armfly)

MDMA,DMA2D 和每个都测试了四种情况:
◆ 64 位带宽的 AXI SRAM 内部做 64KB 数据传输。
◆ 32 位带宽的 D2 域 SRAM1 内部 64KB 数据传输。
◆ AXI SRAM 向 SDRAM 传输 64KB 的数据传输。
◆ 32 位带宽的 SDRAM 内部做 64KB 数据传输。
MDMA:
在 D1 域,支持 64 位带宽的 DMA 数据传输。
DMA2D:
在 D1 域,主要用图形 2D 加速。
DMA1 和 DMA2:
在 D2 域,支持 32 位带宽的 DMA 数据传输。

MDMA测试

采用块传输,源地址和目的地址都是 64bit 数据传输,并设置 16beat 突发,也就是
连续传输 16 组 64bit 数据。

初始化MDMA

	__HAL_RCC_MDMA_CLK_ENABLE();  MDMA_Handle.Instance = MDMA_Channel0;  /* MDMA配置 **********************************************************************/__HAL_RCC_MDMA_CLK_ENABLE();  MDMA_Handle.Instance = MDMA_Channel0;  MDMA_Handle.Init.Request              = MDMA_REQUEST_SW;         /* 软件触发 */MDMA_Handle.Init.TransferTriggerMode  = MDMA_BLOCK_TRANSFER;     /* 块传输 */MDMA_Handle.Init.Priority             = MDMA_PRIORITY_HIGH;      /* 优先级高*/MDMA_Handle.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */MDMA_Handle.Init.SourceInc            = MDMA_SRC_INC_DOUBLEWORD;         /* 源地址自增,双字,即8字节 */MDMA_Handle.Init.DestinationInc       = MDMA_DEST_INC_DOUBLEWORD;        /* 目的地址自增,双字,即8字节 */MDMA_Handle.Init.SourceDataSize       = MDMA_SRC_DATASIZE_DOUBLEWORD;    /* 源地址数据宽度双字,即8字节 */MDMA_Handle.Init.DestDataSize         = MDMA_DEST_DATASIZE_DOUBLEWORD;   /* 目的地址数据宽度双字,即8字节 */MDMA_Handle.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;       /* 小端,右对齐 */                    MDMA_Handle.Init.SourceBurst          = MDMA_SOURCE_BURST_16BEATS;      /* 源数据突发传输,SourceBurst*SourceDataSize <  BufferTransferLength*/MDMA_Handle.Init.DestBurst            = MDMA_DEST_BURST_16BEATS;        /* 目的数据突发传输,DestBurst*DestDataSize < BufferTransferLength */MDMA_Handle.Init.BufferTransferLength = 128;    /* 每次传输128个字节 */MDMA_Handle.Init.SourceBlockAddressOffset  = 0; /* 用于block传输,地址偏移0 */MDMA_Handle.Init.DestBlockAddressOffset    = 0; /* 用于block传输,地址偏移0 *//* 初始化MDMA */if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK){Error_Handler(__FILE__, __LINE__);}/* 设置传输完成回调和中断及其优先级配置 */HAL_MDMA_RegisterCallback(&MDMA_Handle, HAL_MDMA_XFER_CPLT_CB_ID, MDMA_TransferCompleteCallback);HAL_NVIC_SetPriority(MDMA_IRQn, 0, 0);HAL_NVIC_EnableIRQ(MDMA_IRQn);  //配置中断void MDMA_IRQHandler(void)
{HAL_MDMA_IRQHandler(&MDMA_Handle);
}
static void MDMA_TransferCompleteCallback(MDMA_HandleTypeDef *hmdma)
{TransferCompleteDetected = 1;
}

需要注意的是
◆ 第 1 行,务必优先初始化 MDMA 时钟,测试发现没有使能时钟的情况下就配置 MDMA 很容易失败。
◆ 第 14-15 行,突发传输的配置非常考究,每次突发传输的总数据大小不能超过 128 字节。
对于源地址就是 SourceBurst * SourceDataSize <= BufferTransferLength。
对于目的地址就是 DestBurstDestDataSize <= BufferTransferLength。
比如当前的程序配置:
SourceBurst * SourceDataSize = 16
8 =128 字节
DestBurstDestDataSize = 168 =128 字节
这里要特别注意一点,如果实际应用中最好小于 BufferTransferLength,防止不稳定。

数据传输(DWT单位2.5n)

    /* AXI SRAM的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_MDMA_Start_IT(&MDMA_Handle, (uint32_t)0x24000000, (uint32_t)(0x24000000 + 64*1024), 64*1024, 1);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;//64*1024/(cnt/400/1000/1000)/1024/1024 = 64*1000*1000*400/1024/cnt = 25000000/cntprintf("MDMA---AXI SRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* D2域SRAM1的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_MDMA_Start_IT(&MDMA_Handle, (uint32_t)0x30000000, (uint32_t)(0x30000000 + 64*1024), 64*1024, 1);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("MDMA---D2域SRAM1内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* AXI SRAM向SDRAM的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_MDMA_Start_IT(&MDMA_Handle, (uint32_t)0x24000000, (uint32_t)0xC0000000, 64*1024, 1);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("MDMA---AXI SRAM传输64KB数据到SDRAM耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* SDRAM的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_MDMA_Start_IT(&MDMA_Handle, (uint32_t)0xC0000000, (uint32_t)(0xC0000000 + 64*1024), 64*1024, 1);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("MDMA---SDRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);

DMA2D

DMA2D初始化

配置 DMA2D 采用存储器到存储器模式,前景区和输出区都采用 ARGB8888 格式,传输 64256 次,每次 4 字节,即 64256*4 = 64KB 数据。

	__HAL_RCC_DMA2D_CLK_ENABLE();  /* DMA2D采用存储器到存储器模式, 这种模式是前景层作为DMA2D输入 */  DMA2D->CR      = 0x00000000UL;DMA2D->FGOR    = 0;DMA2D->OOR     = 0;/* 前景层和输出区域都采用的RGB565颜色格式 */DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_ARGB8888;DMA2D->NLR     = (uint32_t)(64 << 16) | (uint16_t)256;

数据传输

 /* AXI SRAM的64KB数据传输测试 ***********************************************/DMA2D->FGMAR = (uint32_t)0x24000000;DMA2D->OMAR  = (uint32_t)(0x24000000 + 64*1024);DMA2D->CR   |= DMA2D_CR_START;   start = DWT_CYCCNT;/* 等待DMA2D传输完成 */while (DMA2D->CR & DMA2D_CR_START) {} end = DWT_CYCCNT;cnt = end - start;printf("DMA2D---AXI SRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* D2域SRAM1的64KB数据传输测试 ***********************************************/DMA2D->FGMAR = (uint32_t)0x30000000;DMA2D->OMAR  = (uint32_t)(0x30000000 + 64*1024);DMA2D->CR   |= DMA2D_CR_START;  start = DWT_CYCCNT;/* 等待DMA2D传输完成 */while (DMA2D->CR & DMA2D_CR_START) {} end = DWT_CYCCNT;cnt = end - start;printf("DMA2D---D2域SRAM1内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* AXI SRAM向SDRAM的64KB数据传输测试 ***********************************************/DMA2D->FGMAR = (uint32_t)0x24000000;DMA2D->OMAR  = (uint32_t)0xC0000000;DMA2D->CR   |= DMA2D_CR_START;  start = DWT_CYCCNT;/* 等待DMA2D传输完成 */while (DMA2D->CR & DMA2D_CR_START) {} end = DWT_CYCCNT;cnt = end - start;printf("DMA2D---AXI SRAM传输64KB数据到SDRAM耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);	/* SDRAM的64KB数据传输测试 ***********************************************/DMA2D->FGMAR = (uint32_t)0xC0000000;DMA2D->OMAR  = (uint32_t)(0xC0000000 + 64*1024);DMA2D->CR   |= DMA2D_CR_START;start = DWT_CYCCNT;/* 等待DMA2D传输完成 */while (DMA2D->CR & DMA2D_CR_START) {} end = DWT_CYCCNT;cnt = end - start;	printf("DMA2D---SDRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);	

DMA

程序代码如下,采用存储区到存储区传输方式,源地址和目的地址都是 32bit 数据传输,并设置 4beat突发,也就是连续传输 4 组 32bit 数据。

	__HAL_RCC_DMA1_CLK_ENABLE();DMA_Handle.Instance                 = DMA1_Stream1;DMA_Handle.Init.Request             = DMA_REQUEST_MEM2MEM;  DMA_Handle.Init.Direction           = DMA_MEMORY_TO_MEMORY;DMA_Handle.Init.PeriphInc           = DMA_PINC_ENABLE;DMA_Handle.Init.MemInc              = DMA_MINC_ENABLE;DMA_Handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;DMA_Handle.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;DMA_Handle.Init.Mode                = DMA_NORMAL;DMA_Handle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;DMA_Handle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;DMA_Handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;DMA_Handle.Init.MemBurst            = DMA_MBURST_INC4;     /*WORD方式,仅支持4次突发 */DMA_Handle.Init.PeriphBurst         = DMA_PBURST_INC4;      /*WORD方式,仅支持4次突发 */DMA_Handle.XferCpltCallback         = DMA_TransferCompleteCallback;HAL_DMA_Init(&DMA_Handle);HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 0, 0);HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);void DMA1_Stream1_IRQHandler(void){HAL_DMA_IRQHandler(&DMA_Handle);}static void DMA_TransferCompleteCallback(DMA_HandleTypeDef *hdma){TransferCompleteDetected = 1;}

第 1 行,务必优先初始化 DMA 时钟,测试发现没有使能时钟的情况下就配置 DMA 很容易失败。
第 14-15 行,突发传输的配置非常考究,这里要特别注意数据位宽,FIFO 以及突发的配置。
在这里插入图片描述

	HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)0x24000000, (uint32_t)(0x24000000 + 64*1024), 64*256);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;//64*1024/(cnt/400/1000/1000)/1024/1024 = 64*1000*1000*400/1024/cnt = 25000000/cntprintf("DMA1---AXI SRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* D2域SRAM1的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)0x30000000, (uint32_t)(0x30000000 + 64*1024), 64*256);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("DMA1---D2域SRAM1内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* AXI SRAM向SDRAM的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)0x24000000, (uint32_t)0xC0000000, 64*256);start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("DMA1---AXI SRAM传输64KB数据到SDRAM耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);/* SDRAM的64KB数据传输测试 ***********************************************/TransferCompleteDetected = 0;HAL_DMA_Start_IT(&DMA_Handle, (uint32_t)0xC0000000, (uint32_t)(0xC0000000 + 64*1024), 64*256);	start = DWT_CYCCNT;while(TransferCompleteDetected == 0) {}end = DWT_CYCCNT;cnt = end - start;printf("DMA1---SDRAM内部互传64KB数据耗时 =  %dus %dMB/S\r\n", cnt/400, 25000000/cnt);

最终结论(参考armfly)

在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com