Search

Technical Discussion Group Forum

This forum is provided for user discussion. While Beacon EmbeddedWorks support staff and engineers participate, Beacon EmbeddedWorks does not guarantee the accuracy of all information within in the Technical Discussion Group (TDG).

The "Articles" forums provide brief Articles written by Beacon EmbeddedWorks engineers that address the most frequently asked technical questions.

To receive email notifications when updates are posted for a Beacon EmbeddedWorks product download, please subscribe to the TDG Forum of interest.

TDG Forum

PrevPrev Go to previous topic
NextNext Go to next topic
Last Post 29 Jan 2015 02:19 PM by  Adam Ford
EDMA on UART1 of OMAP L138
 1 Replies
Sort:
You are not authorized to post a reply.
Author Messages
Jeroen van de Sande
New Member
New Member
Posts:1


--
28 Jan 2015 02:27 AM

    Hi Guys,

     

    I'm struggling in getting the EDMA to work on UART1 on the OMAPL138. I have an example (from Starterware) running using UART2 and this is going fine. Now I'd like to change this example to use UART1. I have modified the code to use UART1 but transmitting data does not succeed (no interrupt is thrown when finished). I am not sure whether I configured everything properly. Note that UART1 is working well when just using the ISR without EDMA. My code is given below.

    So basic questions:

    - Is it possible at all to use EDMA for UART1?

    - What am I doing wrong?

     

    Thanks in advance!

     

    Best regards,

    Jeroen

     

    /**

     * \file uartEcho.c
     *
     * \brief This is a sample application file which invokes some APIs
     * from the EDMA3 device abstraction layer as well as UART 
     * device abstraction layer to perform configuration, and 
     * transfer of data between UART and CPU RAM by the 
     * use of EDMA3
     */
    
    
    /*
    * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ 
    *
    * Redistribution and use in source and binary forms, with or without 
    * modification, are permitted provided that the following conditions 
    * are met:
    *
    * Redistributions of source code must retain the above copyright 
    * notice, this list of conditions and the following disclaimer.
    *
    * Redistributions in binary form must reproduce the above copyright
    * notice, this list of conditions and the following disclaimer in the 
    * documentation and/or other materials provided with the 
    * distribution.
    *
    * Neither the name of Texas Instruments Incorporated nor the names of
    * its contributors may be used to endorse or promote products derived
    * from this software without specific prior written permission.
    *
    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    */
    
    
    #include "psc.h"
    #include "uart.h"
    #include "edma.h"
    #include "string.h"
    #include "hw_types.h"
    #include "uartStdio.h"
    #include "evmOMAPL138.h"
    #include "interrupt.h"
    #include "edma_event.h"
    #include "soc_OMAPL138.h"
    #include "hw_psc_OMAPL138.h"
    
    
    /****************************************************************************/
    /* INTERNAL MACRO DEFINITIONS */
    /****************************************************************************/
    #define UART_RBR_THR_REG ((0x01D0D000u) + (0u))
    
    
    #define MAX_ACNT 1
    #define MAX_CCNT 1
    
    
    #define RX_BUFFER_SIZE 50
    
    
    /* EDMA3 Event queue number. */
    #define EVT_QUEUE_NUM 0
    
    
    
    
    #define BAUD_RATE 115200
    
    
    
    
    /****************************************************************************/
    /* LOCAL FUNCTION PROTOTYPES */
    /****************************************************************************/
    static void UartTransmitData(unsigned int tccNum, unsigned int chNum,
     volatile char *buffer, unsigned int buffLength);
    
    
    /* Callback Function Declaration*/
    static void (*cb_Fxn[EDMA3_NUM_TCC]) (unsigned int tcc, unsigned int status);
    static void UartReceiveData(unsigned int tccNum, unsigned int chNum, 
     volatile char *buffer);
    static void callback(unsigned int tccNum, unsigned int status);
    static void ConfigureIntEDMA3(void);
    static void Edma3ComplHandlerIsr(void);
    static void Edma3CCErrHandlerIsr(void);
    static void EDMA3Initialize(void);
    static void SetupInt(void);
    
    
    /****************************************************************************/
    /* GLOBAL VARIABLES */
    /****************************************************************************/
    volatile unsigned int flag = 0;
    
    
    /****************************************************************************/
    /* LOCAL FUNCTION DEFINITIONS */
    /****************************************************************************/
    
    
    /*
    ** Main function.
    */
    
    
    
    
    static void initUART1(unsigned int baudRate, unsigned int rxTrigLevel)
    {
    
    
     /* Enabling the PSC for UARTs.*/
     PSCModuleControl(SOC_PSC_1_REGS, HW_PSC_UART1, PSC_POWERDOMAIN_ALWAYS_ON,
     PSC_MDCTL_NEXT_ENABLE);
    
    
     /* Setup PINMUX */ 
     UARTPinMuxSetup(1, FALSE);
    
    
    
    
     /* Enabling the transmitter and receiver*/ 
     UARTEnable(SOC_UART_1_REGS);
    
    
    
    
     /* Configuring the UART parameters*/ 
     UARTConfigSetExpClk(SOC_UART_1_REGS, SOC_UART_1_MODULE_FREQ,
     BAUD_RATE, UART_WORDL_8BITS,
     UART_OVER_SAMP_RATE_16);
    
    
    
    
     /* Enabling the FIFO and flushing the Tx and Rx FIFOs.*/ 
     UARTFIFOEnable(SOC_UART_1_REGS);
    
    
    
    
     /* Setting the UART Receiver Trigger Level*/ 
     UARTFIFOLevelSet(SOC_UART_1_REGS, rxTrigLevel);
    
    
    
    
    }
    
    
    
    
    
    
    int main(void)
    {
     volatile char enter[] = {170, 7, 0, 42, 1, 50, 239};
     volatile char buffer[RX_BUFFER_SIZE];
     unsigned int buffLength = 0;
    
    
     /* Initialize EDMA3 Controller */
     EDMA3Initialize();
    
    
     /* Initialize UARTs */
     initUART1(BAUD_RATE, UART_RX_TRIG_LEVEL_1);
    
    
     /* Request DMA Channel and TCC for UART Transmit*/
     EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
     EDMA3_CHA_UART1_TX, EDMA3_CHA_UART1_TX,
     EVT_QUEUE_NUM);
    
    
     /* Registering Callback Function for TX*/
     cb_Fxn[EDMA3_CHA_UART1_TX] = &callback;
    
    
     /* Request DMA Channel and TCC for UART Receive */ 
     EDMA3RequestChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
     EDMA3_CHA_UART1_RX, EDMA3_CHA_UART1_RX,
     EVT_QUEUE_NUM);
    
    
     /* Registering Callback Function for RX*/ 
     cb_Fxn[EDMA3_CHA_UART1_RX] = &callback;
    
    
    
    
     /* Used for bCnt */
     buffLength = strlen((const char *) enter); 
    
    
     /* Transmit Data for Enter Message */ 
     UartTransmitData(EDMA3_CHA_UART1_TX, EDMA3_CHA_UART1_TX,
     enter, buffLength);
    
    
     /* Enabling UART in DMA Mode*/ 
     UARTDMAEnable(SOC_UART_1_REGS, UART_RX_TRIG_LEVEL_1 | \
     UART_DMAMODE | \
     UART_FIFO_MODE );
    
    
     /* Wait for control to return from call-back function */
     while(0 == flag); 
     flag = 0;
    
    
     /* Receive Data for Input */
     UartReceiveData(EDMA3_CHA_UART1_RX, EDMA3_CHA_UART1_RX, buffer);
    
    
     /* Enabling UART in DMA Mode*/
     UARTDMAEnable(SOC_UART_1_REGS, UART_RX_TRIG_LEVEL_1 | \
     UART_DMAMODE | \
     UART_FIFO_MODE );
    
    
    
    
     /* Wait for return from callback */ 
     while(0 == flag);
     flag = 0;
     
     /* Transmit Data for Entered value */
     UartTransmitData(EDMA3_CHA_UART1_TX, EDMA3_CHA_UART1_TX,
     buffer, RX_BUFFER_SIZE);
    
    
     /* Enabling UART in DMA Mode*/
     UARTDMAEnable(SOC_UART_1_REGS, UART_RX_TRIG_LEVEL_1 | \
     UART_DMAMODE | \
     UART_FIFO_MODE );
    
    
     /* Wait for return from callback */
     while(0 == flag); 
     flag = 0;
    
    
     /* Free EDMA3 Channels for TX and RX */
     EDMA3FreeChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
     EDMA3_CHA_UART1_TX, EDMA3_TRIG_MODE_EVENT,
     EDMA3_CHA_UART1_TX, EVT_QUEUE_NUM);
    
    
     EDMA3FreeChannel(SOC_EDMA30CC_0_REGS, EDMA3_CHANNEL_TYPE_DMA,
     EDMA3_CHA_UART1_RX, EDMA3_TRIG_MODE_EVENT,
     EDMA3_CHA_UART1_RX, EVT_QUEUE_NUM);
    
    
     while(1);
    
    
    }
    
    
    /*
    ** This function is used to set the PaRAM entries in EDMA3 for the Transmit Channel
    ** of UART. EDMA3 Enable Transfer is also called within this API.
    */
    
    
    static void UartTransmitData(unsigned int tccNum, unsigned int chNum,
     volatile char *buffer, unsigned int buffLength)
    {
     EDMA3CCPaRAMEntry paramSet;
    
    
     /* Fill the PaRAM Set with transfer specific information */
     paramSet.srcAddr = (unsigned int) buffer;
     paramSet.destAddr = UART_RBR_THR_REG;
     paramSet.aCnt = MAX_ACNT;
     paramSet.bCnt = (unsigned short) buffLength;
     paramSet.cCnt = MAX_CCNT;
    
    
     /* The src index should increment for every byte being transferred. */
     paramSet.srcBIdx = (short) 1u;
    
    
     /* The dst index should not be increment since it is a h/w register*/
     paramSet.destBIdx = (short) 0u;
     
     /* A sync Transfer Mode */
     paramSet.srcCIdx = (short) 0u;
     paramSet.destCIdx = (short) 0u;
     paramSet.linkAddr = (unsigned short)0xFFFFu;
     paramSet.bCntReload = (unsigned short)0u;
     paramSet.opt = 0x00000000u;
     paramSet.opt |= (EDMA3CC_OPT_DAM );
     paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
     paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
    
    
     /* Now write the PaRAM Set */
     EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, chNum, &paramSet);
    
    
     /* Enable EDMA Transfer */
     EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);
    }
    
    
    /*
    ** This function is used to set the PARAM SET of EDMA3 for the Receive Channel
    ** of UART. EDMA3 Enable Transfer is also called within this API.
    */
    
    
    static void UartReceiveData(unsigned int tccNum, unsigned int chNum,
     volatile char *buffer)
    {
     EDMA3CCPaRAMEntry paramSet;
    
    
     /* Fill the PaRAM Set with transfer specific information */
     paramSet.srcAddr = UART_RBR_THR_REG;
     paramSet.destAddr = (unsigned int) buffer;
     paramSet.aCnt = MAX_ACNT;
     paramSet.bCnt = RX_BUFFER_SIZE;
     paramSet.cCnt = MAX_CCNT;
    
    
     /* The src index should not be increment since it is a h/w register*/
     paramSet.srcBIdx = 0;
     /* The dest index should incremented for every byte */
     paramSet.destBIdx = 1;
    
    
     /* A sync Transfer Mode */
     paramSet.srcCIdx = 0;
     paramSet.destCIdx = 0;
     paramSet.linkAddr = (unsigned short)0xFFFFu;
     paramSet.bCntReload = 0;
     paramSet.opt = 0x00000000u; 
     paramSet.opt |= ((EDMA3CC_OPT_SAM) << EDMA3CC_OPT_SAM_SHIFT); 
     paramSet.opt |= ((tccNum << EDMA3CC_OPT_TCC_SHIFT) & EDMA3CC_OPT_TCC);
     paramSet.opt |= (1 << EDMA3CC_OPT_TCINTEN_SHIFT);
    
    
     /* Now write the PaRAM Set */
     EDMA3SetPaRAM(SOC_EDMA30CC_0_REGS, chNum, &paramSet);
    
    
     /* Enable EDMA Transfer */
     EDMA3EnableTransfer(SOC_EDMA30CC_0_REGS, chNum, EDMA3_TRIG_MODE_EVENT);
    }
    
    
    /* Function used to Initialize EDMA3 */
    static void EDMA3Initialize(void)
    {
    
    
     /* Enabling the PSC for EDMA3CC_0.*/
     PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_CC0, PSC_POWERDOMAIN_ALWAYS_ON,
     PSC_MDCTL_NEXT_ENABLE);
    
    
     /* Enabling the PSC for EDMA3TC_0.*/
     PSCModuleControl(SOC_PSC_0_REGS, HW_PSC_TC0, PSC_POWERDOMAIN_ALWAYS_ON,
     PSC_MDCTL_NEXT_ENABLE);
    
    
     /* Initialization of EDMA3 */
     EDMA3Init(SOC_EDMA30CC_0_REGS, EVT_QUEUE_NUM);
     
     /*
     ** Enable AINTC to handle interuppts. Also enable IRQ interuppt in 
     ** ARM processor.
     */
     SetupInt();
    
    
     /* Register EDMA3 Interrupts */
     ConfigureIntEDMA3();
    }
    
    
    /* Function used to Setup ARM Interuppt Controller */
    static void SetupInt(void)
    {
    #ifdef _TMS320C6X
     // Initialize the DSP Interrupt controller
     IntDSPINTCInit();
    
    
     // Enable DSP interrupts globally
     IntGlobalEnable();
    #else
     /*Initialize the ARM Interrupt Controller(AINTC). */
     IntAINTCInit();
    
    
     /* Enable IRQ in CPSR.*/ 
     IntMasterIRQEnable();
    
    
     /* Enable the interrupts in GER of AINTC.*/
     IntGlobalEnable();
    
    
     /* Enable the interrupts in HIER of AINTC.*/
     IntIRQEnable();
    #endif
    }
    
    
    /* EDMA3 Completion Handler */
    static void edma3ComplHandler(unsigned int baseAdd, unsigned int regionNum)
    {
     volatile unsigned int pendingIrqs;
     volatile unsigned int isIPR = 0;
    
    
     unsigned int indexl;
     unsigned int Cnt = 0;
     indexl = 1;
     
    #ifdef _TMS320C6X
     IntEventClear(SYS_INT_EDMA3_0_CC0_INT1);
    #else
     IntSystemStatusClear(SYS_INT_CCINT0);
    #endif
     isIPR = HWREG(baseAdd + EDMA3CC_S_IPR(regionNum));
     if(isIPR)
     {
     while ((Cnt < EDMA3CC_COMPL_HANDLER_RETRY_COUNT)&& (indexl != 0u))
     {
     indexl = 0u;
     pendingIrqs = HWREG(baseAdd + EDMA3CC_S_IPR(regionNum));
     while (pendingIrqs)
     {
     if((pendingIrqs & 1u) == TRUE)
     {
     /**
     * If the user has not given any callback function
     * while requesting the TCC, its TCC specific bit
     * in the IPR register will NOT be cleared.
     */
     /* here write to ICR to clear the corresponding IPR bits */
     HWREG(baseAdd + EDMA3CC_S_ICR(regionNum)) = (1u << indexl);
    
    
     (*cb_Fxn[indexl])(indexl, EDMA3_XFER_COMPLETE);
     }
     ++indexl;
     pendingIrqs >>= 1u;
     }
     Cnt++;
     }
     }
    }
    
    
    static void Edma3ComplHandlerIsr(void)
    {
    #ifdef _TMS320C6X
     // Invoke Completion Handler ISR
     edma3ComplHandler(SOC_EDMA30CC_0_REGS, 1);
    #else
     /* Invoke Completion Handler ISR */
     edma3ComplHandler(SOC_EDMA30CC_0_REGS, 0);
    #endif
    }
    
    
    /* EDMA3 Error Handler */
    static void edma3CCErrHandler(unsigned int baseAdd)
    {
     volatile unsigned int pendingIrqs = 0;
     unsigned int regionNum = 0;
     unsigned int evtqueNum = 0; 
     unsigned int index = 1;
     unsigned int Cnt = 0;
     
    #ifdef _TMS320C6X
     IntEventClear(SYS_INT_EDMA3_0_CC0_ERRINT);
    #else
     IntSystemStatusClear(SYS_INT_CCERRINT);
    #endif
    
    
     if((HWREG(baseAdd + EDMA3CC_EMR) != 0 ) || \
     (HWREG(baseAdd + EDMA3CC_QEMR) != 0) || \
     (HWREG(baseAdd + EDMA3CC_CCERR) != 0))
     {
     /* Loop for EDMA3CC_ERR_HANDLER_RETRY_COUNT number of time, breaks 
     when no pending interrupt is found */
     while ((Cnt < EDMA3CC_ERR_HANDLER_RETRY_COUNT) && (index != 0u))
     {
     index = 0u;
     pendingIrqs = HWREG(baseAdd + EDMA3CC_EMR);
     while (pendingIrqs)
     {
     /*Process all the pending interrupts*/
     if((pendingIrqs & 1u)==TRUE)
     {
     /* Write to EMCR to clear the corresponding EMR bits.*/
     HWREG(baseAdd + EDMA3CC_EMCR) = (1u<<index);
     /*Clear any SER*/
     HWREG(baseAdd + EDMA3CC_S_SECR(regionNum)) = (1u<<index);
     }
     ++index;
     pendingIrqs >>= 1u;
     }
     index = 0u;
     pendingIrqs = HWREG(baseAdd + EDMA3CC_QEMR);
     while (pendingIrqs)
     {
     /*Process all the pending interrupts*/
     if((pendingIrqs & 1u)==TRUE)
     {
     /* Here write to QEMCR to clear the corresponding QEMR bits*/
     HWREG(baseAdd + EDMA3CC_QEMCR) = (1u<<index);
     /*Clear any QSER*/
     HWREG(baseAdd + EDMA3CC_S_QSECR(0)) = (1u<<index);
     }
     ++index;
     pendingIrqs >>= 1u;
     }
     index = 0u;
     pendingIrqs = HWREG(baseAdd + EDMA3CC_CCERR);
     if (pendingIrqs != 0u)
     {
     /* Process all the pending CC error interrupts. */
     /* Queue threshold error for different event queues.*/
     for (evtqueNum = 0u; evtqueNum < EDMA3_0_NUM_EVTQUE; evtqueNum++)
     {
     if((pendingIrqs & (1u << evtqueNum)) != 0u)
     {
     /* Clear the error interrupt. */
     HWREG(baseAdd + EDMA3CC_CCERRCLR) = (1u << evtqueNum);
     }
     }
    
    
     /* Transfer completion code error. */
     if ((pendingIrqs & (1 << EDMA3CC_CCERR_TCCERR_SHIFT)) != 0u)
     {
     HWREG(baseAdd + EDMA3CC_CCERRCLR) = \
     (0x01u << EDMA3CC_CCERR_TCCERR_SHIFT);
     }
     ++index;
     }
     Cnt++;
     }
     }
    }
    
    
    static void Edma3CCErrHandlerIsr()
    {
     /* Invoke CC Error Handler ISR */
     edma3CCErrHandler(SOC_EDMA30CC_0_REGS);
    }
    
    
    /* Function to register EDMA3 Interuppts */
    static void ConfigureIntEDMA3(void)
    {
     /* Register Interrupts Here */
    
    
    //Note: _TMS320C6X is defined
    #ifdef _TMS320C6X
     IntRegister(C674X_MASK_INT4, Edma3ComplHandlerIsr);
     IntRegister(C674X_MASK_INT5, Edma3CCErrHandlerIsr);
    
    
     IntEventMap(C674X_MASK_INT4, SYS_INT_EDMA3_0_CC0_INT1);
     IntEventMap(C674X_MASK_INT5, SYS_INT_EDMA3_0_CC0_ERRINT);
    
    
     IntEnable(C674X_MASK_INT4);
     IntEnable(C674X_MASK_INT5);
    #else
     IntRegister(SYS_INT_CCINT0, Edma3ComplHandlerIsr);
    
    
     IntChannelSet(SYS_INT_CCINT0, 2);
    
    
    
    
     IntSystemEnable(SYS_INT_CCINT0);
    
    
     IntRegister(SYS_INT_CCERRINT, Edma3CCErrHandlerIsr);
    
    
     IntChannelSet(SYS_INT_CCERRINT, 2);
    
    
     IntSystemEnable(SYS_INT_CCERRINT);
    #endif
    }
    
    
    
    
    /*
    ** This function is used as a callback from EDMA3 Completion Handler. 
    ** UART in DMA Mode is Disabled over here.
    */
    static void callback(unsigned int tccNum, unsigned int status)
    { 
     UARTDMADisable(SOC_UART_1_REGS, (UART_RX_TRIG_LEVEL_1 | UART_FIFO_MODE)); 
     flag = 1;
    }
    
    
    /********************************* End of file ******************************/
    
    

     

    Adam Ford
    Advanced Member
    Advanced Member
    Posts:794


    --
    29 Jan 2015 02:19 PM
    Since it's not part of the our stock BSP and it's a specialized feature, it will take some time. I think the best solution here would be to contact one of sales people and setup a services contract.

    Sorry, I know it's not what you wanted to hear.

    adam
    You are not authorized to post a reply.