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.

MIBSPI using DMA (Data Receive problem)

Other Parts Discussed in Thread: HALCOGEN

Hi,

   I am using MIBSPI1 of TMS570LS1113 controller for SPI data transfer. Basic driver i have developed for General SPI & SPI using DMS without enabling Multibuffer mode. I have enabled the loopback mode for testing purpose

   While testing i have observed that in General SPI mode whatever the data i am sending its getting loop backed. But in SPI with DMA i am getting the problem.

This is the buffer from which where i am taking the data to be transmitted.

 BL_CONST C_UINT16 Kuc_PM_SecondBSL[64] ={0x1111,0x2222,0x3333,0x4444,0x5555,0x6666,0x7777,0x8888,0x9999,0xAAAA,0xBBBB,
                                                                                         0xCCCC,0xDDDD,0xEEEE,0xFFFF,0x1010,0x1111,0x1212,0x1313,0x1414,0x1515,0x1616,
                                                                                         0x1717,0x1818,0x1919,0x1A1A,0x1B1B,0x1C1C,0x1D1D,0x1E1E,0x1F1F,0x2020,0xE6,0x03,
                                                                                         0x03,0x00,0xE6,0x01,0x03,0x00,0xE6,0xF5,0xE0,0x00,0xE6,0xF4,0x58,0x69,0xB8,0x54,
                                                                                         0xE6,0x01,0x81,0x00,0xE6,0xF4,0x48,0x40,0xE6,0xF7,0x00,0x60,0xB8,0x74};

What i am expecting is the same 64 word needs to be received (using General SPI/SPI with DMA) in my Receive Buffer at the location 0x8012D48

While tranferring using General SPI same 64 word are received properly in my Receive Buffer at the location 0x8012D48

But while transferring with DMA i am receiving like this.. at location 0x8012D48 i am receiving 0x0074 instead of 0x1111. 0x0074 is the last word in my array "Kuc_PM_SecondBSL[64]", but it was received in the first location.

Here i have added my code for your reference

1.Code for SPI initialization

FUNC(void, SPI_GLOBAL_CODE) SPI_Init(void)
{

 int i;

   /*-------------------------------------------------------------------------
      Initialize the MibSPI1
    -------------------------------------------------------------------------*/
 spiREG->SPIGCR0 = 1; /*SPI is out of the reset state*/
 
 /* Pull control Enable */
 spiREG->SPIPC7 = 0;
 
 /* Pullup enable */
 spiREG->SPIPC8 = 0xFFFFFFFF;
 
 /* SPI Pin functionality selection */
 spiREG->SPIPC0 = 0xFFFFFFFF;
     
     
 /* Select the Clock source & enable master mode */
    spiREG->SPIGCR1 =(1U<<16)  /* Loop back enable */
                                          |(1U<<1)  /* Clock is internally-generated */
                                          |(1);   /* Master Mode Operation, SPISOMI pins are inputs, SPISIMO pins are outputs */
 
 /* Select the SPI Data Format */
    spiREG->SPIFMT0 =(1U<<29)  /* Wdelay = 3F */
      |(1U<<28)
      |(1U<<27)
      |(1U<<26)
      |(1U<<25)  
      |(1U<<24)  
      |(0U<<22)  /* No Parity Generation */
      |(0U<<21)  /* SPI doesnot wait for the ENA signal from Slave */
      |(0U<<20)  /* MSB is shifted out first */
      |(0U<<19)  /* Normal Full duplex transfer */
      |(1U<<18)  /* CS to transmission delay & transmission to CS delay disabled */
      |(0U<<17)  /* Polarity = 0 */
      |(0U<<16)  /* Phase = 0 */ 
      |(0U<<15)  /* Prescale to determine bit transfer rate */
      |(0U<<14)  /* Prescale to determine bit transfer rate */
      |(0U<<13)  /* Prescale to determine bit transfer rate */
      |(0U<<12)  /* Prescale to determine bit transfer rate */
      |(1U<<11)  /* 10Mbps bit transfer rate */
      |(0U<<10)  /* Prescale to determine bit transfer rate */
      |(0U<<9)  /* Prescale to determine bit transfer rate */
      |(1U<<8)  /* Prescale to determine bit transfer rate */
      |(1U<<4)  /* Char length MSB */
      |(0U<<3)
      |(0U<<2)  /* Char length = 16 */
      |(0U<<1)  
      |(0);   /* Char length LSB */
     
 /* Configure the SPI Delay */
    spiREG->SPIDELAY = 0;   

 /*Selecting the Data Format*/
 spiREG->SPIDAT1 =(1U<<26)  /*Enable WDEL*/
                                      |(0U<<25)  /* Data Word format 0 Selected*/
                                      |(0U<<24);

/*******************************
   DMA Configuration
*******************************/ 
 
    /*reset dma*/
   dmaREG->GCTRL  = 0x00000001; 

    /* enable dma      */
   dmaREG->GCTRL |= 0x00010000;
   /* stop at suspend */
   dmaREG->GCTRL |= 0x00000300; 
}

