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.

TMS320F280049: Complier Long Cast issue for negative no from signed integer

Part Number: TMS320F280049

Hi, 

We observed a strange behavior in the execution of the below code during casting from 16 bit to 32 bit, the code is snippet from a larger project, we were able to emulate the issue on a evaluation board

The ADC results are subtracted to remove the DC offset. As the ADC registers are unsigned integer (16bit) if we use all 16 bit variables including the result being store in 16 bit signed variable the code is executing fine. When we cast the result from 16bit to 32bit signed (i32Present ), we see strange behavior where the result shows as -6553x or 6553x, we were unable to put a watchpoint or breakpoint as it is randomly shown in the watch window, nor we could put a condition in the code to capture it. We are assuming the behavior is purely due to the JTAG and IDE interface. We could share the eval code for testing the same. The code is tested on LaunchXl-F2800049C

We did look at the assembly level code, it looks fine. As it is random for some values 

int16_t i16Present;
int16_t i16Prev;
int16_t gi16ADC_temp;
int32_t i16Present;

gi16ADC_temp  = (AdccResultRegs.ADCRESULT0);    // storing the result from ADC 0 -- Sine Wave
i16Prev             = (AdccResultRegs.ADCRESULT1);     // Storing the result from ADC 1 -- DC Offset

i16Present        = (gi16ADC_temp - i16Prev);               // REmoving the Offset, expected negative value

i32Present         = (int32_t)i16Present;                          // Type casting to 32 bit integer

Regards, 

