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.

RM48L952: MibSPI Transmit and Receive over DMA

Part Number: RM48L952

Hello Experts,

I am looking for a working example for MibSPI transmit and receive over DMA. I am using MibSPI1 as master which will send the data and MibSPI3 as slave which will receive the data.

Thanks

  • Hello,

    The attached is the example code of MibSPI1+MibSPI3+DMA on TMS570LC43x

    MibSPI1 is SPI master, and MibSPI3 is SPI slave.

    /** @file HL_sys_main.c 
    *   @brief Application main file
    *   @date 11-Dec-2018
    *   @version 04.07.01
    *
    *   This file contains an empty main function,
    *   which can be used for the application.
    */
    
    /* 
    * Copyright (C) 2009-2018 Texas Instruments Incorporated - 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.
    *
    */
    
    
    /* USER CODE BEGIN (0) */
    /* USER CODE END */
    
    /* Include Files */
    
    #include "HL_sys_common.h"
    
    /* USER CODE BEGIN (1) */
    #include "HL_gio.h"
    #include "HL_mibspi.h"
    #include "HL_sys_dma.h"
    #include "HL_sys_core.h"
    #include "HL_sci.h"
    #include "HL_reg_esm.h"
    #include <stdio.h>
    #include <string.h>
    
    #define E_COUNT      4   /*Element count*/
    #define F_COUNT      2   /*Frame count*/
    #define D_SIZE      E_COUNT * F_COUNT
    #define TG0         1
    #define TG1         0
    
    /* USER CODE END */
    
    /** @fn void main(void)
    *   @brief Application main function
    *   @note This function is empty by default.
    *
    *   This function is called after startup.
    *   The user can use this function to implement the application.
    */
    
    /* USER CODE BEGIN (2) */
    void loadDataPattern(uint32 psize, uint16* pptr, uint16 pattern);
    void mibspiDmaConfig(mibspiBASE_t *mibspi,uint32 channel, uint32 txchannel, uint32 rxchannel);
    
    void dmaConfigCtrlRxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt);
    void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt);
    
    /* TG start address */
    uint16 tgPSTART1[8];   //for MibSPI1
    uint16 tgPSTART3[8];   //for MibSPI3
    g_dmaCTRL g_dmaCTRLPKT_RX, g_dmaCTRLPKT_TX;
    
    #pragma SET_DATA_SECTION(".sharedRAM")
    uint16 TXDATA_TG10[D_SIZE];         /* transmit buffer in sys ram, MibSPI1 TG0 */
    uint16 RXDATA_TG10[D_SIZE]= {0};    /* receive  buffer in sys ram, MibSPI1 TG0 */
    
    //uint16 TXDATA_TG11[D_SIZE];         /* transmit buffer in sys ram, MibSPI1 TG1 */
    //uint16 RXDATA_TG11[D_SIZE]= {0};    /* receive  buffer in sys ram, MibSPI1 TG1 */
    
    uint16 TXDATA_TG30[D_SIZE];         /* transmit buffer in sys ram, MibSPI3 TG0 */
    uint16 RXDATA_TG30[D_SIZE]= {0};    /* receive  buffer in sys ram, MibSPI3 TG0 */
    
    #pragma SET_DATA_SECTION()
    
    
    /* USER CODE END */
    
    int main(void)
    {
    /* USER CODE BEGIN (3) */
        uint16 i;
    
        esmREG->SR1[0] = 0xFFFFFFFF;
        esmREG->SR1[1] = 0xFFFFFFFF;
        esmREG->SR1[2] = 0xFFFFFFFF;
        esmREG->EKR = 0x0A;
        esmREG->EKR = 0x00;
        esmREG->EKR = 0x05;
        esmREG->EKR = 0x00;
    
    
        sciInit();
    
        //gioInit();
        //gioSetDirection(gioPORTA, 0x01);
    
        _enable_IRQ_interrupt_();
    
        /* - initializing mibspi - enabling tg 0 , length 127 (halcogen file)*/
        mibspiInit();
    
        mibspiEnableGroupNotification(mibspiREG3, 0, 1);
        mibspiREG1->TICKCNT = (0 << 31) | (0<<28) | (0x100);
    
        //mibspiEnableLoopback(mibspiREG1, Digital_Lbk);
        mibspiREG1->TGCTRL[0U] = (uint32)((uint32)1U << 30U)  /* oneshot */
                               | (uint32)((uint32)0U << 29U)  /* pcurrent reset */
                               | (uint32)((uint32)TRG_ALWAYS<< 20U)  /* trigger event */
                               | (uint32)((uint32)TRG_DISABLED << 16U)  /* trigger source */
                               | (uint32)((uint32)0U << 8U);  /* start buffer */
    
        mibspiREG1->TGCTRL[1U] = (uint32)((uint32)1U << 30U)  /* oneshot */
                               | (uint32)((uint32)0U << 29U)  /* pcurrent reset */
                               | (uint32)((uint32)TRG_ALWAYS << 20U)  /* trigger event */
                               | (uint32)((uint32)TRG_DISABLED << 16U)  /* trigger source */
                               | (uint32)((uint32)4U << 8U);  /* start buffer */
    
    
    /*MibSPI1 TG0*/
        for (i=0; i<3; i++)
        {
            mibspiRAM1->tx[i].control = (uint16)((uint16)5U << 13U)  /* buffer mode */
                                      | (uint16)((uint16)1U << 12U)  /* chip select hold */
                                      | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                      | (uint16)((uint16)0U << 11U)  /* lock transmission */
                                      | (uint16)((uint16)0U << 8U)  /* data format */
                                      | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
        }
        mibspiRAM1->tx[3].control = (uint16)((uint16)5U << 13U)  /* buffer mode */
                                  | (uint16)((uint16)0U << 12U) /* chip select hold */
                                  | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                  | (uint16)((uint16)0U << 8U)  /* data format */
                                  | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
    
    /*MibSPI1 TG1*/
            for (i=4; i<7; i++)
            {
                mibspiRAM1->tx[i].control = (uint16)((uint16)5U << 13U)  /* buffer mode */
                                          | (uint16)((uint16)1U << 12U)  /* chip select hold */
                                          | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                          | (uint16)((uint16)0U << 11U)  /* lock transmission */
                                          | (uint16)((uint16)0U << 8U)  /* data format */
                                          | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
            }
            mibspiRAM1->tx[7].control = (uint16)((uint16)5U << 13U)  /* buffer mode */
                                      | (uint16)((uint16)0U << 12U) /* chip select hold */
                                      | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                      | (uint16)((uint16)0U << 8U)  /* data format */
                                      | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
    
    
    
        /** - initialize transfer groups */
        mibspiREG3->TGCTRL[0U] = (uint32)((uint32)1U << 30U)  /* oneshot */
                               | (uint32)((uint32)0U << 29U)  /* pcurrent reset */
                               | (uint32)((uint32)TRG_ALWAYS << 20U)  /* trigger event */
                               | (uint32)((uint32)TRG_DISABLED << 16U)  /* trigger source */
                               | (uint32)((uint32)0U << 8U);  /* start buffer */
        /** - initialize transfer groups */
        mibspiREG3->TGCTRL[1U] = (uint32)((uint32)1U << 30U)  /* oneshot */
                               | (uint32)((uint32)0U << 29U)  /* pcurrent reset */
                               | (uint32)((uint32)TRG_ALWAYS << 20U)  /* trigger event */
                               | (uint32)((uint32)TRG_DISABLED << 16U)  /* trigger source */
                               | (uint32)((uint32)4U << 8U);  /* start buffer */
    //MibSPI3 Transfer Group 0
        for(i=0; i<3; i++)
        {
            mibspiRAM3->tx[i].control = (uint16)((uint16)6U << 13U)  /* buffer mode */
                                      | (uint16)((uint16)1U << 12U)  /* chip select hold */
                                      | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                      | (uint16)((uint16)0U << 11U)  /* lock transmission */
                                      | (uint16)((uint16)0U << 8U)  /* data format */
                                      | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
        }
        mibspiRAM3->tx[3].control = (uint16)((uint16)6U << 13U)  /* buffer mode */
                                  | (uint16)((uint16)0U << 12U) /* chip select hold */
                                  | (uint16)((uint16)0U << 10U)  /* enable WDELAY */
                                  | (uint16)((uint16)0U << 8U)  /* data format */
                                  | ((uint16)(~((uint16)0xFFU ^ (uint16)CS_0)) & (uint16)0x00FFU);  /* chip select */
    
        /* TG start address. PSTARTx stores the start address of the corresponding TG. The corresponding */
        /* end address is inherently defined by the subsequent TG start address minus 1 (PENDx[TGx] =    */
        /* PSTARTx[TGx+1]-1). PSTARTx is copied into PCURRENTx when:*/
        for(i=0; i<8; i++){
            tgPSTART1[i] = (mibspiREG1->TGCTRL[i] >> 8) & 0xFF;
            tgPSTART3[i] = (mibspiREG3->TGCTRL[i] >> 8) & 0xFF;
        }
    
        /*MibSPI1 TG0, DMA config*/
        /* - creating a data chunk in system ram to start with ... */
        /* TXDATA_TG10 ->MibSPI1 TG0 */
        loadDataPattern(D_SIZE, &TXDATA_TG10[0], 0x5A00);
    
        dmaConfigCtrlTxPacket((uint32)TXDATA_TG10, (uint32)&(mibspiRAM1->tx[tgPSTART1[0]].data), E_COUNT, F_COUNT);
        dmaConfigCtrlRxPacket((uint32)&(mibspiRAM1->rx[tgPSTART1[0]].data), (uint32)RXDATA_TG10, E_COUNT, F_COUNT);
        //using DAM_CH0 for RX, DMA_CH1 for TX
        /* - setting dma control packets */
        dmaSetCtrlPacket(DMA_CH1,g_dmaCTRLPKT_TX);  //tx
        dmaSetCtrlPacket(DMA_CH0,g_dmaCTRLPKT_RX);  //rx
    
        /* - setting the dma channel to trigger on h/w request */
        dmaSetChEnable(DMA_CH1, DMA_HW);
        dmaSetChEnable(DMA_CH0, DMA_HW);
    
        dmaReqAssign(DMA_CH1, DMA_REQ1); //DMA request line 1, TX
        dmaReqAssign(DMA_CH0, DMA_REQ0); //DMA request line 0, RX
    
        /* - configuring the mibspi dma , channel 0 , tx line -0 , rxline -1     */
        /* - refer to the device data sheet dma request source for mibspi tx/rx  */
        mibspiDmaConfig(mibspiREG1,0,0,1);   //RX_DMA_Line=1, TX_DMA_Line=0
    
        /*NOBRKx */
        //mibspiREG1->DMACTRL[0] |=  (1 << 13);
    
        /* Enable Block Transfer Complete interrupt for the receive after transfer complete */
        dmaEnableInterrupt(DMA_CH0, BTC, DMA_INTA);
    
    #if 0
        /* MibSPI TG1, DMA*/
        //using DAM_CH6 for RX, DMA_CH8 for TX
        /* - creating a data chunk in system ram to start with ... */
        loadDataPattern(D_SIZE, &TXDATA_TG11[0], 0x6B00);
    
        dmaConfigCtrlTxPacket((uint32)TXDATA_TG11, (uint32)&(mibspiRAM1->tx[tgPSTART1[1]].data), E_COUNT, F_COUNT);
        dmaConfigCtrlRxPacket((uint32)&(mibspiRAM1->rx[tgPSTART1[1]].data), (uint32)RXDATA_TG11, E_COUNT, F_COUNT);
        /* - setting dma control packets */
        dmaSetCtrlPacket(DMA_CH7,g_dmaCTRLPKT_TX);  //tx
        dmaSetCtrlPacket(DMA_CH4,g_dmaCTRLPKT_RX);  //rx
    
         /* - setting the dma channel to trigger on h/w request */
        dmaSetChEnable(DMA_CH7, DMA_HW);
        dmaSetChEnable(DMA_CH4, DMA_HW);
    
        dmaReqAssign(DMA_CH7, DMA_REQ16);   //DMA request line 16  -- TX   (last col, Table 6-41)
        dmaReqAssign(DMA_CH4, DMA_REQ22);   //DMA request line 22  -- RX   (last col, Table 6-41)
    
        /* - configuring the mibspi dma , channel 2, MibSPI TX Line -8 , MibSPI RX Line - 10    */
        /* MibSPI TX Line and MibSPI RX Line are in the parentheses following MibSPI1  */
        mibspiDmaConfig(mibspiREG1,1,8,10);
    
        /* Enable Block Transfer Complete interrupt for the receive after transfer complete */
        dmaEnableInterrupt(DMA_CH4, BTC, DMA_INTA);
    #endif
    
        /* MibSPI3, Slave, TG0, DMA*/
        //using DAM_CH6 for RX, DMA_CH8 for TX
        /* - creating a data chunk in system ram to start with ... */
        /* TXDATA_TG30 --> MibSPI3, TG0*/
        loadDataPattern(D_SIZE, &TXDATA_TG30[0], 0x3A00);
    
        dmaConfigCtrlTxPacket((uint32)TXDATA_TG30, (uint32)&(mibspiRAM3->tx[tgPSTART3[0]].data), E_COUNT, F_COUNT);
          //TG0
        dmaConfigCtrlRxPacket((uint32)&(mibspiRAM3->rx[tgPSTART3[0]].data), (uint32)RXDATA_TG30, E_COUNT, F_COUNT);
        /* - setting dma control packets */
        dmaSetCtrlPacket(DMA_CH9,g_dmaCTRLPKT_TX);  //tx
        dmaSetCtrlPacket(DMA_CH8,g_dmaCTRLPKT_RX);  //rx
    
         /* - setting the dma channel to trigger on h/w request */
        dmaSetChEnable(DMA_CH9, DMA_HW);
        dmaSetChEnable(DMA_CH8, DMA_HW);
    
        dmaReqAssign(DMA_CH9, DMA_REQ4);   //DMA request line 4  -- TX   (last col, Table 6-41)
        dmaReqAssign(DMA_CH8, DMA_REQ5);   //DMA request line 5  -- RX   (last col, Table 6-41)
    
        /* - configuring the mibspi dma , channel 2, MibSPI TX Line -2 , MibSPI RX Line - 3    */
        /* MibSPI TX Line and MibSPI RX Line are in the parentheses following MibSPI1  */
        /* MibSPI3 transfer group 0*/
        mibspiDmaConfig(mibspiREG3,0,2,3);
    
        /* Enable Block Transfer Complete interrupt for the receive after transfer complete */
        dmaEnableInterrupt(DMA_CH8, BTC, DMA_INTA);
    
        dmaEnable();
    
        /* - start the mibspi transfer tg 0 */
        mibspiTransfer(mibspiREG3, 0);
        mibspiTransfer(mibspiREG1, 0);
    
        while(1);
      /* USER CODE END */
    
        return 0;
    }
    
    
    /* USER CODE BEGIN (4) */
    /** configuring mibspi dma with
    *
    *       channel   > mibspi dma channel number
    *       txchannel > transmit channel dedicated for mibspi
    *       rxchannel > receive  channel dedicated for mibspi
    */
    void mibspiDmaConfig(mibspiBASE_t *mibspi,uint32 channel, uint32 txchannel, uint32 rxchannel)
    {
        uint32 bufid;
        //uint32 bufid  = (channel + 1) * E_COUNT - 1;
    
        if (mibspi == mibspiREG1){
             bufid  = tgPSTART1[channel] + E_COUNT - 1;
        }else{
             bufid  = tgPSTART3[channel] + E_COUNT - 1;
        }
    
    
        /* setting transmit and receive channels */
        mibspi->DMACTRL[channel] |= (rxchannel << 20) | (txchannel << 16);
    
        if (F_COUNT > 1) {
             mibspi->TGCTRL[channel] &= 0xBFFFFFFF; // Disable ONESHOT
        } else {
             mibspi->TGCTRL[channel] |= 0x40000000; // Enable ONESHOT
        }
    
        /* enabling transmit and receive dma */
        mibspi->DMACTRL[channel] |=  0x8000C000;
    
        /* setting Initial Count of DMA transfers and the buffer utilized for DMA transfer */
        mibspi->DMACTRL[channel] |=  (bufid<<24);
    
        /* Enable Large count transfer */
        mibspi->DMACNTLEN = 0x1;
        mibspi->DMACOUNT[channel] = (F_COUNT - 1) << 16;
    
    }
    
    
    
    void loadDataPattern(uint32 psize, uint16* pptr, uint16 pattern)
    {
        int i;
        for(i=0;i<psize;i++)
        {
            *(pptr++) = 0x5A5A;  //pattern + i;
        }
     }
    
    
    void dmaConfigCtrlTxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
    {
          g_dmaCTRLPKT_TX.SADD       = sadd;              /* source address             */
          g_dmaCTRLPKT_TX.DADD       = dadd;           /* destination  address       */
          g_dmaCTRLPKT_TX.CHCTRL     = 0;                 /* channel control            */
          g_dmaCTRLPKT_TX.FRCNT      = FrameCnt ;                 /* frame count                */
          g_dmaCTRLPKT_TX.ELCNT      = ElmntCnt;             /* element count              */
          g_dmaCTRLPKT_TX.ELDOFFSET  = 4;                 /* element destination offset */
          g_dmaCTRLPKT_TX.ELSOFFSET  = 0;             /* element destination offset */
          g_dmaCTRLPKT_TX.FRDOFFSET  = 0;                  /* frame destination offset   */
          g_dmaCTRLPKT_TX.FRSOFFSET  = 0;                 /* frame destination offset   */
          g_dmaCTRLPKT_TX.PORTASGN   = PORTA_READ_PORTB_WRITE;                 /* port b                     */
          g_dmaCTRLPKT_TX.RDSIZE     = ACCESS_16_BIT;     /* read size                  */
          g_dmaCTRLPKT_TX.WRSIZE     = ACCESS_16_BIT;      /* write size                 */
          g_dmaCTRLPKT_TX.TTYPE      = FRAME_TRANSFER ;   /* transfer type              */
          g_dmaCTRLPKT_TX.ADDMODERD  = ADDR_INC1;         /* address mode read          */
          g_dmaCTRLPKT_TX.ADDMODEWR  = ADDR_OFFSET;       /* address mode write         */
          g_dmaCTRLPKT_TX.AUTOINIT   = AUTOINIT_OFF;       /* autoinit                   */
    
          //return g_dmaCTRLPKT_TX;
    }
    
    
    void dmaConfigCtrlRxPacket(uint32 sadd, uint32 dadd, uint16 ElmntCnt, uint16 FrameCnt)
    {
          g_dmaCTRLPKT_RX.SADD       = sadd;              /* source address             */
          g_dmaCTRLPKT_RX.DADD       = dadd;           /* destination  address       */
          g_dmaCTRLPKT_RX.CHCTRL     = 0;                 /* channel control            */
          g_dmaCTRLPKT_RX.FRCNT      = FrameCnt;                 /* frame count                */
          g_dmaCTRLPKT_RX.ELCNT      = ElmntCnt;             /* element count              */
          g_dmaCTRLPKT_RX.ELDOFFSET  = 0;                 /* element destination offset */
          g_dmaCTRLPKT_RX.ELSOFFSET  = 4;                 /* element source offset */
          g_dmaCTRLPKT_RX.FRDOFFSET  = 0;                  /* frame destination offset   */
          g_dmaCTRLPKT_RX.FRSOFFSET  = 0;                 /* frame destination offset   */
          g_dmaCTRLPKT_RX.PORTASGN   = PORTB_READ_PORTA_WRITE;   /* port b                     */
          g_dmaCTRLPKT_RX.RDSIZE     = ACCESS_16_BIT;      /* read size                  */
          g_dmaCTRLPKT_RX.WRSIZE     = ACCESS_16_BIT;      /* write size                 */
          g_dmaCTRLPKT_RX.TTYPE      = FRAME_TRANSFER ;   /* transfer type              */
          g_dmaCTRLPKT_RX.ADDMODERD  = ADDR_OFFSET;         /* address mode read          */
          g_dmaCTRLPKT_RX.ADDMODEWR  = ADDR_INC1;       /* address mode write         */
          g_dmaCTRLPKT_RX.AUTOINIT   = AUTOINIT_OFF;       /* autoinit                   */
    
          //return g_dmaCTRLPKT_RX;
    }
    
    
    /* USER CODE END */