This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/EVMK2G: EDMA Event list

Part Number: EVMK2G

Tool/software: Code Composer Studio

Hi,

I am planning to use EDMA GPIOMUX event to trigger my SPI communication. The setup would be as follows

1. Use paramset A to receive the trigger via GPIO. 

2. Link paramset B to paramset A to continue the data transmission from RAM to SPITxBuffer

3. After transmission of data on SPI, linked paramset C will be called to reset DMAREQEN bit in SPIINT0 register.

Repeat the steps 1 to 3 for every 30us without cpu intervention.

To implement this, I have below questions.

1. How to configure EDMA to receive the event GPIOMUXEventx. ( I am not sure which GPIOx to be used for triggering this event. Is it GPIO0_48 or GPIO1_48 or any GPIO). I do not want to use the GPIO multiplexed with Boot mode functionality.

2. Link Addr of Paramset A will have Paramset B address

3. Link Addr of Paramset B will have Paramset C address. Link Addr of Paramset C will have 0xFFFF to indicate the end of paramset for this transaction.

4. GPIOx can be controlled for every 30us using a timer.

5. should the SPI Rx/Tx interrupts be enabled in this case?

6. should the EDMA be running with supervisor level privilege?

  • I was able to do teh above steps using the code modified as per the attachment. The GPIO is toggled using a PWM O/P at 30kHz rate. I expect teh GPIO MUX Event to be generated at every 33us which means I should be seeing the clock pulses from SPI for every 33us. But what I see actually is for every 4 iterations of GPIO falling edge there is SPI data transmission. I am not sure what is wrong in setting the param set configuration and chaining for EDMA.

    I have configured the GPIO as input and EDMA event is configured to generate on every falling edge. 

    Could anyone  look into this and let us know where is the mistake in teh code.

    /**
     *  \file   SPI_dma_modified.c
     *
     *  \brief  EDMA based SPI driver for IP verion 0
     *
     */
    
    /*
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * 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 <ti/drv/spi/soc/SPI_soc.h>
    #include <ti/sdo/edma3/drv/edma3_drv.h>
    #include <ti/csl/csl_chip.h>
    
    #define SPI_RX_EDMA_CALLBACK_OCCURED    (0x2U)
    /**< Flag to indicate that Reception EDMA callback has occured            */
    
    #define SPI_TX_EDMA_CALLBACK_OCCURED    (0x1U)
    /**< Flag to indicate that Transmission EDMA callback has occured         */
    
    #define SPI_MAXLINKCNT                  (3U)
    /**<  Maximum number of EDMA jobs linked at a time (Must be 2).           */
    
    /**<  Transmit EDMA channel event queue number                            */
    #define SPI_TXEVENTQUE                  (0U)
    
    /**<  Receive EDMA channel event queue number                             */
    #define SPI_RXEVENTQUE                  (1U)
    
    
    /**< Trasnfer Complete chaining enable bit in OPT register for edma      */
    #define SPI_OPT_TCCN_EN                 (0x00000016U)
    
    #define SPI_OPT_TCINTEN_SHIFT           (0x00000014U)
    /**< Interrupt enable bit in OPT register for edma                        */
    
    #define SPI_OPT_TCC_SHIFT               (0x0000000CU)
    /**<  TCC set bit in OPT register for edma                                */
    
    #define SPI_OPT_TCC_EARLY_COMPLETION   (0x00000800U)
    /**<  TCC Early completion bit is set in OPT register for edma            */
    
    #define SPI_OPT_TCC_MASK                (0x0003F000U)
    /**<  Tcc mask in OPT register for edma                                   */
    
    #define SPI_EDMA3CC_OPT_FIFO_WIDTH      (0xFFFFF8FFU)
    /**< Set FIFO Width for edma transfer                                     */
    
    #define SPI_EDMA3CC_OPT_SAM_CONST_MODE  (0x00000001U)
    /**< Set SAM in Constant Addressing Mode                                  */
    
    #define SPI_EDMA3CC_OPT_DAM_CONST_MODE  (0x00000002U)
    /**< Set DAM in Constant Addressing Mode                                  */
    
    #define SPI_EDMA3CC_OPT_SAM_INCR_MODE   (0xFFFFFFFEU)
    /**< Set SAM in Increment Mode                                            */
    
    #define SPI_EDMA3CC_OPT_DAM_INCR_MODE   (0xFFFFFFFDU)
    /**< Set DAM in Increment Mode                                            */
    
    #define SPI_EDMA3CC_OPT_SAM_DAM_INCR_MODE (0xFFFFFFFCU)
    /**< Set DAM in Increment Mode                                            */
    
    #define SPI_EDMA3CC_OPT_SYNC_AB         (0x00000004U)
    /**< It is AB-synchronized                                                */
    
    #define SPI_EDMA3CC_OPT_SYNC_MASK_VALUE (0xFFFFFFFFU)
    /**< Mask Value for Transfer Synchronization                              */
    
    #define SPI_EDMA3CC_PARAM_LINK_ADDRESS  (0xFFFFU)
    /**< Set link Address                                                     */
    
    #define SPI_EDMA3CC_PARAM_ACNT          (1U)
    /**< aCnt Value                                                           */
    
    #define SPI_EDMA3CC_OPT_STATIC_SHIFT    (0x00000003U)
    /**< STATIC Token                                                         */
    
    #define SPI_EDMA3CC_SRC_BINDEX          (1U)
    /**< Src BIndex Value                                                     */
    
    #define SPI_EDMA3CC_DST_BINDEX          (1U)
    /**< Dst BIndex Value                                                     */
    
    #define SPI_EDMA3CC_OPT_SYNC_A          (0x01U)
    /**< It is A-synchronized                                                 */
    
    #define SPI_EDMA3CC_OPT_SYNCDIM_SHIFT   (3U)
    /**< Transfer synchronization dimension Shift Value                       */
    
    #define SPI_EDMA3CC_COUNT_VALUE         (0xFFFFU)
    /**< Count Value                                                          */
    
    #define ADC_1_BUSY_LOW_START_EVENT       EDMA3_DRV_HW_CHANNEL_EVENT_60
    #define ADC_1_SPI_DATA_TRANSMIT_EVENT    EDMA3_DRV_HW_CHANNEL_EVENT_4
    // Any event number which is not used
    #define ADC_1_BUSY_LOW_COMPLETE_EVENT    EDMA3_DRV_HW_CHANNEL_EVENT_59
    
    /* SPI DMA functions */
    static void SPI_dmaRxIsrHandler(uint32_t tcc,
                                    EDMA3_RM_TccStatus status,
                                    void* appData);
    static void SPI_dmaDoNothing(uint32_t tcc,
                               EDMA3_RM_TccStatus edmaStatus,
                                     void* appData);
    static void SPI_dmaTxIsrHandler(uint32_t tcc,
                                    EDMA3_RM_TccStatus status,
                                    void* appData);
    static void SPI_dmaUpdateParams(SPI_Handle handle,
                                    const SPI_Transaction *transaction,
                                    EDMA3_DRV_PaRAMRegs *rxParamSet,
                                    EDMA3_DRV_PaRAMRegs *txParamSet);
    static void SPI_dmaCallback(SPI_Handle handle);
    static void SPI_dmaUpdateParamSet(SPI_Handle  handle,
                                        bool tcc_enable_status,
                                        uint8_t tcc_no,
                                        SPI_Transaction *transaction,
                                        EDMA3_DRV_PaRAMRegs   *ParamSet);
                                        
    int32_t SPI_dmaConfig(SPI_Handle handle);
    void SPI_dmaTransfer(SPI_Handle handle, SPI_Transaction *transaction);
    void SPI_dmaDisableChannel(SPI_Handle handle, bool txChan);
    void SPI_dmaFreeChannel(SPI_Handle handle);
    static uintptr_t l_l2_global_address (uintptr_t addr);
    
    uint32_t             txedmaParamsetNum[6];
    uint32_t             txedmareqTCCNum[6];
    uint32_t srcaddrTx0, srcaddrTx1,destaddrTx0;//, destaddrTx1;
    
    static uintptr_t l_l2_global_address (uintptr_t addr)
    {
        uint32_t corenum;
    
        /* Get the core number. */
        corenum = CSL_chipReadReg (CSL_CHIP_DNUM);
    
        /* Compute the global address. */
        return (addr + (0x10000000 + (corenum * 0x1000000)));
    }
    
    int32_t SPI_dmaConfig(SPI_Handle handle)
    {
        SPI_HWAttrs const   *hwAttrs;
        uint32_t             tcc = 0;
        uint32_t             reqTcc = EDMA3_DRV_TCC_ANY;
        EDMA3_RM_EventQueue  queueNum = 0;
        int32_t              status;
    
        /* Get the pointer to the object and hwAttrs */
        hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
    
        /* TX Section Configuration */
        queueNum = (EDMA3_RM_EventQueue)SPI_TXEVENTQUE;
        
        /* Acquire the  PaRAM entries used for EDMA transfers linking */
        // For Paramset0, Busy signal low event should write 1 in DMAREQEN bit of SPIINT0
        tcc    = ADC_1_BUSY_LOW_START_EVENT;
        //reqTcc = ADC_1_BUSY_LOW_START_EVENT;
        reqTcc = hwAttrs->txDmaEventNumber;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,
                                          &reqTcc,
                                          queueNum,
                                          &SPI_dmaDoNothing,
                                          (void *)handle);
        txedmaParamsetNum[0] = tcc;
        txedmareqTCCNum[0]=reqTcc;
        
        tcc    = EDMA3_DRV_LINK_CHANNEL_WITH_TCC;
        //reqTcc = ADC_1_BUSY_LOW_START_EVENT;
        reqTcc = hwAttrs->txDmaEventNumber;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,
                                          &reqTcc,
                                          queueNum,
                                          &SPI_dmaDoNothing,
                                          (void *)handle);
        txedmaParamsetNum[3] = tcc;
        txedmareqTCCNum[3]=reqTcc;
    
    
        // For Paramset1, Data from RAM is written into SPIDAT0
        tcc    = hwAttrs->txDmaEventNumber;
        //reqTcc = ADC_1_BUSY_LOW_START_EVENT;
        reqTcc = ADC_1_BUSY_LOW_COMPLETE_EVENT;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,//(uint32_t *)&(hwAttrs->txDmaEventNumber),
                                          &reqTcc,//(uint32_t *)&(hwAttrs->txDmaEventNumber),
                                          queueNum,
                                          &SPI_dmaTxIsrHandler,
                                          (void *)handle);
        txedmaParamsetNum[1] = tcc;
        txedmareqTCCNum[1]=reqTcc;
    
        tcc    = EDMA3_DRV_LINK_CHANNEL_WITH_TCC;
        //reqTcc = ADC_1_BUSY_LOW_START_EVENT;
        reqTcc = ADC_1_BUSY_LOW_COMPLETE_EVENT;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,//(uint32_t *)&(hwAttrs->txDmaEventNumber),
                                          &reqTcc,//(uint32_t *)&(hwAttrs->txDmaEventNumber),
                                          queueNum,
                                          &SPI_dmaTxIsrHandler,
                                          (void *)handle);
        txedmaParamsetNum[4] = tcc;
        txedmareqTCCNum[4]=reqTcc;
    
        // For Paramset2, after finishing sending data to ADC write 0 in DMAREQEN bit of SPIINT0 to enable next DMA request
        tcc    = ADC_1_BUSY_LOW_COMPLETE_EVENT;//EDMA3_DRV_LINK_CHANNEL
        reqTcc = EDMA3_DRV_TCC_ANY;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,
                                          &reqTcc,
                                          queueNum,
                                          &SPI_dmaDoNothing,
                                          NULL);
        txedmaParamsetNum[2] = tcc;
        txedmareqTCCNum[2]=reqTcc;
    
        tcc    = EDMA3_DRV_LINK_CHANNEL;//EDMA3_DRV_LINK_CHANNEL
        reqTcc = EDMA3_DRV_TCC_ANY;
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                          &tcc,
                                          &reqTcc,
                                          queueNum,
                                          &SPI_dmaDoNothing,
                                          NULL);
        txedmaParamsetNum[5] = tcc;
        txedmareqTCCNum[5]=reqTcc;
    
        /* RX Section Configuration */
        /* For receive use EDMA Queue 1 and for transmit use EDMA queue 0 */
        queueNum = (EDMA3_RM_EventQueue) SPI_RXEVENTQUE;
    
        status = EDMA3_DRV_requestChannel((EDMA3_DRV_Handle) hwAttrs->edmaHandle,
                                          (uint32_t *)&(hwAttrs->rxDmaEventNumber),
                                          (uint32_t *)&(hwAttrs->rxDmaEventNumber),
                                          queueNum,
                                          &SPI_dmaRxIsrHandler,
                                          (void *)handle);
    
        return(status);
    }
    
    void SPI_dmaTransfer(SPI_Handle       handle,
                         SPI_Transaction *transaction)
    {
        SPI_HWAttrs   const *hwAttrs;
        SPI_v0_Object       *object;
        EDMA3_DRV_PaRAMRegs  rxParamSet = {0};
        EDMA3_DRV_PaRAMRegs  txParamSet = {0};
        EDMA3_DRV_PaRAMRegs  dummyParamSet = {0};
    
        /* Get the pointer to the object and hwAttrs */
        object  = (SPI_v0_Object*)handle->object;
        hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
    
        object->edmaCbCheck = 0;
    
        /* receive parameter set */
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle,
                            hwAttrs->rxDmaEventNumber,
                            &rxParamSet);
    
        /* transmit parameter set */
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle,
                            hwAttrs->txDmaEventNumber,
                            &txParamSet);
    
        /* Update param sets based on the transaction parameters */
        SPI_dmaUpdateParams(handle,
                            transaction,
                            &rxParamSet,
                            &txParamSet);
    
        /* Dummy paramSet Configuration */
        EDMA3_DRV_getPaRAM(hwAttrs->edmaHandle,
                           EDMA3_DRV_LINK_CHANNEL,
                           &dummyParamSet);
    
        dummyParamSet.aCnt     = SPI_EDMA3CC_PARAM_ACNT;
        dummyParamSet.linkAddr = 0xFFFF;//SPI_EDMA3CC_PARAM_LINK_ADDRESS;//Modified
        dummyParamSet.opt     &= ~((uint32_t)0x01U << SPI_EDMA3CC_OPT_STATIC_SHIFT);
    
        /* Now, write the PaRAM Set. */
        EDMA3_DRV_setPaRAM(hwAttrs->edmaHandle,
                           EDMA3_DRV_LINK_CHANNEL,
                           &dummyParamSet);
        /* Write Rx param set */
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                            hwAttrs->rxDmaEventNumber,
                            &rxParamSet);
    
        /* Write Tx param set */
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                           hwAttrs->txDmaEventNumber,
                           &txParamSet);
    
        /* Program the RX side */
        EDMA3_DRV_enableTransfer(hwAttrs->edmaHandle,
                                 hwAttrs->rxDmaEventNumber,
                                 EDMA3_DRV_TRIG_MODE_EVENT);
    
        /* Program the TX side */
        EDMA3_DRV_enableTransfer(hwAttrs->edmaHandle,
                                 hwAttrs->txDmaEventNumber,
                                 EDMA3_DRV_TRIG_MODE_EVENT);
    
        /* Enable SPI DMA for transaction */
        SPIIntEnable(hwAttrs->baseAddr, SPI_INT_DMA_ENABLE);
    }
    
    void SPI_dmaDisableChannel(SPI_Handle handle, bool txChan)
    {
        SPI_HWAttrs const *hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
        uint32_t           dmaEvent;
    
        if (txChan == true)
        {
            dmaEvent = (uint32_t) hwAttrs->txDmaEventNumber;
        }
        else
        {
            dmaEvent = (uint32_t) hwAttrs->rxDmaEventNumber;
        }
    
        EDMA3_DRV_disableLogicalChannel(
                (EDMA3_DRV_Handle) hwAttrs->edmaHandle,
                dmaEvent,
                (EDMA3_DRV_TrigMode) EDMA3_DRV_TRIG_MODE_EVENT);
    }
    
    void SPI_dmaFreeChannel(SPI_Handle handle)
    {
        SPI_HWAttrs const *hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
    
        /* Unlink and free the channels */
        EDMA3_DRV_unlinkChannel(hwAttrs->edmaHandle, EDMA3_DRV_LINK_CHANNEL);
        EDMA3_DRV_freeChannel(hwAttrs->edmaHandle, EDMA3_DRV_LINK_CHANNEL);
    
        EDMA3_DRV_freeChannel(hwAttrs->edmaHandle, hwAttrs->rxDmaEventNumber);
        EDMA3_DRV_freeChannel(hwAttrs->edmaHandle, hwAttrs->txDmaEventNumber);
    }
    
    static void SPI_dmaRxIsrHandler(uint32_t tcc, EDMA3_RM_TccStatus status, void* appData)
    {
        SPI_Handle           handle;
        SPI_v0_Object       *object;
        SPI_HWAttrs const   *hwAttrs;
        EDMA3_DRV_PaRAMRegs  paramSet = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
        /* Get the pointer to the object and hwAttrs */
        handle   = (SPI_Handle)appData;
        object   = (SPI_v0_Object*)handle->object;
        hwAttrs  = (SPI_HWAttrs*)handle->hwAttrs;
    
        if (EDMA3_RM_XFER_COMPLETE != status)
        {
            /* Error condition  */
            /* Ensure to clear the error bits of EDMA channel */
            EDMA3_DRV_clearErrorBits((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                     hwAttrs->rxDmaEventNumber);
    
            /* Get the PaRAM set for default parameters */
            EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle,
                                hwAttrs->rxDmaEventNumber,
                                &paramSet);
    
            /* Update the transaction status and word count transfered */
            object->transaction->status = SPI_TRANSFER_FAILED;
            object->transaction->count -= paramSet.bCnt;
        }
    
        /* EDMA Rx is done disable the Rx DMA channel */
        //EDMA3_DRV_disableTransfer(hwAttrs->edmaHandle, tcc, EDMA3_DRV_TRIG_MODE_EVENT);
    
        /* clear the error bits in the EDMA(as this is the last packet)   */
        EDMA3_DRV_clearErrorBits((EDMA3_DRV_Handle)(hwAttrs->edmaHandle),
                                 (uint32_t)tcc);
    
        if (SPI_TX_EDMA_CALLBACK_OCCURED == object->edmaCbCheck)
        {
            /* Call the completion function */
            SPI_dmaCallback(handle);
            object->edmaCbCheck = 0x0;
        }
        else
        {
            if (EDMA3_RM_XFER_COMPLETE == status)
            {
                object->edmaCbCheck = SPI_RX_EDMA_CALLBACK_OCCURED;
            }
        }
    }
    
    static void SPI_dmaDoNothing(uint32_t           tcc,
                                 EDMA3_RM_TccStatus edmaStatus,
                                 void*              appData)
    {
        /* No implementation required */
    }
    
    static void SPI_dmaTxIsrHandler(uint32_t tcc, EDMA3_RM_TccStatus status, void* appData)
    {
        SPI_Handle           handle;
        SPI_v0_Object       *object;
        SPI_HWAttrs const   *hwAttrs;
        EDMA3_DRV_PaRAMRegs  paramSet = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
        /* Get the pointer to the object and hwAttrs */
        handle   = (SPI_Handle)appData;
        object   = (SPI_v0_Object*)handle->object;
        hwAttrs  = (SPI_HWAttrs*)handle->hwAttrs;
    
        if (EDMA3_RM_XFER_COMPLETE != status)
        {
            /* Ensure to clear the error bits of EDMA channel */
            EDMA3_DRV_clearErrorBits((EDMA3_DRV_Handle)hwAttrs->edmaHandle,
                                     hwAttrs->txDmaEventNumber);
    
            /* Get the PaRAM set for default parameters */
            EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle,
                                hwAttrs->txDmaEventNumber,
                                &paramSet);
    
            /* Update the transaction status and word count transfered */
            object->transaction->status = SPI_TRANSFER_FAILED;
            object->transaction->count -= paramSet.bCnt;
        }
    
        /* EDMA Tx is done disable the Tx DMA channel */
        //EDMA3_DRV_disableTransfer(hwAttrs->edmaHandle, tcc, EDMA3_DRV_TRIG_MODE_EVENT);
    
        /* clear the error bits in the EDMA */
        EDMA3_DRV_clearErrorBits((EDMA3_DRV_Handle) hwAttrs->edmaHandle, (uint32_t) tcc);
    
        if (SPI_RX_EDMA_CALLBACK_OCCURED == object->edmaCbCheck)
        {
            /* Call the completion function */
            SPI_dmaCallback(handle);
            object->edmaCbCheck = 0x0;
        }
        else
        {
            if (EDMA3_RM_XFER_COMPLETE == status)
            {
                object->edmaCbCheck = SPI_TX_EDMA_CALLBACK_OCCURED;
            }
        }
    }
    
    static void SPI_dmaUpdateParams(SPI_Handle             handle,
                                    const SPI_Transaction *transaction,
                                    EDMA3_DRV_PaRAMRegs   *rxParamSet,
                                    EDMA3_DRV_PaRAMRegs   *txParamSet)
    {
        SPI_HWAttrs const *hwAttrs;
        SPI_v0_Object     *object;
    
        /* Get the pointer to the object and hwAttrs */
        hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
        object  = (SPI_v0_Object*)handle->object;
    
        /* Receive param set configuration */
    
        /* Source address */
        rxParamSet->srcAddr = (uint32_t) ((hwAttrs->baseAddr) + CSL_SPI_SPIBUF);
    
        /* destAddr is address of memory location named buffer.*/
        rxParamSet->destAddr = (uint32_t) transaction->rxBuf;
    
        /* aCnt holds the number of bytes in an array.*/
        if (object->frameSize == SPI_v0_8bit)
        {
            /* 8-bit word length */
            rxParamSet->aCnt = 1;
        }
        else
        {
            /* 16-bit word length */
            rxParamSet->aCnt = 2;
        }
    
        /* bCnt holds the number of such arrays to be transferred.*/
        rxParamSet->bCnt = transaction->count;
    
        /* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred.*/
        rxParamSet->cCnt = 1;
    
        /* The srcBidx should not be incremented since it is a h/w register.*/
        rxParamSet->srcBIdx = 0;
    
        if(NULL != transaction->rxBuf)
        {
            /* The destBidx should be incremented aCnt number of bytes.*/
            rxParamSet->destBIdx = rxParamSet->aCnt;
        }
        else
        {
            /* The destBidx should not be incremented.*/
            rxParamSet->destBIdx = 0;
        }
    
        /* A sync Transfer Mode. */
        /* srCIdx and destCIdx set to zero since ASYNC Mode is used.*/
        rxParamSet->srcCIdx = 0;
        rxParamSet->destCIdx += transaction->count;
    
        /* Linking transfers in EDMA3 are not used.*/
        rxParamSet->linkAddr = 0xFFFF;//Modified;
    
        rxParamSet->bCntReload = 0;
    
        /* EDMA3_DRV_OPT_FIELD_TCINTEN */
        rxParamSet->opt |= (uint32_t) 1U << SPI_OPT_TCINTEN_SHIFT;
    
        /* update the transfer completion code */
        rxParamSet->opt &= (~SPI_OPT_TCC_MASK);
        rxParamSet->opt |= ((hwAttrs->rxDmaEventNumber) << SPI_OPT_TCC_SHIFT);
    
        /* Transmit param set configuration */
        /* srcAddr holds address of memory location buffer. */
        txParamSet->srcAddr = (uint32_t) transaction->txBuf;
    
        /* destAddr holds address of SPIDAT1 register. */
        txParamSet->destAddr = (uint32_t) ((hwAttrs->baseAddr) + CSL_SPI_SPIDAT0);
    
        /* aCnt holds the number of bytes in an array. */
        if (object->frameSize == SPI_v0_8bit)
        {
            /* 8-bit word length */
            txParamSet->aCnt = 1;
        }
        else
        {
            /* 16-bit word length */
            txParamSet->aCnt = 2;
        }
    
        /* bCnt holds the number of such arrays to be transferred. */
        txParamSet->bCnt = transaction->count;
    
        /* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred. */
        txParamSet->cCnt = 1;
    
        /*
        ** The srcBidx should be incremented by aCnt number of bytes since the
        ** source used here is memory.
        */
        txParamSet->srcBIdx = txParamSet->aCnt;
        txParamSet->destBIdx = 0;
    
        /* Async Transfer Mode is set in OPT.*/
        /* srCIdx and destCIdx set to zero since ASYNC Mode is used. */
        txParamSet->srcCIdx = 0;
        txParamSet->destCIdx = 0;
    
        /* Linking transfers in EDMA3 are not used. */
        txParamSet->linkAddr = SPI_EDMA3CC_PARAM_LINK_ADDRESS;
        txParamSet->linkAddr = 0xFFFF;//Modified
        txParamSet->bCntReload = 0;
        //txParamSet->bCntReload = transaction->count;//Modified
    
    
        /* EDMA3_DRV_OPT_FIELD_TCINTEN */
        //txParamSet->opt |= ((uint32_t) 1 << SPI_OPT_TCINTEN_SHIFT);
        txParamSet->opt |= ((uint32_t) 1 << SPI_OPT_TCCN_EN);
        //txParamSet->opt |= ((uint32_t)SPI_OPT_TCC_EARLY_COMPLETION);
    
        /* update the transfer completion code */
       //txParamSet->opt &= (~SPI_OPT_TCC_MASK);
       //txParamSet->opt |= ((hwAttrs->txDmaEventNumber) << SPI_OPT_TCC_SHIFT);
    }
    
    
    // This function should be called only by dma rx isr handler. Tx isr should not call
    static void SPI_dmaCallback(SPI_Handle handle)
    {
        SPI_v0_Object     *object;
        SPI_HWAttrs const *hwAttrs;
    
        /* Get the pointer to the object and hwAttrs */
        object  = (SPI_v0_Object*)handle->object;
        hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
    
        EDMA3_DRV_disableTransfer(hwAttrs->edmaHandle,
                                  hwAttrs->txDmaEventNumber,
                                  EDMA3_DRV_TRIG_MODE_EVENT);
    
        EDMA3_DRV_disableTransfer(hwAttrs->edmaHandle,
                                  hwAttrs->rxDmaEventNumber,
                                  EDMA3_DRV_TRIG_MODE_EVENT);
    
        /* Call the transfer completion callback function */
        if ((object->transaction->status != SPI_TRANSFER_FAILED) &&
            (object->transferErr == SPI_XFER_ERR_NONE))
        {
            object->transaction->status = SPI_TRANSFER_COMPLETED;
        }
        else
        {
            object->transaction->status = SPI_TRANSFER_FAILED;
        }
        object->transferCallbackFxn(handle, object->transaction);
        object->transaction = NULL;
    }
    
    static void SPI_dmaUpdateParamSet(SPI_Handle  handle,
                                        bool tcc_enable_status,
                                        uint8_t tcc_no,
                                        SPI_Transaction *transaction,
                                        EDMA3_DRV_PaRAMRegs   *ParamSet)
    {
        SPI_v0_Object     *object;
    
        /* Get the pointer to the object and hwAttrs */
        object  = (SPI_v0_Object*)handle->object;
    
        /* param set configuration */
        /* Source address */
        ParamSet->srcAddr = (uint32_t)transaction->txBuf;
    
        /* destAddr is address of memory location named buffer.*/
        ParamSet->destAddr = (uint32_t)transaction->rxBuf;
    
        /* aCnt holds the number of bytes in an array.*/
        if (object->frameSize == SPI_v0_8bit)
        {
            /* 8-bit word length */
            ParamSet->aCnt = 1;
        }
        else
        {
            /* 16-bit word length */
            ParamSet->aCnt = 2;
        }
    
        /* bCnt holds the number of such arrays to be transferred.*/
        ParamSet->bCnt = transaction->count;
    
        /* cCnt holds the number of frames of aCnt*bBcnt bytes to be transferred.*/
        ParamSet->cCnt = 1;
    
        /* The srcBidx should not be incremented since it is a h/w register.*/
        ParamSet->srcBIdx = 1;
        if(NULL != transaction->rxBuf)
        {
            /* The destBidx should be incremented aCnt number of bytes.*/
            ParamSet->destBIdx = ParamSet->aCnt;
        }
        else
        {
            /* The destBidx should not be incremented.*/
            ParamSet->destBIdx = 0;
        }
    
        /* A sync Transfer Mode. */
        /* srCIdx and destCIdx set to zero since ASYNC Mode is used.*/
        ParamSet->srcCIdx = 0;
        ParamSet->destCIdx = 0;
    
        /* Linking transfers in EDMA3 are not used.*/
        ParamSet->linkAddr = 0xFFFF;//Modified;
    
        ParamSet->bCntReload = 0;
    
        if (true == tcc_enable_status)
        {
            /* EDMA3_DRV_OPT_FIELD_TCCEN */
            ParamSet->opt |= (uint32_t) 1U << SPI_OPT_TCCN_EN;
        }
    }
    
    void SPI_ParamSetConfig(SPI_Handle       handle,
                            SPI_Transaction *l_transaction)
    {
        SPI_HWAttrs   const *hwAttrs;
        SPI_v0_Object       *object;
        EDMA3_DRV_PaRAMRegs  rxParamSet = {0};
        EDMA3_DRV_PaRAMRegs  txParamSet[6] = {0};
        uintptr_t addrtxBuf0, addrtxBuf1;//, addrtxBuf2, addrtxBuf3;
    
        /* Get the pointer to the object and hwAttrs */
        object  = (SPI_v0_Object*)handle->object;
        hwAttrs = (SPI_HWAttrs*)handle->hwAttrs;
    
        object->edmaCbCheck = 0;
    
        /* receive parameter set */
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, hwAttrs->rxDmaEventNumber, &rxParamSet);
    
        /* transmit parameter set */
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[0], &txParamSet[0]);
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[1], &txParamSet[1]);
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[2], &txParamSet[2]);
    
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[3], &txParamSet[3]);
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[4], &txParamSet[4]);
        EDMA3_DRV_getPaRAM((EDMA3_DRV_Handle)hwAttrs->edmaHandle, txedmaParamsetNum[5], &txParamSet[5]);
    
        // Update param sets based on the transaction parameters
        SPI_dmaUpdateParams(handle, l_transaction, &rxParamSet, &txParamSet[1]);
        SPI_dmaUpdateParams(handle, l_transaction, &rxParamSet, &txParamSet[4]);
    
        // Update the linked final paramset - RAM to DMAREQEN bit to be set to 1
        srcaddrTx0 = SPI_INT_DMA_ENABLE;
        addrtxBuf0 = l_l2_global_address((uintptr_t)&srcaddrTx0);
        CacheP_wbInv((void *)(uintptr_t)addrtxBuf0, (int32_t)sizeof(srcaddrTx0));
        l_transaction->txBuf = (void *)addrtxBuf0;
        l_transaction->rxBuf = (void *)((uint32_t)(hwAttrs->baseAddr) + CSL_SPI_SPIINT0);
        l_transaction->count = 4;
        SPI_dmaUpdateParamSet(handle,true, txedmaParamsetNum[0], l_transaction,&txParamSet[0]);
        SPI_dmaUpdateParamSet(handle,true, txedmaParamsetNum[3], l_transaction,&txParamSet[3]);
    
        // Update the linked final paramset - RAM to DMAREQEN bit to be set to 0
        srcaddrTx1 = ~(SPI_INT_DMA_ENABLE);
        addrtxBuf1 = l_l2_global_address((uintptr_t)&srcaddrTx1);
        CacheP_wbInv((void *)(uintptr_t)addrtxBuf1, (int32_t)sizeof(srcaddrTx1));
        l_transaction->txBuf = (void *)addrtxBuf1;
        l_transaction->rxBuf = (void *)((uint32_t)(hwAttrs->baseAddr) + CSL_SPI_SPIINT0);
        l_transaction->count = 4;
        SPI_dmaUpdateParamSet(handle, false, txedmaParamsetNum[2], l_transaction,&txParamSet[2]);
        SPI_dmaUpdateParamSet(handle, false, txedmaParamsetNum[5], l_transaction,&txParamSet[5]);
        txParamSet[2].opt |= (uint32_t) 1U << SPI_OPT_TCCN_EN;
        txParamSet[2].opt |= (uint32_t) (txedmaParamsetNum[2] << SPI_OPT_TCC_SHIFT);
        txParamSet[5].opt = txParamSet[2].opt;
    
        // Write Rx param set
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), hwAttrs->rxDmaEventNumber, &rxParamSet);
    
        // Write Tx param set
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[0], &txParamSet[0]);
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[1], &txParamSet[1]);
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[2], &txParamSet[2]);
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[3], &txParamSet[3]);
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[4], &txParamSet[4]);
        EDMA3_DRV_setPaRAM((EDMA3_DRV_Handle)(hwAttrs->edmaHandle), txedmaParamsetNum[5], &txParamSet[5]);
    
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[0], txedmaParamsetNum[3]);
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[1], txedmaParamsetNum[4]);
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[2], txedmaParamsetNum[5]);
    
        // Self linking of channels to reload the paramset after completion
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[3], txedmaParamsetNum[3]);
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[4], txedmaParamsetNum[4]);
        EDMA3_DRV_linkChannel(hwAttrs->edmaHandle, txedmaParamsetNum[5], txedmaParamsetNum[5]);
    
        EDMA3_DRV_enableTransfer(hwAttrs->edmaHandle, hwAttrs->rxDmaEventNumber, EDMA3_DRV_TRIG_MODE_EVENT);
        EDMA3_DRV_enableTransfer(hwAttrs->edmaHandle, txedmaParamsetNum[0], EDMA3_DRV_TRIG_MODE_EVENT);
    }