Murugavelu 

  • Hello Murugavelu,

    Can you please create a conditional with a print statement or breakpoint for when the variable gets set to -6553x or 6553x? I would think this should be possible since you know if occurs, so the conditional should get executed. I want to be able to see the values of i16Present, gi16ADC_temp, and i16Prev at this point to see what may be going on, otherwise it will just be guesswork on my part.

  • /*
     * main.c
     *
     *  Created on: 09-Jan-2024
     *      Author: 39138
     */
    
    #include "F28x_Project.h"
    #include "device.h"
    #include "math.h"
    #include "Peripherals.h"
    
    #include "Main.h"
    
    //#include "stdint.h"
    
    //uint16_t au16adcAResults[BUFFERSIZE] ={0,};
    STR_CHECK strCheck;
    float32_t gf32OmegaT;
    float32_t gf32Sine;
    float32_t gf32Sine_DAC;
    float32_t gf32ModulationIndex = 1.0;
    uint16_t gu16DAC_value;
    int16_t gi16DAC_value;
    volatile uint16_t gu16ADC_temp;
    volatile int16_t gi16ADC_temp;
    volatile int32_t gi32ADC_temp;
    volatile float32_t gf32ADC_temp;
    volatile float32_t gf32ADC_temp1;
    volatile uint16_t temp;
    int flag =0;
    int16_t au16adcAResults[BUFFERSIZE] ={0.};
    int32_t ai32LogPresent[BUFFERSIZE] ={0,};
    int32_t ai32LogPrev[BUFFERSIZE] ={0,};
    int16_t ai16LogTemp[BUFFERSIZE] ={0,};
    //float32_t af32LogFloat[BUFFERSIZE] ={0,};
    
    void main(void)
    {
        PeripheralsInit();
        System_Initial();
        //flag = 1;
        while(1){}
    }
    
    interrupt void Main_ISR(void)
    {
        //flag = 2;
        static uint16_t u16index = 0;
    
    
        //DAC_CODE........GENERATE_SINE_WAVE
        if(gf32OmegaT>=2.0*PI_VALUE)
        {
           gf32OmegaT-=(2.0*PI_VALUE);
        }
        else
        {
            gf32OmegaT += (OMEGA*PLL_SAMPLING);
        }
    
        gf32Sine                = gf32ModulationIndex * sin(gf32OmegaT);
        gf32Sine_DAC            = 0.5 + (gf32Sine* 0.5);
        gu16DAC_value           = gf32Sine_DAC * ADC_VALUE;
        DacbRegs.DACVALS.all    = gu16DAC_value;
        gi16DAC_value           = gu16DAC_value - 2048;
    
    
        //ADC_CHECK_________________________________________
    
    
        gi16ADC_temp                        = AdccResultRegs.ADCRESULT0;
        strCheck.strinput.i16Prev_Sample    = AdccResultRegs.ADCRESULT1;
        strCheck.strinput.i16Present_Sample = gi32ADC_temp -  strCheck.strinput.i16Prev_Sample;
    
        strCheck.strinput.i32Second_Sample  = (int32_t)strCheck.strinput.i16Present_Sample;
    
        if ((strCheck.strinput.i32Second_Sample > 0x0FFF) && (strCheck.strinput.i32Second_Sample < 0x00100000))
        {
            strCheck.strOutput.i32Present_Sample = (strCheck.strinput.i32Second_Sample ^ 0xFFFFFFFF);
        }
        else
        {
            strCheck.strOutput.i32Present_Sample  = strCheck.strinput.i32Second_Sample;
    
        }
    if (u16index < BUFFERSIZE)
    {
        u16index++;
    }
    else
    {
        u16index = 0;
    }
    
        AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;  //CLEAR FLAG
        //
        // Acknowledge the interrupt
        //
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }
    void System_Initial(void)
    {
        strCheck.strCalibrate.i32Present_Sample =1024;
        strCheck.strCalibrate.i32Prev_Sample = 1024;
    }
    
    
    
    
    

  • Hi Amir,

    Please find the main code, we had added condition to capture the issue, by the breakpoint never hits..

    Since, this is a test code, we could share the complete project for you to test on the eval board. 

    Regards, 

    Muruga

  • Since, this is a test code, we could share the complete project for you to test on the eval board.

    Yes, if you have the exact project I can test on my board that would make this easier. Can you also tell me what sort of signal you're applying to the ADC (i.e. DC, sinusoidal, period/amplitude, etc.)?

  • Sine_DAC.zip

    Amir, 

    Please find the attached project and dev kit setup in the attachment. 

    Hope this help in your setup and finding a solution .

    Regards, 

    Muruga

  • I can import and build the project, but can you please provide me the information on what sort of signal you applied? Was it a DC voltage? Sine wave? If it was a sine wave, what were the max and min? The period?

    I need this information if I want to recreate the exact setup you used.

  • We are generating Sine wave and DC Signal, Shifting the sine wave by the DC signal to get negative sine wave which is being used in the inverter functionality. 

  • Hello Murugavelu,

    I tested the adc_ex5_soc_continuous driverlib example to check the ADC results after the conversions and I wasn't able to replicate your issue. I used a sine wave from 2.5 to 0.5 V as my analog input, and the casting to an int32_t didn't cause any clipping that I could see. Have you verified that you're voltage inputs are valid for the device (not exceeding datasheet specs)? Can you find an exact instance of where one value is converted to +/-6553x? Below is the code I inserted at the end of the while loop to look at the casting results:

    for(i = 0; i < 16; i++)
    {
        testingVal = (int32_t)adcAResults[resultsIndex-i];//FIXME: Test uint32_t cast
    }

  • Amir, 

    The ADC results fetched from the register and if casted to int32_t as mentioned above we do not see the issue, as the result is postive value. The result is subtracted with a value to generate a negative value and then type casted to int32_t then you should be able to replicate the issue.. 

    If the above adc_ex5_soc_continous code 

    int62_t u16offset= 2048;

    int26_t u16subValue;

    int32_t u32subValue;

    for(i = 0; i < 16; i++)
    {
                 testingVal = (int32_t)adcAResults[resultsIndex-i];

                 u16subValue = testingVal - u16offset;          // u16SubValue result is correct

                 u32subValue = (int32_t) u32subValue ;        // u32SubValue ramdomly shows at 6553x 

    }

    In the shared project please refer to line no 74 and line 76 as given below ...

    strCheck.strinput.i16Present_Sample = gi16ADC_temp -  strCheck.strinput.i16Prev_Sample;        // This gives the proper result

    strCheck.strinput.i32Second_Sample  = (int32_t)strCheck.strinput.i16Present_Sample;                  // This line does not randomly... 

    Regards, 

    Muruga

  • Hello Muruga,

    int62_t and int26_t are not valid datatypes, I assume you meant to use int32_t and int16_t. Also, the I believe you meant to have "u32subValue = (int32_t)u16subValue;" for the last line in the for-loop. Below is what I added to the example to check:

    //
    // Defines
    //
    
    int32_t testingVal = 0;
    int16_t subVal16 = 0;
    int32_t subVal32 = 0;
    int16_t offset = 2048;
    
    /*Other main code*/
                //Inserted at the end of the while(resultsIndex < RESULTS_BUFFER_SIZE) loop
                int16_t i;
                for(i = 0; i < 16; i++)
                {
                    testingVal = (int16_t)adcAResults[resultsIndex-i];
                    subVal16 = testingVal - offset;
                    subVal32 = (int32_t)subVal16;
                }

    I was still not able to find any issues, the subtraction occurred fine without going to 6553x or any incorrect value while stepping through it. If the code you've shown in your post is what you're using in your project, I'm not sure why you're seeing an issue where I'm not, since I'm also testing a sine wave and I'm able to subtract an offset to get a negative value. The only recommendation I have is to make sure at no point you're trying to subtract an offset from an unsigned integer, but it doesn't seem like that's what you're doing above.

  • Amir,

    "int62_t and int26_t are not valid datatypes" was typo.. thanks for pointing it out

    If you are running the loop for 16, then u wouldn't be able to check it..the below code should run in while (1), the value from the ADC should be changing so that the result is negative value, it is the same reason we where using the Sine wave generation as input to the ADC. 

    testingVal = (int16_t)adcAResults[resultsIndex-i];
    subVal16 = testingVal - offset;
    subVal32 = (int32_t)subVal16;

    We have already shared the complete project files and the hardware setup to emulate the issue.. prefer you to test that.

    Regards, 

    Muruga

  • Hello Muruga,

    We have already shared the complete project files and the hardware setup to emulate the issue.. prefer you to test that.

    No, you have provided me code for a single source file not the entire project. If you want me to be able to run your example, please export it using the CCS option so that I can have any necessary resource to run the project on my side (right-click the file in the Project Explorer window of CCS and select Export). There are two header files within that which seem to have structs and typedefs which I don't have visibility to. I have done my best to replicate your issue on my side based on your description and what I could see in your code.

    If you are running the loop for 16, then u wouldn't be able to check it..the below code should run in while (1), the value from the ADC should be changing so that the result is negative value, it is the same reason we where using the Sine wave generation as input to the ADC. 

    That for-loop was something I had within the main while(resultsIndex < RESULTS_BUFFER_SIZE) loop that was in the example but I can see how that might have been unclear from my shortening in the code above. I have modified the code to run infinitely and I'm still not seeing the issue you mention. If you can verify this runs on your side (you will need to use a driverlib example to test this), but your own project doesn't then please export your entire project and send it to me.

    //###########################################################################
    //
    // FILE:   adc_ex5_soc_continuous.c
    //
    // TITLE:  ADC continuous self-triggering.
    //
    //! \addtogroup driver_example_list
    //! <h1> ADC Continuous Triggering (adc_soc_continuous)</h1>
    //!
    //! This example sets up the ADC to convert continuously, achieving maximum
    //! sampling rate.\n
    //!
    //! \b External \b Connections \n
    //!  - A0 pin should be connected to signal to convert
    //!
    //! \b Watch \b Variables \n
    //! - \b adcAResults - A sequence of analog-to-digital conversion samples
    //! from pin A0. The time between samples is the minimum possible based on the
    //! ADC speed.
    //
    //#############################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 2023 Texas Instruments Incorporated - http://www.ti.com/
    //
    // 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.
    // $
    //#############################################################################
    //
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    //
    // Defines
    //
    #define RESULTS_BUFFER_SIZE     256 //buffer for storing conversion results
                                    //(size must be multiple of 16)
    int32_t testingVal = 0;
    int16_t subVal16 = 0;
    int32_t subVal32 = 0;
    int16_t offset = 2048;
    int16_t checker = 0;
    
    //
    // Globals
    //
    uint16_t adcAResults[RESULTS_BUFFER_SIZE];
    uint16_t resultsIndex;
    
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        // 
        // Board Initialization
        // - Configure the ADC and power it up
        // - Setup the ADC for continuous conversions on channel 0
        // 
        Board_init();
    
        //
        // Initialize results buffer
        //
        for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
        {
            adcAResults[resultsIndex] = 0;
        }
        resultsIndex = 0;
    
        //
        // Enable global Interrupts and higher priority real-time debug events:
        //
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
        //
        // Take conversions indefinitely in loop
        //
        do
        {
            //
            // Enable ADC interrupts
            //
            ADC_enableInterrupt(myADC0_BASE, ADC_INT_NUMBER1);
            ADC_enableInterrupt(myADC0_BASE, ADC_INT_NUMBER2);
            ADC_enableInterrupt(myADC0_BASE, ADC_INT_NUMBER3);
            ADC_enableInterrupt(myADC0_BASE, ADC_INT_NUMBER4);
    
            //
            // Clear all interrupts flags(INT1-4)
            //
            HWREGH(myADC0_BASE + ADC_O_INTFLGCLR) = 0x000F;
    
            //
            // Initialize results index
            //
            resultsIndex = 0;
    
            //
            // Software force start SOC0 to SOC7
            //
            HWREGH(myADC0_BASE + ADC_O_SOCFRC1) = 0x00FF;
    
            //
            // Keep taking samples until the results buffer is full
            //
            while(1)
            {
                //
                // Wait for first set of 8 conversions to complete
                //
                while(false == ADC_getInterruptStatus(myADC0_BASE, ADC_INT_NUMBER3));
    
                //
                // Clear the interrupt flag
                //
                ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER3);
    
                //
                // Save results for first 8 conversions
                //
                // Note that during this time, the second 8 conversions have
                // already been triggered by EOC6->ADCIN1 and will be actively
                // converting while first 8 results are being saved
                //
                adcAResults[resultsIndex] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER0);
                adcAResults[resultsIndex + 1] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER1);
                adcAResults[resultsIndex + 2] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER2);
                adcAResults[resultsIndex + 3] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER3);
                adcAResults[resultsIndex + 4] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER4);
                adcAResults[resultsIndex + 5] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER5);
                adcAResults[resultsIndex + 6] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER6);
                adcAResults[resultsIndex + 7] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER7);
    
                //
                // Wait for the second set of 8 conversions to complete
                //
                while(false == ADC_getInterruptStatus(myADC0_BASE, ADC_INT_NUMBER4));
    
                //
                // Clear the interrupt flag
                //
                ADC_clearInterruptStatus(myADC0_BASE, ADC_INT_NUMBER4);
    
                //
                // Save results for second 8 conversions
                //
                // Note that during this time, the first 8 conversions have
                // already been triggered by EOC14->ADCIN2 and will be actively
                // converting while second 8 results are being saved
                //
                adcAResults[resultsIndex + 8] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER8);
                adcAResults[resultsIndex + 9] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER9);
                adcAResults[resultsIndex + 10] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER10);
                adcAResults[resultsIndex + 11] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER11);
                adcAResults[resultsIndex + 12] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER12);
                adcAResults[resultsIndex + 13] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER13);
                adcAResults[resultsIndex + 14] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER14);
                adcAResults[resultsIndex + 15] = ADC_readResult(ADCARESULT_BASE,
                                                             ADC_SOC_NUMBER15);
    
                resultsIndex = (resultsIndex + 1) & 0xF;
                int16_t i;
                for(i = 0; i < 16; i++)
                {
                    testingVal = (int16_t)adcAResults[(resultsIndex-i) & 0xF];
                    subVal16 = testingVal - offset;
                    subVal32 = (int32_t)subVal16;
    
                    if((testingVal > 4096) || (subVal32 > 4096))
                    {
                        checker = 1;
                        ESTOP0;
                        break;
                    }
                }
            }
    
            //
            // Disable all ADCINT flags to stop sampling
            //
            ADC_disableInterrupt(myADC0_BASE, ADC_INT_NUMBER1);
            ADC_disableInterrupt(myADC0_BASE, ADC_INT_NUMBER2);
            ADC_disableInterrupt(myADC0_BASE, ADC_INT_NUMBER3);
            ADC_disableInterrupt(myADC0_BASE, ADC_INT_NUMBER4);
    
            //
            // At this point, adcAResults[] contains a sequence of conversions
            // from the selected channel
            //
    
            //
            // Software breakpoint, hit run again to get updated conversions
            //
            asm("   ESTOP0");
        }
        while(1); // Loop forever
    }
    
    //
    // End of file
    //