• AVR Freaks

Hot!USART Transmission using DMA

Author
Mohammed_Hassan
Starting Member
  • Total Posts : 31
  • Reward points : 0
  • Joined: 2019/03/13 06:05:20
  • Location: 0
  • Status: offline
2019/07/16 07:55:05 (permalink)
0

USART Transmission using DMA

Hello, 
I want to use the USART to transmit a specific array of data using the DMA, I am using PIC32Mz0512eff064 contrller.
I used Harmony V2.06 and generated the static driver for USART and DMA and here are my code inside the generic APIs for Application: 
void SYS_Initialize ( void* data )
{
    /* Core Processor Initialization */
    SYS_CLK_Initialize( NULL );
    SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)NULL);
    SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet());

    /* Initialize Drivers */
    sysObj.sysDma = SYS_DMA_Initialize((SYS_MODULE_INIT *)&sysDmaInit);
    SYS_INT_VectorPrioritySet(INT_VECTOR_DMA0, INT_PRIORITY_LEVEL1);
    SYS_INT_VectorSubprioritySet(INT_VECTOR_DMA0, INT_SUBPRIORITY_LEVEL3);


    SYS_INT_SourceEnable(INT_SOURCE_DMA_0);



    sysObj.drvUsart0 = DRV_USART_Initialize(DRV_USART_INDEX_0, (SYS_MODULE_INIT *)NULL);
    SYS_INT_VectorPrioritySet(INT_VECTOR_UART2_TX, INT_PRIORITY_LEVEL5);
    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART2_TX, INT_SUBPRIORITY_LEVEL1);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART2_FAULT, INT_PRIORITY_LEVEL1);
    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART2_FAULT, INT_SUBPRIORITY_LEVEL0);

    /* Initialize System Services */
    SYS_PORTS_Initialize();

    /*** Interrupt Service Initialization Code ***/
    SYS_INT_Initialize();

    /* Initialize Middleware */

    /* Enable Global Interrupts */
    SYS_INT_Enable();

    /* Initialize the Application */
    APP_Initialize();
}


 
void APP_Initialize ( void )
{
    /* Configure the DMA to use it for transmission */
    DMAhandle_Ch0_Tx= SYS_DMA_ChannelAllocate(DMA_CHANNEL_0);
    
    SYS_DMA_ChannelSetup(
                       DMAhandle_Ch0_Tx,
                       SYS_DMA_CHANNEL_OP_MODE_BASIC,
                       DMA_TRIGGER_USART_2_TRANSMIT
            );
    
    
    SYS_DMA_ChannelTransferEventHandlerSet(DMAhandle_Ch0_Tx, APP_DMASYSTransferEventHandler,
                                                            (uintptr_t)&myAppObj);
    
    
    SYS_DMA_ChannelEnable(DMAhandle_Ch0_Tx);
    
    
    
    /* Place the App state machine in its initial state. */
    appData.state = APP_STATE_INIT;
    
    appData.handleUSART0 = DRV_HANDLE_INVALID;
    
    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
}

 
and this is the task: 
static void USART_Task (void)
{
    volatile bool test = true;
    switch (usartBMState)
    {
        default:
        case USART_BM_INIT:
        {
            appData.tx_count = 0;
            appData.rx_count = 0;
            appData.handleUSART0 = DRV_USART_Open(0, DRV_IO_INTENT_READWRITE|DRV_IO_INTENT_NONBLOCKING);
            usartBMState = USART_BM_SEND_MSG;
            for (i = 0 ; i < 1000 ; i++)
                Nop();
        }break;

        case USART_BM_SEND_MSG:
        {
            SYS_DMA_ChannelTransferAdd(
                        DMAhandle_Ch0_Tx,
                        app_tx_buf, 2,
                        (uint8_t*) &U2TXREG, 1,
                        1
            );
            
    PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE);
    PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL);


    PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL);
    PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE);
    
            SYS_DMA_ChannelEnable(DMAhandle_Ch0_Tx);
        }break;

        case USART_BM_ECHO:
        {
                DRV_USART_Close(appData.handleUSART0);
                usartBMState = USART_BM_INIT;
        }break;

    }
}

 
and this is the event handler:
void APP_DMASYSTransferEventHandler(SYS_DMA_TRANSFER_EVENT event,
            SYS_DMA_CHANNEL_HANDLE handle, uintptr_t contextHandle)
    {
        switch(event)
        {
            case SYS_DMA_TRANSFER_EVENT_COMPLETE:
                    usartBMState = USART_BM_ECHO;
                // This means the data was transferred.
                break;

            case SYS_DMA_TRANSFER_EVENT_ERROR:

                // Error handling here.
                break;

            default:
                break;
        }
    }

 
But This handler I cannot get it called and I cannot receive any data on the Terminal via UART communication.. 
I am quite new to microship and harmony.. So anyone can help me? 
 
Thanks in advance,
 
 
#1

3 Replies Related Threads

    Mohammed_Hassan
    Starting Member
    • Total Posts : 31
    • Reward points : 0
    • Joined: 2019/03/13 06:05:20
    • Location: 0
    • Status: offline
    Re: USART Transmission using DMA 2019/07/16 08:31:59 (permalink)
    0
    now the handler came! 
    I enabled the DMA interrupt events by myself inside DMA_Init function .. but no data received in UART?! 
    I used these APIs after configuring the DMA: 
     
    PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE);
    PLIB_DMA_ChannelXINTSourceFlagClear(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL);

    PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_HALF_FULL);
    PLIB_DMA_ChannelXINTSourceEnable(DMA_ID_0, DMA_CHANNEL_0, DMA_INT_DESTINATION_DONE);
     
     
    #2
    Mohammed_Hassan
    Starting Member
    • Total Posts : 31
    • Reward points : 0
    • Joined: 2019/03/13 06:05:20
    • Location: 0
    • Status: offline
    Re: USART Transmission using DMA 2019/07/17 01:55:14 (permalink)
    0
    Some more updates: 
    Now I can transmit via DMA, but for the reception I failed to make the event hander fire based on DMA interrupt.
    Here you can find attached my project.
    I configured DMA Ch0 for USART2Tx and Ch1 for USART2Rx.
    There are two event handlers:
    • APP_DMASYSTransferEventHandler à This should be called when transmission is done
    • APP_DMASYSReceiveEventHandlerà This should be called when Reception is done
     
    The trigger for DMA channel0 is the USARTTX interrupt and for channel1 the Rx interrupt.
    The transfer event handler called correctly but the Receive handler couldn’t be fired.
     
    I use this function to add a transfer for both cases transmission and reception:
     
                  SYS_DMA_ChannelTransferAdd( DMAhandle_Ch0_Tx,  KVA_TO_PA((void*)app_tx_buf),10,  KVA_TO_PA((uint8_t*) &U2TXREG), 1, (size_t)1 );
     
    SYS_DMA_ChannelTransferAdd( DMAhandle_Ch1_Rx,  KVA_TO_PA((uint8_t*) &U2RXREG),1,  KVA_TO_PA((void*)app_rx_buf), 1, (size_t)1 );
     
    Always when I am sending a byte from PC via UART, the program halted!
    your help will be very appreciated.
    #3
    Mohammed_Hassan
    Starting Member
    • Total Posts : 31
    • Reward points : 0
    • Joined: 2019/03/13 06:05:20
    • Location: 0
    • Status: offline
    Re: USART Transmission using DMA 2019/10/15 04:38:57 (permalink)
    0
    Any Help! 
    #4
    Jump to:
    © 2019 APG vNext Commercial Version 4.5