/**************************************************************************//** 
 * @file     main.c 
 * 
 * @brief    Demonstrate UART transmit and receive function with PDMA 
 * 
 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved. 
 * 
 ******************************************************************************/ 
#include <stdio.h> 
#include "NuMicro.h" 
 
#define PDMA                   ((PDMA_T *)  PDMA2_BASE) 
 
#define ENABLE_PDMA_INTERRUPT 1 
#define PDMA_TEST_LENGTH 100 
#define PDMA_TIME 0x5555 
 
/*---------------------------------------------------------------------------------------------------------*/ 
/* Global variables                                                                                        */ 
/*---------------------------------------------------------------------------------------------------------*/ 
static uint8_t g_u8Tx_Buffer[PDMA_TEST_LENGTH]; 
static uint8_t g_u8Rx_Buffer[PDMA_TEST_LENGTH]; 
 
volatile uint32_t u32IsTestOver = 0; 
 
/*---------------------------------------------------------------------------------------------------------*/ 
/* Define functions prototype                                                                              */ 
/*---------------------------------------------------------------------------------------------------------*/ 
void PDMA_IRQHandler(void); 
void UART_PDMATest(void); 
 
 
void SYS_Init(void) 
{ 
    /* Unlock protected registers */ 
    SYS_UnlockReg(); 
 
    /* Enable HXT */ 
    CLK->PWRCTL |= CLK_PWRCTL_HXTEN_Msk; 
 
    /* Waiting clock ready */ 
    CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk); 
 
    /* Enable IP clock */ 
    CLK_SetModuleClock(UART16_MODULE, CLK_CLKSEL3_UART16SEL_HXT, CLK_CLKDIV3_UART16(1)); 
    CLK_EnableModuleClock(UART16_MODULE); 
    CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL2_UART1SEL_HXT, CLK_CLKDIV1_UART1(1)); 
    CLK_EnableModuleClock(UART1_MODULE); 
    CLK_EnableModuleClock(PDMA2_MODULE); 
 
    /*---------------------------------------------------------------------------------------------------------*/ 
    /* Init I/O Multi-function                                                                                 */ 
    /*---------------------------------------------------------------------------------------------------------*/ 
    /* Set multi-function pins for Debug UART RXD and TXD */ 
    SYS->GPK_MFPL &= ~(SYS_GPK_MFPL_PK2MFP_Msk | SYS_GPK_MFPL_PK3MFP_Msk); 
    SYS->GPK_MFPL |= SYS_GPK_MFPL_PK2MFP_UART16_RXD | SYS_GPK_MFPL_PK3MFP_UART16_TXD; 
    /* Set multi-function pins for UART1 */ 
    SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA0MFP_Msk | SYS_GPA_MFPL_PA1MFP_Msk | SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk); 
    SYS->GPA_MFPL |= SYS_GPA_MFPL_PA0MFP_UART1_nCTS | SYS_GPA_MFPL_PA1MFP_UART1_nRTS | 
                     SYS_GPA_MFPL_PA2MFP_UART1_RXD | SYS_GPA_MFPL_PA3MFP_UART1_TXD; 
 
    /* Lock protected registers */ 
    SYS_LockReg(); 
} 
 
void UART_Init() 
{ 
    UART_Open(UART16, 115200); 
} 
 
void UART1_Init() 
{ 
    UART_Open(UART1, 115200); 
} 
 
void PDMA_Init(void) 
{ 
    /* Open PDMA Channel */ 
    PDMA_Open(PDMA,1 << 0); // Channel 0 for UART1 TX 
    PDMA_Open(PDMA,1 << 1); // Channel 1 for UART1 RX 
    // Select basic mode 
    PDMA_SetTransferMode(PDMA,0, PDMA_UART1_TX, 0, 0); 
    PDMA_SetTransferMode(PDMA,1, PDMA_UART1_RX, 0, 0); 
    // Set data width and transfer count 
    PDMA_SetTransferCnt(PDMA,0, PDMA_WIDTH_8, PDMA_TEST_LENGTH); 
    PDMA_SetTransferCnt(PDMA,1, PDMA_WIDTH_8, PDMA_TEST_LENGTH); 
    //Set PDMA Transfer Address 
    PDMA_SetTransferAddr(PDMA,0, ((uint32_t) (&g_u8Tx_Buffer[0])), PDMA_SAR_INC, UART1_BASE, PDMA_DAR_FIX); 
    PDMA_SetTransferAddr(PDMA,1, UART1_BASE, PDMA_SAR_FIX, ((uint32_t) (&g_u8Rx_Buffer[0])), PDMA_DAR_INC); 
    //Select Single Request 
    PDMA_SetBurstType(PDMA,0, PDMA_REQ_SINGLE, 0); 
    PDMA_SetBurstType(PDMA,1, PDMA_REQ_SINGLE, 0); 
    //Set timeout 
    //PDMA_SetTimeOut(0, 0, 0x5555); 
    //PDMA_SetTimeOut(1, 0, 0x5555); 
 
#ifdef ENABLE_PDMA_INTERRUPT 
    PDMA_EnableInt(PDMA,0, 0); 
    PDMA_EnableInt(PDMA,1, 0); 
    NVIC_EnableIRQ(PDMA2_IRQn); 
    u32IsTestOver = 0; 
#endif 
} 
 
int main(void) 
{ 
    /* Init System, IP clock and multi-function I/O */ 
    SYS_Init(); 
    /* Init UART0 for printf */ 
    UART_Init(); 
 
    /* Init UART1 */ 
    UART1_Init(); 
 
 
    printf("\n\nCPU @ %dHz\n", SystemCoreClock); 
 
    UART_PDMATest(); 
 
    while(1); 
} 
 
