[DemoCode下载] PDMA功能进行内存到内存的数据传输

[复制链接]
840|2
 楼主| xuanhuanzi 发表于 2024-2-19 22:56 | 显示全部楼层 |阅读模式
  1. /******************************************************************************
  2. * [url=home.php?mod=space&uid=288409]@file[/url]     main.c
  3. * [url=home.php?mod=space&uid=895143]@version[/url]  V1.00
  4. * $Revision: 4 $
  5. * $Date: 18/07/13 4:20p $
  6. * [url=home.php?mod=space&uid=247401]@brief[/url]    Use PDMA channel 1 to transfer data from memory to memory.
  7. * @note
  8. * SPDX-License-Identifier: Apache-2.0
  9. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  10. *****************************************************************************/
  11. #include <stdio.h>
  12. #include "NuMicro.h"

  13. #define PDMA_CH    1

  14. /*---------------------------------------------------------------------------------------------------------*/
  15. /* Global variables                                                                                        */
  16. /*---------------------------------------------------------------------------------------------------------*/
  17. uint32_t PDMA_TEST_LENGTH = 64;
  18. #ifdef __ICCARM__
  19. #pragma data_alignment=4
  20. uint8_t au8SrcArray[256];
  21. uint8_t au8DestArray[256];
  22. #else
  23. __attribute__((aligned(4))) uint8_t au8SrcArray[256];
  24. __attribute__((aligned(4))) uint8_t au8DestArray[256];
  25. #endif
  26. uint32_t volatile g_u32IsTestOver = 0;

  27. /**
  28. * @brief       DMA IRQ
  29. *
  30. * @param       None
  31. *
  32. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  33. *
  34. * [url=home.php?mod=space&uid=1543424]@Details[/url]     The DMA default IRQ, declared in startup_M031Series.s.
  35. */
  36. void PDMA_IRQHandler(void)
  37. {
  38.     uint32_t status = PDMA_GET_INT_STATUS(PDMA);

  39.     if (status & PDMA_INTSTS_ABTIF_Msk)   /* abort */
  40.     {
  41.         /* Check if channel 1 has abort error */
  42.         if (PDMA_GET_ABORT_STS(PDMA) & PDMA_ABTSTS_ABTIF1_Msk)
  43.             g_u32IsTestOver = 2;

  44.         /* Clear abort flag of channel 1 */
  45.         PDMA_CLR_ABORT_FLAG(PDMA, PDMA_ABTSTS_ABTIF1_Msk);
  46.     }
  47.     else if (status & PDMA_INTSTS_TDIF_Msk)     /* done */
  48.     {
  49.         /* Check transmission of channel 1 has been transfer done */
  50.         if (PDMA_GET_TD_STS(PDMA) & PDMA_TDSTS_TDIF1_Msk)
  51.             g_u32IsTestOver = 1;

  52.         /* Clear transfer done flag of channel 1 */
  53.         PDMA_CLR_TD_FLAG(PDMA, PDMA_TDSTS_TDIF1_Msk);
  54.     }
  55.     else
  56.         printf("unknown interrupt !!\n");
  57. }

  58. void SYS_Init(void)
  59. {
  60.     /*---------------------------------------------------------------------------------------------------------*/
  61.     /* Init System Clock                                                                                       */
  62.     /*---------------------------------------------------------------------------------------------------------*/

  63.     /* Unlock protected registers */
  64.     SYS_UnlockReg();

  65.     /* Enable HIRC clock (Internal RC 48MHz) */
  66.     CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;

  67.     /* Wait for HIRC clock ready */
  68.     while((CLK->STATUS & CLK_STATUS_HIRCSTB_Msk) != CLK_STATUS_HIRCSTB_Msk);

  69.     /* Select HCLK clock source as HIRC and HCLK source divider as 1 */
  70.     CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
  71.     CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | CLK_CLKDIV0_HCLK(1);

  72.     /* Enable UART0 clock */
  73.     CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk;

  74.     /* PDMA Clock Enable */
  75.     CLK->AHBCLK |= CLK_AHBCLK_PDMACKEN_Msk;

  76.     /* Switch UART0 clock source to HIRC and UART0 clock divider as 1 */
  77.     CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_UART0SEL_Msk)) | CLK_CLKSEL1_UART0SEL_HIRC;
  78.     CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_UART0DIV_Msk)) | CLK_CLKDIV0_UART0(1);

  79.     /* Update System Core Clock */
  80.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and cyclesPerUs automatically. */
  81.     SystemCoreClockUpdate();

  82.     /*---------------------------------------------------------------------------------------------------------*/
  83.     /* Init I/O Multi-function                                                                                 */
  84.     /*---------------------------------------------------------------------------------------------------------*/
  85.     /* Set PB multi-function pins for UART0 RXD=PB.12 and TXD=PB.13 */
  86.     SYS->GPB_MFPH = (SYS->GPB_MFPH & ~(SYS_GPB_MFPH_PB12MFP_Msk | SYS_GPB_MFPH_PB13MFP_Msk)) |
  87.                     (SYS_GPB_MFPH_PB12MFP_UART0_RXD | SYS_GPB_MFPH_PB13MFP_UART0_TXD);

  88.     /* Lock protected registers */
  89.     SYS_LockReg();
  90. }

  91. void UART0_Init(void)
  92. {
  93.     /*---------------------------------------------------------------------------------------------------------*/
  94.     /* Init UART                                                                                               */
  95.     /*---------------------------------------------------------------------------------------------------------*/
  96.     /* Reset UART IP */
  97.     SYS->IPRST1 |=  SYS_IPRST1_UART0RST_Msk;
  98.     SYS->IPRST1 &= ~SYS_IPRST1_UART0RST_Msk;

  99.     /* Configure UART0 and set UART0 Baudrate */
  100.     UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HIRC, 115200);
  101.     UART0->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
  102. }

  103. int main()
  104. {
  105.     SYS_Init();

  106.     /* Init UART0 to 115200-8n1 for print message */
  107.     UART0_Init();

  108.     printf("\n\nCPU [url=home.php?mod=space&uid=72445]@[/url] %dHz\n", SystemCoreClock);
  109.     printf("+------------------------------------------------------+ \n");
  110.     printf("|    PDMA Memory to Memory Driver Sample Code          | \n");
  111.     printf("+------------------------------------------------------+ \n");

  112.     /*------------------------------------------------------------------------------------------------------

  113.                          au8SrcArray                         au8DestArray
  114.                          ---------------------------   -->   ---------------------------
  115.                        /| [0]  | [1]  |  [2] |  [3] |       | [0]  | [1]  |  [2] |  [3] |\
  116.                         |      |      |      |      |       |      |      |      |      |
  117.        PDMA_TEST_LENGTH |            ...            |       |            ...            | PDMA_TEST_LENGTH
  118.                         |      |      |      |      |       |      |      |      |      |
  119.                        \| [60] | [61] | [62] | [63] |       | [60] | [61] | [62] | [63] |/
  120.                          ---------------------------         ---------------------------
  121.                          \                         /         \                         /
  122.                                32bits(one word)                     32bits(one word)

  123.       PDMA transfer configuration:

  124.         Channel = 1
  125.         Operation mode = basic mode
  126.         Request source = PDMA_MEM(memory to memory)
  127.         transfer done and table empty interrupt = enable

  128.         Transfer count = PDMA_TEST_LENGTH
  129.         Transfer width = 32 bits(one word)
  130.         Source address = au8SrcArray
  131.         Source address increment size = 32 bits(one word)
  132.         Destination address = au8DestArray
  133.         Destination address increment size = 32 bits(one word)
  134.         Transfer type = burst transfer

  135.         Total transfer length = PDMA_TEST_LENGTH * 32 bits
  136.     ------------------------------------------------------------------------------------------------------*/

  137.     /* Open Channel 1 */
  138.     PDMA->CHCTL |= (1 << PDMA_CH);

  139.     /* Transfer configuration of Channel 1 */
  140.     PDMA->DSCT[PDMA_CH].CTL = ((PDMA_TEST_LENGTH - 1) << PDMA_DSCT_CTL_TXCNT_Pos) | /* Transfer count is PDMA_TEST_LENGTH */ \
  141.                               PDMA_WIDTH_32 |  /* Transfer width is 32 bits(one word) */ \
  142.                               PDMA_SAR_INC |   /* Source increment size is 32 bits(one word) */ \
  143.                               PDMA_DAR_INC |   /* Destination increment size is 32 bits(one word) */ \
  144.                               PDMA_REQ_BURST | /* Transfer type is burst transfer type */ \
  145.                               PDMA_BURST_4 |   /* Burst size is 4. No effect in single transfer type */ \
  146.                               PDMA_OP_BASIC;   /* Operation mode is basic mode */

  147.     /* Configure source address */
  148.     PDMA->DSCT[PDMA_CH].SA = (uint32_t)au8SrcArray;

  149.     /* Configure destination address */
  150.     PDMA->DSCT[PDMA_CH].DA = (uint32_t)au8DestArray;

  151.     /* Configure PDMA channel 1 as memory to memory transfer */
  152.     PDMA->REQSEL0_3 = (PDMA->REQSEL0_3 & ~PDMA_REQSEL0_3_REQSRC1_Msk) | (PDMA_MEM << PDMA_REQSEL0_3_REQSRC1_Pos);

  153.     /* Enable interrupt */
  154.     PDMA->INTEN |= (1 << PDMA_CH);

  155.     /* Enable NVIC for PDMA */
  156.     NVIC_EnableIRQ(PDMA_IRQn);

  157.     g_u32IsTestOver = 0;

  158.     /* Generate a software request to trigger transfer with PDMA channel 1  */
  159.     PDMA->SWREQ = (1 << PDMA_CH);

  160.     /* Waiting for transfer done */
  161.     while (g_u32IsTestOver == 0);

  162.     /* Check transfer result */
  163.     if (g_u32IsTestOver == 1)
  164.         printf("test done...\n");
  165.     else if (g_u32IsTestOver == 2)
  166.         printf("target abort...\n");

  167.     /* Close channel 1 */
  168.     PDMA->CHCTL = 0;

  169.     while (1);

  170. }

  171. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/


 楼主| xuanhuanzi 发表于 2024-2-19 22:56 | 显示全部楼层
