Halt and restart SPORT DMA

Hi,

I'm doing some filtering on a SHARC 21369, and I want to change filter coefficients in real time. I have based my program on the Block based talkthru example.

To realize the change in coefficients, I want to pause/stop the SPORT DMA, change the coefficients and then restart the DMA.

I am having some trouble with this, as it only works 80% of the time. The rest of the time, the audio doesn't get filteret.

I think the procedure should be:

1) Clear SCHEN for both receive and transmit port

2) Clear SDEN for both receive and transmit port

3) Clear CPSP for both receive and transmit port

4) Change the filter coefficients

5) Re-setup the SPORT with the InitSPORT(); function

Is this correct?

Best regards,

Mads

  • Just to be clear, the setup and clear function is as follows:

    ///////////////////////////////////////////////////////////////////////////////////////

    //NAME:     initSPORT.c (Block-based Talkthrough)

    //DATE:     7/29/05

    //PURPOSE:  Talkthrough framework for sending and receiving samples to the AD1835.

    //

    //USAGE:    This file uses SPORT0 to receive data from the ADC and transmits the

    //                              data to the DAC's via SPORT1A, SPORT1B, SPORT2A and SPORT2B.

    //                              DMA Chaining is enabled

    //

    ////////////////////////////////////////////////////////////////////////////////////////

    #include "tt.h"

    #define DAC3 //Lowpass

    #define DAC4 //Highpass

    /*

       Here is the mapping between the SPORTS and the DACS

       ADC -> DSP  : SPORT0A : I2S

       DSP -> DAC1 : SPORT1A : I2S

       DSP -> DAC2 : SPORT1B : I2S

       DSP -> DAC3 : SPORT2A : I2S

       DSP -> DAC4 : SPORT2B : I2S

    */

    unsigned int PCI = 0x00080000 ;

    unsigned int OFFSET = 0x00080000 ;

    // TCB blocks for Chaining

    //Each block will be used for:

    //      Filling from the ADC

    //      Processing filled data

    //      Sending to DAC

    //

    //Each one is doing only one of these steps for each SPORT interrupt.

    //For this example the startup state is

    // Start to 1st interrupt: Block_A is filled first, Block_C is sent

    // 1st int to 2nd int: Block_C filled, Block_A processed, Block_B sent

    // 2nd int to 3rd int: Block_B filled, Block_C processed, Block_A sent

    // 3rd int to 4th int: Block_A filled, Block_B processed, Block_C sent

    unsigned int Block_A[NUM_SAMPLES] ;

    unsigned int Block_B[NUM_SAMPLES] ;

    unsigned int Block_C[NUM_SAMPLES] ;

    unsigned int Block_D[NUM_SAMPLES] ;

    unsigned int Block_E[NUM_SAMPLES] ;

    //Set up the TCBs to rotate automatically

    // TCB = {Chain pointer, Internal count, Internal modifier, Internal index}

    // Chain pointer points to next index of chain, Internal index is the block that will be loaded to the internal index register

    int TCB_Block_A[4] = { 0, sizeof(Block_A), 1, 0};

    int TCB_Block_B[4] = { 0, sizeof(Block_B), 1, 0};

    int TCB_Block_C[4] = { 0, sizeof(Block_C), 1, 0};

    //For output channel 2

    int TCB_Block_D[4] = { 0, sizeof(Block_D), 1, 0};

    int TCB_Block_E[4] = { 0, sizeof(Block_E), 1, 0};

    void InitSPORT()

    {

        //Proceed from Block A to Block C

        TCB_Block_A[0] = (int) TCB_Block_C + 3 - OFFSET + PCI ;

        TCB_Block_A[3] = (unsigned int) Block_A - OFFSET ;

        //Proceed from Block B to Block A

        TCB_Block_B[0] = (int) TCB_Block_A + 3 - OFFSET + PCI ;

        TCB_Block_B[3] = (unsigned int) Block_B - OFFSET ;

        //Proceed from Block C to Block B

        TCB_Block_C[0] = (int) TCB_Block_B + 3 - OFFSET + PCI ;

        TCB_Block_C[3] = (unsigned int) Block_C - OFFSET ;

        //For output channel 2

        //Proceed from Block D to E

        TCB_Block_D[0] = (int) TCB_Block_E + 3 - OFFSET;// + PCI ;

        TCB_Block_D[3] = (unsigned int) Block_D - OFFSET ;

       

        //Proceed from block E to D

        TCB_Block_E[0] = (int) TCB_Block_D + 3 - OFFSET;// + PCI ;

        TCB_Block_E[3] = (unsigned int) Block_E - OFFSET ;

       

        //Clear the Mutlichannel control registers

        *pSPMCTL0 = 0;

        *pSPMCTL1 = 0;

        *pSPMCTL2 = 0;

        *pSPCTL0 = 0 ;

        *pSPCTL1 = 0 ;

        *pSPCTL2 = 0 ;

        //============================================================

        //

        // Configure SPORT 0 for input from ADC

        //

        //------------------------------------------------------------

        *pSPCTL0 = (OPMODE | SLEN24 | SPEN_A | SCHEN_A | SDEN_A);

        // Enabling Chaining

        // Block A will be filled first

        *pCPSP0A = (unsigned int) TCB_Block_A - OFFSET + 3 ;

        //============================================================

        //

        // Configure SPORTs 1 & 2 for output to DACs 1-4

        //

        //------------------------------------------------------------

        #ifdef DAC1

        *pSPCTL1 |= (SPTRAN | OPMODE | SLEN24 | SPEN_A | SCHEN_A | SDEN_A) ;

        // write to DAC1

        *pCPSP1A = (unsigned int) TCB_Block_C - OFFSET + 3 ;

        #endif

        #ifdef DAC2

        *pSPCTL1 |= (SPTRAN | OPMODE | SLEN24 | SPEN_B | SCHEN_B | SDEN_B) ;

        // write to DAC2

        *pCPSP1B = (unsigned int) TCB_Block_C - OFFSET + 3 ;

        #endif

        //Use this for lowpass

        #ifdef DAC3

        *pSPCTL2 |= (SPTRAN | OPMODE | SLEN24 | SPEN_A | SCHEN_A | SDEN_A) ;

        // write to DAC3

        *pCPSP2A = (unsigned int) TCB_Block_D - OFFSET + 3 ;

        #endif

        //Use this for highpass

        #ifdef DAC4

        *pSPCTL2 |= (SPTRAN | OPMODE | SLEN24 | SPEN_B | SCHEN_B | SDEN_B) ;

        // write to DAC4

        *pCPSP2B = (unsigned int) TCB_Block_C - OFFSET + 3 ;

        #endif

    }

    void RstSPORT()

    {

              //ADC

              //Clear Serial control register

              *pSPCTL0 &=~ SCHEN_A; //Disable chaining

              *pSPCTL0 &=~ SDEN_A; //Disable DMA

              *pCPSP0A = 0x0; //Reset chain pointer

     

     

              //DAC

              //Clear Registers

              #ifdef DAC1

        *pSPCTL1 &=~ SCHEN_A;

        *pSPCTL1 &=~ SDEN_A;

        *pCPSP1A = 0x0;

        #endif

        #ifdef DAC2

        *pSPCTL1 &=~ SCHEN_B;

        *pSPCTL1 &=~ SDEN_B;

        *pCPSP1B = 0x0;

        #endif

        #ifdef DAC3

        *pSPCTL2 &=~ SCHEN_A;

        *pSPCTL2 &=~ SDEN_A;

        *pCPSP2A = 0x0;

        #endif

        #ifdef DAC4

        *pSPCTL2 &=~ SCHEN_B;

        *pSPCTL2 &=~ SDEN_B;

        *pCPSP2B = 0x0;

        #endif

     

       //Clear the Mutlichannel control registers

        *pSPMCTL0 = 0;

        *pSPMCTL1 = 0;

        *pSPMCTL2 = 0;

        *pSPCTL0 = 0 ;

        *pSPCTL1 = 0 ;

        *pSPCTL2 = 0 ;

        TCB_Block_A[0] =0x0;

        TCB_Block_A[3] = 0x0;

       

              TCB_Block_B[0] = 0x0;

        TCB_Block_B[3] = 0x0;

       

              TCB_Block_C[0] = 0x0;

        TCB_Block_C[3] = 0x0;

       

              TCB_Block_D[0] = 0x0;

        TCB_Block_D[3] = 0x0;

       

                TCB_Block_E[0] = 0x0;

        TCB_Block_E[3] = 0x0;

    }

    As you can see, I have modded the project to have another DMA chain, so I can output the filtered data to a seperate channel.

  • I figured it out. The problem was actually situated another place in my code. It seems that the stop/start of the DMA works correctly after all.

  • This question has been closed by the EZ team and is assumed answered.