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.

TMS320F28377D: How to setup spi dma?

Part Number: TMS320F28377D


Hello,
I need to know how to setup SPI DMA. I have setup plain SPI with interrupts successfully but I am not able to do that with DMA.  I am not sure what mistake I am doing. Below is the source if you can help I would really appreciate it.

I am trying to trigger DMA channel 1 for Tx of SPIA Tx which is master. I am not sure what am I missing. My goal is to go into DMA_ISR. Just some dummy data Tx, not loopback though. I would do receive Rx later.

Thanks in Advance!

Regards

Varun

#ifndef DMA_INIT_C
#define DMA_INIT_C

/* Header Files includes */
#include "driverlib.h"
#include "device.h"
#include "dma_init.h"
#include "dma.h"

//
// Defines
//
#define BURST         (FIFO_LVL-1)    // burst size should be less than 8
#define TRANSFER      15              // [(MEM_BUFFER_SIZE/FIFO_LVL)-1]
#define FIFO_LVL      8               // FIFO Interrupt Level

//
// Globals
//
#pragma DATA_SECTION(sdata, "ramgs0");    // map the TX data to memory
#pragma DATA_SECTION(rdata, "ramgs1");    // map the RX data to memory
uint16_t sdata[128];     // Send data buffer
uint16_t rdata[128];     // Receive data buffer
uint16_t rdata_point;    // Keep track of where we are
                       // in the data stream to check received data

volatile uint16_t *DMADest;
volatile uint16_t *DMASource;
volatile uint16_t done;

void Init_DMA()
{
    uint16_t i;
    
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    Interrupt_register(INT_DMA_CH1, &DMACh1ISR);
    Interrupt_register(INT_DMA_CH2, &DMACh2ISR);
    
    //! Initializes the DMA controller to a known state.
    DMA_initController();
    
    //Sets DMA emulation mode.
    DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);
    
    //Configure DMA settings for SPITX.
    Set_DMA_Config_TX();
    
    //Configure DMA settings for SPITX.
    Set_DMA_Config_RX();
    //
    // Initialize the data buffers
    //
    for(i=0; i<128; i++)
    {
        sdata[i] = i;
        rdata[i]= 0;
    }
    rdata_point = 0;
    
    Interrupt_enable(INT_DMA_CH1);              // Enable PIE Group 7, INT 1 (DMA CH1)
    Interrupt_enable(INT_DMA_CH2);              // Enable PIE Group 7, INT 2 (DMA CH2)
    Interrupt_enableInCPU(INTERRUPT_CPU_INT6);  // Enable CPU INT6

    //! Starts a DMA channel.    
    DMA_startChannel(DMA_CH2_BASE);      // Start SPI RX DMA channel
    
    DMA_startChannel(DMA_CH1_BASE);      // Start SPI TX DMA channel
    
    done = 0;                            // Test is not done yet

    //while(!done);                        // wait until the DMA transfer is complete
}

void Set_DMA_Config_TX()
{
    DMASource = (volatile uint16_t *)sdata;
    
    // configure DMACH1 for TX
    //! Configures the DMA channel
    DMA_configAddresses(DMA_CH1_BASE, (SPIA_BASE+SPI_O_TXBUF), DMASource);
    
    //! Configures the DMA channel's burst settings.
    DMA_configBurst(DMA_CH1_BASE, BURST, 0x0001, 0x0000);
    
    //! Configures the DMA channel's transfer settings.
    DMA_configTransfer(DMA_CH1_BASE, TRANSFER, 0x0001, 0x0000);
    
    //! Disables the DMA channel overrun interrupt.
    DMA_disableOverrunInterrupt(DMA_CH1_BASE);
    
    //! Configures the DMA channel trigger and mode.
    DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_SPIATX, DMA_CFG_SIZE_16BIT);
    
    //! Enables a DMA channel interrupt source.
    DMA_enableInterrupt(DMA_CH1_BASE);
    
    //! Sets the interrupt generation mode of a DMA channel interrupt.
    DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_BEGINNING); /* DMA interrupt is generated at the end of a transfer */
    
    //! Clears a DMA channel's peripheral trigger flag.
    DMA_clearTriggerFlag(DMA_CH1_BASE);
    
    //! Clears the DMA channel error flags.
    DMA_clearErrorFlag(DMA_CH1_BASE);    
    
}


