AnsweredAssumed Answered

SPORT Tx/Rx DMA on BF592

Question asked by khal on Jan 10, 2012
Latest reply on Jan 17, 2012 by Prashant

Hi,

I am setting up a system that communicates between BF592, an ADC (AD7689) and a DAC (AD5664) via Rx/Tx SPORT. My ADC is on SPORT0/DMA1 pair and my DAC is on SPORT1/DMA4 pair. The problem I am having is when the interrupt arrives through IVG9, how do I test which one has issued the interrupt (i.e. SPORT0/DMA1 or SPORT1/DMA4). I have tried to start the receive later than the transmit (i.e. a frame later) but still the output have frequent gaps among properly looped signal. To make the loopback seemless, I used a ping/pong buffer switching mechanism for the Rx and TX, yet still I see the gaps occuring. The code I wrote is:

 

#include<cdefbf592-A.h>
#include<sysreg.h>
#include<ccblkfn.h>
#include <sys\exception.h>
#include<stdio.h>

#define Size 0x0200
//#define ADC_CONFIG_WORD  (0x3C49<<2);
#define CFG(val)   (val << 13)
#define INCC(val)  (val << 10)
#define INx(val)  (val << 7)
#define BW(val)   (val << 6)
#define REF(val)  (val << 3)
#define SEQ(val)  (val << 1)
#define nRB(val)    (val)

#define DAC_CONFIGURATION 0x00380001
#define CONFIGURE_DAC_A  0x0018
#define CONFIGURE_DAC_B  0x0019
#define CONFIGURE_DAC_C  0x001A
#define CONFIGURE_DAC_D  0x001B

unsigned short AD7689_CFG = CFG(1) | INCC(7) | INx(0) | BW(1) | REF(0) | SEQ(0) | nRB(1);//For ADC Channel 0
unsigned short ipPing[Size];
unsigned short ipPong[Size];
unsigned int opPing[Size];
unsigned int opPong[Size];
unsigned int ADC_Samples2[Size];
static short ADC = 0;
static short Flag = 0;

EX_INTERRUPT_HANDLER(SPORT0_Rx_ISR);

int i =0;

void main()

{


int i,j,data;
#if 0
for (j=0;j<Size; j++)
{
  data = 16*j;
//  data |= (CONFIGURE_DAC_A << 16);
//  ADC_Samples2[j] = data;
}
#endif

//change PLL

*pPLL_CTL = 0x2000;
asm("idle;");
*pPLL_DIV = 0x4;
asm("ssync;");


//SPORT Pin Mux config
*pPORTG_MUX = 0;
*pPORTG_FER = 0x00FF;

//enable SPORT Rx interrupts
register_handler(ik_ivg9, SPORT0_Rx_ISR); 
*pSIC_IMASK0 = IRQ_DMA1;
ssync();
 
/*****************************************************************************/
//Init SPORT
*pSPORT0_TCLKDIV = 4;
*pSPORT0_TFSDIV = 36; //should be greater than 16 bit + time for conversion

*pSPORT0_RCR2 = SLEN(15);
*pSPORT0_RCR1 = DTYPE_NORM | LRFS | LARFS | RFSR ;

*pSPORT0_TCR2 = SLEN(15);
*pSPORT0_TCR1 = ITFS | DITFS | ITCLK | TFSR | LTFS | LATFS | TCKFE | DTYPE_NORM;

//enable Gated Clock
*pSPORT_GATECLK = 0x0001;

//enable SPORT and then TIMER

*pDMA1_START_ADDR = ipPing;
*pDMA1_X_MODIFY= 2;
*pDMA1_X_COUNT = Size;
*pDMA1_CONFIG = DI_EN | SYNC | WNR | WDSIZE_16 | DMAEN;


/*****************************************************************************/
   //GPIO configuration
*pPORTF_MUX = 0;
*pPORTF_FER = 0x00FF;
*pSPORT1_TCLKDIV = 4;
*pSPORT1_TFSDIV = 16;
*pSPORT1_TCR2 = 23;
*pSPORT1_TCR1 = ITFS | DITFS | ITCLK | TFSR | LTFS | LATFS | DTYPE_NORM;

// enable SPORT_1/DMA interrupt
*pSIC_IMASK0 |= IRQ_DMA4;        
register_handler(ik_ivg9, SPORT0_Rx_ISR);     // redirect interrupt

*pDMA4_START_ADDR = opPing;       // setup start address
*pDMA4_X_COUNT = Size;      // setup buffer end
*pDMA4_X_MODIFY = 4;        // setup buffer step size reading 2 locations at a time
*pDMA4_CONFIG = DI_EN | SYNC | WDSIZE_32 | DMAEN; // enable dma

/***************************************************************************/ 
//Since TX Buffer is empty when SPORT is enabled, send the Config Word.
//you can check if buffer is empty and then send the config word also.
*pSPORT0_RCR1 |= RSPEN;
*pSPORT0_TCR1 |= TSPEN;
//for(i=0;i<32;i++)
// j=0;
 
*pSPORT0_TX16 =  (AD7689_CFG << 2);
ssync();


while(1)
{
  idle();
}


}


/****************************************************************************************/

static short First = 1;
void SPORT0_Rx_ISR()
{
int j;

if(First == 1)
{
  First = 0;
  *pSPORT1_TCR1 |= TSPEN;
  *pSPORT1_TX32 = DAC_CONFIGURATION;
  ssync();
}
else
{   
    *pDMA4_IRQ_STATUS = DMA_DONE;
  while((*pSPORT1_STAT & TXF));
    while((*pSPORT1_STAT & TXF));

  if(ADC == 0)
  {
   for (j=0;j<Size; j++)
    opPong[j] = (ipPing[j] | (CONFIGURE_DAC_A << 16));
  }
  else
  {
   for (j=0;j<Size; j++)
    opPing[j] = (ipPong[j] | (CONFIGURE_DAC_A << 16));
  }
  *pDMA4_START_ADDR = (ADC == 0)? opPong:opPing;
  *pDMA4_CONFIG = DI_EN | SYNC | WDSIZE_32 | DMAEN; // enable dma
}

   *pDMA1_IRQ_STATUS = DMA_DONE;   
   while((*pSPORT0_STAT & TXF));
   while((*pSPORT0_STAT & TXF));

*pDMA1_START_ADDR = (ADC == 0)? ipPong:ipPing;
ADC = (ADC == 0)? 1:0;

*pDMA1_CONFIG = DI_EN | SYNC | WNR | WDSIZE_16 | DMAEN;
  
}


/****************************************************************************************/

 

 

How can I make the switching between Ping/Pong buffers for both input and output seemless?

How do I acknowledge the interrupts and identify the which SPORT/DMA buffer issued the interrupt for seemless operation?

 

Regards

Khal

Outcomes