AnsweredAssumed Answered

Problem with SPORT Interrupt - Blackfin BF533 processor

Question asked by ndquangr on Jan 25, 2012
Latest reply on Jan 27, 2012 by PrasanthR

Hello,

I recently started to work with eval-bf5xx board, cm-bf533 and audio extension board. Because I am new with embedded system programming so there are some problems I could not solve although I have refered to many blackfin documents.

Firstly I want to describe detaily my problem. I have modified the audio talkthough tdm code for bf533 to push data obtained from microphones to a data buffer every SPORT interrupt. I only modify the interrupt handler, not other settings or code.

 

This is initialize_bf533.c file, just the same with original file:

 

 

#include "Talkthrough.h"
#include "parameter.h"
//--------------------------------------------------------------------------//
// Function:     Init1836()                                                                 //
//                                                                                               //
// Description:     This function sets up the SPI port to configure the AD1836. //
//                    The content of the array sCodec1836TxRegs is sent to the      //
//                    codec.                                                                      //
//--------------------------------------------------------------------------//
void Init1836(void)
{
int j;
// Enable PF5
*pSPI_FLG = FLS5;
// Set baud rate SCK = HCLK/(2*SPIBAUD) SCK = 2MHz
*pSPI_BAUD = 16;
// configure spi port
// SPI DMA write, 16-bit data, MSB first, SPI Master
*pSPI_CTL = TIMOD_DMA_TX | SIZE | MSTR;
// Set up DMA5 to transmit
// Map DMA5 to SPI
*pDMA5_PERIPHERAL_MAP     = 0x5000;
// Configure DMA5
// 16-bit transfers
*pDMA5_CONFIG = WDSIZE_16;
// Start address of data buffer
*pDMA5_START_ADDR = (void *)sCodec1836TxRegs;
// DMA inner loop count
*pDMA5_X_COUNT = CODEC_1836_REGS_LENGTH;
// Inner loop address increment
*pDMA5_X_MODIFY = 2;
// enable DMAs
*pDMA5_CONFIG = (*pDMA5_CONFIG | DMAEN);
// enable spi
*pSPI_CTL = (*pSPI_CTL | SPE);
// wait until dma transfers for spi are finished
for (j=0; j<0xaff0; j++) asm("nop;");
// disable spi
*pSPI_CTL = 0x0000;
}
//--------------------------------------------------------------------------//
// Function:     Init_Sport0                                                                 //
//                                                                                               //
// Description:     Configure Sport0 for TDM mode, to transmit/receive data      //
//                    to/from the AD1836. Configure Sport for external clocks and //
//                    frame syncs.                                                            //
//--------------------------------------------------------------------------//
void Init_Sport0(void)
{
// Sport0 receive configuration
// External CLK, External Frame sync, MSB first
// 32-bit data
*pSPORT0_RCR1 = RFSR;
*pSPORT0_RCR2 = SLEN_32;
// Sport0 transmit configuration
// External CLK, External Frame sync, MSB first
// 24-bit data
*pSPORT0_TCR1 = TFSR;
*pSPORT0_TCR2 = SLEN_32;
// Enable MCM 8 transmit & receive channels
*pSPORT0_MTCS0 = 0x000000FF;
*pSPORT0_MRCS0 = 0x000000FF;
// Set MCM configuration register and enable MCM mode
*pSPORT0_MCMC1 = 0x0000;
*pSPORT0_MCMC2 = 0x101c;
}
//--------------------------------------------------------------------------//
// Function:     Init_DMA                                                                 //
//                                                                                               //
// Description:     Initialize DMA1 in autobuffer mode to receive and DMA2 in     //
//                    autobuffer mode to transmit                                             //
//--------------------------------------------------------------------------//
void Init_DMA(void)
{
// Set up DMA1 to receive
// Map DMA1 to Sport0 RX
*pDMA1_PERIPHERAL_MAP = 0x1000;
// Configure DMA1
// 32-bit transfers, Interrupt on completion, Autobuffer mode
*pDMA1_CONFIG = WNR | WDSIZE_32 | DI_EN | FLOW_1;
// Start address of data buffer
*pDMA1_START_ADDR = (void *)iRxBuffer1;
// DMA inner loop count
//*pDMA1_X_COUNT = 8;
*pDMA1_X_COUNT = 8 * FRAME_SIZE;
// Inner loop address increment
*pDMA1_X_MODIFY     = 4;
// Set up DMA2 to transmit
// Map DMA2 to Sport0 TX
*pDMA2_PERIPHERAL_MAP = 0x2000;
// Configure DMA2
// 32-bit transfers, Autobuffer mode
*pDMA2_CONFIG = WDSIZE_32 | FLOW_1;
// Start address of data buffer
*pDMA2_START_ADDR = (void *)iTxBuffer1;
// DMA inner loop count
//*pDMA2_X_COUNT = 8;
*pDMA2_X_COUNT = 8 * FRAME_SIZE;
// Inner loop address increment
*pDMA2_X_MODIFY     = 4;
}
//--------------------------------------------------------------------------//
// Function:     Init_Interrupts                                                            //
//                                                                                               //
// Description:     Initialize Interrupt for Sport0 RX                                   //
//--------------------------------------------------------------------------//
void Init_Sport_Interrupts(void)
{
// using the adi interrupt manager
// get the IVG
unsigned long nCurrentIVG;
adi_int_SICGetIVG(ADI_INT_DMA1_SPORT0_RX, &nCurrentIVG);
//printf("current ivg: %d", nCurrentIVG);
// hook the sport0 rx interrupt handler
adi_int_CECHook(nCurrentIVG, SPORT0RxHandler, NULL, FALSE);
adi_int_SICWakeup(ADI_INT_DMA1_SPORT0_RX, TRUE);
adi_int_SICEnable(ADI_INT_DMA1_SPORT0_RX);
}
//--------------------------------------------------------------------------//
// Function:     Enable_DMA_Sport                                                       //
//                                                                                               //
// Description:     Enable DMA1, DMA2, Sport0 TX and Sport0 RX                         //
//--------------------------------------------------------------------------//
void Enable_DMA_Sport0(void)
{
// enable DMAs
*pDMA2_CONFIG     = (*pDMA2_CONFIG | DMAEN);
*pDMA1_CONFIG     = (*pDMA1_CONFIG | DMAEN);
// enable Sport0 TX and RX
*pSPORT0_TCR1      = (*pSPORT0_TCR1 | TSPEN);
*pSPORT0_RCR1      = (*pSPORT0_RCR1 | RSPEN);
}