void Set_DMA_Config_RX()
{
    DMADest = (volatile uint16_t *)rdata;
    
    // configure DMACH2 for RX
    //! Configures the DMA channel
    DMA_configAddresses(DMA_CH2_BASE, DMADest, (SPIA_BASE+SPI_O_RXBUF));
    
    //! Configures the DMA channel's burst settings.
    DMA_configBurst(DMA_CH2_BASE, BURST, 0x0000, 0x0001);
    
    //! Configures the DMA channel's transfer settings.
    DMA_configTransfer(DMA_CH2_BASE, TRANSFER, 0x0000, 0x0001);
    
    //! Disables the DMA channel overrun interrupt.
    DMA_disableOverrunInterrupt(DMA_CH2_BASE);
    
    //! Configures the DMA channel trigger and mode.
    DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_SPIARX, DMA_CFG_SIZE_16BIT);

    //! Enables a DMA channel interrupt source.
    DMA_enableInterrupt(DMA_CH2_BASE);
    
    //! Sets the interrupt generation mode of a DMA channel interrupt.
    DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_BEGINNING); /* DMA interrupt is generated at the end of a transfer */
    
    //! Clears a DMA channel's peripheral trigger flag.
    DMA_clearTriggerFlag(DMA_CH2_BASE);
    
    //! Clears the DMA channel error flags.
    DMA_clearErrorFlag(DMA_CH2_BASE);
        
}


//
// INTCH1_ISR - DMA Channel 1 ISR
//
__interrupt void DMACh1ISR(void)
{
    //! Halts a DMA channel.
    DMA_stopChannel(DMA_CH1_BASE);
    
    //! Acknowledges PIE Interrupt Group
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}

//
// INTCH2_ISR - DMA Channel 2 ISR
//
__interrupt void DMACh2ISR(void)
{
    uint16_t i;

    //! Halts a DMA channel.
    DMA_stopChannel(DMA_CH2_BASE);
    
    //! Acknowledges PIE Interrupt Group
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);

    for( i = 0; i<128; i++ )
    {
        //
        // check for data integrity
        //
        if(rdata[i] != i)
        {
            error();
        }
    }

    done = 1;  // test done.
    return;
}

//
// error - Halt debugger when error received
//
void error(void)
{
   asm("     ESTOP0");  //Test failed!! Stop!
   for (;;);
}

#endif /* #ifndef DMA_INIT_C */
#ifndef SPI_INIT_C
#define SPI_INIT_C


//
// Included Files
//
#include "spi_init.h"
#include "driverlib.h"
#include "device.h"

volatile uint16_t sData[8];         // Send data buffer
volatile uint16_t rData[8];         // Receive data buffer
volatile uint16_t rDataPoint = 0;   // To keep track of where we are in the
                                    // data stream to check received data
uint16_t TG1_TX_DATA[8] = {0x0F00, 0x0F01, 0x0F02, 0x0F03, 0x0F04, 0x0F05, 0x0F06, 0x0F07};
spi_config config_spi_channelA={ SPIA_BASE,
                                 DEVICE_LSPCLK_FREQ,
                                 SPI_PROT_POL0PHA0,
                                 SPI_MODE_MASTER,
                                 500000,
                                 16,
                                 SPI_FIFO_TX8,
                                 SPI_FIFO_RX8,
                                 SPI_EMULATION_FREE_RUN,

};

spi_config config_spi_channelB={ SPIB_BASE,
                                 DEVICE_LSPCLK_FREQ,
                                 SPI_PROT_POL0PHA0,
                                 SPI_MODE_SLAVE,
                                 500000,
                                 16,
                                 SPI_FIFO_TX2,
                                 SPI_FIFO_RX2,
                                 SPI_EMULATION_FREE_RUN,

};

