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条回答
9509238
1楼-- · 2019-12-16 23:34
楼主的时间是用cpu算出来的吧?其实dma工作时跟cpu的时间根本不是同步的,所以说这个时间不对
myxiaonia
2楼-- · 2019-12-17 04:15
wye11083 发表于 2015-3-12 16:17
曾经花了一些时间研究CRC,1位CRC改一下字就行了,通常在传输过程中就算好了。并行的则一般用于后校验用 ...

你是说硬件crc原理么,那个不是像移位寄存器一样一位位算的
myxiaonia
3楼-- · 2019-12-17 10:07
 精彩回答 2  元偷偷看……
redroof
4楼-- · 2019-12-17 14:39
myxiaonia 发表于 2015-3-12 19:35
那个寄存器窗口时间是通过指令数计算的,我用ms中断测过,非常准,我在dma开启处和中断入口打断点,这个 ...

外设是不会被调试器断下来的。调试器只能中断cpu,
所以让cpu断下来或者单步运行的时候,来数外设的时间都是不准的。
正确方法是在运行中由程序自身来读计数器的时间,存放在某个变量里,开始结尾各读一次相减。然后调试器直接查看那个变量来得到运行时间。
foxpro2005
5楼-- · 2019-12-17 18:47
按理来说,应该不可能的
canspider
6楼-- · 2019-12-17 23:05
wye11083 发表于 2015-3-12 16:17
曾经花了一些时间研究CRC,1位CRC改一下字就行了,通常在传输过程中就算好了。并行的则一般用于后校验用 ...

还有一种并行的非查表算法

一周热门 更多>