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.

_IQtoF doesn 't work

Genius 5910 points

Other Parts Discussed in Thread: MOTORWARE

hi,

I want to convert the IQ values to float values

This works:

return (intr->AdcData.dcBus *(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0)) / 16777216.0;

 this doesn't:

return _IQtoF (_IQmpy((float)intr->AdcData.dcBus,_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0)));

I tied many typecast to float. But without success.

 What is wrong?

 

  • EVS,

    It is difficult to tell what you are doing here.

    What is the type and value of each variable, especially intr->AdcData.dcBus?

    I don't understand why you typecast intr->AdcData.dcBus to (float) before operating on it with _IQmpy.

    I believe intr->AdcData.dcBus is a float.  Therefore, you must convert it to IQ type before you can use __IQmpy on it.

    For example:

    _iq a=_IQ(10.0);
    float32 b=2.5;
    float32 x=0.0;
    x = _IQtoF(_IQmpy(_IQ(b), a));

    When I run the above, I correctly get x=25.0.

    You should try this line:

    return _IQtoF(_IQmpy(_IQ(intr->AdcData.dcBus),_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0)));

     

    Regards,

    David

     

  • David thanks for the reply.

     When I run this:

    _iq a=_IQ(10.0);
    float b=2.5; // typedef float         float32;
    float x=0.0;
    x = _IQtoF(_IQmpy(_IQ(b), a));

    My result is:  0.244462 (that is the result i always have with _IQtoF or 0.0)

     

    AdcData.dcBus is the untangle data from gMotorVars. control data and debug data are separated.

    can you please do the test again:

     Compile it at FPU32. Test that the motor works correctly (important).

     And try again.

     Thanks.

     

     

  • evs,

    evs said:

    can you please do the test again:

    Compile it at FPU32. Test that the motor works correctly (important).

    The motor running is not really relevant here.  We're checking a specific computation here.  You are not getting the correct result.  I am.  You need to figure out why your computation is not working.  Then you can move on to the motor.

    I ran the test again.  I get the correct result, 25.0.

    The problem is not with the _IQtoF() function.  It must be elsewhere in your project.  Maybe you didn't link the IQ lib correctly.  I don't know.  Some devices have some of the IQ stuff in ROM.  You didn't say which device you are using.

    I broke the test case down into smaller pieces.

    _iq a=_IQ(10.0);
    _iq c,d;
    float32 b=2.5;
    float32 x=0.0;
    c = _IQ(b);
    d = _IQmpy(c,a);
    x = _IQtoF(d);

      Have the compiler generate a .asm file from your .c file, and check the generated assembly code against what I show below.  Make sure the code is actually calling the IQtoF function.  In my case, I am using GLOBAL_Q of 24, so it is calling _IQ24toF().  Below is my generated asm code.  I removed the extra lines with all the debug info junk, and also trailing compiler garbage at each line end.

    ;------------------------
    ;  58 | c = _IQ(b);     
    ;------------------------
            MOVW      DP,#_b
            SPM       #0
            MOVZ      AR6,SP
            MOV32     R0H,@_b
            SUBB      XAR6,#8
            LCR       #FS$$TOFD
            MOVZ      AR4,SP
            MOVZ      AR6,SP
            MOVL      XAR5,#$C$FL1
            SUBB      XAR4,#8
            SUBB      XAR6,#4
            LCR       #FD$$MPY
            MOVZ      AR4,SP
            SUBB      XAR4,#4
            LCR       #FD$$TOL
            MOVW      DP,#_c
            MOVL      @_c,ACC
    ;------------------------
    ;  59 | d = _IQmpy(c,a);
    ;------------------------
            MOVL      XT,@_c     \
            IMPYL     P,XT,@_a    \
            QMPYL     ACC,XT,@_a   |-- IQmpy inlines
            LSL64     ACC:P,#8    /
            MOVL      @_d,ACC    /
    ;------------------------
    ;  60 | x = _IQtoF(d);  
    ;------------------------
            MOVL      ACC,@_d
            LCR       #__IQ24toF  <--- call to IQ24toF()
            MOVW      DP,#_x
            MOV32     @_x,R0H

     

    Just a side comment, but the _IQ(b) seems pretty costly in terms of cycles.  First it is converted from a single to a doule precision float.  Then it apparently is multiplied by a scaling factor.  Finally, it is converted from a double precision float to a long.  Seems to me a better way to do this calculation is this:

    x = b*_IQtoF(a);

    which generates much more efficient code:

    ;--------------------------
    ;  62 | x = b*_IQtoF(a);  
    ;--------------------------
            MOVW      DP,#_a
            SPM       #0
            MOVL      ACC,@_a
            LCR       #__IQ24toF
            MOVW      DP,#_b
            MOV32     R1H,@_b
            MPYF32    R0H,R0H,R1H
            NOP
            MOV32     @_x,R0H

     

    Regards,

    David

  • I'm using the F28069M and I think there is something wrong in the rom or the IQmath lib. Specially the IQ to float conversion.  That is the reason why I ask to compile the library under FPU32 and test if the motor is running.

    how do I output asm code?

    edit: I think the problem is in IQ24toF compiled with FPU32  But I can't check that.

  • My project is built using fpu32 code model:

    I am running on a F28069 (regular device, not the Instaspin 'M' device).

    You can access the .asm files in the project options, Build->C2000 Compiler->Advanced Options ->Asxsembler Options.  Check the -k option, and also use -ss to interlist the C source.

    If you think there is a ROM problem (I doubt there is, but...), adjust your linker .cmd file to NOT use the IQ stuff in the ROM.  You probably have something like this in your .cmd:

    IQmath            : > FLASH,                 PAGE = 0
    IQmathTables      : > IQTABLES,              PAGE = 0, TYPE = NOLOAD
    IQmathTables2     : > IQTABLES2,             PAGE = 0, TYPE = NOLOAD
    {
        IQmath_fpu32.lib<IQNexpTable.obj> (IQmathTablesRam)
    }
    IQmathTables3     : > IQTABLES3,             PAGE = 0, TYPE = NOLOAD
    {
        IQmath_fpu32.lib<IQNasinTable.obj> (IQmathTablesRam)
    }

     

    Instead, link the tables to flash and get rid of the NOLOAD:

    IQmath            : > FLASH,                 PAGE = 0
    IQmathTables      : > FLASH,                 PAGE = 0
    IQmathTables2     : > FLASH,                 PAGE = 0
    {
        IQmath_fpu32.lib<IQNexpTable.obj> (IQmathTablesRam)
    }
    IQmathTables3     : > FLASH,                 PAGE = 0
    {
        IQmath_fpu32.lib<IQNasinTable.obj> (IQmathTablesRam)
    }

    This will create new tables in flash for these sections, and not use the ROM tables.

    - David

  • Before you doubt it: please check the following: replace your controller with a M type

     - do Lab10 fpu32 test

    - Try to set GPIO28 and GP29 as input and check that they work correctly

    - Try to get a stable usb to serial interface

    If there is an other controller that is proven to work well I like to know. Those problem cost me a lot of time.

    Do I need to change this line also:FPUmathTables       : > FPUTABLES,  PAGE = 0, TYPE = NOLOAD

    This I my asm result. It is the raw format because I am afraid i throw away something useful. I like to avoid

    _Contrl_GetVdcBus_kV:
        .dwcfi    cfa_offset, -2
        .dwcfi    save_reg_to_mem, 26, 0
        .dwcfi    save_reg_to_reg, 78, 26
            ADDB      SP,#20                ; [CPU_U]
        .dwcfi    cfa_offset, -22
    $C$DW$1594    .dwtag  DW_TAG_variable, DW_AT_name("intr")
        .dwattr $C$DW$1594, DW_AT_TI_symbol_name("_intr")
        .dwattr $C$DW$1594, DW_AT_type(*$C$DW$T$266)
        .dwattr $C$DW$1594, DW_AT_location[DW_OP_breg20 -2]
    $C$DW$1595    .dwtag  DW_TAG_variable, DW_AT_name("a")
        .dwattr $C$DW$1595, DW_AT_TI_symbol_name("_a")
        .dwattr $C$DW$1595, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1595, DW_AT_location[DW_OP_breg20 -4]
    $C$DW$1596    .dwtag  DW_TAG_variable, DW_AT_name("c")
        .dwattr $C$DW$1596, DW_AT_TI_symbol_name("_c")
        .dwattr $C$DW$1596, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1596, DW_AT_location[DW_OP_breg20 -6]
    $C$DW$1597    .dwtag  DW_TAG_variable, DW_AT_name("d")
        .dwattr $C$DW$1597, DW_AT_TI_symbol_name("_d")
        .dwattr $C$DW$1597, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1597, DW_AT_location[DW_OP_breg20 -8]
    $C$DW$1598    .dwtag  DW_TAG_variable, DW_AT_name("b")
        .dwattr $C$DW$1598, DW_AT_TI_symbol_name("_b")
        .dwattr $C$DW$1598, DW_AT_type(*$C$DW$T$16)
        .dwattr $C$DW$1598, DW_AT_location[DW_OP_breg20 -10]
    $C$DW$1599    .dwtag  DW_TAG_variable, DW_AT_name("x")
        .dwattr $C$DW$1599, DW_AT_TI_symbol_name("_x")
        .dwattr $C$DW$1599, DW_AT_type(*$C$DW$T$16)
        .dwattr $C$DW$1599, DW_AT_location[DW_OP_breg20 -12]
            MOVL      *-SP[2],XAR4          ; [CPU_] |523|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 529,column 7,is_stmt
            MOV       ACC,#5120 << 15       ; [CPU_] |529|
            MOVL      *-SP[4],ACC           ; [CPU_] |529|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 531,column 9,is_stmt
            MOVIZ     R0H,#16416            ; [CPU_] |531|
            MOV32     *-SP[10],R0H          ; [CPU_] |531|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 532,column 9,is_stmt
            ZERO      R0H                   ; [CPU_] |532|
            MOV32     *-SP[12],R0H          ; [CPU_] |532|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 533,column 2,is_stmt
            MOV32     R0H,*-SP[10]          ; [CPU_] |533|
            MOVZ      AR6,SP                ; [CPU_U] |533|
            SUBB      XAR6,#20              ; [CPU_U] |533|
    $C$DW$1600    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1600, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1600, DW_AT_name("FS$$TOFD")
        .dwattr $C$DW$1600, DW_AT_TI_call
            LCR       #FS$$TOFD             ; [CPU_] |533|
            ; call occurs [#FS$$TOFD] ; [] |533|
            MOVZ      AR4,SP                ; [CPU_U] |533|
            MOVZ      AR6,SP                ; [CPU_U] |533|
            MOVL      XAR5,#$C$FL1          ; [CPU_U] |533|
            SUBB      XAR4,#20              ; [CPU_U] |533|
            SUBB      XAR6,#16              ; [CPU_U] |533|
    $C$DW$1601    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1601, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1601, DW_AT_name("FD$$MPY")
        .dwattr $C$DW$1601, DW_AT_TI_call
            LCR       #FD$$MPY              ; [CPU_] |533|
            ; call occurs [#FD$$MPY] ; [] |533|
            MOVZ      AR4,SP                ; [CPU_U] |533|
            SUBB      XAR4,#16              ; [CPU_U] |533|
    $C$DW$1602    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1602, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1602, DW_AT_name("FD$$TOL")
        .dwattr $C$DW$1602, DW_AT_TI_call
            LCR       #FD$$TOL              ; [CPU_] |533|
            ; call occurs [#FD$$TOL] ; [] |533|
            MOVL      *-SP[6],ACC           ; [CPU_] |533|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 534,column 2,is_stmt
            MOVL      XT,*-SP[6]            ; [CPU_] |534|
            IMPYL     P,XT,*-SP[4]          ; [CPU_] |534|
            QMPYL     ACC,XT,*-SP[4]        ; [CPU_] |534|
            LSL64     ACC:P,#8              ; [CPU_] |534|
            MOVL      *-SP[8],ACC           ; [CPU_] |534|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 535,column 2,is_stmt
            MOVL      ACC,*-SP[8]           ; [CPU_] |535|
    $C$DW$1603    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1603, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1603, DW_AT_name("__IQ24toF")
        .dwattr $C$DW$1603, DW_AT_TI_call
            LCR       #__IQ24toF            ; [CPU_] |535|
            ; call occurs [#__IQ24toF] ; [] |535|
            MOV32     *-SP[12],R0H          ; [CPU_] |535|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 536,column 2,is_stmt
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 538,column 1,is_stmt
            SUBB      SP,#20                ; [CPU_U]
        .dwcfi    cfa_offset, -2
    $C$DW$1604    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1604, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1604, DW_AT_TI_return
            LRETR     ; [CPU_]
            ; return occurs ; []
        .dwattr $C$DW$1592, DW_AT_TI_end_file("I:/workspace/sw/solutions/CremerServo/src/control_Interface.c")
        .dwattr $C$DW$1592, DW_AT_TI_end_line(0x21a)
        .dwattr $C$DW$1592, DW_AT_TI_end_column(0x01)
        .dwendentry
        .dwendtag $C$DW$1592

     

    _Contrl_GetVdcBus_kV:
        .dwcfi    cfa_offset, -2
        .dwcfi    save_reg_to_mem, 26, 0
        .dwcfi    save_reg_to_reg, 78, 26
            ADDB      SP,#20                ; [CPU_U]
        .dwcfi    cfa_offset, -22
    $C$DW$1594    .dwtag  DW_TAG_variable, DW_AT_name("intr")
        .dwattr $C$DW$1594, DW_AT_TI_symbol_name("_intr")
        .dwattr $C$DW$1594, DW_AT_type(*$C$DW$T$266)
        .dwattr $C$DW$1594, DW_AT_location[DW_OP_breg20 -2]
    $C$DW$1595    .dwtag  DW_TAG_variable, DW_AT_name("a")
        .dwattr $C$DW$1595, DW_AT_TI_symbol_name("_a")
        .dwattr $C$DW$1595, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1595, DW_AT_location[DW_OP_breg20 -4]
    $C$DW$1596    .dwtag  DW_TAG_variable, DW_AT_name("c")
        .dwattr $C$DW$1596, DW_AT_TI_symbol_name("_c")
        .dwattr $C$DW$1596, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1596, DW_AT_location[DW_OP_breg20 -6]
    $C$DW$1597    .dwtag  DW_TAG_variable, DW_AT_name("d")
        .dwattr $C$DW$1597, DW_AT_TI_symbol_name("_d")
        .dwattr $C$DW$1597, DW_AT_type(*$C$DW$T$83)
        .dwattr $C$DW$1597, DW_AT_location[DW_OP_breg20 -8]
    $C$DW$1598    .dwtag  DW_TAG_variable, DW_AT_name("b")
        .dwattr $C$DW$1598, DW_AT_TI_symbol_name("_b")
        .dwattr $C$DW$1598, DW_AT_type(*$C$DW$T$16)
        .dwattr $C$DW$1598, DW_AT_location[DW_OP_breg20 -10]
    $C$DW$1599    .dwtag  DW_TAG_variable, DW_AT_name("x")
        .dwattr $C$DW$1599, DW_AT_TI_symbol_name("_x")
        .dwattr $C$DW$1599, DW_AT_type(*$C$DW$T$16)
        .dwattr $C$DW$1599, DW_AT_location[DW_OP_breg20 -12]
            MOVL      *-SP[2],XAR4          ; [CPU_] |523|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 529,column 7,is_stmt
            MOV       ACC,#5120 << 15       ; [CPU_] |529|
            MOVL      *-SP[4],ACC           ; [CPU_] |529|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 531,column 9,is_stmt
            MOVIZ     R0H,#16416            ; [CPU_] |531|
            MOV32     *-SP[10],R0H          ; [CPU_] |531|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 532,column 9,is_stmt
            ZERO      R0H                   ; [CPU_] |532|
            MOV32     *-SP[12],R0H          ; [CPU_] |532|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 533,column 2,is_stmt
            MOV32     R0H,*-SP[10]          ; [CPU_] |533|
            MOVZ      AR6,SP                ; [CPU_U] |533|
            SUBB      XAR6,#20              ; [CPU_U] |533|
    $C$DW$1600    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1600, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1600, DW_AT_name("FS$$TOFD")
        .dwattr $C$DW$1600, DW_AT_TI_call
            LCR       #FS$$TOFD             ; [CPU_] |533|
            ; call occurs [#FS$$TOFD] ; [] |533|
            MOVZ      AR4,SP                ; [CPU_U] |533|
            MOVZ      AR6,SP                ; [CPU_U] |533|
            MOVL      XAR5,#$C$FL1          ; [CPU_U] |533|
            SUBB      XAR4,#20              ; [CPU_U] |533|
            SUBB      XAR6,#16              ; [CPU_U] |533|
    $C$DW$1601    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1601, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1601, DW_AT_name("FD$$MPY")
        .dwattr $C$DW$1601, DW_AT_TI_call
            LCR       #FD$$MPY              ; [CPU_] |533|
            ; call occurs [#FD$$MPY] ; [] |533|
            MOVZ      AR4,SP                ; [CPU_U] |533|
            SUBB      XAR4,#16              ; [CPU_U] |533|
    $C$DW$1602    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1602, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1602, DW_AT_name("FD$$TOL")
        .dwattr $C$DW$1602, DW_AT_TI_call
            LCR       #FD$$TOL              ; [CPU_] |533|
            ; call occurs [#FD$$TOL] ; [] |533|
            MOVL      *-SP[6],ACC           ; [CPU_] |533|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 534,column 2,is_stmt
            MOVL      XT,*-SP[6]            ; [CPU_] |534|
            IMPYL     P,XT,*-SP[4]          ; [CPU_] |534|
            QMPYL     ACC,XT,*-SP[4]        ; [CPU_] |534|
            LSL64     ACC:P,#8              ; [CPU_] |534|
            MOVL      *-SP[8],ACC           ; [CPU_] |534|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 535,column 2,is_stmt
            MOVL      ACC,*-SP[8]           ; [CPU_] |535|
    $C$DW$1603    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1603, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1603, DW_AT_name("__IQ24toF")
        .dwattr $C$DW$1603, DW_AT_TI_call
            LCR       #__IQ24toF            ; [CPU_] |535|
            ; call occurs [#__IQ24toF] ; [] |535|
            MOV32     *-SP[12],R0H          ; [CPU_] |535|
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 536,column 2,is_stmt
        .dwpsn    file "I:/workspace/sw/solutions/CremerServo/src/control_Interface.c",line 538,column 1,is_stmt
            SUBB      SP,#20                ; [CPU_U]
        .dwcfi    cfa_offset, -2
    $C$DW$1604    .dwtag  DW_TAG_TI_branch
        .dwattr $C$DW$1604, DW_AT_low_pc(0x00)
        .dwattr $C$DW$1604, DW_AT_TI_return
            LRETR     ; [CPU_]
            ; return occurs ; []
        .dwattr $C$DW$1592, DW_AT_TI_end_file("I:/workspace/sw/solutions/CremerServo/src/control_Interface.c")
        .dwattr $C$DW$1592, DW_AT_TI_end_line(0x21a)
        .dwattr $C$DW$1592, DW_AT_TI_end_column(0x01)
        .dwendentry
        .dwendtag $C$DW$1592

  • evs,

    evs said:

    Before you doubt it: please check the following: replace your controller with a M type

     - do Lab10 fpu32 test

    - Try to set GPIO28 and GP29 as input and check that they work correctly

    - Try to get a stable usb to serial interface

    I am not on the Instaspin team, and do not have the F28069M hardware setup.  I was just trying to answer your original assertion that the _IQtoF() function does not work.  I have tested it, and it does work.  If your motor system is not working, then something else is going on in your system.

    Again, I suggest working the _IQtoF() issue first and forget about the motor.  I showed a simple test case where the result is 25.0.  You are not getting that.  The question is why.  I'd work that problem first.  Once resolved, it may fix the rest of the problems with the motor too.

    Regards,

    - David

     

  • evs,

    which version of the compiler are you using as effective in your project?

    version 6.2.0-6.2.2 has an IQmath saturation bug.

  • David, I really appreciate you 're help. But I have a lot of problems that are impossible to solve with the information provided by TI. 

    When I go to this forum I already spend days to pinpoint the problem. So maybe you understand my frustrations. What I'm trying to say is, that we may have a look in the library function _IQmpy  that there maybe conditions that the function doesn't work as expected. And what I tried to show is that there are enough examples that legitimate that question.

     My cl2000 version is.  6.2.8

  • Results!!

        float x=0.0;
        _iq c,d;
        _iq a=_IQ(10.0);
        volatile float b=5;
        //c = _IQ(b);
        x = _IQ24toF(a);

     result: X=5

        float x=0.0;
        _iq c,d;
        _iq a=_IQ(10.0);
        volatile float b=2.5;
        //c = _IQ(b);
        x = _IQ24toF(a);

    result: x=2.5

    Stack problem? I resized my stack form 1k to 4k but still the same result.

  • evs,

    This should be debuggable.

    The parameter 'a' is a long (32-bit), so the compiler will pass it to the function in the ACC (see Compiler Users Guide, SPRU514G, p.132).  You should be able to step through the disassembly and see what value is being passed to _IQ24toF(), and anything else that is going wrong here.

    - David

  • David,

     I really, really like to avoid debugging assembly. specially a controller i'm not familiar with.

     But ok.

     How do I put register in the watch window:  like R0 and *+XAR2[4]

    Thanks

  • evs,

    In CCS, try View->Registers.

    - David

  • Found it!

    133         volatile float b=2.5;
    3e6566:   E8020100    MOVIZ        R0, #0x4020
    3e6568:   E20300E2    MOV32        *+XAR2[4], R0H
    134         x = _IQ24toF(a);
    3e656a:   06F2        MOVL         ACC, *+XAR2[6]
    3e656b:   767FF1D4    LCR          0x3ff1d4
    3e656d:   D008        MOVB         XAR0, #0x8
    3e656e:   E2030092    MOV32        *+XAR2[AR0], R0H

    AT 3e6568 R0H is filled with 0x4020 end at 3e656e it is moved back in the result register

    R0H is not used in the  _IQ24toF code:

    3ff1d4:   5635        CSB          ACC
    3ff1d5:   563B        LSLL         ACC, T
    3ff1d6:   A3A9        MOVL         P, @ACC
    3ff1d7:   1CABFFFF    XOR          @PL, #0xffff
    3ff1d9:   1CAA7FFF    XOR          @PH, #0x7fff
    3ff1db:   564803AB    MOVL         @P, ACC, GEQ
    3ff1dd:   9B85        MOVB         AH, #0x85
    3ff1de:   EBAC        SUBR         @T, AH
    3ff1df:   06AB        MOVL         ACC, @P
    3ff1e0:   56B100AC    MOVB         @T, #0x00, EQ
    3ff1e2:   568D        ASR64        ACC:P, 14
    3ff1e3:   18A8FF00    AND          @AH, #0xff00
    3ff1e5:   95AC        ADD          AH, @T
    3ff1e6:   56A6        LSL64        ACC:P, 7
    3ff1e7:   0006        LRETR       

    Edit: Missing return result(P) in code?

  • evs,

    The key line of code is this one:

    3e656a:   06F2        MOVL         ACC, *+XAR2[6]

    That is supposed to be loading 'a' into the ACC.  The value in ACC is picked up by the _IQtoF() function.  It converts to float, and then passes the return value (in float format) back in the ACC.

    - David

  • David,

     Why do you think that is not happening?

    I can trace the result back in the IQ24toF

    at 

    3ff1e6:   56A6        LSL64        ACC:P, 7

     In P register only nothings is done with the result.

     When I check other functions then the result is passed to R0H before the return. I can 't find that is this function and that explains the problem.

     

  • evs,

    I mistated before that the return value will be put in the ACC.  For a float return, R0H is used.  So, you are correct here.

    This is the _IQ24toF() assembly code from my test case:

            $..\src\IQNtoF_fpu32.asm:118:261$(), _IQ24toF:
    00a8d6:   5635        CSB          ACC
    00a8d7:   563B        LSLL         ACC, T
    00a8d8:   A3A9        MOVL         P, @ACC
    00a8d9:   1CABFFFF    XOR          @PL, #0xffff
    00a8db:   1CAA7FFF    XOR          @PH, #0x7fff
    00a8dd:   564803AB    MOVL         @P, ACC, GEQ
    00a8df:   9B85        MOVB         AH, #0x85
    00a8e0:   EBAC        SUBR         @T, AH
    00a8e1:   06AB        MOVL         ACC, @P
    00a8e2:   56B100AC    MOVB         @T, #0x00, EQ
    00a8e4:   568D        ASR64        ACC:P, 14
    00a8e5:   18A8FF00    AND          @AH, #0xff00
    00a8e7:   95AC        ADD          AH, @T
    00a8e8:   56A6        LSL64        ACC:P, 7
    00a8e9:   BDA90F12    MOV32        R0H, @ACC
    00a8eb:   0006        LRETR

    and we can compare with the code you showed a couple of posts back:

    3ff1d4:   5635        CSB          ACC
    3ff1d5:   563B        LSLL         ACC, T
    3ff1d6:   A3A9        MOVL         P, @ACC
    3ff1d7:   1CABFFFF    XOR          @PL, #0xffff
    3ff1d9:   1CAA7FFF    XOR          @PH, #0x7fff
    3ff1db:   564803AB    MOVL         @P, ACC, GEQ
    3ff1dd:   9B85        MOVB         AH, #0x85
    3ff1de:   EBAC        SUBR         @T, AH
    3ff1df:   06AB        MOVL         ACC, @P
    3ff1e0:   56B100AC    MOVB         @T, #0x00, EQ
    3ff1e2:   568D        ASR64        ACC:P, 14
    3ff1e3:   18A8FF00    AND          @AH, #0xff00
    3ff1e5:   95AC        ADD          AH, @T
    3ff1e6:   56A6        LSL64        ACC:P, 7
    3ff1e7:   0006        LRETR

    So I understand what you've been saying now.  Your code is missing the MOV32 to put the return value into R0H.

    What version of the IQmath library are you using?

    Have you tried linking the IQmath stuff to flash (as I showed previously) and not use the ROM contents?

    - David

    Update 10/8/14, 1025AM EDT: I've asked the C2000 team to check the ROM on the F2806xM devices.  Something seems potentially amiss here.

  • David,

    I changed the Linker Command File to this:

       IQmath              : > FLASHA_B,   PAGE = 0            /* Math Code */
       IQmathTables        : > IQTABLES,   PAGE = 0//, TYPE = NOLOAD
       
       /* Allocate FPU math areas: */
       FPUmathTables       : > FPUTABLES,  PAGE = 0//, TYPE = NOLOAD

     Results are the same.

     I have motorware version: 1_01_00_13

      IQmath.h file It is version: 1.5C.

     Compiler 6.2.8

     

     

  • EVS,

    are you using the correct libs for an FPU project that we use in MotorWare

    AND are you following the correct LINK ORDER per our projects?

  • evs,

    The factory team confirmed that the IQmath functions in ROM on the F2806xM devices are not built with fpu32 option.  So, they will not work that way.

    Put all the IQmath stuff in flash.  It has to work.

       IQmath            : > FLASH,             PAGE = 0
       IQmathTables      : > FLASH,             PAGE = 0
       IQmathTables2     : > FLASH,             PAGE = 0
       {
           IQmath_fpu32.lib<IQNexpTable.obj> (IQmathTablesRam)
       }
       IQmathTables3     : > FLASH,             PAGE = 0
       {
           IQmath_fpu32.lib<IQNasinTable.obj> (IQmathTablesRam)
       }

    I suspect that the IQmathTables and IQmathTables2 is the same for fpu32 and non-fpu32 builds, but I'm not certain for better to start by using everything from flash.  Anyway, I know you indicated a few posts back that you linked IQmath to flash and it still didn't work, but that doesn't make sense.  Take a look at the ASM code for the _IQ24toF() function in flash.  It should put the return value in R0H.  Make certain you are calling this function (put a breakpoint there).

    - David

     

  • EVS,

    The motor control library in ROM is built in fixed point, NO float.  You can use the FPU in your own code, but you need to take action on motor ROM functions that return a floating point value.  Note that in every proj_lab## example built for user floating point we show the following in the

    void updateGlobalVariables_motor(CTRL_Handle handle)

      // when calling EST_ functions that return a float, and fpu32 is enabled, an integer is needed as a return
      // so that the compiler reads the returned value from the accumulator instead of fpu32 registers
      // get the magnetizing current
      tmp = EST_getIdRated(obj->estHandle);
      gMotorVars.MagnCurr_A = *((float_t *)&tmp);

  • David,

     If I understand correctly the difference between the FPU32 and non FPU32 code is the way it handles the return of a value in the function return?  Is this for all values or only for float?
     So moving _IQtoF to user space solve the problem. and the other way around,  _IQ is that  a problem?

     I checked the code size and it didn't change. so moving iqmatch library to RAM didn't work.

     So I replaced it with your code:

       IQmath            : > FLASHA_B,             PAGE = 0
       IQmathTables      : > FLASHA_B,             PAGE = 0
       IQmathTables2     : > FLASHA_B,             PAGE = 0
       {
           IQmath_fpu32.lib<IQNexpTable.obj> (IQmathTablesRam) <= warning #10068-D: no matching section
       }
       IQmathTables3     : > FLASHA_B,             PAGE = 0                    
       {
           IQmath_fpu32.lib<IQNasinTable.obj> (IQmathTablesRam)   <= warning #10068-D: no matching section
       }

     To fix it. I tried someting like this:

         IQmathTablesRam       : > RAML5,    PAGE = 1

     But that did not helped much. Any suggestion? Is there an working example anywhere so I can see how it is done?



     The F28069M is a really expansive controller  (http://www.digikey.nl/product-detail/en/TMS320F28069MPZT/296-36224-5-ND/3789658)
     I can't use the CLA because of the ROM code the use of the FPU is limited because of the ROM code.  Controlling multiple processes is limited because limited (non) interrupt priority system. When a interrupt is serviced no other can't be serviced. And I really like to know how to get a stable usb connection.
     So I was wondering what is the advantage to use the F28069M compared with the F28054M?

  • evs said:
     I can't use the CLA because of the ROM code the use of the FPU is limited because of the ROM code.

    False. You can use the CLA with the InstaSPIN ROM enabled devices/projects. There are customers in production doing just this.

    evs said:
     So I was wondering what is the advantage to use the F28069M compared with the F28054M?

    Not an advantage, a choice: 50% more MIPS, FPU option, CLA option, larger Flash/RAM, larger package option, more peripheral options

    That's why we offer a portfolio of InstaSPIN enabled devices

    http://www.ti.com/ww/en/mcu/instaspin/instaspin-foc_MCUs.shtml