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.

CCS/TMDX5535EZDSP: DMA problem when booting from SPI flash

Part Number: TMDX5535EZDSP

Tool/software: Code Composer Studio

I'm trying to run an audio application from SPI flash on the EZDSPC5535 board. The application uses 4 DMA channels to transmit and receive data over I2S. Each DMA channel is configured in a scheme with two buffers (Ping-Pong). When the playback of the ping buffer is completed, the DMA controller generates an interrupt and the program writes new data to the ping buffer, while the pong buffer is played.

Everything works well when I load the program through a debugger, but when I boot from spi flash, DMA interrupts do not occur (as if they were disabled), so no sound is played. However all initialization was successful without errors.

I have already found out that a frequent problem when booting from SPI flash is the lack of initial steps defined in the gel file. So I deleted everything from the gel file, leaving the empty event handlers. But program still works when I load it through the debugger.

However, I found a strange thing: if you connect a board to start the program from the SPI flash (DMA does not work at that moment), then Launch Selected Configuration (even with empty event handlers), then Connect Target and Resume the program execution, then the DMA interrupts start working.

I'm wondering what happens when you press Connect Target that affects the generation of DMA interrupts

  • The team is notified. They will post their feedback directly here.

    BR
    Tsvetolin Shulev
  • Today I checked that booting from uSD is no different from booting from SPI flash. 
    The program runs without errors, but no interrupts are generated until the target device is connected to the CCS.

  • I also checked that timer interrupts (TIMER0) work fine regardless of the boot method.
    This means that the problem is not in all interrupts, but only in DMA interrupts.

    UPDATE: In order to ensure that the problem is not in I2S, I temporarily removed the I2S trigger from the DMA configuration (CSL_DMA_SOFTWARE_TRIGGER, CSL_DMA_EVT_NONE).
    Now the DMA does not wait for synchronization with I2S, but continuously moves data and generates interrupts when it reaches the end of the buffer. 
    As before, everything works when run through the debugger. But when you boot from micro SD or SPI flash, DMA interrupts do not appear until you Connect target to CSS

  • I was able to reproduce my problem on a slightly modified example from c55_csl_3.08\ccs_v6.x_examples\dma\CSL_DMA_IntcExample\csl_dma_IntcExample.c 

    1) If you replace the original source file with a file attached to the message. And run it on TMDX5535EZDSP board you should see a blinking red LED that is controlled from the DMA interrupt service routine.

    2) Generate a boot image and copy it to an uSD card or SPI flash (hex55 -i CSL_DMA_IntcExample.out -o bootimg.bin -boot -v5505 -b -serial8)

    3) Boot from uSD and make sure that the red LED does not blinking

    4) Create in CCS target configuration for EZDSP5535, in Advanced tab click on C55xx, delete path to initialization script and click Save. (Because we dont want any register changes on connect)

    5) Launch Selected Configuration, press Connect Target and Resume. 

    6) Make sure that red LED blinking, that is, DMA interrupts are generated

    7) WHY?

    csl_dma_IntcExample.c
    /* ============================================================================
     * Copyright (c) 2008-2016 Texas Instruments Incorporated.
     * 
     *  Redistribution and use in source and binary forms, with or without 
     *  modification, are permitted provided that the following conditions 
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright 
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the 
     *    documentation and/or other materials provided with the   
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
    */
    
    
    /** @file csl_dma_IntcExample.c
     *
     *  @brief Test for all the channel in interrupt mode.
     *
     *
     * \page    page2  DMA EXAMPLE DOCUMENTATION
     *
     * \section DMA2   DMA EXAMPLE2 - INTERRUPT MODE TEST
     *
     * \subsection DMA2x TEST DESCRIPTION:
     * 	   	This test verifies operation of the CSL DMA module in interrupt mode.
     * C5535/C5515 and C5517 DSPs have four DMA Engines and each DMA engine has
     * four channels for the data transfers. Total 16 channels can be configured
     * and used for the data transfer simultaneously. DMA can be used to transfer
     * data with in the memory and between the memory and peripherals with out
     * having the intervention of CPU.
     *
     * During the test DMA functionality is verified by transferring the data
     * between two buffers allocated in memory of C5535/C5515/C5517 DSP. Data in the
     * source buffer 'dmaSRCBuff' is copied into the destination buffer
     * 'dmaDESTBuff'. DMA interrupts are configured and DMA ISR is registered
     * using CSL INTC module. DMA ISR will be triggered by the DMA transfer
     * completion interrupt. DMA is configured with proper source and destination
     * address and data length using DMA_config() API. Configured values are read
     * back using DMA_getConfig() API and are verified with the original values.
     * DMA data transfer is triggered using DMA_start() API. After starting the
     * DMA data transfer execution of the test will wait for the occurrence of
     * DMA transfer interrupt. This is done by checking a global variable which
     * will be updated by the DMA ISR. After the transfer completion data in the
     * source and destination buffers is compared. The same test procedure is
     * repeated on all the 16 DMA channels.
     *
     * NOTE: THIS TEST HAS BEEN DEVELOPED TO WORK WITH CHIP VERSIONS C5535, C5515, AND
     * C5517. MAKE SURE THAT PROPER CHIP VERSION MACRO IS DEFINED IN THE FILE
     * c55xx_csl\inc\csl_general.h.
     *
     * \subsection DMA2y TEST PROCEDURE:
     *  @li Open the CCS and connect the target
     *  @li Open the project "CSL_DMA_IntcExample.pjt" and build it
     *  @li Load the program on to the target
     *  @li Set the PLL frequency to 12.288MHz
     *  @li Run the program and observe the test result
     *  @li Repeat the test at the following PLL frequencies
     *      C5515: 60MHz and 100MHz
     *      C5517: 60MHz, 100MHz, 150MHz and 200MHz
     *      C5535 eZdsp: 60MHz and 100MHz
     *  @li Repeat the test in Release mode
     *
     * \subsection DMA2z TEST RESULT:
     *  @li All the CSL APIs should return success
     *  @li DMA configuration values should be read back and verified successfully
     *  @li DMA transfer should be successful and source and destination data should
     *      match on all the 16 DMA channels
     *
     * =============================================================================
     */
    
    /* ============================================================================
     * Revision History
     * ================
     * 28-Aug-2008 Created
     * 09-Jul-2012 Added C5517 chip version
     * 10-Mar-2016 Updates to header
     * ============================================================================
     */
    
    #include "csl_dma.h"
    #include "csl_intc.h"
    #include "csl_gpio.h"
    #include "csl_sysctrl.h"
    #include <stdio.h>
    #include <csl_general.h>
    
    #define CSL_DMA_BUFFER_SIZE 1024
    
    /* Reference the start of the interrupt vector table */
    extern void VECSTART(void);
    /* Protype declaration for ISR function */
    interrupt void dma_isr(void);
    
    /* Declaration of the buffer */
    Uint16 dmaSRCBuff[CSL_DMA_BUFFER_SIZE];
    Uint16 dmaDESTBuff[CSL_DMA_BUFFER_SIZE];
    static int count ;
    static int isrEntryCount = 0;
    
    CSL_DMA_ChannelObj  dmaObj;
    CSL_DMA_Handle 		dmaHandle;
    CSL_DMA_Config 		dmaConfig;
    CSL_DMA_Config 		getdmaConfig;
    
    
    
    CSL_GpioObj gpio;
    GPIO_Handle hGPIO;
    
    #define CSL_RED_LED  CSL_GPIO_PIN16
    
    //----------------------------------------------------------------------------------
    CSL_Status gpio_init()
    {
    	CSL_Status           status;
    	CSL_GpioPinConfig    config;
    
    	// Open GPIO module
    	hGPIO = GPIO_open(&gpio, &status);
    	if(CSL_SOK != status)
    	{
    		printf("GPIO_open failed\n");
    		return status;
    	}
    
    	SYS_setEBSR(CSL_EBSR_FIELD_PPMODE, CSL_EBSR_PPMODE_1);
    
    	// Reset all the pins
    	GPIO_reset(hGPIO);
    
    	// Configure GPIO pins as output
    	config.direction = CSL_GPIO_DIR_OUTPUT;
    	config.trigger   = CSL_GPIO_TRIG_CLEAR_EDGE;
    	config.pinNum 	 = CSL_RED_LED;
    
    	status = GPIO_configBit(hGPIO, &config);
    	if(CSL_SOK != status)
    	{
    		printf("GPIO_configBit failed\n");
    		return status;
    	}
    
    	// Turn off led!
    	GPIO_write(hGPIO, CSL_RED_LED, 1);
    
    	return CSL_SOK;
    }
    
    
    void start(int chanNumber)
    {
    	CSL_Status           status;
        printf("\n Test for DMA Channel No : %d \t", chanNumber);
    
    	dmaHandle = DMA_open((CSL_DMAChanNum)chanNumber,&dmaObj, &status);
        if (dmaHandle == NULL)
        {
            printf("DMA_open() Failed \n");
            exit(1);
        }
    
    	status = DMA_config(dmaHandle, &dmaConfig);
        if (status != CSL_SOK)
        {
            printf("DMA_config() Failed \n");
            exit(1);
        }
    
    	status = DMA_start(dmaHandle);
        if (status != CSL_SOK)
        {
            printf("DMA_start() Failed \n");
            exit(1);
        }
    }
    
    void stop()
    {
    	CSL_Status           status;
    
    	status = DMA_close(dmaHandle);
        if (status != CSL_SOK)
        {
            printf("DMA_close() Failed \n");
            exit(1);
        }
    
        status = DMA_reset(dmaHandle);
        if (status != CSL_SOK)
        {
            printf("DMA_reset() Failed \n");
            exit(1);
        }
    
    }
    
    
       /////INSTRUMENTATION FOR BATCH TESTING -- Part 1 --
       /////  Define PaSs_StAtE variable for catching errors as program executes.
       /////  Define PaSs flag for holding final pass/fail result at program completion.
            volatile Int16 PaSs_StAtE = 0x0001; // Init to 1. Reset to 0 at any monitored execution error.
            volatile Int16 PaSs = 0x0000; // Init to 0.  Updated later with PaSs_StAtE when and if
       /////                                  program flow reaches expected exit point(s).
       /////
    void main(void)
    {
    	CSL_Status 			status;
    	Uint16   			chanNumber;
    	Uint16   			i;
    
    	gpio_init();
    
    	printf("\n DMA INTERRUPT MODE TEST!\n");
    
    	for(i = 0; i< CSL_DMA_BUFFER_SIZE; i++)
    	{
    		//dmaSRCBuff[i]  = 0xFFFF;
    		dmaSRCBuff[i]  = i;
    		dmaDESTBuff[i] = 0x0000;
    	}
    
    #if (defined(CHIP_C5505_C5515) || defined(CHIP_C5504_C5514) || defined(CHIP_C5517) || defined(CHIP_C5535) || defined(CHIP_C5545))
    	dmaConfig.pingPongMode = CSL_DMA_PING_PONG_DISABLE;
    #endif
    
    	dmaConfig.autoMode     = CSL_DMA_AUTORELOAD_DISABLE;
    	dmaConfig.burstLen     = CSL_DMA_TXBURST_8WORD;
    	dmaConfig.trigger      = CSL_DMA_SOFTWARE_TRIGGER;
    	dmaConfig.dmaEvt       = CSL_DMA_EVT_NONE;
    	dmaConfig.dmaInt       = CSL_DMA_INTERRUPT_ENABLE;
    	dmaConfig.chanDir      = CSL_DMA_READ;
    	dmaConfig.trfType      = CSL_DMA_TRANSFER_MEMORY;
    	dmaConfig.dataLen      = CSL_DMA_BUFFER_SIZE * 2;
    	dmaConfig.srcAddr      = (Uint32)dmaSRCBuff;
    	dmaConfig.destAddr     = (Uint32)dmaDESTBuff;
    
        IRQ_globalDisable();
    
    	IRQ_clearAll();
    
    	IRQ_disableAll();
    
    	IRQ_setVecs((Uint32)&VECSTART);
    	IRQ_clear(DMA_EVENT);
    
    	IRQ_plug (DMA_EVENT, &dma_isr);
    
    	IRQ_enable(DMA_EVENT);
    	IRQ_globalEnable();
    
        status = DMA_init();
        if (status != CSL_SOK)
        {
            printf("DMA_init() Failed \n");
       /////INSTRUMENTATION FOR BATCH TESTING -- Part 2 --
       /////  Reseting PaSs_StAtE to 0 if error detected here.
            PaSs_StAtE = 0x0000; // Was intialized to 1 at declaration.
       /////
        }
    
        while(1)
        {
        	for( chanNumber = 0; chanNumber < CSL_DMA_CHAN_MAX; chanNumber++)
    		{
    			count = 0;
    
    			start(chanNumber);				// open dma channel and start copying
    
    			while(count != 1);				// wait end (isr)
    
    			stop();							// close dma channel
    
    			for (i = 0; i < 0xFFFF; i++);	// pause
    		}
        }
    
    	IRQ_clearAll();
    	IRQ_disableAll();
    	IRQ_globalDisable();
    
    	if(isrEntryCount == 16)
    	{
    		printf("\n\n DMA INTERRUPT MODE TEST PASSED!!\n");
    	}
    	else
    	{
    		printf("\n\n DMA INTERRUPT MODE TEST FAILED!!\n");
       /////INSTRUMENTATION FOR BATCH TESTING -- Part 2 --
       /////  Reseting PaSs_StAtE to 0 if error detected here.
            PaSs_StAtE = 0x0000; // Was intialized to 1 at declaration.
       /////
    	}
       /////INSTRUMENTATION FOR BATCH TESTING -- Part 3 --
       /////  At program exit, copy "PaSs_StAtE" into "PaSs".
            PaSs = PaSs_StAtE; //If flow gets here, override PaSs' initial 0 with
       /////                   // pass/fail value determined during program execution.
       /////  Note:  Program should next exit to C$$EXIT and halt, where DSS, under
       /////   control of a host PC script, will read and record the PaSs' value.
       /////
    }
    
    interrupt void dma_isr(void)
    {
        int ifrValue;
    
      	ifrValue = CSL_SYSCTRL_REGS->DMAIFR;
    	CSL_SYSCTRL_REGS->DMAIFR |= ifrValue;
    
    	++count;
    	++isrEntryCount;
    
    	// Blinking on interrupt
    	if(GPIO_write(hGPIO, CSL_RED_LED, isrEntryCount & 1) != CSL_SOK)
    	{
    		printf("GPIO_write Failed\n");
    	}
    }
    
    

  • Could someone reproduce the steps that I listed and confirm or deny my results? Thanks!