初始化设置:
启用 HIRC(High Internal RC,内部高速振荡器)作为系统时钟源,并等待 HIRC 就绪。
将 UART0 时钟源设置为 HIRC,并配置波特率为 115200。
启用 UART0 和 PDMA 的时钟。
配置 PB12 和 PB13 为 UART0 的 RXD 和 TXD。
PDMA 中断处理函数:
定义了一个 PDMA_IRQHandler() 函数,用于处理 PDMA 中断。当数据传输完成或发生异常时,会触发中断,根据中断状态来更新相应的标志位。
主函数:
初始化系统和 UART0。
配置 PDMA 通道 1 的传输设置:
设置传输计数为 PDMA_TEST_LENGTH(64)。
设置传输宽度为 32 位(一个字)。
源地址和目的地址的增量大小均为 32 位。
传输类型为 burst transfer。
将源地址和目的地址配置为对应的数组 au8SrcArray 和 au8DestArray。
将 PDMA 请求源设置为内存到内存传输。
启用 PDMA 通道 1 的中断。
通过软件触发 PDMA 通道 1 的传输。
等待传输完成,并根据 g_u32IsTestOver 的值来判断传输是否成功或是否发生异常。
最后关闭 PDMA 通道 1,程序进入无限循环。
 楼主| xuanhuanzi 发表于 2024-2-19 22:57 | 显示全部楼层
在这段代码中,PDMA 负责将 au8SrcArray 中的数据传输到 au8DestArray 中,传输过程中可以处理中断事件,以便及时处理传输完成或异常情况。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

183

主题

2331

帖子

3

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