[应用相关] AT32 MCU上使用DMA传输数据加速进行CRC计算

[复制链接]
 楼主| muyichuan2012 发表于 2024-11-5 14:43 | 显示全部楼层 |阅读模式
本帖最后由 muyichuan2012 于 2024-11-5 14:46 编辑

AT32 MCU上使用DMA传输数据加速进行CRC计算



示例目的
演示在AT32 MCU上使用DMA传输数据加速进行CRC计算,支持CRC8,CRC16,CRC32。
支持型号列表:
支持型号 AT32 全系列
主要使用外设
CRC
DMA
USART
GPIO


快速使用方法
硬件资源
1) USART1(PA9/PA10)
2) AT-START实验板,如下是AT-START-F403A开发板。


软件资源
1) SourceCode
 SC0150_SourceCode
2) Doc
 SC0150_AT32_CRC_computing_by_using_DMA 使用方法。
Note: 所有project 都是基于keil 5 而建立,若用户需要在其他编译环境上使用,请参考
AT32F407_Firmware_Library_V2.x.x/project/at_start_f407/templates 中各种编译环境(例如
IAR6/7,keil 4/5)进行简单修改即可。
示例使用
1) 打开SC0150_SourceCode_V2.0.0\utilities\crc_dma\mdk_v5源程序。
2) 编译并下载到目标开发板,接上串口(PA9/PA10)。
3) 计算结果会从串口打印输出。


相关代码
  1. #include "at32f403a_407_board.h"
  2. #include "at32f403a_407_clock.h"

  3. /** @addtogroup UTILITIES_examples
  4.   * @{
  5.   */

  6. /** @addtogroup CRC_dma_demo
  7.   * @{
  8.   */

  9. confirm_state dma_done_flag = FALSE;

  10. uint8_t data_buffer[]  = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB};

  11. /**
  12.   * [url=home.php?mod=space&uid=247401]@brief[/url]  calculate 8-bit data CRC.
  13.   * @param  pbuffer: pointer to the buffer containing the data to be computed.
  14.   * @param  length: length of the buffer to be computed.
  15.   * @retval crc
  16.   */
  17. uint32_t crc8_block_calculate(uint8_t *pbuffer, uint32_t length)
  18. {
  19.   uint32_t index = 0;

  20.   for(index = 0; index < length; index++)
  21.   {
  22.     (*(uint8_t *)&CRC->dt) = pbuffer[index];
  23.   }

  24.   return (CRC->dt);
  25. }

  26. /**
  27.   * [url=home.php?mod=space&uid=247401]@brief[/url]  calculate 16-bit data CRC.
  28.   * @param  pbuffer: pointer to the buffer containing the data to be computed.
  29.   * @param  length: length of the buffer to be computed.
  30.   * @retval crc
  31.   */
  32. uint32_t crc16_block_calculate(uint16_t *pbuffer, uint32_t length)
  33. {
  34.   uint32_t index = 0;

  35.   for(index = 0; index < length; index++)
  36.   {
  37.     (*(uint16_t *)&CRC->dt) = pbuffer[index];
  38.   }

  39.   return (CRC->dt);
  40. }

  41. /**
  42.   * [url=home.php?mod=space&uid=247401]@brief[/url]  config nvic.
  43.   * @param  none
  44.   * @retval none
  45.   */
  46. void nvic_config(void)
  47. {
  48.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  49.   nvic_irq_enable(DMA1_Channel1_IRQn, 1, 0);
  50. }

  51. /**
  52.   * @brief  config crc.
  53.   * @param  none
  54.   * @retval none
  55.   */
  56. void crc_config(void)
  57. {
  58.   crm_periph_clock_enable(CRM_CRC_PERIPH_CLOCK, TRUE);

  59.   crc_init_data_set(0xFFFFFFFF);
  60.   crc_poly_value_set(0x04C11DB7);
  61.   crc_reverse_output_data_set(CRC_REVERSE_OUTPUT_DATA);
  62. }

  63. /**
  64.   * @brief  config dma, using DMA1_CHANNEL1.
  65.   * @param  none
  66.   * @retval none
  67.   */
  68. void dma_config(void)
  69. {
  70.   dma_init_type dma_init_struct = {0};

  71.   crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

  72.   dma_reset(DMA1_CHANNEL1);
  73.   dma_default_para_init(&dma_init_struct);

  74.   dma_init_struct.direction = DMA_DIR_MEMORY_TO_MEMORY;
  75.   dma_init_struct.memory_inc_enable = FALSE;
  76.   dma_init_struct.peripheral_inc_enable = TRUE;
  77.   dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
  78.   dma_init_struct.loop_mode_enable = FALSE;
  79.   dma_init(DMA1_CHANNEL1, &dma_init_struct);

  80.   dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
  81.   dma_channel_enable(DMA1_CHANNEL1, FALSE);
  82. }

  83. /**
  84.   * @brief  calculate CRC with dma mode.
  85.   * @param  pbuff: pointer of data buffer.
  86.   * @param  length: data buffer length
  87.   * @retval none
  88.   */
  89. uint32_t dma_calculate(uint8_t *pbuff, uint32_t length)
  90. {
  91.   crc_data_reset();
  92.   crc_reverse_input_data_set(CRC_REVERSE_INPUT_BY_WORD);

  93.   DMA1_CHANNEL1->dtcnt = length;
  94.   DMA1_CHANNEL1->maddr = (uint32_t)&(CRC->dt);
  95.   DMA1_CHANNEL1->ctrl_bit.mwidth = DMA_MEMORY_DATA_WIDTH_BYTE;
  96.   DMA1_CHANNEL1->paddr = (uint32_t)pbuff;
  97.   DMA1_CHANNEL1->ctrl_bit.pwidth = DMA_PERIPHERAL_DATA_WIDTH_BYTE;

  98.   dma_done_flag = FALSE;
  99.   dma_channel_enable(DMA1_CHANNEL1, TRUE);
  100.   /* waiting dma complete */
  101.   while(dma_done_flag == FALSE);

  102.   return crc_data_get();
  103. }

  104. /**
  105.   * @brief  calculate CRC with polling mode.
  106.   * @param  pbuff: pointer of data buffer.
  107.   * @param  length: data buffer length
  108.   * @retval none
  109.   */
  110. uint32_t poll_calculate(uint8_t *pbuff, uint32_t length)
  111. {
  112.   crc_data_reset();

  113.   /* word */
  114.   if(length > 3)
  115.   {
  116.     crc_reverse_input_data_set(CRC_REVERSE_INPUT_BY_WORD);
  117.     crc_block_calculate((uint32_t *)pbuff, length / 4);
  118.     pbuff = pbuff + ((length / 4) * 4);
  119.     length = length % 4;
  120.   }
  121.   /* halfword */
  122.   if(length > 2)
  123.   {
  124.     crc_reverse_input_data_set(CRC_REVERSE_INPUT_BY_HALFWORD);
  125.     crc16_block_calculate((uint16_t *)pbuff, 1);
  126.     pbuff = pbuff + 2;
  127.     length = length - 2;
  128.   }
  129.   /* byte */
  130.   if(length > 0)
  131.   {
  132.     crc_reverse_input_data_set(CRC_REVERSE_INPUT_BY_BYTE);
  133.     crc8_block_calculate((uint8_t *)pbuff, 1);
  134.     length = 0;
  135.   }

  136.   return crc_data_get();
  137. }

  138. /**
  139.   * @brief  main function.
  140.   * @param  none
  141.   * @retval none
  142.   */
  143. int main(void)
  144. {
  145.   uint32_t crc_result = 0;
  146.   system_clock_config();

  147.   at32_board_init();
  148.   uart_print_init(115200);
  149.   nvic_config();
  150.   crc_config();
  151.   dma_config();

  152.   /* calculate CRC-32 using dma and polling mode */
  153.   crc_poly_size_set(CRC_POLY_SIZE_32B);
  154.   crc_result = dma_calculate(data_buffer, sizeof(data_buffer));
  155.   printf("crc32 dma result: 0x%x\n", crc_result);
  156.   crc_result = poll_calculate(data_buffer, sizeof(data_buffer));
  157.   printf("crc32 poll result: 0x%x\n", crc_result);

  158.   /* calculate CRC-16 using dma and polling mode */
  159.   crc_poly_size_set(CRC_POLY_SIZE_16B);
  160.   crc_result = dma_calculate(data_buffer, sizeof(data_buffer));
  161.   printf("crc16 dma result: 0x%x\n", crc_result);
  162.   crc_result = poll_calculate(data_buffer, sizeof(data_buffer));
  163.   printf("crc16 poll result: 0x%x\n", crc_result);

  164.   /* calculate CRC-8 using dma and polling mode */
  165.   crc_poly_size_set(CRC_POLY_SIZE_8B);
  166.   crc_result = dma_calculate(data_buffer, sizeof(data_buffer));
  167.   printf("crc8 dma result: 0x%x\n", crc_result);
  168.   crc_result = poll_calculate(data_buffer, sizeof(data_buffer));
  169.   printf("crc8 poll result: 0x%x\n", crc_result);

  170.   while(1)
  171.   {
  172.   }
  173. }




