[DemoCode下载] 新唐M0A21的PDMA使用起来很容易

[复制链接]
648|4
 楼主| mintspring 发表于 2023-9-24 20:37 | 显示全部楼层 |阅读模式
  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: 2 $
  5. * $Date: 20/06/01 1:35p $
  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) 2020 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. uint8_t au8SrcArray[256];
  19. uint8_t au8DestArray[256];
  20. uint32_t volatile g_u32IsTestOver = 0;

  21. /**
  22. * @brief       DMA IRQ
  23. *
  24. * @param       None
  25. *
  26. * [url=home.php?mod=space&uid=266161]@return[/url]      None
  27. *
  28. * [url=home.php?mod=space&uid=1543424]@Details[/url]     The DMA default IRQ, declared in startup_M0A21.s.
  29. */
  30. void PDMA_IRQHandler(void)
  31. {
  32.     uint32_t status = PDMA_GET_INT_STATUS(PDMA);

  33.     if (status & PDMA_INTSTS_ABTIF_Msk)   /* abort */
  34.     {
  35.         /* Check if channel 1 has abort error */
  36.         if (PDMA_GET_ABORT_STS(PDMA) & PDMA_ABTSTS_ABTIF1_Msk)
  37.             g_u32IsTestOver = 2;

  38.         /* Clear abort flag of channel 1 */
  39.         PDMA_CLR_ABORT_FLAG(PDMA, PDMA_ABTSTS_ABTIF1_Msk);
  40.     }
  41.     else if (status & PDMA_INTSTS_TDIF_Msk)     /* done */
  42.     {
  43.         /* Check transmission of channel 1 has been transfer done */
  44.         if (PDMA_GET_TD_STS(PDMA) & PDMA_TDSTS_TDIF1_Msk)
  45.             g_u32IsTestOver = 1;

  46.         /* Clear transfer done flag of channel 1 */
  47.         PDMA_CLR_TD_FLAG(PDMA, PDMA_TDSTS_TDIF1_Msk);
  48.     }
  49.     else
  50.         printf("unknown interrupt !!\n");
  51. }

  52. void SYS_Init(void)
  53. {
  54.     /*---------------------------------------------------------------------------------------------------------*/
  55.     /* Init System Clock                                                                                       */
  56.     /*---------------------------------------------------------------------------------------------------------*/

  57.     /* Enable HIRC clock (Internal RC 48MHz) */
  58.     CLK_EnableXtalRC(CLK_PWRCTL_HIRCEN_Msk);

  59.     /* Wait for HIRC clock ready */
  60.     CLK_WaitClockReady(CLK_STATUS_HIRCSTB_Msk);

  61.     /* Select HCLK clock source as HIRC and HCLK source divider as 1 */
  62.     CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HIRC, CLK_CLKDIV0_HCLK(1));

  63.     /* Enable UART0 clock */
  64.     CLK_EnableModuleClock(UART0_MODULE);

  65.     /* Switch UART0 clock source to HIRC */
  66.     CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART0SEL_HIRC, CLK_CLKDIV0_UART0(1));

  67.     /* Enable PDMA clock */
  68.     CLK_EnableModuleClock(PDMA_MODULE);

  69.     /* Update System Core Clock */
  70.     /* User can use SystemCoreClockUpdate() to calculate SystemCoreClock and cyclesPerUs automatically. */
  71.     SystemCoreClockUpdate();

  72.     /*---------------------------------------------------------------------------------------------------------*/
  73.     /* Init I/O Multi-function                                                                                 */
  74.     /*---------------------------------------------------------------------------------------------------------*/
  75.     /* Set PB multi-function pins for UART0 RXD=PB.6 and TXD=PB.4 */
  76.     SYS->GPB_MFP1 = (SYS->GPB_MFP1 & ~(SYS_GPB_MFP1_PB4MFP_Msk | SYS_GPB_MFP1_PB6MFP_Msk)) |
  77.                     (SYS_GPB_MFP1_PB4MFP_UART0_TXD | SYS_GPB_MFP1_PB6MFP_UART0_RXD);

  78. }

  79. int main()
  80. {
  81.     /* Unlock protected registers */
  82.     SYS_UnlockReg();

  83.     SYS_Init();

  84.     /* Lock protected registers */
  85.     SYS_LockReg();

  86.     /* Init UART0 to 115200-8n1 for print message */
  87.     UART_Open(UART0, 115200);

  88.     printf("+------------------------------------------------------+ \n");
  89.     printf("|    PDMA Memory to Memory Driver Sample Code          | \n");
  90.     printf("+------------------------------------------------------+ \n");


  91.     /*------------------------------------------------------------------------------------------------------

  92.                          au8SrcArray                         au8DestArray
  93.                          ---------------------------   -->   ---------------------------
  94.                        /| [0]  | [1]  |  [2] |  [3] |       | [0]  | [1]  |  [2] |  [3] |\
  95.                         |      |      |      |      |       |      |      |      |      |
  96.        PDMA_TEST_LENGTH |            ...            |       |            ...            | PDMA_TEST_LENGTH
  97.                         |      |      |      |      |       |      |      |      |      |
  98.                        \| [60] | [61] | [62] | [63] |       | [60] | [61] | [62] | [63] |/
  99.                          ---------------------------         ---------------------------
  100.                          \                         /         \                         /
  101.                                32bits(one word)                     32bits(one word)

  102.       PDMA transfer configuration:

  103.         Channel = 1
  104.         Operation mode = basic mode
  105.         Request source = PDMA_MEM(memory to memory)
  106.         transfer done and table empty interrupt = enable

  107.         Transfer count = PDMA_TEST_LENGTH
  108.         Transfer width = 32 bits(one word)
  109.         Source address = au8SrcArray
  110.         Source address increment size = 32 bits(one word)
  111.         Destination address = au8DestArray
  112.         Destination address increment size = 32 bits(one word)
  113.         Transfer type = burst transfer

  114.         Total transfer length = PDMA_TEST_LENGTH * 32 bits
  115.     ------------------------------------------------------------------------------------------------------*/

  116.     /* Open Channel 1 */
  117.     PDMA_Open(PDMA, 1 << PDMA_CH);
  118.     /* Transfer count is PDMA_TEST_LENGTH, transfer width is 32 bits(one word) */
  119.     PDMA_SetTransferCnt(PDMA, PDMA_CH, PDMA_WIDTH_32, PDMA_TEST_LENGTH);
  120.     /* Set source address is au8SrcArray, destination address is au8DestArray, Source/Destination increment size is 32 bits(one word) */
  121.     PDMA_SetTransferAddr(PDMA, PDMA_CH, (uint32_t)au8SrcArray, PDMA_SAR_INC, (uint32_t)au8DestArray, PDMA_DAR_INC);
  122.     /* Request source is memory to memory */
  123.     PDMA_SetTransferMode(PDMA, PDMA_CH, PDMA_MEM, FALSE, 0);
  124.     /* Transfer type is burst transfer and burst size is 4 */
  125.     PDMA_SetBurstType(PDMA, PDMA_CH, PDMA_REQ_BURST, PDMA_BURST_4);

  126.     /* Enable interrupt */
  127.     PDMA_EnableInt(PDMA, PDMA_CH, PDMA_INT_TRANS_DONE);

  128.     /* Enable NVIC for PDMA */
  129.     NVIC_EnableIRQ(PDMA_IRQn);
  130.     g_u32IsTestOver = 0;

  131.     /* Generate a software request to trigger transfer with PDMA channel 1  */
  132.     PDMA_Trigger(PDMA, PDMA_CH);

  133.     /* Waiting for transfer done */
  134.     while (g_u32IsTestOver == 0);

  135.     /* Check transfer result */
  136.     if (g_u32IsTestOver == 1)
  137.         printf("test done...\n");
  138.     else if (g_u32IsTestOver == 2)
  139.         printf("target abort...\n");

  140.     /* Close channel 1 */
  141.     PDMA_Close(PDMA);

  142.     while (1);
  143. }

  144. /*** (C) COPYRIGHT 2020 Nuvoton Technology Corp. ***/


 楼主| mintspring 发表于 2023-9-24 20:38 | 显示全部楼层
