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.

MSP430 Arithmetic

Other Parts Discussed in Thread: MSP430F5438

Hello,

I am pretty new to programming microcontrollers and i am useing a msp4330fg4618 with IAR Embedded Workbench.

I am looking to do quite a bit of multiplication and division within my code. I need to use both signed numbers and fractions.

My question is what is the most efficient way to do this?

 Currently in my code i just declare all my variables as floats and use the * and / symbles, so it would look like somthing like this:

float a, b, c, x;

x = (a* b) / c;

 

The problem is that this is too slow and I need to increase the speed at which my code runs.

 

Is there a way to do multiplication and divisionuseing with fractions useing fixed point numbers? Maybe with the hardware multiplier?

 

Any help will be greatly appreciated

Thanks,

Jacob

  • Hi Jacob,

    well, dealing with float numbers on a 8- or 16-bit micro is always a pain (even on some other architectures). You should think about your code and only use floats were you really need them.

    TI has published an app note (theory and source code) how to do efficient multiplication and divison. You can find it here: http://focus.ti.com/mcu/docs/litabsmultiplefilelist.tsp?sectionId=96&tabId=1502&literatureNumber=slaa329&docCategoryId=1&familyId=342

    Rgds
    aBUGSworstnightmare

  • MSP430 is not very good at doing numerical calculations. FG4618 can only run at 8MHz. It does have a 16x16 bit hardware multiplier.

    IAR compiler does use the hardware multiplier and is quite efficient in most of the cases. However, for certain computations, you may have an advantage if you use the hardware multiplier directly, or even use shift and add instead.

    If your application is computation intensive and do not need the advantages MSP430 offers, you should consider other processors. And even if you decide to use MSP430 but you do not need to drive LCD directly, you should consider MSP430F5xx/6xx. They can run at 25MHz and have 32x32 hardware multiplier. (But the IAR compiler does not seem to be able to take advantage of 32x32 and still use it as 16x16.)

  • The limitation to be aware of when using the SLAA329 related methods cited above is that they're best used when dealing with a CONSTANT factor as one of the terms which is known and fixed well before compile time since they're generating specific code to multiply/divide by that CONSTANT and ONLY that CONSTANT, so you cannot at run time use it to speed up any other multiplication / division processes where variables are used as both terms. Because of this you may find that a smart well optimizing compiler will just automatically generate similarly efficient code if you were to just give it code like:

    int x1, y1, y2, y3;

    ...

    x = x + y1*17 + y2*34 + y3/19;

    ...where the multiplication routines for *17, *34, /19 are possible to be generated at compile time either by the manual code generation techniques in the app note, or by the compiler if it is smart enough to realize the possible optimization available by generating intrinsic code for the expression evaluation.

    Some people write customized multiply / divide routines that are able to operate on two variable terms like int x,y,z; z=x*y; which are aware of the exact numbers of bits of accuracy needed for the expected input terms and output product since sometimes you'll need not just 8 bits char, 16 bits int, 32 bits long, but maybe 24 bits, or 12 bits or whatever, or maybe you know that a zero or one input will happen frequently enough that it is worth checking for as a special case, et. al.  Sometimes you will want to do mixed size products like (16bit*8bit) or whatever.  So in these ways you can write a (variable,variable) function that will do the operation to the precision you need that is much better than what the compiler might generate for you, if you know the range of precisions and types you need to work with and it presents some opportunity for optimization that a compiler could not predict.

    As others have said, you really want to avoid float/double at all costs unless speed and code size are just irrelevant for your concerns because it works OK with those data types.  It is generally best to figure out how to rescale the problem so that fractional numbers become scaled up whole integer numbers such as x*3 percent versus x*0.03 by scaling up the fraction *100 and realizing your result needs to be interpreted as 1/100th its resultant value, but calculate it using scaled up integer math.

    Similarly you should try and convert divides to multiplies wherever possible.

    And as above if you can make some of the terms or functions use a lot of explicitly initialized constant values known to the compiler at compile time versus variables, it will make the code generation much more efficient lacking a good single cycle hardware multiplier / fast divider.

    The others are right about looking for a MSP430 variant with better multiplier hardware if this is a big area of performance / code capacity limitation for you, or better yet, some CPU like some of the Stellaris or C2000 parts that more efficiently support wider data types, are faster, more optimized for multiply/divide operations, et. al.

     

  • There is an alternative to the slow float operations: The Q fractional numbers. The MSP430F5438 has a 32bit hardware multiplier that supports fractional numbers. Of course there is no support in the compiler.

    The good thing is that additionand subtraction of a Q number is just a signed addition/subtraction. You can even store the values in a signed (long) int. Only multiplication and division need special functionality and for multiplication there is hardware support (it's just an add and a shift more than a normal multiplication)

     

    A completely different way is to use scaled values. It works if your values aren't too big.

    Just multiply the values by, say, 1024 and thread them as integers. This gives you a fractional resolution of 0.000976562 (roughly 0.001 or 3 fractional digits). After a multiplication, shift the result right by 10 bits (so your values may not be larger than 6 bits or the result would exceed 32 bit before shifting it right). If you do the multiplication yourself, you can use the 32bit multiplier, which gives a 64 bit result, than your values can grow to +-2097152.
    On a division, left-shift the dividend by 10 more bits (limiting the range here to +-2047 for a long int) before doing the division and the result will again have 10 bits fraction. Or shift the one left by 5 bit and the other right by 5 bit. It affects precision a bit, but extends the possible range of the values by 5 bits (+-131071).

    It is actually the cheapest way to do the stuff. You can even change the number of fractional digits you need. To divide a fractional number by an integer, you don't need to shift at all. (the shift before the division is only to compensate for the divisors fractional digits). Just divide normally.

**Attention** This is a public forum