Author Topic: STM32F4 number overflow  (Read 7363 times)

0 Members and 1 Guest are viewing this topic.

Offline pyrohazTopic starter

  • Regular Contributor
  • *
  • Posts: 186
  • Country: gb
    • Harris' Electronics!
STM32F4 number overflow
« on: July 14, 2014, 08:49:21 pm »
After all the love I've given to STM32 series microcontrollers these past few days, they're not loving me back and I feel like ripping my hair out!  |O

I've literally got a program as simple as it gets: Incrementing a number.

The main code is as follows:

Code: [Select]
int main(void)
{

uint32_t X = 0;
while(1)
{
X+=1e7;
}
}

Now I'm using the debugger to track the value of X and it just seems to saturate at 2^32 - 1 (4294967295)! Its literally just declared as an unsigned integer so I expect it to overflow not saturate! Could anybody care to enlighten me on why the hell this is happening?

I'm using CooCox, an STM32F405 with an STLink V2.

Absolutely any help is appreciated!

Harris
 

Offline bwat

  • Frequent Contributor
  • **
  • Posts: 278
  • Country: se
    • My website
Re: STM32F4 number overflow
« Reply #1 on: July 14, 2014, 08:59:18 pm »
Change the float to an int. What happens then?

Floats are contagious and the conversion of a big float (X+1e7) to the unsigned int (X) will end up as the max int. That's what I'm guessing anyway.
« Last Edit: July 14, 2014, 09:03:46 pm by bwat »
"Who said that you should improve programming skills only at the workplace? Is the workplace even suitable for cultural improvement of any kind?" - Christophe Thibaut

"People who are really serious about software should make their own hardware." - Alan Kay
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: STM32F4 number overflow
« Reply #2 on: July 14, 2014, 09:11:28 pm »
If your main variable is an (unsigned) integer you should add with an (unsigned) integer or at least cast it to an (unsigned) integer.
 

Offline pyrohazTopic starter

  • Regular Contributor
  • *
  • Posts: 186
  • Country: gb
    • Harris' Electronics!
