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.

TMS320F28377S: SPI-B is not working with DMA

Part Number: TMS320F28377S
Other Parts Discussed in Thread: CONTROLSUITE

Hello,

I am having issue, SPI-B is not working along with DMA. I have copied spi_loopback_dma_cpu01 from ControlSUITE example which is for SPI-A and make changes as following but I am not getting any signal out.

I have just replaced all spia with spib and change GPIOs accordingly. I have tried to troubleshoot but not able to get what is missing. Please help.

//###########################################################################
// FILE: Example_2837xS_Spi_dma.c
// TITLE: SPI Digital Loop Back with DMA Example.
//
//! \addtogroup cpu01_example_list
//! <h1>SPI Digital Loop Back with DMA (spi_loopback_dma)</h1>
//!
//! This program uses the internal loop back test mode of the peripheral.
//! Other then boot mode pin configuration, no other hardware configuration
//! is required. Both DMA Interrupts and the SPI FIFOs are used.
//!
//! A stream of data is sent and then compared to the received stream.
//! The sent data looks like this: \n
//! 0000 0001 \n
//! 0001 0002 \n
//! 0002 0003 \n
//! .... \n
//! 007E 007F \n
//!
//! \b Watch \b Variables \n
//! - \b sdata - Data to send
//! - \b rdata - Received data
//! - \b rdata_point - Used to keep track of the last position in
//! the receive stream for error checking
//
//###########################################################################
// $TI Release: F2837xS Support Library v190 $
// $Release Date: Mon Feb 1 16:59:09 CST 2016 $
// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
// http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

#include "F28x_Project.h" // Device Headerfile and Examples Include File
#include "spi.h"

// Prototype statements for functions found within this file.
__interrupt void local_D_INTCH5_ISR(void);
__interrupt void local_D_INTCH6_ISR(void);

void delay_loop(void);
void dma_init(void);
void spi_fifo_init(void);
void error();
void SPI_delay_us(long i);
void InitSpibGpio(void);

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

volatile Uint16 *DMADest;
volatile Uint16 *DMASource;

#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

volatile Uint16 done;


void main(void)
{
Uint16 i;

// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xS_SysCtrl.c file.
InitSysCtrl();

// Step 2. Initialize GPIO:
// This example function is found in the F2837xS_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for this example
// Setup only the GP I/O only for SPI-A functionality
InitSpibGpio();

// Step 3. Initialize PIE vector table:
// Disable and clear all CPU interrupts
DINT;
IER = 0x0000;
IFR = 0x0000;

// Initialize PIE control registers to their default state:
// This function is found in the F2837xS_PieCtrl.c file.
InitPieCtrl();

// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xS_DefaultIsr.c.
// This function is found in F2837xS_PieVect.c.
InitPieVectTable();

// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.DMA_CH5_INT= &local_D_INTCH5_ISR;
PieVectTable.DMA_CH6_INT= &local_D_INTCH6_ISR;
EDIS; // This is needed to disable write to EALLOW protected registers

// Step 4. Initialize the Device Peripherals:
dma_init(); // set up dma for SPI configuration
spi_fifo_init(); // Initialize the SPI only

// Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)
EALLOW;
CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
EDIS;


// Step 5. User specific code, enable interrupts:

// Initialize the data buffers
for(i=0; i<128; i++)
{
sdata[i] = i;
rdata[i]= 0;
}
rdata_point = 0;

// Enable interrupts required for this example
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block
PieCtrlRegs.PIEIER7.bit.INTx5 = 1; // Enable PIE Group 7, INT 1 (DMA CH1)
PieCtrlRegs.PIEIER7.bit.INTx6 = 1; // Enable PIE Group 7, INT 2 (DMA CH2)
IER= M_INT7; // Enable CPU INT6
EINT; // Enable Global Interrupts

StartDMACH6(); // Start SPI RX DMA channel
StartDMACH5(); // Start SPI TX DMA channel

done = 0; // Test is not done yet

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

// when the DMA transfer is complete the program will stop here
ESTOP0;

}
/*
// Some Useful local functions
void delay_loop()
{
long i;
for (i = 0; i < 1000000; i++) {}
}
*/
void error(void)
{
asm(" ESTOP0"); //Test failed!! Stop!
for (;;);
}