Then I moved the SPORT0RxHandler to main.c to use a variable which I create to manager data buffer.

 

static RTDataState *rt;

 

void main(void)

{

rt = rt_data_state_init(FRAME_SHIFT, WINDOW_LEN, FRAME_SHIFT);


 

// initialize the interrupt manager

adi_int_Init( intmgr_storage, sizeof(intmgr_storage), &response_count, &critical_reg);


 

Init1836();

Init_Sport0();

Init_DMA();

Init_Sport_Interrupts();

Enable_DMA_Sport0();


while(1)

{

   while(rt_data_IS_AVAILABLE(rt))

    {

         // Pop data from circular buffer

         rt_data_pop(rt, data_mic_1, data_mic_2, data_mic_3);

   

    }

 


}


ADI_INT_HANDLER_RESULT SPORT0RxHandler(void *pa_pClientArg)

{

int i, i_frame;

 


   

#if defined (__ADSPBF533__)

// clear interrupt flag

*pDMA1_IRQ_STATUS = 0x0001;

#elif defined (__ADSPBF537__)

*pDMA3_IRQ_STATUS |= 0x0001;

#elif defined (__ADSPBF561__)

*pDMA2_0_IRQ_STATUS |= 0x0001;

#else

#error "processor not yet supported"

#endif


for(i=0; i<FRAME_SIZE; i++)

{

      i_frame = i << 3;     // x FRAME_SIZE   


      // copy input data from dma input buffer into variables

      iChannel0LeftIn[i]  = iRxBuffer1[INTERNAL_ADC_L0 + i_frame];

      iChannel0RightIn[i] = iRxBuffer1[INTERNAL_ADC_R0 + i_frame];

      iChannel1LeftIn[i]  = iRxBuffer1[INTERNAL_ADC_L1 + i_frame];

      iChannel1RightIn[i] = iRxBuffer1[INTERNAL_ADC_R1 + i_frame];

 


 

      }

 

      rt_data_push(rt, iChannel0LeftIn,iChannel0RightIn,iChannel1LeftIn);


      return ADI_INT_RESULT_PROCESSED;

}

 

 

I have remove some pieces of code in above 2 functions (for power management service and measure sampling rate) because I think they do not relate to my purpose. (The problem is not different if I do not remove them).

 

RTDataState is my class to manage data buffer with the funtions rt_data_push (push data to buffer), rt_data_pop (pop data from buffer), rt_data_IS_AVAILABLE (check if data is available).

 

Now, the problem is:

I put a breakpoint at the line while(rt_data_IS_AVAILABLE(rt)) in the while loop inside main function. When I debug, the program stop there, but when I press F11 with the hope it will run into rt_data_IS_AVAILABLE function, it strangely run into _adi_int_NonNestingISR function in adi_int_asm.asm and then run to SPORT0RxHandler. I remove breakpoint and put printf function in  three functions rt_data_push, rt_data_pop, rt_data_IS_AVAILABLE, the console alway print out the text I put inside rt_data_push (in interrupt handler), never print out the text in two other functions.

 

I am not familiar with embedded system programming, so I do not understand this situation.

Please explain for me why it always run interrupt handler and show me the way to solve it. I'm in a hurry so I need your help very much. I have attached my project in this post.

Thank you in advance!

Attachments

Outcomes