Re: STM32F4 number overflow
« Reply #3 on: July 14, 2014, 09:30:09 pm »
Oh my gosh, I feel completely stupid! Thats solved it, thank you both very much! I never knew that declaring a number in the e notation instantly made it a float (I'm used to using scientific e notation for generally large numbers).

Thank you all again!
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: STM32F4 number overflow
« Reply #4 on: July 14, 2014, 09:33:08 pm »
type promotion: 1e7 is a floating number / double.
================================
https://dannyelectronics.wordpress.com/
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: STM32F4 number overflow
« Reply #5 on: July 15, 2014, 06:26:21 pm »
Now I'm using the debugger to track the value of X and it just seems to saturate at 2^32 - 1 (4294967295)! Its literally just declared as an unsigned integer so I expect it to overflow not saturate! Could anybody care to enlighten me on why the hell this is happening?

Quote
Oh my gosh, I feel completely stupid! Thats solved it, thank you both very much! I never knew that declaring a number in the e notation instantly made it a float (I'm used to using scientific e notation for generally large numbers).

Glad you solved your problem. However, it would be instructive to know exactly why your uint variable was saturating.

1e7 is 10000000, and well within what can be represented by uint32_t. The fact that you got weird behavior suggests that something else is at work here. Maybe you could post the assembly listing output from the compiler so we can figure it out?
 

Offline pyrohazTopic starter

  • Regular Contributor
  • *
  • Posts: 186
  • Country: gb
    • Harris' Electronics!
Re: STM32F4 number overflow
« Reply #6 on: July 15, 2014, 07:03:33 pm »
Happily!

080000d2:   ldr r0, [r7, #4]
080000d4:   bl 0x8001014 <__aeabi_ui2d>
080000d8:   adds r3, r0, #0
080000da:   adds r4, r1, #0
080000dc:   adds r0, r3, #0
080000de:   adds r1, r4, #0
080000e0:   ldr r3, [pc, #32]       ; (0x8000104 <main+60>)
080000e2:   ldr r2, [pc, #28]       ; (0x8000100 <main+56>)
080000e4:   bl 0x8000300 <__aeabi_dadd>
080000e8:   adds r3, r0, #0
080000ea:   adds r4, r1, #0
080000ec:   adds r0, r3, #0
080000ee:   adds r1, r4, #0
080000f0:   bl 0x80002c0 <__fixunsdfsi>
080000f4:   adds r3, r0, #0
080000f6:   str r3, [r7, #4]

(The there are a few more lines to just loop back to the top)

My best assumption to the unsigned + float could be the instruction 0x80002c0. I've searched for __fixunsdfsi on the internet but didn't seem to get many results. At a guess, it could mean fix unsigned float sum ...?
 

Offline bwat

  • Frequent Contributor
  • **
  • Posts: 278
  • Country: se
    • My website
Re: STM32F4 number overflow
« Reply #7 on: July 15, 2014, 07:04:49 pm »

1e7 is 10000000, and well within what can be represented by uint32_t. The fact that you got weird behavior suggests that something else is at work here. Maybe you could post the assembly listing output from the compiler so we can figure it out?
It was answered in the first post. In the case X gets close to 0xffffffff then floating contagion turns X into a float, adds 1e7 which is greater than 0xffffffff so conversion to the unsigned int "sticks" at 0xffffffff. To get at the nub of the problem, try this on a platform where unsigned int are 32-bits and see how the compiler doesn't want to wrap around back to zero. It actually makes sense from a mathematician's point of view, but not from a ALU designer's. The overflow status bit should be enough but C doesn't let you get at that bit from your code.
Code: [Select]
#include <stdio.h>

int main(void)
{
  unsigned int x;
  x = (unsigned int)99e99;
  printf("%x\n", x);
}

I get
Code: [Select]
bwat@eeepc:~/slask$ uname -a
Linux eeepc 2.6.32-57-generic #119-Ubuntu SMP Wed Feb 19 01:04:55 UTC 2014 i686 GNU/Linux
bwat@eeepc:~/slask$ make contagion
cc     contagion.c   -o contagion
bwat@eeepc:~/slask$ ./contagion
ffffffff

Edit: OK, my claim that it was answered in the first post is me being oversure. I don't have the specific compiler and platform to test it on. I am however pretty confident :)
« Last Edit: July 15, 2014, 07:13:06 pm by bwat »
"Who said that you should improve programming skills only at the workplace? Is the workplace even suitable for cultural improvement of any kind?" - Christophe Thibaut

"People who are really serious about software should make their own hardware." - Alan Kay
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: STM32F4 number overflow
« Reply #8 on: July 15, 2014, 09:09:03 pm »
Edit: OK, my claim that it was answered in the first post is me being oversure. I don't have the specific compiler and platform to test it on. I am however pretty confident :)
You could be right. But here's a piece of the C99 standard (Section 6.2.5):
Quote
A computation involving unsigned operands can never over?ow,
because a result that cannot be represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the largest value that can be
represented by the resulting type.

The left-hand side (lhs) of "X += 1e7;" is certainly unsigned, but the rhs isn't. Maybe it depends on when/how the float is "promoted" to unsigned int? There's some subtlety at work here.
 

Offline gxti

  • Frequent Contributor
  • **
  • Posts: 507
  • Country: us
Re: STM32F4 number overflow
« Reply #9 on: July 15, 2014, 09:15:38 pm »
It's expanding to "x = (uint32_t)( (double) x + 1e7 )", so it does a floating-point add then truncates. There's no integer math happening at all, thus no overflow or modulus math.
 

Offline andyturk

  • Frequent Contributor
  • **
  • Posts: 895
  • Country: us
Re: STM32F4 number overflow
« Reply #10 on: July 15, 2014, 10:00:30 pm »
It's expanding to "x = (uint32_t)( (double) x + 1e7 )", so it does a floating-point add then truncates. There's no integer math happening at all, thus no overflow or modulus math.
Yup, looks that way. And in the case where a floating point value isn't representable in the target of the conversion, the standard says the result is undefined. I.e., it's up to whoever wrote the compiler or the library of intrinsics.

In pyrohaz's assembly code, __eabi_dadd is adding two floating point values. The name of the function suggests it's doing this in *double-precision* floating point, not the single-precision which is supported natively by the STM32F4. So this is probably a bad thing even if you wanted floating point in the first place, because it relies on software emulation of (double precision) floating point. FYI, here's a header file that lists these functions: http://users.sosdg.org/~qiyong/mxr/source/sys/arch/arm/include/aeabi.h#L41

__fixunsdfsi is the routine that converts a double to an unsigned int. One implementation is here: http://opensource.apple.com/source/clang/clang-137/src/projects/compiler-rt/lib/fixunsdfsi.c

It's not the one that pyrohaz's compiler uses though. The one he's using probably maps double values that are outside the range of uint23_t to 0xffffffff.

Pyrohaz, can you dig up the source to your __fixunsdfsi routine and check this?
 

Offline Gridstop

  • Contributor
  • Posts: 42
  • Country: us
Re: STM32F4 number overflow
« Reply #11 on: July 17, 2014, 01:17:35 am »
1e7 is a double, not a float. That's why it's doing double math. 1e7f is a float.
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: STM32F4 number overflow
« Reply #12 on: July 23, 2014, 06:10:18 pm »
I am on holiday so terrible connection but reading an arm book i just read that the cortex M4 has saturation instructions, this might also be a cause of  not overflowing.
 

Offline mrflibble

  • Super Contributor
  • ***
  • Posts: 2051
  • Country: nl
Re: STM32F4 number overflow
« Reply #13 on: July 23, 2014, 06:27:50 pm »
I am on holiday so terrible connection but reading an arm book i just read that the cortex M4 has saturation instructions, this might also be a cause of  not overflowing.
That would be an interesting luxury problem, in reverse! What C/C++ constructs do you use (aside from asm) to get saturated arithmetic using a regular compiler?

Put another way: it would be really interesting if you accidentally got saturating arithmetic. If so, would you be so kind to post the exact code and compiler used? That would help in duplicating the accident. ;)

 

Offline jeremy

  • Super Contributor
  • ***
  • Posts: 1079
  • Country: au
Re: STM32F4 number overflow
« Reply #14 on: July 23, 2014, 08:55:51 pm »
if i recall correctly, the cmsis dsp library uses lots of saturating arithmetic. It is indeed part of the M4.
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: STM32F4 number overflow
« Reply #15 on: July 24, 2014, 12:16:16 am »
-cortex M4 has saturation instructions, this might-

you can easily verify if this is a C-thing or a cortex thing by typecasting a sufficiently large float or double type to an integer type.

or reading the C standards or a decent C book.
================================
https://dannyelectronics.wordpress.com/
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6460
  • Country: nl
Re: STM32F4 number overflow
« Reply #16 on: July 24, 2014, 09:31:55 am »
I agree its a long shot and improbable, still its a good thing to know that these instructions exist.
They are mostly used for audio calculations to prevent overflow and get clipping which is the lesser of both  bad options.
I was also surprised that there are a lot of different Cortex M3 revisions and that the board i am now playing with STM32F100 has an older r1 revision core.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf