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.

TMS320F28377S: DSP F28377S, DMA not work after de Initialize

Part Number: TMS320F28377S

Hi ,

My DMA usage is as follows:

{
   sInitDma();
   sInitSpiAFifo();
   sInitSpiBFifo();
   
   {
        //
        DMA Transmission is normal;
        //
    }
    
    
    DMAInitialize();
    spiaInit();     //quit fifo mode
    spibInit();     //quit fifo mode
    
    delay;
    
    
    
    
    /**************************************************/
    sInitDma();
    sInitSpiAFifo();
    sInitSpiBFifo();
    
    {
        //
        DMA Can not work normally;
        //
    }
    
    
    DMAInitialize();
    spiaInit();     //quit fifo mode
    spibInit();     //quit fifo mode
    
}
    
    

Because I made a loop, using DMA mode inside the loop. In the middle of the cycle interval, the spi needs to be switched to the normal mode (non-DMA, non-FIFO).
But when I looped for the second time and entered DMA mode, I found that DMA transmission could not work normally.

I checked DMA register, as following:

After I start DMA4 with 

//run
EALLOW;
DmaRegs.CH4.CONTROL.bit.RUN = 1;
DmaRegs.CH5.CONTROL.bit.RUN = 1;
EDIS;

,

"DmaRegs.CH4.CONTROL.bit.RUNSTS"  is  1,   but  "SRC_BEG_ADDR_ACTIVE"  and   "DST_BEG_ADDR_ACTIVE"  is still 0.

Is this phenomenon normal?

Thanks!

  • Hi, 

    I tested the problem again, and it was OK when tested with the example "lab44_spi_loopback_dma". But add  "DMAInitialize()" following , and then repeat the lab44_spi_loopback_dma  again, and find that the DMA does not work successfully.

    The code is following:

    void main(void)
    {
       Uint16 i;
    
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2837xS_SysCtrl.c file.
       InitSysCtrl();
    
       //initial LSPCLK
       EALLOW;
       ClkCfgRegs.LOSPCP.bit.LSPCLKDIV = 0;        //000,LSPCLK = SYSCLK / 1
       EDIS;
    
    // Step 2. Initialize GPIO:
    // This example function is found in the F2837xS_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio();  // Skipped for this example
    // Setup only the GP I/O only for SPI-A functionality
       InitSpiaGpio();
    
    // Step 3. Initialize PIE vector table:
    // Disable and clear all CPU interrupts
       DINT;
       IER = 0x0000;
       IFR = 0x0000;
    
    // Initialize PIE control registers to their default state:
    // This function is found in the F2837xS_PieCtrl.c file.
       InitPieCtrl();
    
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2837xS_DefaultIsr.c.
    // This function is found in F2837xS_PieVect.c.
       InitPieVectTable();
    
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
       EALLOW;  // This is needed to write to EALLOW protected registers
       PieVectTable.DMA_CH5_INT= &local_D_INTCH5_ISR;
       PieVectTable.DMA_CH6_INT= &local_D_INTCH6_ISR;
       EDIS;   // This is needed to disable write to EALLOW protected registers
    
    // Step 4. Initialize the Device Peripherals:
       dma_init();			// set up dma for SPI configuration
       spi_fifo_init();		// Initialize the SPI only
    
    	// Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)
    	EALLOW;
    	CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
    	EDIS;
    
    
    // Step 5. User specific code, enable interrupts:
    
    	// Initialize the data buffers
    	for(i=0; i<1024; i++)
    	{
    		sdata[i] = i;
    		rdata[i]= 0;
    		wTest[i] = 0;
    	}
    	rdata_point = 0;
    
    // Enable interrupts required for this example
       PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
       PieCtrlRegs.PIEIER7.bit.INTx5 = 1;	// Enable PIE Group 7, INT 1 (DMA CH1)
       PieCtrlRegs.PIEIER7.bit.INTx6 = 1;	// Enable PIE Group 7, INT 2 (DMA CH2)
       IER= M_INT7;							// Enable CPU INT6
       EINT;                                // Enable Global Interrupts
    
       StartDMACH6();		// Start SPI RX DMA channel
       StartDMACH5();		// Start SPI TX DMA channel
    
       done = 0;			// Test is not done yet
    
       while(!done);		// wait until the DMA transfer is complete
    
        {
            /************************************de initial DMA***********************************/
            while(wTest[1] < 10000)
            {
                wTest[1]++;
            }
            //added by xiaofei
            DMAInitialize();
            sInitSpiA();
            /************************************de initial DMA***********************************/
    
    
            // Step 4. Initialize the Device Peripherals:
            dma_init();          // set up dma for SPI configuration
            spi_fifo_init();     // Initialize the SPI only
            // Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)
            EALLOW;
            CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
            EDIS;
    
            // Initialize the data buffers
            for(i=0; i<1024; i++)
            {
                sdata[i] = i;
                rdata[i]= 0;
                wTest[i] = 0;
            }
            rdata_point = 0;
    
            // Enable interrupts required for this example
            PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
            PieCtrlRegs.PIEIER7.bit.INTx5 = 1;   // Enable PIE Group 7, INT 1 (DMA CH1)
            PieCtrlRegs.PIEIER7.bit.INTx6 = 1;   // Enable PIE Group 7, INT 2 (DMA CH2)
            IER= M_INT7;                         // Enable CPU INT6
            EINT;                                // Enable Global Interrupts
    
            StartDMACH6();       // Start SPI RX DMA channel
            StartDMACH5();       // Start SPI TX DMA channel
    
            done = 0;            // Test is not done yet
            while(!done);       // wait until the DMA transfer is complete
        }
    
    
       while(done)
       {
           wTest[0]++;
       }
       // when the DMA transfer is complete the program will stop here
       ESTOP0;
    
    }

  • Fei,

    The issue is that the DMA_Initialize function will perform a hard reset of the DMA module, clearing out all of your settings.  For your application you can just use the RUN bit to start/stop the DMA.  So when you want to pause the DMA for manual reading of the SPI, make the RUN bit = 0

    EALLOW;
    DmaRegs.CH4.CONTROL.bit.RUN = 0;
    DmaRegs.CH5.CONTROL.bit.RUN = 0;
    EDIS;

    This will pause the DMA, but retain all the other settings.  Then, when your system is ready for the DMA to be active again, you can write a "1" back to the RUN bits.

    Best,

    Matthew

  • Hi ,Matthew:

    Thanks,it works!