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.

Compiler/TMS570LC4357: Function call not passing all parameters?

Part Number: TMS570LC4357

Tool/software: TI C/C++ Compiler

Hi, 

I have a function that is setting up a write over a SPI bus, the prototype looks like:

uint32_t fpga_write_burst(uint8_t length, uint8_t bank, uint8_t addr, uint16_t *txdata, uint8_t channel)

Curiously, it doesn't seem like the last parameter is passed into the function. I've also tried swapping out the last parameter length to channel, and have the same result. 

The results of step by step debugging are shown in the images:

 

I'm not familiar enough with assembly to decypher exactly what's going on here, but it would seem like it isn't storing the values in the stack properly during the function call? 

Here's the disassembly from the call when it works:

Any help would be greatly appreciated, thanks!

Nick

  • Considering this on a high level, one of three things could be wrong ...

    1. The compiler generated assembly code
    2. The compiler generated debug information
    3. The debugger display

    While anything is possible, I doubt it is the first one.  The compiler has to pass lots of tests to get released.  Something this basic would be caught.  When you run through the code with no breakpoints, does it work as expected?

    For the source file that contains the problem call to fpga_write_burst, please submit a test case as described in the article How to Submit a Compiler Test Case.  If it contains more than one call to fpga_write_burst, then please add the comment /* THIS IS THE PROBLEM CALL */ just before the problem call.  

    Thanks and regards,

    -George

  • Hi George,

    I was pretty sure it wasn't 2 or 3 but I think that is the case now, but I still think it's a bug and I'd like to open a ticket if possible?

    Using the following code, the debugger updates the variable temp and the debugger shows both channel and temp to be the expected value. 

    uint32_t fpga_write_burst(uint8_t length, uint8_t bank, uint8_t addr, uint16_t *txdata, uint8_t channel)
    {
        uint8_t temp;
        temp = channel;
    	if (length < FPGA_SPI_MAX_TRANSFER_LENGTH)
    	{
    	    // TODO: return success / fail based on result of fpgaWriteRegisterSequential
    		fpgaWriteRegisterSequential(channel, bank, addr, txdata, length);
    		//return FPGA_SUCCESS;
    	}
    	else
    	{
    		//return FPGA_FAILURE;
    	}
    
    	return temp;
    }

    I think the debugger is not updating the variables if they are not used in a function and they are pushed on to the stack instead of a register? With my original code, if you trace down into fpgaWriteRegisterSequential, you can see that channel contains the expected value that was passed in by the high level function. Meaning the original issue I was trying to debug is somewhere else and not here :( 

  • Do you build with optimization?  Because it is easy to get confused when debugging optimized code.  Does that explain what you see?

    Thanks and regards,

    -George

  • Hi, 

    No, I'm reasonably certain there is no optimization turned on, that was one of the first things I checked. The function prototype and declaration also match each other as well. This is the invocation that is used to build the files, it shows -Ooff and --opt_for_speed = 0. 

    Building file: "../g3_fpga_driver/source/HL_system.c"
    Invoking: ARM Compiler
    "C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/bin/armcl" -mv7R5 --code_state=32 --float_support=VFPv3D16 -Ooff --opt_for_speed=0 --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-arm_18.1.1.LTS/include" -g --diag_warning=225 --diag_wrap=off --display_error_number --enum_type=packed --abi=eabi --preproc_with_compile --preproc_dependency="g3_fpga_driver/source/HL_system.d_raw" --obj_directory="g3_fpga_driver/source"  "../g3_fpga_driver/source/HL_system.c"
    Finished building: "../g3_fpga_driver/source/HL_system.c"

    This is happening on multiple functions actually, so I'm reasonably sure it's the problem I described above. For example, the following code:

    void fpgaWriteRegisterSequential(uint8_t channel, uint8_t bank, uint8_t addr, uint16_t *data, uint8_t length)
    {
    
    
    /** Other code removed for brevity **/
    
    	packet.tx_len = length;
    	for (i = 0; i < length; i++)
    	{
    	    packet.tx_buffer[i] = data[i];
    	}
    	fpgaTransfer(&packet);
    
    }





    Then execute line 295:

    In this function, CCS reports length as zero, but when the packet.tx_len = length line is executed, somehow packet.tx_len takes on the correct value, but length still shows up as zero. When the for loop executes below, it will run the expected number of times as well. If I swap the length and channel variables in the function call, the behaviour above transfers over to channel (channel = 0, but the line packet.channel = channel assigns a nonzero value to packet.channel). 

    I don't think this is expected behaviour and isn't related to issues I normally see when debugging with optimization. 

  • Nick,

    Which version of CCS are you using?

    Are you able to share a cutdown version of your project that we can build and run to see if we can reproduce the issue? From your description it sounds like the variables are actually set to their correct values, but the CCS expressions view is not reflecting it. Is that correct? If we have a reproducible test case that will help us determine if there is a bug in the debugger display.

    Also as a quick test could you check if declaring that variable as 'volatile' makes a difference in the outcome?
  • Hello AartiG, 

    See attached example, the following code is all you need to see the issue. 

    int main(void)
    {
        uint8_t retVal;
        while(1)
        {
            retVal = testFunc(1U,2U,3U,4U,5U);
        }
        return 0;
    }
    
    uint8_t testFunc(uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4, uint8_t var5)
    {
        /* In this function, var5 shows in the variables tab equalling zero, but the function correctly returns 6 */
        var5 += 1;
    
        return var5;
    }

    calling testfunc, you see var5 is zero whil eyou are in testfunc, even after adding += 1. However, retVal = 6 after returning from the function. I'm using CCS 8.0.0.00016 

    Declaring var5 as volatile, or declaring uint8_t  or volatile uint8_t var1,2,3,4,5 and then calling those in the function makes no difference. The fifth variable does nto show up correctly in the debugger. 

    In a test that makes me want to gouge my eyes out, using uint32_t works fine and displays correctly in the debugger. 

    uint8_t testFunc(uint32_t var1, uint32_t var2, uint32_t var3, uint32_t var4, uint32_t var5) { /* In this function, var5 shows in the variables tab equalling zero, but the function correctly returns 6 */ var5 += 1; return var5; }




    Thanks,

    Nick

    demo_issue_archive.zip

  • Nick,

    Thank you for providing a test case. I can reproduce the issue and we are currently investigating to find the source of the problem. I will keep you updated when we have more information.
  • Nick,

    I have filed bug # CCBT-2248 for this issue to be investigated and fixed. You may track the status of the issue using the SDOWP link in my signature (link may take a few hours to update). Thank you again for bringing this to our attention and for providing a concise test case.