void spi_fifo_init()
{
int m;

// FIFO configuration
SpibRegs.SPIFFCT.all=0x0; // place SPI in reset
for(m=0;m<3;m++);
SpibRegs.SPIFFRX.all=0x2040; // RX FIFO enabled, clear FIFO int
SpibRegs.SPIFFRX.bit.RXFFIL = FIFO_LVL; // Set RX FIFO level
SpibRegs.SPIFFTX.all=0xE040; // FIFOs enabled, TX FIFO released,
SpibRegs.SPIFFTX.bit.TXFFIL = FIFO_LVL; // Set TX FIFO level

// SPI configuration
SpibRegs.SPICCR.all = 0x000F ; // SPI in reset, POL=0, 16bit words
SpibRegs.SPICTL.all = 0x0006 ; // TX enable, Master
SpibRegs.SPIBRR.all = 0x63; // LSPCLK/100
SpibRegs.SPICCR.all = 0x008F ; // Release SPI from Reset, enable LB mode
}

// DMA setup for both TX and RX channels.
void dma_init()
{
// refer to dma.c for the descriptions of the following functions.

//Initialize DMA
DMAInitialize();

DMASource = (volatile Uint16 *)sdata;
DMADest = (volatile Uint16 *)rdata;

// configure DMACH5 for TX
DMACH5AddrConfig(&SpibRegs.SPITXBUF,DMASource);
DMACH5BurstConfig(BURST,1,0); // Burst size, src step, dest step
DMACH5TransferConfig(TRANSFER,1,0); // transfer size, src step, dest step
DMACH5ModeConfig(DMA_SPIBTX,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE
,SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);

// configure DMA CH2 for RX
DMACH6AddrConfig(DMADest,&SpibRegs.SPIRXBUF);
DMACH6BurstConfig(BURST,0,1);
DMACH6TransferConfig(TRANSFER,0,1);
DMACH6ModeConfig(DMA_SPIBRX,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,
SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);

}


// INT7.1
__interrupt void local_D_INTCH5_ISR(void) // DMA Ch5
{
EALLOW; // NEED TO EXECUTE EALLOW INSIDE ISR !!!
DmaRegs.CH5.CONTROL.bit.HALT=1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // ACK to receive more interrupts from this PIE group
EDIS;
return;
}


