cancel
Showing results for 
Search instead for 
Did you mean: 

ARM fixed point vs. floating point Cortex M-3

danrokk
Associate
Posted on July 02, 2010 at 15:04

ARM fixed point vs. floating point Cortex M-3

6 REPLIES 6
Posted on May 17, 2011 at 13:57

I'll assume by ''instructions'' you mean ''cycles''

If you cared about speed you wouldn't be writing this in C, you need to post ALL the code if you want people to look at it.

A Q1.31 multiply would look like this:

reg64 = reg32 * reg32

reg32 = (reg64 >> 62)

Quick back of the envelope solution,

    EXPORT _FixMul_1_31 ; r0(1.31) = r0(1.31) * r1(1.31)

_FixMul_1_31    umull    r1, r0, r0, r1 ; r0:r1 = r0 * r1

        adds    r1, r1, r1    ; r0 = r0:r1 >> 62, ie (r0 << 1) + (r1 >> 31)

        adc    r0, r0, r0

        bx    lr

Q1.31 will hold 0.000000000 1.999999999

Q1.31 Won't hold -150.534433, you'd need Q9:23. Q1.31 is not going to represent positive/negative numbers unless your integer bit is actually a sign bit. What is the range of numbers you actually need? How do you want to handle OVERFLOW conditions.

A Q16.16 format would be easier to manage.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
danrokk
Associate
Posted on May 17, 2011 at 13:57

You recommend me writing my code in assembler? I know, that representation

won't hold more than (-1, +1), I assume first bit is bit of sign. In my problem,

which is multiplying a lot of matrix I have to multiply almost all the time.

In representation Q1.31 I won't get overflow (my numbers are less than 1), but

anyway, I'm multiplying int's, so I can easily get sth more than int can hold in.

I attached 2 files (FixedPoint.c and FixedPoint.h), can You tell me if I'm going

into right direction?

In my project I have object (black box), on which I do experiment. I collect

ADC data from object and I have to recognize it's transmitation (Z or Laplace).

That's why I need to do a lot of operations in very short period of time.

I'm thinking about collecting data from ADC, converting it into fixed point

representation and using ARMA identification model to recognize trantmitation.

darcy23
Associate II
Posted on May 17, 2011 at 13:57

Another, some times simpler solution, is to use scaled down units.  This may or may not be appropriate for what you're doing though...  We measure length in micro metres yet what we really care about is milli-metres and 2dp.  So, our types are:

typedef    sint32_t   length_micro_m_t;

So, with an s32 you could get something like +/- 1.999999999 (9dp) by using nano-units rather than fixed point.  That may or may not help  🙂

darcy23
Associate II
Posted on May 17, 2011 at 13:57

I just noticed your mention of CrossWorks.  The simulator isn't the best for calculating the type of measurement you wanted below.  For example, multiplying two U32's should only take a couple of cycles.

All I can suggest for a more acurrate method of measurement is to set up a timer without a prescaler so that it counts at 36-72MHz.  Take copies of that counter before your operation, then again afterwards.  It won't be completely acurrate due to the time it takes to read the peripheral and store the counter but it should be more indicative than the estimates using the simulator.

where _fxpnt_accu64 is global object, to hold result.

I made few tests in CrossWorks and results are weird:

float a = -150.534433;

float b = 0.05323;

c = a*b; // 47 Instructions

c = a+b; // 55 Instructions

c = a-b; // 49 Instructions

c = a/b; // 139 Instructions

ans = fxmul(&fx2, &fx1); // 165 Instructions

domen23
Associate II
Posted on May 17, 2011 at 13:57

BTW. instead of bothering with timers you could just use the CYCCNT.

daviddavid940
Associate II
Posted on May 17, 2011 at 13:57

Just to note, the Cortex-M3 can hold 64-bit intermediate with the UMULL and SMULL instruction (for signed). Nothing like that for divide though (unfortunately) but you can multiply by reciprocal constants to get same effect.

You probably need to cast some some of those variables to int64_t (long long).