你知道吗,单片机有一个东东叫DMA,可以搬运数据,这样就可以腾出CPU做专业的事情了,对于简单的搬砖工作交给DMA即可。
 楼主| mintspring 发表于 2023-9-24 20:41 | 显示全部楼层
传输单个宽度该例子设置的是PDMA_WIDTH_32,其实还可以设置为16,8.
该例子中传输的变量是256个8BIT字节符,所以按32BIT传输单位那就是64个。
如果改成16BITPDMA宽度,那么就要128个宽度了。
 楼主| mintspring 发表于 2023-9-24 20:42 | 显示全部楼层
9864465102e9b9eb80.png
编译后可以定位参数的位置,查看其他可用的参数。
 楼主| mintspring 发表于 2023-9-24 20:44 | 显示全部楼层
对于下次传输的地址是否增加还是固定不变也有参数设置PDMA_SAR_INC
  1. /*---------------------------------------------------------------------------------------------------------*/
  2. /*  Address Attribute Constant Definitions                                                                 */
  3. /*---------------------------------------------------------------------------------------------------------*/
  4. #define PDMA_SAR_INC        0x00000000UL            /*!<DMA SAR increment  \hideinitializer */
  5. #define PDMA_SAR_FIX        0x00000300UL            /*!<DMA SAR fix address  \hideinitializer */
  6. #define PDMA_DAR_INC        0x00000000UL            /*!<DMA DAR increment  \hideinitializer */
  7. #define PDMA_DAR_FIX        0x00000C00UL            /*!<DMA DAR fix address  \hideinitializer */
您需要登录后才可以回帖 登录 | 注册

本版积分规则

303

主题

4972

帖子

24

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