Integer Sättigung

Gast #3549885
Lesenswert?

Hallo,

ich habe einen vermeintlichen Fehler in meinem C Programm (CoIDE) unter 
einem STM32F405 gefunden, der sich aber nicht auswirkt. Jetzt ist die 
Frage, ob evtl. an der DSP-Fähigkeit des Controllers liegt und sich 
daher alles noch normal verhält.

Normalerweise würde ich hier
1
  uint32_t MSDelayCounter = 0;
2
  /* Wartezeit */
3
  if ( MSDelayCounter-- );
erwarten, dass die Variable MSDelayCounter einen Underflow hat, sodass 
sie wieder bei 2^32 - 1 anfängt, wenn sie auf 0 steht.
Tut sie aber nicht. Auf einem AVR führt dieser Code zu einem Underflow, 
auf dem STM32F4xx unter GCC nicht.

Auf einem AVR ist folgendes nötig:
1
  uint32_t MSDelayCounter = 0;
2
  /* Wartezeit */
3
  if ( MSDelayCounter ) MSDelayCounter--;

Liegt das nun am DSP der Controllers?




Ingo
#3549891
Lesenswert?

Ingo schrieb:

> Tut sie aber nicht.

Was tut sie statt dessen?
Da es sich hier um eine unsigned Variable handelt, ist an und für sich 
aus dem C Standard heraus genau definiert, was hier zu geschehen hat. Da 
hat ein Compiler keine Freiheiten. Der C Standard sagt eindeutig, dass 
es hier zu einem Wrap Around Effekt kommt, so wie du das erwartest.
Gast #3549932
Lesenswert?

Peter Dannegger schrieb:
> Ein If mit leerer Anweisung, wer schreibt denn sowas?
Das ist ja der Fehler. Da er sich aber nicht ausgewirkt hat lief es so.
1
volatile int MSDelayCounter;
1
/* Delayroutine */
2
void MyDelayMS( int DelayInMS )
3
{
4
  MSDelayCounter = DelayInMS * SYSTICK_IN_HZ / 1000;
5
  while (MSDelayCounter);
6
}

im Timeraufruf
1
if ( MSDelayCounter-- );

und es funktioniert wie es soll...

Ich bereite den alten Code gerade auf, habe aber das System grad nicht 
zur Hand und bin darüber gestolpert. Ich bin der Meinung ich habe es 
damals im Debugger so gehabt, dass es nicht negativ wird und keinen 
Unterflow gibt.

Die erste Info mit dem uint32_t war falsch, sorry, es handelt sich um 
einen normalen int...


Ingo
#3549968
Lesenswert?

Ingo schrieb:
> uint32_t MSDelayCounter = 0;

Ingo schrieb:
> volatile int MSDelayCounter;

Was denn nun?
Entscheide Dich mal für einen Typ.

Beim 32Bit-Boliden brauchst Du keinen Unterlauftest, weil das MyDelayMS 
oft genug vorbeikommt, um jede Änderung mitzukriegen.

Beim 8Bit-AVR mußt Du aber das 32Bit-Lesen atomar kapseln. Außerdem kann 
ein anderer Interrupt so lange verzögern, daß der Timer schon 2 Schritte 
weiter gezählt hat.
#3550015
Lesenswert?

Es war nur der Erklärungsversuch, warum ARM-C/AVR-C sich scheinbar 
unterschiedlich verhalten sollten.

Aber da der wirkliche Code nun schlußendlich doch mit (signed) int lief, 
ist all das hinfällig geworden, da nicht definiert.

Ich finds immer wieder nervig, wenn völlig anderer ungetesteter Code 
gepostet wird und dann die wildesten Behauptungen darüber aufgestellt 
werden.

A. K. schrieb:
> Ich würde es drin lassen.

Bei (signed) int musses sogar drin bleiben, damit man nicht in 
undefiniert rein rennt.
Gast #3550031
Lesenswert?

Ingo schrieb:
> ob evtl. an der DSP-Fähigkeit des Controllers liegt und sich
> daher alles noch normal verhält.
Nein, für die brauchts spezielle Instruktionen (zB "QSUB"), die man 
durch Inline-Assembler oder durch Verwendung der entsprechenden 
CMSIS-DSP-Library nutzen kann.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren