2010-07-02 06:04 AM
ARM fixed point vs. floating point Cortex M-3
2011-05-17 04:57 AM
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.2011-05-17 04:57 AM
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.2011-05-17 04:57 AM
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 :)2011-05-17 04:57 AM
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 Instructions2011-05-17 04:57 AM
BTW. instead of bothering with timers you could just use the CYCCNT.
2011-05-17 04:57 AM
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).