dma crc,令人吃惊的性能,计算1k个值竟然在0.2us内完成

2019-12-13 18:23发布

本帖最后由 myxiaonia 于 2015-3-12 00:51 编辑

dma实在太强大,stm32f1的crc计算,使用dma传输,在72m主频下,1k次竟然在0.2us内完成。。。。。。。。。。作为对比的软件传递方法,用时128us,这个差距,简直爆出翔了

不敢私藏代码,愿把测试代码奉上,希望对大家有用(计时是用的mdk调试模式时寄存器窗口中的时间值)

  1. #define CRC_START(src, len)     CRC->CR = CRC_CR_RESET;                 
  2.                                {DMA_Channel_TypeDef *ps = DMA2_Channel1;  
  3.                                                                 while(ps->CCR & DMA_CCR1_EN);   
  4.                                 ps->CMAR         = (uint32_t)src;   
  5.                                 ps->CNDTR         = len;            
  6.                                 ps->CCR     |= DMA_CCR1_EN; }


  7. void CRC_DMA_Configuration(void)
  8. {
  9.     RCC->AHBENR          |= 0
  10.                          | RCC_AHBENR_CRCEN
  11.                          | RCC_AHBENR_DMA2EN
  12.                          ;
  13.     DMA2_Channel1->CPAR   = (uint32_t)&CRC->DR;
  14.         DMA2_Channel1->CCR         = 0
  15.                          | DMA_CCR1_MEM2MEM              //M2M模式传送
  16.                          | DMA_CCR1_PLVH                 //优先级最高
  17.                          | DMA_CCR1_MSIZE32              //外设位宽32位
  18.                          | DMA_CCR1_PSIZE32              //缓冲区位宽32位
  19.                          | DMA_CCR1_MINC                //缓冲区地址自增
  20. //                         | DMA_CCR1_PINC                //外设地址不变
  21. //                         | DMA_CCR1_CIRC                //非循环模式
  22.                          | DMA_CCR1_DIR                 //存储器到外设
  23.                          | DMA_CCR1_TEIE                //传输错误中断
  24. //                         | DMA_SxCR_HTIE
  25.                          | DMA_CCR_TCIE                //开启传输完成中断
  26. //                         | DMA_SxCR_EN                  //DMA流使能
  27.                          ;
  28. }


  29. void DMA2_Channel1_IRQHandler(void)
  30. {
  31.     DMA_Channel_TypeDef *pch = DMA2_Channel1;
  32.     DMA_TypeDef *pdma = DMA2;
  33.    
  34.     pch->CCR    &=~DMA_CCR1_EN;
  35.     pdma->IFCR   = DMA_IFCR_CGIF1;
  36. }

  37. uint32_t clc_crc(const uint32_t *ptr,uint32_t length)
  38. {
  39.         CRC->CR=CRC_CR_RESET;
  40.         for( ; length; --length)
  41.                 CRC->DR = *ptr++;
  42.         return CRC->DR;
  43. }

  44. int main(void)
  45. {
  46.     NVIC_SetPriority(DMA2_Channel1_IRQn,NVIC_EncodePriority(3,6,0));
  47.         NVIC_EnableIRQ(DMA2_Channel1_IRQn);
  48.         CRC_DMA_Configuration();
  49.         while(1)
  50.         {
  51.                 clc_crc((uint32_t *)0x2000c000,1024);
  52.                 CRC_START((void *)0x2000c000,1024);
  53.         }
  54. }
复制代码
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
40条回答
myxiaonia
1楼-- · 2019-12-18 20:47
 精彩回答 2  元偷偷看……
maninblack
2楼-- · 2019-12-19 00:16
redroof 发表于 2015-3-13 10:26
整个运行过程只要你用了断点,调试器自带的周期计数就不准了。
正确方法是开个定时器,在crc开启的时候读 ...

楼主后来有用过redroof上面的方法再测次时间么,是否还是0.2us?
myxiaonia
3楼-- · 2019-12-19 03:01
maninblack 发表于 2015-4-2 16:04
楼主后来有用过redroof上面的方法再测次时间么,是否还是0.2us?

0.2us肯定是不对的,至于问题在哪里没找到,有例程可以试试
tomzbj
4楼-- · 2019-12-19 08:48
本帖最后由 tomzbj 于 2019-2-28 15:11 编辑

不错,我也试了下,速度是常规方法的2倍左右
不过奇怪的是,只能用DMA1, 换成DMA2就卡死。mcu是stm32f072。
-----------------------糊涂了,stm32f072没有DMA2...
  1. unsigned long CRC32_Calc(unsigned long initial, const void* msg, int size)
  2. {
  3.     static DMA_InitTypeDef DMA_InitStructure;
  4.     static int first_run = 1;

  5.     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  6.     DMA_DeInit(DMA1_Channel1);
  7.     initial = ((initial >> 1) & 0x55555555) | ((initial & 0x55555555) << 1);
  8.     initial = ((initial >> 2) & 0x33333333) | ((initial & 0x33333333) << 2);
  9.     initial = ((initial >> 4) & 0x0f0f0f0f) | ((initial & 0x0f0f0f0f) << 4);
  10.     initial = ((initial >> 8) & 0x00ff00ff) | ((initial & 0x00ff00ff) << 8);
  11.     initial = (initial >> 16) | (initial << 16);                         //    st提供了源操作数按位反转,却没有提供初值也按位反转的功能。。。

  12.     CRC_SetInitRegister(initial);
  13.     CRC_ResetDR();

  14.     if(first_run) {
  15.         DMA_StructInit(&DMA_InitStructure);
  16.         DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  17.         DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  18.         DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  19.         DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  20.         DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  21.         DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
  22.         DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
  23.         DMA_InitStructure.DMA_PeripheralBaseAddr = (unsigned long)CRC_BASE;
  24.         DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
  25.     }
  26.     DMA_InitStructure.DMA_MemoryBaseAddr = (unsigned long)(msg);
  27.     DMA_InitStructure.DMA_BufferSize = size;
  28.     DMA_Init(DMA1_Channel1, &DMA_InitStructure);
  29.     DMA_Cmd(DMA1_Channel1, ENABLE);

  30.     ( {  while(DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET);});
  31.     first_run = 0;
  32.     return CRC_GetCRC();
  33. }
复制代码

一周热门 更多>