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 optimization problem

Other Parts Discussed in Thread: TM4C123GH6PGE

Hi,

I have developed a large project with Optimization Disabled. All working well.

During testing I noticed some functions running extremely slowly. So I set Optimization to 2, which is I believe a standard level.

The first issues highlighted by this were where I had not put the qualifier "volatile" on variables changed in an intterupt and inspected in main code. This was easy to fix.

The next issue is that it appears that the function call

ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
                                   UDMA_MODE_BASIC,
                                   SSITXnul,
                                   (void *)(SSI0_BASE + SSI_O_DR),
                                   SSI_TXNUL_SIZE);

(where SSITXnul is a uint16_t array and SSI_TXNUL_SIZE = 2)

is overwriting some variable memory which it doesn't do with Optimization Disabled. I detected this by putting a write watchpoint on the variable.

Has anyone got any advice as to what I've done wrong please?

Thanks

Richard

  • Hello Richard,

    Moving it to the CCS Forum. Also please specify which CCS version and ARM Compiler version is being used?

    Regards
    Amit
  • Richard,

    In addition to what Amit requested, it would be very helpful if you could provide a small project that demonstrates the issue that we can use to reproduce the behavior.
  • I'm using CCSv5.5.0. I don't know how to find the ARM compiler version I'm afraid, Eclipse has thousands of settings!

    I was hoping for some general guidance on what to look out for when switching from Optimization Disabled to Optimization On and what the various levels do. Maybe there's a document on the TI website but it so often goes "page has timed out" on me that I can't browse.

    I have improved my problem by making the SSITXnul buffer two words longer, so it no longer overwrites the variable which is in the next location. Seems odd that the Optimization would cause this though.

    Thanks
    Richard
  • Richard Bland said:
    I have improved my problem by making the SSITXnul buffer two words longer, so it no longer overwrites the variable which is in the next location. Seems odd that the Optimization would cause this though.

    Optimization might move the address of variables which are in memory. However, the ROM_uDMAChannelTransferSet function is in the device ROM and so isn't affected by a change in the Compiler optimization level.

    What values are passed to the corresponding ROM_uDMAChannelControlSet function?

    The reason is I found this old thread ROM_uDMAChannelTransferSet which may be related.

    Richard Bland said:
    I'm using CCSv5.5.0. I don't know how to find the ARM compiler version I'm afraid, Eclipse has thousands of settings!

    If look at the CCS Project Properties  under CCS General the compiler version used is under Advanced Settings.

    Since the code calls ROM functions, can you also clarify which device is used.
     

  • Hi Chester,

    Thanks for your reply.

    I confirm I am using TI v4.9.8 compiler with CCS v5.5.0.00077 on Windows7 and the device is TM4C123GH6PGE.

    I have attached some code snippets from the relevant part of my project.

    Description: The SSI port is connected to an FPGA and they continuously exchange a pair of uint16_t words. When there is no information to pass, NUL pairs are transferred. The data flow is handled by uDMA with "ping pong" buffers such that there is no interruption in data flow and incoming rx data is placed in a 1024 word fifo for handling by a background service. Outgoing tx data is simply loaded into a buffer (protected by TXopen lock flag). If there is nothing in this buffer, the "NUL" buffer is used.


    All this code works very well when Optimization is disabled, but when I set Optimization to 2 it becomes unreliable and is proving hard to debug.

    I looked at the post you found, but it is for LM3S devices from 2009 - one assumes ROM errors have been sorted by now?

    Many thanks for any help/clues/advice.

    Richard

    SSI and uDMA snippets.txt
    
    
    //***********************************************************************************
    Variables
    
    #pragma DATA_ALIGN(uDmaControlTable, 1024)
    uint8_t uDmaControlTable[1024];
    
    uint16_t SSITXbuf[SSI_TXBUF_SIZE];
    uint16_t SSITXnul[SSI_TXNUL_SIZE+2];
    volatile uint32_t SSITXbufInPtr = 0;
    volatile uint32_t SSITXbufCount = 0;
    volatile uint32_t ssiTxBufferOverflow = 0;
    volatile uint32_t TXopen = 1;
    
    uint16_t SSIRXbufA[SSI_RXBUF_SIZE];
    uint16_t SSIRXbufB[SSI_RXBUF_SIZE];
    
    #define SSIRX_FIFO_SIZE		1024		//size must be power of 2
    
    volatile uint16_t SSIRXfifo[SSIRX_FIFO_SIZE];
    volatile uint32_t SSIRXinptr = 0;
    volatile uint32_t SSIRXoutptr = 0;
    volatile uint32_t SSIRXcount = 0;
    
    volatile uint32_t ssiRxFifoOverflow = 0;
    
    
    
    
    //***********************************************************************************
    //Initialisation
    
    //SSI0..............................................................................................................................
    	ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);			//fpga spi comms
    	ROM_SSIDisable(SSI0_BASE);					//disable it while we configure it
    	ROM_GPIOPinConfigure(GPIO_PA2_SSI0CLK);
    	ROM_GPIOPinConfigure(GPIO_PA3_SSI0FSS);
    	ROM_GPIOPinConfigure(GPIO_PA4_SSI0RX);
    	ROM_GPIOPinConfigure(GPIO_PA5_SSI0TX);
    	ROM_GPIOPinTypeSSI(GPIO_PORTA_BASE, GPIO_PIN_5 | GPIO_PIN_4 | GPIO_PIN_3 | GPIO_PIN_2);	//tx, rx, fr, ck
    	ROM_SSIClockSourceSet(SSI0_BASE, SSI_CLOCK_SYSTEM);
    	ROM_SSIConfigSetExpClk(SSI0_BASE,
    				ROM_SysCtlClockGet(),
    				SSI_FRF_TI,
    				SSI_MODE_MASTER,
    				5000000,
    				16);
    	ROM_SSIEnable(SSI0_BASE);
    	ROM_SSIDMAEnable(SSI0_BASE, SSI_DMA_RX | SSI_DMA_TX);
    //	ROM_IntEnable(INT_SSI0);    					//enable SSI0 peripheral interrupts
    									//note that no interrupts were enabled, but the uDMA controller will cause an interrupt on the SSI0 interrupt signal when a uDMA transfer is complete
    
    
    
    
    //***********************************************************************************
    //Interrupt
    
    void SSI0IntHandler(void)
    {
        uint32_t ui32Status;
        uint32_t ui32Mode;
        int i;
    
        ui32Status = ROM_SSIIntStatus(SSI0_BASE, 1);
        ROM_SSIIntClear(SSI0_BASE, ui32Status);    					// Clear any pending ints - there should be none - this is triggered by uDMA
    
    //is A transfer complete?
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT);	// Check the DMA control table to see if the ping-pong "A" transfer is complete
        if(ui32Mode == UDMA_MODE_STOP) {						// If the primary control structure indicates stop, that means the "A" receive buffer is done.  The uDMA controller should still be receiving data into the "B" buffer
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_PRI_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(SSI0_BASE + SSI_O_DR),
                                       SSIRXbufA,
                                       SSI_RXBUF_SIZE);				// Set up the next transfer for the "A" buffer
    
    		for(i=0;i<SSI_RXBUF_SIZE;i+=2) {				//look for non-zero in an addr (even) posn
    			if(SSIRXbufA[i] != 0) {
    				SSIRXfifo[SSIRXinptr++] = SSIRXbufA[i];		//put valid data into RXfifo
    				SSIRXfifo[SSIRXinptr++] = SSIRXbufA[i+1];
    				SSIRXinptr &= (SSIRX_FIFO_SIZE - 1);		//wrap pointer
    				SSIRXcount += 2;				//inc count
    				if(SSIRXcount > SSIRX_FIFO_SIZE) {
    					ssiRxFifoOverflow = 1;			//fifo overflow
    					break;
    				}
    			}
    		}
        }
    
    //is B transfer complete?
        ui32Mode = ROM_uDMAChannelModeGet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT);	// Check the DMA control table to see if the ping-pong "B" transfer is complete
        if(ui32Mode == UDMA_MODE_STOP) {						// If the alternate control structure indicates stop, that means the "B"
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0RX | UDMA_ALT_SELECT,
                                       UDMA_MODE_PINGPONG,
                                       (void *)(SSI0_BASE + SSI_O_DR),
                                       SSIRXbufB,
                                       SSI_RXBUF_SIZE);				// Set up the next transfer for the "B" buffer
    
    		for(i=0;i<SSI_RXBUF_SIZE;i+=2) {				//look for non-zero in an addr (even) posn
    			if(SSIRXbufB[i] != 0) {
    				SSIRXfifo[SSIRXinptr++] = SSIRXbufB[i];		//put valid data into RXfifo
    				SSIRXfifo[SSIRXinptr++] = SSIRXbufB[i+1];
    				SSIRXinptr &= (SSIRX_FIFO_SIZE - 1);		//wrap pointer
    				SSIRXcount += 2;				//inc count
    				if(SSIRXcount > SSIRX_FIFO_SIZE) {
    					ssiRxFifoOverflow = 1;			//fifo overflow
    					break;
    				}
    			}
    		}
        }
    
    //is TX done?
        if(!ROM_uDMAChannelIsEnabled(UDMA_CHANNEL_SSI0TX)) {  			// If the SSI0 DMA TX channel is disabled, that means the TX DMA transfer is done
        	if((SSITXbufCount != 0) && (TXopen != 0)) {				//if nothing to send do a null packet
    			ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
    							UDMA_MODE_BASIC,
    							SSITXbuf,
    							(void *)(SSI0_BASE + SSI_O_DR),
    							SSITXbufCount);		// Start another DMA transfer to SSI0 TX.
    			SSITXbufCount = 0;
    			SSITXbufInPtr = 0;
            }
        	else {
            ROM_uDMAChannelTransferSet(UDMA_CHANNEL_SSI0TX | UDMA_PRI_SELECT,
                                       UDMA_MODE_BASIC,
                                       SSITXnul,
                                       (void *)(SSI0_BASE + SSI_O_DR),
                                       SSI_TXNUL_SIZE);				// Start another DMA transfer to SSI0 TX.
            }
    
            ROM_uDMAChannelEnable(UDMA_CHANNEL_SSI0TX);				// The uDMA TX channel must be re-enabled.
        }
    }
    
    
    
    //***********************************************************************************
    //Code
    
    //---------------------------------------------------------------------------
    void sendFPGApair(uint16_t addr, uint16_t data)
    {
    	if((SSITXbufCount + 2) > SSI_TXBUF_SIZE) {
    		ssiTxBufferOverflow = 1;		//no room, set overflow flag, exit
    		return;
    	}
    
    	TXopen = 0;							//add pair to the SSI TX FIFO
    	SSITXbuf[SSITXbufInPtr++] = addr;
    	SSITXbuf[SSITXbufInPtr++] = data;
    	SSITXbufCount += 2;
    	TXopen = 1;
    }
    
    

  • Ah - apologies to all - looks like my problem has been the venerable Stack Overflow! I should have thought of that with all this weirdness going on. I still think I have an issue with the Optimization, but it's been masked by the stack problem. Please consider the issue closed - thank to all - this is a fabulous resource.
    Richard