// INT7.2
__interrupt void local_D_INTCH6_ISR(void) // DMA Ch6
{
Uint16 i;
EALLOW; // NEED TO EXECUTE EALLOW INSIDE ISR !!!
DmaRegs.CH6.CONTROL.bit.HALT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // ACK to receive more interrupts from this PIE group
EDIS;

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

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

//
// InitSpibGpio - Initialize SPIB GPIOs
//
void InitSpibGpio(void)
{
EALLOW;

GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0; // Enable pull-up on GPIO16 (SPISIMOA)
// GpioCtrlRegs.GPAPUD.bit.GPIO5 = 0; // Enable pull-up on GPIO5 (SPISIMOA)
GpioCtrlRegs.GPCPUD.bit.GPIO64 = 0; // Enable pull-up on GPIO17 (SPISOMIA)
// GpioCtrlRegs.GPAPUD.bit.GPIO3 = 0; // Enable pull-up on GPIO3 (SPISOMIA)
GpioCtrlRegs.GPCPUD.bit.GPIO65 = 0; // Enable pull-up on GPIO18 (SPICLKA)
GpioCtrlRegs.GPCPUD.bit.GPIO66 = 0; // Enable pull-up on GPIO19 (SPISTEA)

/* Set qualification for selected pins to asynch only */
// This will select asynch (no qualification) for the selected pins.
// Comment out other unwanted lines.

GpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 3; // Asynch input GPIO16 (SPISIMOA)
// GpioCtrlRegs.GPAQSEL1.bit.GPIO5 = 3; // Asynch input GPIO5 (SPISIMOA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 3; // Asynch input GPIO17 (SPISOMIA)
// GpioCtrlRegs.GPAQSEL1.bit.GPIO3 = 3; // Asynch input GPIO3 (SPISOMIA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO65 = 3; // Asynch input GPIO18 (SPICLKA)
GpioCtrlRegs.GPCQSEL1.bit.GPIO66 = 3; // Asynch input GPIO19 (SPISTEA)

/* Configure SPI-A pins using GPIO regs*/
// This specifies which of the possible GPIO pins will be SPI functional pins.
// Comment out other unwanted lines.

GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 1; // Configure GPIO16 as SPISIMOA
// GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 2; // Configure GPIO5 as SPISIMOA
GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 1; // Configure GPIO17 as SPISOMIA
// GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 2; // Configure GPIO3 as SPISOMIA
GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 1; // Configure GPIO18 as SPICLKA
GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 1; // Configure GPIO19 as SPISTEA

EDIS;
}

void SPI_delay_us(long i)
{
i = i * 12;

while(i>0)
{
i--;
}
}

Thank you,

Jaydeep

  • Hi Jaydeep,

    I suspect your GPIO configuration is wrong. According to the data sheet, to use pins 63-66 as SPIB pins, you need to set both the MUX and GMUX registers to 3. You're currently writing the wrong values to the MUX registers and not writing to the GMUX registers at all.

    Whitney

  • Hi Whitney,

    Thank you very much for your advice. My issue has been resolved. Now my updated configuration is as per following...

    //
    // InitSpibGpio - Initialize SPIB GPIOs
    //
    void InitSpibGpio(void)
    {
             EALLOW;

    /* Enable internal pull-up for the selected pins */
    // Pull-ups can be enabled or disabled by the user.
    // This will enable the pullups for the specified pins.
    // Comment out other unwanted lines.

    GpioCtrlRegs.GPBPUD.bit.GPIO63 = 0; // Enable pull-up on GPIO63 (SPISIMOB)
    GpioCtrlRegs.GPCPUD.bit.GPIO64 = 0; // Enable pull-up on GPIO64 (SPISOMIA)
    GpioCtrlRegs.GPCPUD.bit.GPIO65 = 0; // Enable pull-up on GPIO65 (SPICLKA)
    GpioCtrlRegs.GPCPUD.bit.GPIO66 = 0; // Enable pull-up on GPIO66 (SPISTEA)

    /* Set qualification for selected pins to asynch only */
    // This will select asynch (no qualification) for the selected pins.
    // Comment out other unwanted lines.

    GpioCtrlRegs.GPBQSEL2.bit.GPIO63 = 3; // Asynch input GPIO63 (SPISIMOA)
    GpioCtrlRegs.GPCQSEL1.bit.GPIO64 = 3; // Asynch input GPIO64 (SPISOMIA)
    GpioCtrlRegs.GPCQSEL1.bit.GPIO65 = 3; // Asynch input GPIO65 (SPICLKA)
    GpioCtrlRegs.GPCQSEL1.bit.GPIO66 = 3; // Asynch input GPIO66 (SPISTEA)

    /* Configure SPI-B pins using GPIO regs*/
    // This specifies which of the possible GPIO pins will be SPI functional pins.
    // Comment out other unwanted lines.

    GpioCtrlRegs.GPBMUX2.bit.GPIO63 = 3; // Configure GPIO63 as SPISIMOA
    GpioCtrlRegs.GPCMUX1.bit.GPIO64 = 3; // Configure GPIO64 as SPISOMIA
    GpioCtrlRegs.GPCMUX1.bit.GPIO65 = 3; // Configure GPIO65 as SPICLKA
    GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 3; // Configure GPIO66 as SPISTEA

    GpioCtrlRegs.GPBGMUX2.bit.GPIO63 = 3;
    GpioCtrlRegs.GPCGMUX1.bit.GPIO64 = 3;
    GpioCtrlRegs.GPCGMUX1.bit.GPIO65 = 3;
    GpioCtrlRegs.GPCGMUX1.bit.GPIO66 = 3;

    EDIS;

    }

    Regards

    Jaydeep

  • Glad that took care of it. I will mention that we recommend that you configure the GMUX registers before the MUX registers to avoid transient pulses from an intermediate mux selection, but other than that, it looks good.

    Whitney