2. Function for SPI transfer using Gen SPI/ DMA SPI

void SPI_Transmit( C_UINT16 *Lpp_Tx_Data,
                                          C_UINT16 *Lpp_Rx_Data,
                                          C_UINT16 Lus_Data_Len,C_UINT8 TX_RX_GEN_SPI_OR_DMA_SPI)
{
    C_UINT16 Lucloop ;
    C_UINT16 i;
 if(TX_RX_GEN_SPI_OR_DMA_SPI == GEN_SPI)
 {
  spiREG->SPIGCR1 |= (1U<<24); /* Activates SPI (SPIEN =1) */
     
  for(Lucloop=ZERO;Lucloop<Lus_Data_Len;Lucloop++)
  {
  
   /* Transmit Data */
   while(((spiREG->SPIBUF)&0x20000000) == 0x20000000)
   {
     ;
   }
  
   spiREG->SPIDAT0 = *Lpp_Tx_Data;
    
   /* Read Rx buffer */      
   while(((spiREG->SPIBUF)&0x80000000) == 0x80000000)
   {
   ;
   }
   *Lpp_Rx_Data =  (C_UINT16)spiREG->SPIBUF;
  
   /* Increment buffers */
   Lpp_Tx_Data++;
   Lpp_Rx_Data++;
 
  }
  spiREG->SPIGCR1 |= (0U<<24); /* Deactivates SPI (SPIEN =0) */
 }
 else if(TX_RX_GEN_SPI_OR_DMA_SPI == DMA_SPI)
 {
 
 /****************************************
   Initialising the data to be send
 ****************************************/
  
  GusRxBuffer[0]=0;
  for(i=1;i<65;i++)
   {
   GusRxBuffer[i] = 0;
   }
  
   /* Assign DMA request 1 to Chan 1*/
  dmaREG->DREQASI[0] |=(1U <<16U);
  
   /* Assign DMA request 0 to Chan 0*/
  dmaREG->DREQASI[0] |=(0U <<24U);
  
 /****************************************
   TX Configuration
 ****************************************/ 
  /*Source Address*/
  dmaRAMREG->PCP[1].ISADDR =(C_UINT32)Lpp_Tx_Data;
   
  /*Destinaton Address*/
  dmaRAMREG->PCP[1].IDADDR =(C_UINT32)0xFFF7F43E;//&spiREG->SPIDAT1;
  
  /*Initial frame transfer count & Initial element transfer count*/
  dmaRAMREG->PCP[1].ITCOUNT = (C_UINT32)(((Lus_Data_Len)<< 16U) |1);
  
  /*Channel Control Register*/
  dmaRAMREG->PCP[1].CHCTRL =   (0<<15)
           | (1 << 14)  /*Read element size is WORD*/
           | (1 << 12) /*Write element size is WORD*/
           | (0 << 8)  /*A hardware request triggers one frame transfer*/
           | (1 << 3) /*Read address Post-increment*/
           | (0 << 1)  /*Write address fixed*/
           | (1);      /*Auto-initiation mode is enabled*/
            
  /*Destination address element index and Source address element index*/
  dmaRAMREG->PCP[1].EIOFF =0;

  /*Destination address frame index and Source address frame index*/
  dmaRAMREG->PCP[1].FIOFF =0;
  
  /*Assign PortB for channel 1 */
  dmaREG->PAR[0] = (0x04 << 24U);
  
  /*Enable Hardware triggering for channel 1*/
  dmaREG->HWCHENAS = (1 << 1);
  
 /****************************************
   RX Configuration
 ****************************************/ 
    
  /*Source Address*/
  dmaRAMREG->PCP[0].ISADDR =(C_UINT32)0xFFF7F442;//&spiREG->SPIBUF;
  
  /*Destinaton Address*/
  dmaRAMREG->PCP[0].IDADDR =(C_UINT32)Lpp_Rx_Data;
  
  /*Initial frame transfer count & Initial element transfer count*/
  dmaRAMREG->PCP[0].ITCOUNT = (C_UINT32)(((Lus_Data_Len)<< 16U) |1);
  
  /*Channel Control Register*/
  dmaRAMREG->PCP[0].CHCTRL =   (0<<15)
           | (1 << 14)  /*Read element size is WORD*/
           | (1 << 12) /*Write element size is WORD*/
           | (0 << 8)  /*A hardware request triggers one frame transfer*/
           | (0 << 3) /*Read address fixed*/
           | (1 << 1)  /*Write Post-increment*/
           | (1);      /*Auto-initiation mode is enabled*/
  
  /*Destination address element index and Source address element index*/
  dmaRAMREG->PCP[0].EIOFF =0;

  /*Destination address frame index and Source address frame index*/
  dmaRAMREG->PCP[0].FIOFF =0;
  
  /*Assign PortB for channel 0 */
  dmaREG->PAR[0] |= (0x04 << 28U);
  
  /*Enable Hardware triggering for channel 0*/
  dmaREG->HWCHENAS |= 1;
  
  /*Selecting the Data Format*/
  spiREG->SPIDAT1 &= (0xFCFFFFFF); /* Data Word format 0 Selected*/
       
  
  /*For testing DMA request enable*/
  spiREG->SPIINT0 |= (1 << 16);
  
  /* Activates SPI (SPIEN =1) */
  spiREG->SPIGCR1 |= (1U<<24);
  
  /* Start Data Transfer */
  while(dmaREG->BTCFLAG != 3);
  
  /*Clearing the Interrupt flags*/
  dmaREG->BTCFLAG = 3;
  
  /*Disable Hardware triggering for channel 0,1*/
  dmaREG->HWCHENAR = (1 << 1)
                                                  | 1 ;
       
 }
 else
 {
 /*do nothing*/
 }
}