void setup_spi()
{
    //
    // Must put SPI into reset before configuring it
    //

    uint16_t i;
    for(i = 0; i < 8; i++)
    {
        sData[i] = 0xAB;
        rData[i]= 0;
    }


    //SPIA Module Init Master//
    // SPI configuration. Use a 500kHz SPICLK and 16-bit word size.



    SPI_disableModule(SPIA_BASE);
    SPI_setConfig(config_spi_channelA.base, config_spi_channelA.lspclkHz, config_spi_channelA.protocol,config_spi_channelA.mode, config_spi_channelA.bitRate, config_spi_channelA.dataWidth);
    SPI_disableLoopback(SPIA_BASE);
    SPI_setEmulationMode(config_spi_channelA.base, config_spi_channelA.EmulationMode);
    //
    // FIFO and interrupt configuration
    //
    SPI_enableFIFO(config_spi_channelA.base);
    SPI_clearInterruptStatus(config_spi_channelA.base, SPI_INT_RXFF | SPI_INT_TXFF);
    SPI_setFIFOInterruptLevel(config_spi_channelA.base, config_spi_channelA.TxLevel, config_spi_channelA.RxLevel);
    SPI_disableInterrupt(config_spi_channelA.base, SPI_INT_RXFF);
    SPI_enableModule(config_spi_channelA.base); // Configuration complete. Enable the module.


     //SPI Module B as slave.
     //
     // SPI configuration. Use a 500kHz SPICLK and 16-bit word size.
     Interrupt_enable(INT_SPIB_TX);
     Interrupt_enable(INT_SPIB_RX);
     Interrupt_register(INT_SPIB_TX, &spiTxBFIFOISR);//todo
     Interrupt_register(INT_SPIB_RX, &spiRxBFIFOISR);//todo
     SPI_disableModule(config_spi_channelB.base);
     SPI_setConfig(config_spi_channelB.base, config_spi_channelB.lspclkHz, config_spi_channelB.protocol,config_spi_channelB.mode, config_spi_channelB.bitRate, config_spi_channelB.dataWidth);
     SPI_disableLoopback(SPIB_BASE);
     SPI_setEmulationMode(config_spi_channelB.base, config_spi_channelB.EmulationMode);

     //
     // FIFO and interrupt configuration
     //
     SPI_enableFIFO(config_spi_channelB.base);
     SPI_clearInterruptStatus(config_spi_channelB.base, SPI_INT_RXFF | SPI_INT_TXFF);
     SPI_setFIFOInterruptLevel(config_spi_channelB.base, config_spi_channelB.TxLevel, config_spi_channelB.RxLevel);
     SPI_disableInterrupt(config_spi_channelB.base, SPI_INT_RXFF);

     // Configuration complete. Enable the module.
      SPI_enableModule(config_spi_channelB.base);


}
// SPI A Transmit FIFO ISR
//
__interrupt void spiTxAFIFOISR(void)
{
    uint16_t i;

    //debug only #todo
    GPIO_writePin(31u,0);      /* temp debug only */
    DEVICE_DELAY_US(10000);    /* temp debug only */
    GPIO_writePin(31u,1);      /* temp debug only */
    DEVICE_DELAY_US(50000);    /* temp debug only */

    //
    // Send data
    //
    for(i = 0; i < 8; i++)
    {
       SPI_writeDataNonBlocking(SPIA_BASE, sData[i]);
    }

    //
    // Increment data for next cycle
    //
//    for(i = 0; i < 2; i++)
//    {
//       sData[i] = sData[i]<<1;
//    }

    //
    // Clear interrupt flag and issue ACK
    //
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_TXFF);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
}

//
// SPI A Receive FIFO ISR
//
 __interrupt void spiRxAFIFOISR(void)
{
    uint16_t i;

    //
    // Read data
    //
    for(i = 0; i < 2; i++)
    {
        rData[i] = SPI_readDataNonBlocking(SPIA_BASE);
    }

    //
    // Check received data
    //
    for(i = 0; i < 2; i++)
    {
        if(rData[i] != (rDataPoint + i))
        {
            // Something went wrong. rData doesn't contain expected data.
            //ESTOP0;
        }
    }

    rDataPoint++;

    //
    // Clear interrupt flag and issue ACK
    //
    SPI_clearInterruptStatus(SPIA_BASE, SPI_INT_RXFF);
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
}

 // SPI B Transmit FIFO ISR
 //
 __interrupt void spiTxBFIFOISR(void)
 {
     uint16_t i;

     //debug only #todo
     GPIO_writePin(31u,0);      /* temp debug only */
     DEVICE_DELAY_US(10000);    /* temp debug only */
     GPIO_writePin(31u,1);      /* temp debug only */
     DEVICE_DELAY_US(50000);    /* temp debug only */

     //
     // Send data
     //
     for(i = 0; i < 8; i++)
     {
        SPI_writeDataNonBlocking(SPIB_BASE, sData[0]);
     }

     //
     // Increment data for next cycle
     //
 //    for(i = 0; i < 2; i++)
 //    {
 //       sData[i] = sData[i]<<1;
 //    }

     //
     // Clear interrupt flag and issue ACK
     //
     SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_TXFF);
     Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
 }

 //
 // SPI B Receive FIFO ISR
 //
  __interrupt void spiRxBFIFOISR(void)
 {
     uint16_t i;

     //
     // Read data
     //
     for(i = 0; i < 2; i++)
     {
         rData[i] = SPI_readDataNonBlocking(SPIB_BASE);
     }

     //
     // Check received data
     //
     for(i = 0; i < 2; i++)
     {
         if(rData[i] != (rDataPoint + i))
         {
             // Something went wrong. rData doesn't contain expected data.
             //ESTOP0;
         }
     }

     rDataPoint++;

     //
     // Clear interrupt flag and issue ACK
     //
     SPI_clearInterruptStatus(SPIB_BASE, SPI_INT_RXFF);
     Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP6);
 }


#endif