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.

TMS320F28379D: SPI and DMA configurations from SysConfig tool not working.

Part Number: TMS320F28379D
Other Parts Discussed in Thread: SYSCONFIG, C2000WARE

I have configured SPIA as a slave device and want to use it with DMA for sending and receiving data.  All the settings have been done using the SysConfig tool (version 1.12.1). The C2000Ware version is 4.1.0.00. The following codes have been generated by SysConfig for SPI and DMA initializations:

SPI initialization code:

void SPI_init()
{
	
	//CM4_SPI initialization
	SPI_disableModule(CM4_SPI_BASE);
	SPI_setConfig(CM4_SPI_BASE, DEVICE_LSPCLK_FREQ, SPI_PROT_POL0PHA1,
				  SPI_MODE_SLAVE, 1000000, 16);
	SPI_enableFIFO(CM4_SPI_BASE);
	SPI_setFIFOInterruptLevel(CM4_SPI_BASE, SPI_FIFO_TX8, SPI_FIFO_RX8);
	SPI_clearInterruptStatus(CM4_SPI_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
	SPI_enableInterrupt(CM4_SPI_BASE, SPI_INT_RXFF | SPI_INT_TXFF);
	SPI_disableLoopback(CM4_SPI_BASE);
	SPI_setEmulationMode(CM4_SPI_BASE, SPI_EMULATION_FREE_RUN);
	SPI_enableModule(CM4_SPI_BASE);
}

DMA initialization code:

void DMA_init(){
    DMA_initController();
     
    //CM4_SPI_RX_DMA initialization
    DMA_setEmulationMode(DMA_EMULATION_STOP);
    DMA_configAddresses(CM4_SPI_RX_DMA_BASE, rx_Data, CM4_SPI_RX_DMA_ADDRESS);
    DMA_configBurst(CM4_SPI_RX_DMA_BASE, 8U, 0, 1);
    DMA_configTransfer(CM4_SPI_RX_DMA_BASE, 14U, 0, 1);
    DMA_configWrap(CM4_SPI_RX_DMA_BASE, 65535U, 0, 14U, 0);
    DMA_configMode(CM4_SPI_RX_DMA_BASE, CM4_SPI_RX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
    DMA_setInterruptMode(CM4_SPI_RX_DMA_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(CM4_SPI_RX_DMA_BASE);
    DMA_disableOverrunInterrupt(CM4_SPI_RX_DMA_BASE);
    DMA_enableTrigger(CM4_SPI_RX_DMA_BASE);
    DMA_startChannel(CM4_SPI_RX_DMA_BASE);
     
    //CM4_SPI_TX_DMA initialization
    DMA_setEmulationMode(DMA_EMULATION_STOP);
    DMA_configAddresses(CM4_SPI_TX_DMA_BASE, CM4_SPI_TX_DMA_ADDRESS, tx_Data);
    DMA_configBurst(CM4_SPI_TX_DMA_BASE, 8U, 1, 0);
    DMA_configTransfer(CM4_SPI_TX_DMA_BASE, 14U, 1, 0);
    DMA_configWrap(CM4_SPI_TX_DMA_BASE, 14U, 0, 65535U, 0);
    DMA_configMode(CM4_SPI_TX_DMA_BASE, CM4_SPI_TX_DMA_TRIGGER, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT);
    DMA_setInterruptMode(CM4_SPI_TX_DMA_BASE, DMA_INT_AT_END);
    DMA_disableInterrupt(CM4_SPI_TX_DMA_BASE);
    DMA_disableOverrunInterrupt(CM4_SPI_TX_DMA_BASE);
    DMA_enableTrigger(CM4_SPI_TX_DMA_BASE);
    DMA_startChannel(CM4_SPI_TX_DMA_BASE);
}

Basically I want to transfer 112 words to and from SPI buffers. The burst size is set to 8 and transfer size to 14 such that 14 X 8= 112 words transfer. The pointers rx_Data and tx_Data have been defined in my main.c file and are pointing to buffers rData and sData allocated in globally shared RAM. each 112 words in length. sData is initialize with values 0 through 111 whereas rData is all initialized to zeros. Following is the code segment for declaring the arrays:

//buffers for SPI and DMA transfer
// Send data buffer for DMA transmission
int16_t sData[NWORDS];
// Receive data buffer for DMA reception
int16_t rData[NWORDS];
// Place buffers in GSRAM so that DMA can access these
#pragma DATA_SECTION(sData, "GSRAM");
#pragma DATA_SECTION(rData, "GSRAM");
//pointers to receive buffers and transmit buffers
const void *rx_Data= rData;
const void *tx_Data= sData;

GSRAM section is defined in the linker command file to be residing in globally shared ram. Below is the linker command file for reference.

//CPU1 PROGRAM GSRAM is allocated to GS7 & GS8
#define CPU1_RAMGS_PROG_START       0x013000
#define CPU1_RAMGS_PROG_LENGTH      0x002000

//CPU1 DATA GSRAM is allocated from GS2 RAM to GS6 RAM
#define CPU1_RAMGS_DATA_START       0x00E000
#define CPU1_RAMGS_DATA_LENGTH      0x005000

//required for MemCfgRegs settings
#define RAMGS_START				   0x00000C

#ifdef CLA_BLOCK_INCLUDED
// Define a size for the CLA scratchpad area that will be used
// by the CLA compiler for local symbols and temps
// Also force references to the special symbols that mark the
// scratchpad are. 
CLA_SCRATCHPAD_SIZE = 0x100;
--undef_sym=__cla_scratchpad_end
--undef_sym=__cla_scratchpad_start
#endif //CLA_BLOCK_INCLUDED
MEMORY
{
PAGE 0 :
   /* BEGIN is used for the "boot to SARAM" bootloader mode   */
   BEGIN           	            : origin = 0x000000, length = 0x000002
   BEGIN_FLASH     	            : origin = 0x080000, length = 0x000002
   /*Defining CLA program and data memory*/
    #if (CPU_RAMLS_PROG_LENGTH > 0)
    RAMLS_PROG      	    : origin = CPU_RAMLS_PROG_START, length = CPU_RAMLS_PROG_LENGTH
    #endif //CPU_RAMLS_PROG_LENGTH
    RAMLS_CLA_PROG          : origin = CLA_RAMLS_PROG_START, length = CLA_RAMLS_PROG_LENGTH
    RAMLS_CLA_DATA          : origin = CLA_RAMLS_DATA_START, length = CLA_RAMLS_DATA_LENGTH

   
   /*Defining CPU1 program memory in GSRAM*/
    #if (CPU1_RAMGS_PROG_LENGTH > 0)
        RAMGS_PROG          : origin = CPU1_RAMGS_PROG_START, length = CPU1_RAMGS_PROG_LENGTH
    #endif //(CPU1_RAMGS_PROG_LENGTH > 0)


   RESET           	            : origin = 0x3FFFC0, length = 0x000002
   /* Flash sectors */
   FLASHA_N                : origin = 0x080002, length = 0x03FFFE	/* on-chip Flash 256 K Words */

PAGE 1 :

   BOOT_RSVD                : origin = 0x000002, length = 0x000120     /* Part of M0, BOOT rom will use this for stack */
   RAMM0M1           	    : origin = 0x000122, length = 0x0006DE
   RAMD0D1           	        : origin = 0x00B000, length = 0x001000

   RAMGS_DATA              : origin = CPU1_RAMGS_DATA_START, length = CPU1_RAMGS_DATA_LENGTH
                                
   CLA1_MSGRAMLOW               : origin = 0x001480, length = 0x000080
   CLA1_MSGRAMHIGH              : origin = 0x001500, length = 0x000080
                                
   CPU2TOCPU1RAM                : origin = 0x03F800, length = 0x000400
   CPU1TOCPU2RAM                : origin = 0x03FC00, length = 0x000400

}

SECTIONS
{
#if BOOT_FROM_FLASH
   /* Allocate program areas: */
   .init_array         : > FLASHA_N                      PAGE = 0, ALIGN(8)
   .cinit              : > FLASHA_N                      PAGE = 0, ALIGN(8)
   .pinit              : > FLASHA_N,                     PAGE = 0, ALIGN(8)
   .text               : > FLASHA_N                      PAGE = 0, ALIGN(8)
   codestart           : > BEGIN_FLASH                   PAGE = 0, ALIGN(8)
   .switch             : > FLASHA_N                      PAGE = 0, ALIGN(8)
   .const             : > FLASHA_N                       PAGE = 0, ALIGN(8)
   .data               : > RAMLS_PROG,       			 PAGE = 0
   .bss            	   : > RAMGS_DATA ,                  PAGE = 1
#if defined(__TI_EABI__)
    .TI.ramfunc : {} LOAD = FLASHA_N,
					 #if CPU_RAMLS_PROG_LENGTH>0
                     RUN =  RAMLS_PROG,
                     #else // Applicable when CLA BLOCK is included and CPULSRAM is zero
                     RUN = RAMGS_PROG,
                     #endif
        	         LOAD_START(RamfuncsLoadStart),
         	         LOAD_SIZE(RamfuncsLoadSize),
         	         LOAD_END(RamfuncsLoadEnd),
          	         RUN_START(RamfuncsRunStart),
          	         RUN_SIZE(RamfuncsRunSize),
           	         RUN_END(RamfuncsRunEnd),
					 PAGE = 0, ALIGN(8)
#else
	.TI.ramfunc : {} LOAD = FLASHA_N,
					 #if CPU_RAMLS_PROG_LENGTH>0
                     RUN =  RAMLS_PROG,
                     #else // Applicable when CLA BLOCK is included and CPULSRAM is zero
                     RUN = RAMGS_PROG,
                     #endif
        	         LOAD_START(_RamfuncsLoadStart),
         	         LOAD_SIZE(_RamfuncsLoadSize),
         	         LOAD_END(_RamfuncsLoadEnd),
          	         RUN_START(_RamfuncsRunStart),
          	         RUN_SIZE(_RamfuncsRunSize),
           	         RUN_END(_RamfuncsRunEnd),
					 PAGE = 0, ALIGN(8)
#endif


   /* Initalized sections go in Flash */


   /* Allocate IQmath areas: */                          
   IQmath			   : > FLASHA_N,                     PAGE = 0, ALIGN(8)            /* Math Code */
   IQmathTables		   : > FLASHA_N,                     PAGE = 0, ALIGN(8)
   
   
   /* CLA specific sections */
   Cla1Prog        :  LOAD = FLASHA_N,
                      RUN = RAMLS_CLA_PROG,
                      LOAD_START(Cla1ProgLoadStart),
                      LOAD_END(Cla1ProgLoadEnd),
                      RUN_START(Cla1ProgRunStart),
                      LOAD_SIZE(Cla1ProgLoadSize),
                      PAGE = 0, ALIGN(8)

   .const_cla	    :  LOAD = FLASHA_N,
                       RUN = RAMLS_CLA_DATA,
                       RUN_START(Cla1ConstRunStart),
                       LOAD_START(Cla1ConstLoadStart),
                       LOAD_SIZE(Cla1ConstLoadSize),
                       PAGE = 0

#else
   codestart            : >  BEGIN,                       PAGE = 0
    #if (CPU_RAMLS_PROG_LENGTH > 0)
       .cinit               : > RAMLS_PROG,     PAGE = 0
    #else
       .cinit               : > RAMGS_PROG,     PAGE = 0
    #endif
   ramfuncs             : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   .TI.ramfunc          : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   .pinit               : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   .switch              : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   .econst              : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   /* Allocate IQ math areas: */
   IQmath			    : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0            /* Math Code */
   IQmathTables		    : >> RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   /* CLA specific sections */
   Cla1Prog         : > RAMLS_CLA_PROG,              PAGE = 0
  .text                : >> RAMLS_PROG | RAMGS_PROG,    PAGE = 0
  .const_cla	    : >  RAMLS_CLA_DATA, PAGE = 0
   .ebss                : > RAMGS_DATA ,        PAGE = 1
 #endif //BOOT_FROM_FLASH

   .stack               : > RAMM0M1,                     PAGE = 1
   .reset               : > RESET,                       PAGE = 0, TYPE = DSECT /* not used, */
   .sysmem             : > RAMD0D1,                     PAGE = 1
   #ifdef CLA_BLOCK_INCLUDED
   .cio                 : > RAMLS_PROG | RAMGS_PROG,     PAGE = 0
   #else
   .cio                 : > RAMLS_PROG     PAGE = 0
   #endif //CLA_BLOCK_INCLUDED 

   /* CLA C compiler sections */
   //
   // Must be allocated to memory the CLA has write access to
   //
   Cla1DataRam0		: > RAMLS_CLA_DATA,              PAGE=0

   Cla1ToCpuMsgRAM  : > CLA1_MSGRAMLOW,              PAGE = 1
   CpuToCla1MsgRAM  : > CLA1_MSGRAMHIGH,             PAGE = 1
   CLAscratch       :
                     { *.obj(CLAscratch)
                     . += CLA_SCRATCHPAD_SIZE;
                     *.obj(CLAscratch_end) } >  RAMLS_CLA_DATA,  PAGE = 0

   .scratchpad      : > RAMLS_CLA_DATA,              PAGE = 0
   .bss_cla		    : > RAMLS_CLA_DATA,              PAGE = 0
   /*Allocate area for SPI DMA transfer buffers*/
    GSRAM : > RAMGS_DATA, PAGE=1
     /* Allocate twiddle factors area: */
   twiddleFactors   : > FLASHA_N,                     PAGE = 0
   /*Allocate areas for 32 points RFFT input and output buffers*/
   buffer1          : > RAMLS_PROG, ALIGN = 64, PAGE = 0
   buffer2          : > RAMLS_PROG, ALIGN = 64, PAGE = 0

}

/*
//===========================================================================
// End of file.
//===========================================================================
*/

I am getting a very strange behavior with the above mentioned setup. The SPI master device (Arduino Due for testing purpose) is getting the echoed version of its transmitted data with one word delay. In the debug mode I can verify that sData[] array contains valid data and rData[] array remains initialized to all zeros. It appears that DMA is not doing any transfers with these two arrays and SPI is some how sending back the previously received word against each word transfer. Kindly guide in fixing the issue

  • I noticed that the calculations for burst and transfer were not correct. Following the formulas in TRM the burst size should be 7 (for FIFO interrupt level of 8) and the transfer size should be 13 (i.e. 14 transfers). Following are the snapshots from the Sysconfig tool. Also note that I am starting both the DMA channels manually in my code after all initializations are done:

    // Starting the DMA channels
    DMA_startChannel(CM4_SPI_RX_DMA_BASE);
    DMA_startChannel(CM4_SPI_TX_DMA_BASE);

    Is there a requirement to configure DMA as a secondary master for SPI?. I have tried following setting but no success:

    SysCtl_selectSecMaster(SYSCTL_SEC_MASTER_CLA, SYSCTL_SEC_MASTER_DMA);

  • From your description, it does seem like the SPI is not getting serviced by the DMA. The reason you see the "echo" data is that the SPI MISO pin will shift out what the SPI MOSI shifted in *if* no new data is loaded to the SPI TX buffer. I cannot tell from your description if the DMA is not servicing the SPI *or* if the SPI is not generating the DMA interrupts. 

    Some suggestions:

    • Try to enable the DMA channels *before* starting the SPI. In sysconfig there is an option to start the channel. If you do that, it looks like the sysconfig generated code will init the DMA before starting the SPI.
    • Use CCS to look at the DMA registers after your master has started SPI transfers. Specifically you can look at the TRANSFER_COUNT register for the DMA TX and RX channels you have configured. If these are not changing, then its a good indication the problem is with the SPI not generating interrupts.
    • Enable the SPI interrupt & add an interrupt handler just to see if the SPI is indeed generating interrupts. 

    Lastly, are you running this code from CPU1? It looks like CPU1 DMA is the only one with access to the SPI modules. 

  • Hi Gus Martinez,

         Thank you very much for your reply. Indeed it was very helpful for troubleshooting. There were multiple issues with my initial project:

    1- The SPI interrupts were not enabled as referred to the picture below:

    2- It is actually required to make DMA as secondary master for peripheral frame 2 since power up default access is to CLA1:

     SysCtl_selectSecMaster(SYSCTL_SEC_MASTER_CLA, SYSCTL_SEC_MASTER_DMA);

    If I don't add above instruction to my initialization code then same echo back happens.

    Just want to add one more information for other developers that are configuring DMA via Sysconfig tool: The calculations for burst size and transfer count need not be decremented by one as mentioned in the TRM. For example in my case if I wanted to transfer 112 bytes I had to configure burst size to 8 and transfer size to 14 (8*14=112) as opposed to TRM calculations of 7 and 13 respectively.