3. My function call will be like this

GppSCI_Command_Buf =(C_UINT16 *) &Kuc_PM_SecondBSL[0];

SPI_Transmit( GppSCI_Command_Buf,GusRxBuffer,64,GEN_SPI);

SPI_Transmit( GppSCI_Command_Buf,GusRxBuffer,64,DMA_SPI);

 

Please guide me to solve this problem of data reception using DMA.

 

Thanks & Regards,

Kamala VIgnesh.

  • Kamala,

    To me it looks like there is a problem in your configuration of the DMA channel triggering from MbiSPI.  I didn't see the registers in the MibSPI being set up (DMACTRLx) but I suspect that perhaps the transmit and receive are crossed.   It looks like you are initially getting an extra recieve request and the data is 0000.  Then all the rest of your data is shifted by +0x02 in address compared to your reference non-DMA example.   The reason your last data 0x0074 would be written to the first location in the buffer is that you configured the DMA channel to auto initialize after it completes, and to start the next frame at the same address as the previous frame.

    To spot check please confirm that the DMAxCTRL register in MibSPI for your buffer is setup correctly, i.e. that the DMA channels for RXDMA_MAPx and TXDMA_MAPx are not swapped.

    To debug,  you can do the following:

    a) run your code to the point of having configured the DMA controller and MibSPI but not so far as to have initiated any transfers.

    b) edit in the register map of the DMA controller  the registers DbgCtrl / DCTRL,  WpReg / WPR, and WmReg / WMR.   The first name before the / is what you see in CCS and after the / is what you should search for in the TRM (SPNU499b) if you want to read about them.

       Set: 

          DbgCtrl = 1

          WpReg = 0x08012D48

          WmReg = 0x00000000

    This will configure the DMA such that it halts the processor as soon as it's written to the first location in your receive buffer.

    c) run the processor - it should stop immediately.

    d) if the theory is correct you should see that 0x0000 has been written to address 0x08012D48

        Note: you might want to go back to step b and put something non-zero at that address to confirm it's actually being written.

    e) where you stopped should be a little after the place in your code where the first DMA was triggered.

        Whereis this and is it where you would have expected, or is it too early to have received data yet.

    f) you can read the other fields of the DCTL register to find out the exact DMA channel number that wrote to 0x08012D48.

       is this channel pointed to by the RXDMA_MAPx?

    Three final comments:

      a) My theory could certainly be wrong, but hopefully the watch-point technique gives more clues as to the cause of the problem; maybe enough that the real issue would become evident.

      b) The only downside of the watchpoint is that you need to go through a nPORST to clear the DBGEN bit once it's set.  Just a minor nuisance.

      c) If this doesn't help - it would be quickest for you to send your project and a .out file that we can debug.  

  • Hi Anthony,

       Thanks for your reply. I want to understand your answer little more. The "TMS570LS12x/11x 16/32-Bit RISC Flash Microcontroller Technical Reference Manual" says Hardware Request the channel needs to be retriggered each time after a block is complete even if auto-initiation is enabled. So DMA channel wont be auto initialized after a Frame transfer since i have used hardware request for the channel triggering. So 0x0074 could not be received at the first location i think. The problem might be some where else.

    One more point i want to clarify you is i have used the MIBSPI1 in general SPI mode only not in multi buffer mode. So only i didnt configured the DMACTRL register. As per my knowledge there is no need of configuring the DMACTRL register if it is used in general SPI mode. Please correct me if i am wrong.

    DMA channels i have assigned using "DMA Request Assignment Register 0".

  • Hi Kamala Vignesh,

    KamalaVignesh Nagendran said:
    One more point i want to clarify you is i have used the MIBSPI1 in general SPI mode only not in multi buffer mode.

    Does this mean that you checked the right hand option in HalCoGen? 

    KamalaVignesh Nagendran said:
    So only i didnt configured the DMACTRL register. As per my knowledge there is no need of configuring the DMACTRL register if it is used in general SPI mode. Please correct me if i am wrong

      

    If the answer to the above is yes, then this is correct.

    EDIT:  Actually I mean if you configured for "Enable SPI1 Driver" and not "Enable MibSPI1 Driver" as the first question shows, then you are correct you don't use the DMACTRL regs.

    KamalaVignesh Nagendran said:
    The "TMS570LS12x/11x 16/32-Bit RISC Flash Microcontroller Technical Reference Manual" says Hardware Request the channel needs to be retriggered each time after a block is complete even if auto-initiation is enabled. So DMA channel wont be auto initialized after a Frame transfer since i have used hardware request for the channel triggering. So 0x0074 could not be received at the first location i think. The problem might be some where else.

    Yes, but it's certainly possible that somehow an extra DMA request is generated by the SPI.   And the idea of an extra DMA request generated at the beginning of the buffer, then being written over by the last data word as the buffer wraps - is the only one that fits the data pattern that I can see.
     
    This is why I'm thinking you should try the DMA watchpoint.  You might find that the initial DMA request is coming at some unexpected time; possibly as a by-product of something in spiInit()  (a guess).
     
    For example, this code in spiInit()

        /** SPI1 master mode and clock configuration */
        spiREG1->GCR1 = (spiREG1->GCR1 & 0xFFFFFFFCU) | ((1U << 1U)  /* CLOKMOD */
                      | 1U);  /* MASTER */

        /** SPI1 enable pin configuration */
        spiREG1->INT0 = (spiREG1->INT0 & 0xFEFFFFFFU)| (0U << 24U);  /* ENABLE HIGHZ */

    Could actually generate a DMA request, but it depends on the state of the SPI module when it's executed.
    If you're not always running from a "SYSTEM RESET" then there might be config hanging out in the SPI.
    OR it might be that you're duplicating some parts of this init in your own code and that's causing an extra
    initial DMA request.

    That's my thought on the direction this probably leads.  If you do the test with the watchpoint I think it will narrow down very quickly what's going on.

    If you don't feel comfortable doing that test, you can send me your project and I'll run the test.  It shouldn't take long if your project is just SPI loopback
    and doesn't need any specific external hardware.
     
  • Hi Kamala Vignesh,

    Just wanted to see if you're still having issues with the MibSPI, or if the issue is resolved.   If it's resolved please let us know so we can close this thread.