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.

IQmath conversion problem

Other Parts Discussed in Thread: TM4C1294NCPDT

Hello,

I'm trying to use the IQmath library with Stellaris LM4F.

Everything seems to compile right, but I've written a simple code:

#define PI    3.14159265359
#define PI2    _IQ21((float)PI)

    float n1, n2;

    n1=_IQ21toF(PI2);

    n2=0; // for breakpoint

And now I debug it (optimization level: off, optimization for speed: 0, floating point mode: strict). After reaching breakpoint the CCS shows n1=0. 

View of the disassembly code:

             n1=_IQ21toF(PI2);
00000626:    4805     LDR             R0, $C$CON1
00000628:    F000F81E BL              $C:/DriverLib/build/DriverLib.test/IQmath/ti/IQNtoF.asm:1275:1328$
0000062c:    ED8D0A04 FSTS            S0, [R13, #16]

It's interesting, since trace "C:/DriverLib/build/DriverLib.test/IQmath/ti/IQNtoF.asm" doesn't exist, but never mind.

The "$C:/DriverLib/build/DriverLib.test/IQmath/ti/IQNtoF.asm:1275:1328$" disasembled code:

           $C:/DriverLib/build/DriverLib.test/IQmath/ti/IQNtoF.asm:1275:1328$, _IQ21toF:
00000668:    B178     CZBEQ           R0, r0isZero21
0000066a:    F0104100 ANDS.W          R1, R0, #2147483648
0000066e:    BF48     IT              MI
00000670:    4240     NEG             R0, R0
00000672:    FAB0F380 CLZ.W           R3, R0
00000676:    F1C30289 RSB.W           R2, R3, #137
0000067a:    FA00F003 LSL.W           R0, R0, R3
0000067e:    EA4F2010 MOV.W           R0, R0, LSR #8
00000682:    F36250DE BFI.W           R0, R2, #23, #8
00000686:    EA410000 ORR.W           R0, R1, R0
           r0isZero21:
0000068a:    4770     BX              R14

Can you tell me find what is wrong? I've tried an _IQ21cos function and it probably works (result is !=0 ), so the library seems be used ok.

  • Mikolaj,

    Do the results change if you add an 'f' after the PI constant like this:

    #define PI    3.14159265359f

    Which version of CCS and compiler are you using?

    Thanks,

    Sean

  • Thank you for the answer, but unfortunately it still doesn't work.

    I tried also:

        _iq21 var=50;

        n1=_IQ21toF(var);

    and the result is also 0, so there is probably a library or project error.

    Compiler version: TI v5.0.4

  • Mikolaj Filar said:
    After reaching breakpoint the CCS shows n1=0.

    I have repeated the problem using TivaWare 1.0 running on a Stellaris Launchpad. The main.c test program was compiled with the default LM4F --float_support option of FPv4SPD16. 

    The prototype for _IQ21toF is defined in IQMathLib.h as the following, which as per the EABI the result should be returned in floating point register S0:

    extern float _IQ21toF(_iq21 A);

    Single stepping the assembler of _IQ21toF shows it only using integer registers and returning a result of 0x40490FDC in integer register R0.  0x40490FDC interpreted as a 32-bit float = 3.141593 which is the correct value. However, the problem is that the result is returned in the integer register R0 rather than the floating-point register S0 expected by the caller.

    Guess the problem is that _IQ21toF has been written in assembler, and doesn't conform the EABI for returning floating point values. i.e. a problem in the IQMath library. Haven't (yet) checked if a similar problem exists in other IQMath library functions.

  • Chester Gillon said:
    I have repeated the problem using TivaWare 1.0 running on a Stellaris Launchpad. The main.c test program was compiled with the default LM4F --float_support option of FPv4SPD16.

    Also tried using IQMath from StellarisWare version 9453:

    1) Compiling for a LM4F120H5QR with --float_support=FPv4SPD16 and linking against the StellarisWare IQmath\ccs-cm4f\IQmathLib-cm4f\IQmathLib-cm4f.lib produced the same results as with TivaWare 1.0, in that the result from _IQ21toF is returned in register R0 rather than S0 that the caller expects.

    2) Compling for a LM4F120H5QR with --float_support=vfplib and linking against the StellarisWare IQmath\ccs-cm3\IQmathLib-cm3\Debug\IQmathLib-cm3.lib produced the correct results in that n1 = 3.141593. With --float_support=vfplib (software floating point) the C compiler expects _IQ21toF to return a result in integer register R0 which is what  _IQ21toF does.

    Compiling main.c for a LM4F with the --float_support option of FPv4SPD16 is the correct option for linking against the TivaWare TivaWare_C_Series-1.0\IQmath\ccs\IQmathLib\Debug\IQmathLib.lib, since trying any other --float_support option results in either a compiler error about not supported on a Cortex M4F or a linker error about incompatible library files. Therefore, the problem is not an incorrect CCS project setting.

  • Chester,

    Good work on the debugging -- it does appear there is a problem with IQmath and the Cortem M4F.  I will bring up this issue with the compiler team.  In the meantime, is there a reason you are using IQmath over just using the hardware floating point module?

    Thanks,

    Sean

  • Thank you for your commitment.

    There is a IQmath library for Stellaris and Tiva microcontrollers and I expect it's possible to gain something using it. Since I haven't found comparison between math.h and IQmath functions time execution for floating point mcus I want to try it and maybe use in some solutions.

    I also want to check if IQmath uses somewhere floating point unit, even there isn't info abut it. IQmath description in TivaWare™ IQmath Library  User's Guide is copied from Stellaris - "Stellaris" word is using instead of "Tiva" word - so there is a chance the library uses FPU  :)

  • Mikolaj Filar said:
    I also want to check if IQmath uses somewhere floating point unit, even there isn't info abut it.

    To investigate:

    a) Used armar to extract the .obj files from the TivaWare 1.0 IQmath\ccs\IQmathLib\Debug\IQmathLib.lib

    b) Used armdis to disassemble each .obj file from the the IQmathLib.lib

    c) Used grep "S[0-9]" and grep " D[0-9]" to check for any floating point registers being used in the disassembled IQmath functions.

    No floating point registers were seen in the disassembled IQmath functions, so the conclusion is that IQmath doesn't use the floating point unit.

    Edit: Added a check of doubleword floating point registers, as well as single word floating point registers.

  • Chester Gillon said:
    Haven't (yet) checked if a similar problem exists in other IQMath library functions.

    Checked the _IQ21tofunction in TivaWare 1.0, and it has a similar problem to the _IQ21toF in that:

    a) _IQ21toD returned its result in the integer register pair R0, R1.

    b) Whereas as the calling C function expected the result to be returned in the floating point double word register D0.

    Looking in the IQmathLib.h include file the only functions which use floating point arugments are the _IQntoF and _IQntoD which convert an IQ number to single-precision or double-precision floating point values. Therefore, believe that only these two sets of functions are affected.

    [but haven't tested all the functions on a LM4F]

  • Nice one!

    Thank you for investigation. Problem is still open but I will use FPU and standard math.h implementations for Stellaris LM4F and Tiva chips.

    Best regards,

    Mikolaj

  • Sean de la Haye said:
    it does appear there is a problem with IQmath and the Cortem M4F.  I will bring up this issue with the compiler team.

    Is it planed to fix this?

    The problem still exists in the IQmathLib.lib for CCS in TivaWare_C_Series 2.0.1.11577 [I haven't tested the IQmath library supplied for toolchains other than CCS]

  • Was this ever solved? I'm seeing the same problem 2 years later.

  • Even though this post now nears two years of age - Chester's significant effort & excellence - still shines brightly.

    With or without "vendor's fix"- his contribution - here & elsewhere - must be acknowledged/memorialized.    Great ongoing job, Sir!   Thank you.

    (I'd key in 10 "Likes" - if such was allowed!)

  • Yes, I'm very appreciative of everyone that contributes to these forums, they are invaluable. I didn't really form my question correctly. 

    I ran across the fact that the conversions from IQ math to doubles does not work as described in the documentation (or in a useful manner). I found this (two year old) string with the same issue, and the confirmation of what is happening on the stack. I wrote my own "fix" for the issue which was not difficult once I thought about it.

    But, if this rather easily solved issue has not been fixed by the vendor (TI) over a two year span, what else might be wrong with the IQ math library? I don't want to have to double check every calculation and edge condition, or study these forums for problems others have flagged that may still exist. My confidence level in TI products has dropped and I question my choice to use them. 

    I apologize for the fact that this is just a rant, but I expected better from TI.

  • David Jarrett93 said:
    I apologize for the fact that this is just a rant, but I expected better...

    Just a rant - hardly - have you not provided multiple, hard facts - surely of use to many?

    While we should not be disrespectful - often the findings, issues & client-user work-arounds - reported here - prove of immense benefit.    (useful to the vendor & client-users)

    It may be that the M4F device has reduced the "need" for "IQ math" - yet the vendor cannot bring themselves to pull it...(from life support...)

  • David Jarrett93 said:
    Was this ever solved? I'm seeing the same problem 2 years later.

    I just checked the IQmathLib.lib library from the latest TivaWare release v2.1.1.71 (from May 2015) and _IQ21toF still has the error that the floating point result is returned in the integer register R0 rather than floating point register S0. i.e. the problem hasn't been fixed.

    Can Amit Ashara confirm if a defect was raised for this problem?

  • I just checked the IQmathLib.lib library from the latest TivaWare release v2.1.1.71 (from May 2015) and _IQ21toF still has the error that the floating point result is returned in the integer register R0 rather than floating point register S0. i.e. the problem hasn't been fixed.

    I never used the IQmath software, but wouldn't that match exactly the softfp ABI convention ? Similiar "issues" exist with other libs and other vendors - you can't mix objects translated with -mfloat-abi=hard and such with -mfloat-abi=softfp, because one passes arguments and results in FP registers, the other in "normal" core registers. And if you don't do really heavy realtime calculations, you won't notice much difference in performance for either.

    But I tend to agree with CB1 here - IQmath was designed for cores without floating point support, so there is no real need to use IQmath on the M4F, except probably for your own backward compatibility reasons.

  • f. m. said:
    I never used the IQmath software, but wouldn't that match exactly the softfp ABI convention ? Similiar "issues" exist with other libs and other vendors - you can't mix objects translated with -mfloat-abi=hard and such with -mfloat-abi=softfp, because one passes arguments and results in FP registers, the other in "normal" core registers.

    Agreed. 

    Initially I tried to compile the program for "softfp" support with the TI compiler, by setting --float_support=vfplib but the linker then reported an error about incompatible objects:

    Building target: TM4C_IQMath_TI.out
    Invoking: ARM Linker
    "/opt/ti/ti_ccs6_1/ccsv6/tools/compiler/arm_5.1.12/bin/armcl" -mv7M4 --code_state=16 --float_support=vfplib --abi=eabi -me -O2 -g --gcc --define="ccs" --define=PART_LM4F232H5BB --define=ccs="ccs" --define=TARGET_IS_TM4C123_RA3 --display_error_number --diag_warning=225 --diag_wrap=off --gen_func_subsections=on --ual -z -m"project_ccs.map" --heap_size=0 --stack_size=256 -i"/opt/ti/ti_ccs6_1/ccsv6/tools/compiler/arm_5.1.12/lib" -i"/opt/ti/ti_ccs6_1/ccsv6/tools/compiler/arm_5.1.12/include" --reread_libs --warn_sections --display_error_number --diag_wrap=off --xml_link_info="TM4C_IQMath_TI_linkInfo.xml" --rom_model -o "TM4C_IQMath_TI.out" "./project.obj" "./startup_ccs.obj" "../project_ccs.cmd" -l"/opt/ti/SW-TM4C-2.1.1.71/examples/project/ccs/../../../IQmath/ccs/IQmathLib/Debug/IQmathLib.lib" -l"libc.a"
    <Linking>
    error #16004-D: file "/opt/ti/SW-TM4C-2.1.1.71/examples/project/ccs/../../../IQmath/ccs/IQmathLib/Debug/IQmathLib.lib<IQNtoF.obj>" has a Tag_ABI_VFP_args attribute value of "0" that is different than one previously seen ("1"); combining incompatible files
    error #10010: errors encountered during linking; "TM4C_IQMath_TI.out" not built

    One work-around is to suppress the linker error 16004, which then allowed the program to linked using "softtp" support and the _IQ21toF function then returned the expected value.

    This is still a "bug" in the IQmathLib.lib supplied for the TI compiler that it's functions use "softfp" (Tag_ABI_VFP_args 0), but yet the library is tagged as using "hardfp" (Tag_ABI_VFP_args 1) as far as the linker is concerned.

  • f. m. said:
    ...tend to agree with CB1 here - IQmath was designed for cores w/out floating point support, ... no real need to use IQmath on the M4F

    Thank you, f.m..   

    There will always be needed - "fixes" & "improvements" - yet for many (most) - the arrival of the M4F's "FP" proves a very acceptable alternative...

  • I agree with everyone. However, my issue is speed. I have a large number of calculations to do to create a table that's handed off to an FPGA at regular intervals.  I did some timings and found the time to do the full calculation set using float was 14msec. The time to do the calculations using IQ was about 8 msec. That would be an easy choice to use float. But, single precision float does not quite have the resolution I need. To go to doubles increases time of calculation to 52msec, which is longer than I'm comfortable with given the loop time and other activities.  IQ has better resolution than float and is much faster than using doubles. That was why I was using the library and doing conversions. 

    Sent from my mobile
  • Well, when I was writing this topic it wassn't a Tiva family it was a Stellaris (LM4F) so I understood that something can not work properly. Now some of you writes that it still opened. I'm not sure if Tiva package contains also libraries for LM3S but if not, there is a question why IQMath is included. In my opinion It shall be at least repaired by ifdefs and calculations provided in standard way (+warning) or just make compilation error. I can imagine a developer porting software that will spend some time investigating that it's IQmath issue.

    Best regards,
    Mikolaj
  • Hello Chester, All,

    Unfortunately there are so many such buried threads, that need to be dug up. Thanks for bringing it up. I would file a bug thread when I understand the issue better, have a discussion with all forum members, relook at the implementation issues (seemingly a recent one in 2.1.1.71 was improperly fixed and want to avoid the same mistake twice) and update.

    Regards
    Amit
  • I just ran across this same thing today for Tiva C Series.  Our company is using the TM4C1294NCPDT chip.  I was trying to use _IQtoF and through debugging, I saw that the result from the library was being placed in the R0 register, but my calling program expected it to be in the S0 register (thus storing garbage into the floating point variable that was supposed to be assigned by the function).

    Can somebody at TI please provide a gcc version of IQmathLib.a which has been compiled with the following additional flags:

    -mfloat-abi=hard -mfpu=fpv4-sp-d16

    or at least provide a link to the source code so I can compile it myself?

    I have the same issues - I want a little more precision (for motor control), and find it absurd that I must disable the floating-point co-processor in order to get all of the functions in IQMath to work properly.

     

     

  • Can somebody at TI please provide a gcc version of IQmathLib.a which has been compiled with the following additional flags:

    -mfloat-abi=hard -mfpu=fpv4-sp-d16

    Unless I got something wrong - I think this would not help. The IQmath library is about fixed-point data types, which are not supported by the M4 FPU (and are incompatible with the IEEE-754 single-precision floating point format).

    My suggestion would be to either stay in one domain (floating-point or fixed-point), or write an appropriate layer of "glue" functions yourself.

    Assuming the increased precision of fixed-point is required, I could see a need for floating-point only for stdio functions.

  • James lOCKWOOD said:

    Can somebody at TI please provide a gcc version of IQmathLib.a which has been compiled with the following additional flags:

    -mfloat-abi=hard -mfpu=fpv4-sp-d16

    I haven't seen the source code, but was under the impression that the source for _IQtoF was in assembler, and so simply re-compiling with different options wouldn't fix the problem.

  • If it is indeed hand-coded assembler, then I agree that compiling with these flags does not solve the issue.

    I am exploring how to patch the IQmathLib.a file with an alternative IQNtoF.o file of my creation and will create an IQmathLib_fpu.a.  The C28x version provides an alternate library for C28x variants that contain a FPU, so this solution would be in the same spirit as what was done for the C28x with FPU.

    I will upload the file if I am successful so all can benefit, as well as the source code I create for IQNtoF and instructions how to do this so others can patch future versions of IQmathLib.a using this method.

  • The C28x version provides an alternate library for C28x variants that contain a FPU, so this solution would be in the same spirit as what was done for the C28x with FPU.

    Sorry for my ignorance in regard to C28x details - but I expect the respective FPU to support fixed-point (rather than floating-point) operations to be supported in hardware. The TM4C, and Cortex M4/M7 in general, do not. Thus, using fixed-point on this MCUs is always a kind of compromise.

  • OK. I got it patched.

    Here is the IQNtoF.asm file I created. It simply transfers the R0 registers into the S0 register before returning for all these functions.


    .syntax unified
    .align 4

    /* ---------------------------------------------------
    * _IQ30toF
    * ---------------------------------------------------*/
    .global _IQ30toF
    .sect ".text._IQ30toF"
    .text
    .func
    .thumb_func
    _IQ30toF:
    cbz r0, r0isZero30
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x80
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero30:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ29toF
    * ---------------------------------------------------*/
    .global _IQ29toF
    .sect ".text._IQ29toF"
    .text
    .func
    .thumb_func
    _IQ29toF:
    cbz r0, r0isZero29
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x81
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero29:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ28toF
    * ---------------------------------------------------*/
    .global _IQ28toF
    .sect ".text._IQ28toF"
    .text
    .func
    .thumb_func
    _IQ28toF:
    cbz r0, r0isZero28
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x82
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero28:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ27toF
    * ---------------------------------------------------*/
    .global _IQ27toF
    .sect ".text._IQ27toF"
    .text
    .func
    .thumb_func
    _IQ27toF:
    cbz r0, r0isZero27
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x83
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero27:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ26toF
    * ---------------------------------------------------*/
    .global _IQ26toF
    .sect ".text._IQ26toF"
    .text
    .func
    .thumb_func
    _IQ26toF:
    cbz r0, r0isZero26
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x84
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero26:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ25toF
    * ---------------------------------------------------*/
    .global _IQ25toF
    .sect ".text._IQ25toF"
    .text
    .func
    .thumb_func
    _IQ25toF:
    cbz r0, r0isZero25
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x85
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero25:
    vmov s0, r0
    bx lr
    .endfunc


    /* ---------------------------------------------------
    * _IQ24toF
    * ---------------------------------------------------*/
    .global _IQ24toF
    .sect ".text._IQ24toF"
    .text
    .func
    .thumb_func
    _IQ24toF:
    cbz r0, r0isZero24
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x86
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero24:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ23toF
    * ---------------------------------------------------*/
    .global _IQ23toF
    .sect ".text._IQ23toF"
    .text
    .func
    .thumb_func
    _IQ23toF:
    cbz r0, r0isZero23
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x87
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero23:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ22toF
    * ---------------------------------------------------*/
    .global _IQ22toF
    .sect ".text._IQ22toF"
    .text
    .func
    .thumb_func
    _IQ22toF:
    cbz r0, r0isZero22
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x88
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero22:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ21toF
    * ---------------------------------------------------*/
    .global _IQ21toF
    .sect ".text._IQ21toF"
    .text
    .func
    .thumb_func
    _IQ21toF:
    cbz r0, r0isZero21
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x89
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero21:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ20toF
    * ---------------------------------------------------*/
    .global _IQ20toF
    .sect ".text._IQ20toF"
    .text
    .func
    .thumb_func
    _IQ20toF:
    cbz r0, r0isZero20
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x8a
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero20:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ19toF
    * ---------------------------------------------------*/
    .global _IQ19toF
    .sect ".text._IQ19toF"
    .text
    .func
    .thumb_func
    _IQ19toF:
    cbz r0, r0isZero19
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x8b
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero19:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ18toF
    * ---------------------------------------------------*/
    .global _IQ18toF
    .sect ".text._IQ18toF"
    .text
    .func
    .thumb_func
    _IQ18toF:
    cbz r0, r0isZero18
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x8c
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero18:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ17toF
    * ---------------------------------------------------*/
    .global _IQ17toF
    .sect ".text._IQ17toF"
    .text
    .func
    .thumb_func
    _IQ17toF:
    cbz r0, r0isZero17
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, 0x8d
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero17:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ16toF
    * ---------------------------------------------------*/
    .global _IQ16toF
    .sect ".text._IQ16toF"
    .text
    .func
    .thumb_func
    _IQ16toF:
    cbz r0, r0isZero16
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x8e
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero16:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ15toF
    * ---------------------------------------------------*/
    .global _IQ15toF
    .sect ".text._IQ15toF"
    .text
    .func
    .thumb_func
    _IQ15toF:
    cbz r0, r0isZero15
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x8f
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero15:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ14toF
    * ---------------------------------------------------*/
    .global _IQ14toF
    .sect ".text._IQ14toF"
    .text
    .func
    .thumb_func
    _IQ14toF:
    cbz r0, r0isZero14
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x90
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero14:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ13toF
    * ---------------------------------------------------*/
    .global _IQ13toF
    .sect ".text._IQ13toF"
    .text
    .func
    .thumb_func
    _IQ13toF:
    cbz r0, r0isZero13
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x91
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero13:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ12toF
    * ---------------------------------------------------*/
    .global _IQ12toF
    .sect ".text._IQ12toF"
    .text
    .func
    .thumb_func
    _IQ12toF:
    cbz r0, r0isZero12
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x92
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero12:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ11toF
    * ---------------------------------------------------*/
    .global _IQ11toF
    .sect ".text._IQ11toF"
    .text
    .func
    .thumb_func
    _IQ11toF:
    cbz r0, r0isZero11
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x93
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero11:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ10toF
    * ---------------------------------------------------*/
    .global _IQ10toF
    .sect ".text._IQ10toF"
    .text
    .func
    .thumb_func
    _IQ10toF:
    cbz r0, r0isZero10
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x94
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero10:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ9toF
    * ---------------------------------------------------*/
    .global _IQ9toF
    .sect ".text._IQ9toF"
    .text
    .func
    .thumb_func
    _IQ9toF:
    cbz r0, r0isZero9
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x95
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero9:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ8toF
    * ---------------------------------------------------*/
    .global _IQ8toF
    .sect ".text._IQ8toF"
    .text
    .func
    .thumb_func
    _IQ8toF:
    cbz r0, r0isZero8
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x96
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero8:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ7toF
    * ---------------------------------------------------*/
    .global _IQ7toF
    .sect ".text._IQ7toF"
    .text
    .func
    .thumb_func
    _IQ7toF:
    cbz r0, r0isZero7
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x97
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero7:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ6toF
    * ---------------------------------------------------*/
    .global _IQ6toF
    .sect ".text._IQ6toF"
    .text
    .func
    .thumb_func
    _IQ6toF:
    cbz r0, r0isZero6
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x98
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero6:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ5toF
    * ---------------------------------------------------*/
    .global _IQ5toF
    .sect ".text._IQ5toF"
    .text
    .func
    .thumb_func
    _IQ5toF:
    cbz r0, r0isZero5
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x99
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero5:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ4toF
    * ---------------------------------------------------*/
    .global _IQ4toF
    .sect ".text._IQ4toF"
    .text
    .func
    .thumb_func
    _IQ4toF:
    cbz r0, r0isZero4
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x9a
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero4:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ3toF
    * ---------------------------------------------------*/
    .global _IQ3toF
    .sect ".text._IQ3toF"
    .text
    .func
    .thumb_func
    _IQ3toF:
    cbz r0, r0isZero3
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x9b
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero3:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ2toF
    * ---------------------------------------------------*/
    .global _IQ2toF
    .sect ".text._IQ2toF"
    .text
    .func
    .thumb_func
    _IQ2toF:
    cbz r0, r0isZero2
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x9c
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero2:
    vmov s0, r0
    bx lr
    .endfunc

    /* ---------------------------------------------------
    * _IQ1toF
    * ---------------------------------------------------*/
    .global _IQ1toF
    .sect ".text._IQ1toF"
    .text
    .func
    .thumb_func
    _IQ1toF:
    cbz r0, r0isZero1
    ands.w r1, r0, #0x80000000
    it mi
    negmi r0, r0
    clz r3, r0
    rsb r2, r3, #0x9d
    lsl.w r0, r0, r3
    mov.w r0, r0, lsr #8
    bfi r0, r2, #23, #8
    orr.w r0, r1, r0
    r0isZero1:
    vmov s0, r0
    bx lr
    .endfunc

    .end

    You can extact the original object files with the following command:
    ar -x IQmathLib.a

    after compiling the substitute IQNtoF.asm, replace the original IQNtoF.o file with the new one.
    You can create the new library with the following command:
    ar cr IQmathLib_fpu.a atoIQN.o IQNasin.o IQNatan2.o IQNatan2PU.o IQNcos.o IQNcosPU.o IQNdiv.o IQNexp.o IQNexp2.o IQNfrac.o IQNint.o IQNisqrt.o IQNmag.o IQNmpy.o IQNmpyI32frac.o IQNmpyI32int.o IQNrmpy.o IQNrsmpy.o IQNsin.o IQNsinPU.o IQNsqrt.o IQNtoa.o IQNtoD.o IQNtoF.o IQtables.o IQxmpy.o

    of course, ar command must be the arm-none-eabi version.
  • Here is the IQNtoF.asm file I created. It simply transfers the R0 registers into the S0 register before returning for all these functions.

    Not to critisize, but that would only be valid in a "float-abi=hard" context.

  • Exactly. That is what was intended.
  • I assume you know the "softfp" ABI which utilizes the FPU as well, but passes arguments in core registers (R0..R3) instead of FPU registers.

  • I tried this, but for some reason I get a fault when calling memset. I don't know why. What I have works for me now, so I am satisfied to call it "good enough".
  • I tried this, but for some reason I get a fault when calling memset. I don't know why.

    That's strange. memset supposedly comes with the clib - and usually from the toolchain provider. Perhaps an alignment issue ?

    What I have works for me now, so I am satisfied to call it "good enough".

    Just loosely related: some vendors already offer Cortex M7 silicons with double-precision FPUs. Not sure about TI's plans here.

    As a matter of fact, a lot of DSP algorithms/implementations keel over with the limited single floating-point precision.

  • We've written a lot of code for the Tiva so far, and hadn't seen the memset issue, so I doubt it is an alignment issue.  I find it strange as well, but I can't get side-tracked with a non-essential issue that doesn't move our project forward.

    Funny you mention the Cortex M7, as I had just stumbled across is last week and wasn't aware of it until then.  The M7 looks like the next step up for us in the future.  I am personally a big fan of FPGAs because of the limitless flexibility and opportunity to dramatically speed things up with custom written Verilog peripherals/accelerators, but it scares the bejesus out of our company.  I am the only one here that knows how to work with them, so we only use them as supplements to the CPU when a software solution on the CPU is impractical/impossible.

    I am mainly using floating-point for non-critical things that don't require excellent precision, such as displaying values in user units over a serial terminal.

    I am sure my motor control routine benefits with the precision that IQ Math provides.  We use the routine on the C28x (28069) and it works well, so I wanted to achieve identical results with the Tiva by using IQ Math.  I was concerned that it wouldn't fare very well if it was implemented with all single-precision floating point calculations, as you pointed out in your last sentence (I didn't even try to do it).  I just got it running last night, and am happy to report that it all looks great.

  • We've written a lot of code for the Tiva so far, and hadn't seen the memset issue, so I doubt it is an alignment issue.

    Sounds plausible. And I don't know which toolchain/clib implementation it's based on. I would be concerned if I could trace the issue to the lib (and not to the app).

    I am personally a big fan of FPGAs...

    I have just superficial knowledge in regard to FPGAs, but I think for certain applications (like yours) they are far superior to high-performance MCUs. Sub-millisecond cycle-by-cycle control loops, side by side with high DMA/interrupt load are a PITA, even with a M7. And the M7 steps complexity up a few notches (e.g. introduces I-cache and D-cache ...).

    Many applications, including control loops, work equally well with carefully designed integer-based algorithms. Few people realize that float has just 24 bits of precision. I believe float is most appealing to PC developers and beginners who go for the easy route.

  • If you have the time, learning how to write FPGA code opens up a whole new world of opportunity -- I recommend it. It is amazing how much logic in an algorithm can be done in a single clock cycle (typically 10 ns/100Mhz) with zero impact on the speed of execution of all the other existing logic since all logic circuits operate in parallel.