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 32-bit division with / operator

Genius 4170 points

Other Parts Discussed in Thread: MSP430F5437A, MSP430F5438A

Good morning everyone,

I have another perhaps rather easy question for all fo those who get out of bed early on a monday morning :)

MaxUVA = Temp_longint / Time_real;

uint         =  long int    /  (long int )  uint  <----- typecast

I use this kind of division regardless of time and code consumption right now, in a routine for calculating something. Now the result is not correct.

I am not far enough into C to see all the errors i make, please could someone tell me how can I calculate a 32 bit division in C without using some fancy assambler code?

I am afraid I cannot break this calculation down to 16 bit, because before that division i will have to add around 80 16-bit values together, so my result will be a  32-bit in first place.

My assupmtion now, this monday morning :), was that it is simply impossible to do a 32 bit division with the "/" operator in C, is that true?

I am using the MSP430F5437A CCS4.2.5

If no other answer comes up, I guess i could use the hardware multiplyer, which is capable of 32 bit multiplications, as i can always calculate 1/(16 bit).

Thanks for reading and helping me out.

Best wishes,

Seb

  • Seb,

    this should actually work. I have just tested it with the MSP430F5438A and CCS v4.2.4.

    What was your test case (the values of your variables)?

    Regards,

    -Leo-

  • I have used 32bit division with CCS v4.1.3 and it worked ok.

    One possibility is that you are using "long int" which might be interpreted as "signed long int" and therefore the wrong calculation be performed?

    If you look in the disassembly I think it should show Temp_longint loaded into R12/13, Time_real loaded into R14/15 and then a call to __divul.  If you post the disassembly and/or examples of the input values and the result then we should be able to work out what's going wrong.

    Regards,

    Chris.

  • Thanks for your post, it is really helpful.

    Unfortunetly i found out smoe mroe things about my math now.

    So i assumed a long is a 32 bit variable, now my debugger tells me it isnt, it is just a 16 bit value, i have no clue at all why this is so.

    To make it clear, i sum about 80 results in a for-loop, i have the following values:

    for(i=U_MIN;i<U_MAX;i++)                      
                        {
                            Temp_longint = Temp_longint + (unsigned long int) Result[i];
                        }

    My loop goes from 20 to 100, so i have 80 repetitions; my result is for testing always 3694, that comes frmo my 12-bit ADC.

    now if i do the math here it is : 80 * 3694 = 295520 which is a 32 bit result. But when i go through my loop in debug mode, i strangely recognized that the Temp_longint variable rolls over at 16-bit Maximum...

    I didnt expect that to happen at all. Someone perhaps has some more insight of the MSP430 math and types, i am now testing some more stuff:

    unsigned long ulong_x1 = 100000;
    unsigned long ulong_x2 = 200000;
    unsigned long ulong_ergl = 0;
    unsigned int uint_erg1 = 0;

    //  Result comes in from an actual ADC result, so that my compiler cannot do the division but it actually has to be done inside the MSP430!!!

    ulong_ergl = ulong_x1 / Result[1];  // Result is 4095-400;

    // ulong_ergl = 27 

    So this seems to work, just like your example, this i good.

    I am now doing more tests and will keep this updated till everything works.

    Thanks everyone for reading.

  • Hello all,

    so i think i found my mistake, it was rpetty simple, as it is always once you realize your mistakes :)

    unsigned long int Temp_longint = 0;

    The former Code was written with long int, which i now know cannot work as a long itself.

    in the sdtint.h it is clearly declared:   typedef          long   int32_t;

    So i will test my math with my newly found 32 bit values for real :)

    But i guess i will come back soon with mroe problems. Be prepared.

    Thanks again.

    Seb

  • seb said:
    unsigned long int Temp_longint = 0;

    THis should be perfectly legal.

    The only uncertainity in C langage is the size of an INT. It is the native size of a machine. So on some machins, INT is 32 bit (= long int) , on others it is 16 bit (= short int).
    But the "unsigned long int" you used is 32 bit. I don't know what was wrong wirth your code.

    It's a good idea to apply a railing 'L' to constants outside the signed shor tint rage. Some compilers accept the constants without, some truncate the value to 16 bit signed.

  • Hello Jens,

    ok this knid of suprises me as i thought this was my solution.

    I did open another post with some other occurances around the 16 bit and 32 bit issue in MSP430. Although i did declare variables with long they are still 16 bit, if i declare them locally. kind of confusing. But I will find a solution this week i have promised myself :)

    Greetings.

  • It could be a debugger bug. Local variables often end up in register pairs rather than on the stack. It is possible that the debugger has problems 'finding' the place where the current value is at a given moment.

    Also, it could be a subject of optimization. If the compiler notices that certain variables are never used in the code flow (even though you might want to inspec tthem with the debugger) it may discard them completely. This might have happened to the upper word of your local 32 bit variables.
    To ensure that this is not the problem, deactivate the cod eoptimization in the project settings (compiler settings)

  • I have tested a couple of different settings now and I come to the following things:

    The debugger cannot read local variables, probably as you said because he cannot get the physical memory locations, or something like that, I helped myself by a little trick.

    I declare a global testvariable with the same type as my local variable i am looking for, in my program i assign the local to my global variable, so I can debug it and see it.

    Those two values differ a lot, but in reality they have the same value so the debugger cant be trustes with local variables, but the MSP430 gets the right numbers anyway.

    Of course this makes it a little awkward to program and debug, when one cannot trust the debugger but only the results...

    Next thing I have on my mind is memory usage, for some reason some of my local variables overwrite memory space of other variabel arrays, which of course is not wanted by me.

    Perhaps I will open a new post or find out the solution by myself this morning.

    I have the feeling that all global variables respect the space usage of other global variables but local ones dont respect global variable space. Instead they simply overwrite some memory addresses with their own values, could that be? Or is it me and my bad programming style, with mixing local and global variables?

    THanks for helping, as always :)

    Seb

  • Well it's probably as Jens said - local variables are often kept in registers. So there seems to be an issue if a variable kept in a register is bigger than the natural word length of the MSP - that's an interesting point and I'll look into it some time, maybe this can be filed as a bug and fixed in a future version, it does seem to be a bit of a software bug (I mean the registers are read perfectly fine, just not stitched together like they should).

    seb said:
    Next thing I have on my mind is memory usage, for some reason some of my local variables overwrite memory space of other variabel arrays, which of course is not wanted by me.

     

    Now what you might expect is not always how the compiler sees things. For example if you have defined an array locally and do some stuff with it, then declare a new variable at some later point - if the compiler sees no more access to the values of the array it concludes: okay the value there isn't actually needed so I can put my new variable there. This might be a problem for your debugging but should not cause a problem for the program.

    If your new variable is actually overwriting array values which are indeed needed at a further point - then there might be a problem with your program, or a problem with the compiler.

    I wouldn't go that far to say mixing global and local variables is bad programming style - just the use of global variables should be minimized where possible, but in some scenarios you just have to use a global variable. 

  • When debugging code, all optimizations should be switched off. So the compiler won't make any analysis on the lifespan of local variables, reorder code or move calculations out of loops etc.

    The problem is, the debugger cannot know what compiler optimization has done to the code. It only knows a relation of code address to source code, and memory location to variable. Things like double-usage or out-of-order execution/common subexpressions are not part of the debugging info available to the debugger.

    Once the program runs as expected, one can enable optimizations and then start again with debugging the optimized code (or at least test it once more for optimization-induced bugs) :)

**Attention** This is a public forum