/** 
 * @brief       DMA IRQ 
 * 
 * @param       None 
 * 
 * @return      None 
 * 
 * @details     The DMA default IRQ. 
 */ 
void PDMA1_IRQHandler(void)//这里应该是pdm2,官方测试代码没有改过来,所以这部分功能官方肯定没测试 
{ 
    uint32_t status = PDMA_GET_INT_STATUS(PDMA); 
 
    if (status & 0x1)   /* abort */ 
    { 
        printf("target abort interrupt !!\n"); 
        if (PDMA_GET_ABORT_STS(PDMA) & 0x4) 
            u32IsTestOver = 2; 
        PDMA_CLR_ABORT_FLAG(PDMA,PDMA_GET_ABORT_STS(PDMA)); 
    } 
    else if (status & 0x2)     /* done */ 
    { 
        if ( (PDMA_GET_TD_STS(PDMA) & (1 << 0)) && (PDMA_GET_TD_STS(PDMA) & (1 << 1)) ) 
        { 
            u32IsTestOver = 1; 
            PDMA_CLR_TD_FLAG(PDMA,PDMA_GET_TD_STS(PDMA)); 
        } 
    } 
    else if (status & 0x300)     /* channel 2 timeout */ 
    { 
        printf("timeout interrupt !!\n"); 
        u32IsTestOver = 3; 
 
        PDMA_SetTimeOut(PDMA,0, 0, 0); 
        PDMA_CLR_TMOUT_FLAG(PDMA,0); 
        PDMA_SetTimeOut(PDMA,0, 1, PDMA_TIME); 
 
        PDMA_SetTimeOut(PDMA,1, 0, 0); 
        PDMA_CLR_TMOUT_FLAG(PDMA,1); 
        PDMA_SetTimeOut(PDMA,1, 1, PDMA_TIME); 
    } 
    else 
        printf("unknown interrupt !!\n"); 
} 
 
 
/*---------------------------------------------------------------------------------------------------------*/ 
/*  UART PDMA Test                                                                                     */ 
/*---------------------------------------------------------------------------------------------------------*/ 
void UART_PDMATest() 
{ 
    uint32_t i; 
 
    printf("+-----------------------------------------------------------+\n"); 
    printf("|  UART PDMA Test                                           |\n"); 
    printf("+-----------------------------------------------------------+\n"); 
    printf("|  Description :                                            |\n"); 
    printf("|    The sample code will demo UART1 PDMA function.         |\n"); 
    printf("|    Please connect UART1_TX and UART1_RX pin.              |\n"); 
    printf("+-----------------------------------------------------------+\n"); 
    printf("Please press any key to start test. \n\n"); 
 
    getchar(); 
 
    /* 
        Using UAR1 external loop back. 
        This code will send data from UART1_TX and receive data from UART1_RX. 
    */ 
 
    for (i=0; i<PDMA_TEST_LENGTH; i++) 
    { 
        g_u8Tx_Buffer[i] = i; 
        g_u8Rx_Buffer[i] = 0xff; 
    } 
 
    while(1) 
    { 
        PDMA_Init(); 
 
        UART1->INTEN = UART_INTEN_RLSIEN_Msk; // Enable Receive Line interrupt 
        NVIC_EnableIRQ(UART1_IRQn); 
 
        UART1->INTEN |= UART_INTEN_TXPDMAEN_Msk | UART_INTEN_RXPDMAEN_Msk; 
 
#ifdef ENABLE_PDMA_INTERRUPT 
        while(u32IsTestOver == 0); 
 
        if (u32IsTestOver == 1) 
            printf("test done...\n"); 
        else if (u32IsTestOver == 2) 
            printf("target abort...\n"); 
        else if (u32IsTestOver == 3) 
            printf("timeout...\n"); 
#else 
        while( (!(PDMA_GET_TD_STS() & (1 << 0))) || (!(PDMA_GET_TD_STS() & (1 << 1))) ); 
 
        PDMA_CLR_TD_FLAG(PDMA_TDSTS_TDIF0_Msk|PDMA_TDSTS_TDIF1_Msk); 
#endif 
 
        UART1->INTEN &= ~UART_INTEN_TXPDMAEN_Msk; 
        UART1->INTEN &= ~UART_INTEN_RXPDMAEN_Msk; 
 
        for (i=0; i<PDMA_TEST_LENGTH; i++) 
        { 
            if(g_u8Rx_Buffer[i] != i) 
            { 
                printf("\n Receive Data Compare Error !!"); 
                while(1); 
            } 
 
            g_u8Rx_Buffer[i] = 0xff; 
        } 
 
        printf("\nUART PDMA test Pass.\n"); 
    } 
 
} 
 
void UART1_IRQHandler(void) 
{ 
    uint32_t u32DAT; 
    uint32_t u32IntSts = UART1->INTSTS; 
 
    if(u32IntSts & UART_INTSTS_PRLSIF_Msk) 
    { 
        if(UART1->FIFOSTS & UART_FIFOSTS_BIF_Msk) 
            printf("\n BIF \n"); 
        if(UART1->FIFOSTS & UART_FIFOSTS_FEF_Msk) 
            printf("\n FEF \n"); 
        if(UART1->FIFOSTS & UART_FIFOSTS_PEF_Msk) 
            printf("\n PEF \n"); 
 
        u32DAT = UART1->DAT; // read out data 
        printf("\n Error Data is '0x%x' \n", u32DAT); 
        UART1->FIFOSTS = (UART_FIFOSTS_BIF_Msk | UART_FIFOSTS_FEF_Msk | UART_FIFOSTS_PEF_Msk); 
    } 
} 
 
 
 
 
 |