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.

CLA and inline function problem, assembly incorrect

Genius 5910 points

Other Parts Discussed in Thread: CONTROLSUITE

I have the following issue:

adcmemory is pointer to ADCRESULT registers

I have the following code:

#define MOTORVI_IIRA (0.414)        // EXP (-2 * PI 20k/160k)
#define MOTORVI_IIRB (0.293)        // (1 - A) /2
#pragma DATA_SECTION(CLARlastinputValue,"Cla1DataRam0")
volatile float CLARlastinputValue[13];

#pragma DATA_SECTION(adcmemory,"CpuToCla1MsgRAM")
 volatile unsigned short *adcmemory;
#pragma DATA_SECTION(CLARESULT,"Cla1ToCpuMsgRAM")
 volatile float CLARESULT[13];

#pragma FUNC_ALWAYS_INLINE(CLA_FILTER_Motor)
static inline void CLA_FILTER_Motor( int nummer )
{

  volatile float    inputValue = (unsigned short)*(adcmemory + nummer);
  float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * CLARlastinputValue[nummer]) + ((float)MOTORVI_IIRA * CLARESULT[nummer]);

  CLARlastinputValue[nummer] = inputValue;
  CLARESULT[nummer] = result;
}

__interrupt void Cla1Task2 ( void )
{
    // Read ADC and Filter Result
    __mdebugstop();

    CLA_FILTER_Motor (1);
}

This is the compiler output/disassembly:

0000903a:   7F600000    MDEBUGSTOP
0000903c:   7FA00000    MNOP       
0000903e:   7FA00000    MNOP       
00009040:   7FA00000    MNOP       
00009042:   799FFFBE    MCCNDD     0xffbe, UNCF
00009044:   7FA00000    MNOP       
00009046:   78400000    MMOVIZ     MR0, #0x0
00009048:   78800001    MMOVXI     MR0, #0x1
0000904a:   7FA00000    MNOP       
0000904c:   7FA00000    MNOP       
0000904e:   7FA00000    MNOP       
00009050:   7F800000    MSTOP     

I think I lost some code in the optimization.

Somebody any suggestion how to solve this? I like to have it in  a (inline) function because I have 10 adc channels to filter.

Any suggestion?

  • You expect CLA_FILTER_Motor to be inlined.  But it isn't.  Add the build option --src_interlist then inspect the assembly file created by the compiler (with extension .asm).  You will see something similar to this ...

    _Cla1Task2:
    ;*** 25	-----------------------    __mdebugstop();
    ;*** 27	-----------------------    CLA_FILTER_Motor(1);
    ;***  	-----------------------    return;
            MNOP      ; [CPU_] |25| 
            MNOP      ; [CPU_] |25| 
            MNOP      ; [CPU_] |25| 
            MDEBUGSTOP ; [CPU_] |25| 
            MNOP      ; [CPU_] |25| 
            MNOP      ; [CPU_] |25| 
            MNOP      ; [CPU_] |25| 
            MCCNDD    #_CLA_FILTER_Motor    ; [CPU_] |27| 
            MNOP      ; [CPU_] 
            MMOVIZ    MR0,#0                ; [CPU_] |27| 
            MMOVXI    MR0,#1                ; [CPU_] |27| 
            ; call occurs [#_CLA_FILTER_Motor] ; [] |27| 
            MSTOP     ; [CPU_] 
            ; ireturn occurs ; [] 

    The instructions are the same.  But now that you can see the symbol names and some comments, it makes more sense.

    Thanks and regards,

    -George

  • George Mock said:

    You expect CLA_FILTER_Motor to be inlined.  But it isn't.  

     

    The compiler does not like to inline functions with volatile locals.  I believe part of the reasoning is that "volatile" implies that the variable may be changed in some way that the compiler does not know about, and inlining would create multiple copies of the variable (one for each inlined body) which could interfere with that external mechanism.

    This restriction is documented in the compiler user's guide, typically in chapter 2 in a section named "Inlining Restrictions."

  • It is way more strange:

     This function works:

    static inline void CLA_FILTER_Motor( int number )
    {

      float    inputValue = (unsigned short)*(adcmemory + number);
     // float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * CLARADC[nummer]) + ((float)MOTORVI_IIRA * CLARESULT[number]);
      float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRA * CLARESULT[number]);
      CLARESULT[number] = result;
    }

    This function does not work: Result is garbage mainly zeros

    static inline void CLA_FILTER_Motor( int number )
    {

     volatile float    inputValue = (unsigned short)*(adcmemory + number); // VOLATILE is added,
      float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRA * CLARESULT[number]);
      CLARESULT[number] = result;
    }

    This function also doesn't work:

    static inline void CLA_FILTER_Motor( int number )
    {

      float    inputValue = (unsigned short)*(adcmemory + number);
       float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRA * CLARESULT[number]);
      CLARESULT[number] = result;
      CLARADC[number] = inputValue;   // Added this line no function
    }

    This function work:

    static inline void CLA_FILTER_Motor( int number )
    {

      float    inputValue = (unsigned short)*(adcmemory + number);
      float result = ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRB * inputValue) + ((float)MOTORVI_IIRA * CLARESULT[number]);
      CLARESULT[number] = result;
      CLARADC[number] = result + 10; // changed input
    }

    What I done to get it working is again. I moving   CLARADC[number] = (unsigned short)*(adcmemory + number); outsize the inline function and in to the TASK function. So In my (limited) view I think there is an issue with the compiler. But please tell me what I did wrong Or what document I didn't read.

     Thanks!

  • What version of the compiler do you use?  Please show all the build options.

    I cannot run the code.  I compared the assembly files generated by the compiler for the first two implementations of CLA_FILTER_Motor.  Making intputValue volatile changes things a lot.  The function is not inlined.  Every time inputValue is referenced in the C source, a memory reference occurs in the assembly. As far as I can tell, the same result is computed.  Please be very specific about how you know the result is incorrect.  Exactly how do you see this incorrect result?

    Thanks and regards,

    -George

  • How do I verify that the code is working: In debug mode I compare the results from CLARESULT with the ADC result register they should be the same. When they not the first  2 are updated and the rest of the not and are 0. My guess is, that is is a memory priority issue with memory location and ADC . 

    It is connected as follow:  Timer0(160khz) -> ADC(13 samples) ->  CLA -> CLARESULT   Without CPU intervention. Controller is F28069M.

    This is the compile command:

     'Invoking: C2000 Compiler'
    "C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.6/bin/cl2000" -v28 -ml -mt --float_support=fpu32 --tmu_support=tmu0 --cla_support=cla0 -O2 --opt_for_speed=2 --include_path="C:/ti/ccsv6/tools/compiler/ti-cgt-c2000_6.4.4/include" --include_path="I:/workspace/sw/solutions/CremerServo/src" --include_path="I:/workspace/sw/solutions/CremerServo/src/Canopen" --include_path="I:/workspace/sw/modules/hal/boards/drv8312kit_revD/f28x/f2806x/src" --include_path="I:/workspace" --include_path="C:/ti/controlSUITE/device_support/f2806x/v135/F2806x_common/include" --include_path="C:/ti/controlSUITE/device_support/f2806x/v135/F2806x_headers/include" --include_path="C:/ti/controlSUITE/device_support/f2806x/v135/MWare" --advice:performance=all -g --define=FAST_ROM_V1p6 --define=FLASH --define=QEP --diag_warning=225 --display_error_number --diag_suppress=2615 -k --src_interlist --preproc_with_compile --preproc_dependency="CLA_Tasklist.pp"  "../CLA_Tasklist.cla"