SC0150_AT32_CRC_computing_by_using_DMA_V2.0.0.zip

3.81 MB, 下载次数: 9

SC0150_AT32_CRC_computing_by_using_DMA_ZH_V2.0.0.pdf

585.81 KB, 下载次数: 5

呐咯密密 发表于 2024-11-9 17:37 | 显示全部楼层
是用DMA进行内存到内存的数据搬运,用DMA来减少CPU搬运数据的时间,是这个意思吧
顽强de板子 发表于 2024-11-21 16:59 | 显示全部楼层
配置DMA控制器:首先,您需要配置AT32 MCU上的DMA控制器,设置源地址(数据输入源)、目标地址(CRC计算模块)、传输方向以及数据传输大小等参数。配置CRC模块:配置AT32 MCU上的CRC模块,选择合适的CRC算法和参数(如CRC多项式)。启动DMA传输:当一切配置妥当后,通过启动DMA传输来触发数据从源地址到目标地址(CRC模块)的自动传输。在数据传输过程中,CRC计算将同时进行。读取结果:一旦数据传输完成,可以从CRC模块中读取计算结果。使用DMA传输数据加速进行CRC计算可以显著减少CPU的参与,提高数据处理速度。但是,具体实现细节会根据AT32 MCU的具体型号、开发工具链和固件版本而有所不同。因此,建议查阅AT32 MCU的数据手册、开发指南或参考相关的开发文档,以获取更详细的配置和使用指南。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

215

主题

2065

帖子

37

粉丝
快速回复 在线客服 返回列表 返回顶部