von uint16 nach uint32 und wieder zurück.

OP Persönliche Seite #2480228
Hi Leute


Ich brüte gerade über einem Problem bei diesem Code, bei der 
return-Anweisung:
1
int16_t timer0_stop() {
2

3
   uint16_t ticks;
4

5
   ticks = TCNT0;    // stilles Aufruesten auf 16bit
6
   if (ticks < timer0.wstart) ticks += 256;  // wrap-around?
7
   ticks -= timer0.wstart;    // vergangene Ticks
8

9
   return ((uint32_t) ticks * timer0.tick_ns)/1000;  // Mikrosekunden zurueckgeben
10
   //return ticks;
11
}

Ich möchte ticks auf 32 bit aufpumpen, damit das Produkt nicht 
überläuft. /timer0.tick_ns/ ist ein uint16_t und momentan auf 4000 
gesetzt (timer tick intervall ist 4000 Nanosekunden, bei F_CPU 16Mhz und 
Prescaler 64).

Sollte doch so klappen, oder? Tut es aber nicht, die Werte die ich 
rauskriege sind bogus, ich vermute ein Problem mit den Wertebereichen, 
aber wo?. Das direkte Zurückgeben des ticks liefert mir aber 
erwartungsgemässe Ergebnisse, nur eben in timer ticks und nicht in 
Sekunden(bruchteilen)... Was mache ich falsch oder hab ich übersehen?
Gast #2480241
So vielleicht?
1
int16_t timer0_stop() {
2

3
   uint32_t ticks;
4

5
   ticks = (uint32_t)TCNT0;    // stilles Aufruesten auf 32bit
6

7
   if (ticks < timer0.wstart)
8
      ticks += 256;  // wrap-around?
9

10
   ticks -= timer0.wstart;    // vergangene Ticks
11

12
   return (uint16_t)(ticks * timer0.tick_ns/1000);  // Mikrosekunden zurueckgeben
13
   //return ticks;
14
}

TCNT0 max. ist 255.
Plus evtl. 256 = 511.
Minus 0 = 511.
Mal 4000 = 2044000
Durch 1000 = 2044

2044000 passt nicht in uint16_t.

Gruß Dirk
#2480273
Hallo,

ich bin mir jetzt nicht sicher, wie der Compiler die Priorität zwischen 
dem Cast und der Multiplikation regelt. Versuch mal:
1
int16_t timer0_stop() {
2

3
   uint16_t ticks;
4

5
   ticks = TCNT0;    // stilles Aufruesten auf 16bit
6
   if (ticks < timer0.wstart) ticks += 256;  // wrap-around?
7
   ticks -= timer0.wstart;    // vergangene Ticks
8

9
   return ( ((uint32_t) ticks) * timer0.tick_ns)/1000;  // Mikrosekunden zurueckgeben
10
   //return ticks;
11
}


Grüße,
Florian
OP Persönliche Seite #2481863
Danke für eure Beiträge. Ich glaub' ich hab's gefunden: Ich verwende in 
der Routine 32 bit Variablen. Im Listing sehe ich calls zu Routinen wie 
__udivmodsi4 und __mulsi3. Das gehört wohl irgendwie zur avr-libc (oder 
ist es war avr-gcc spezifisches)? für die avr-libc zumindest gilt:

"Unless otherwise noted, functions of this library are not guaranteed to 
be reentrant."

Meine timer_stop() Funktion rufe ich via callback aus einem Interrupt 
auf. Ich hab die Funktion lang und breit aus main() raus getestet, da 
funzt sie wunderbar. Im Interrupt-Kontext sind die Ergebnisse wild.

Muss mir mal überlegen, ob ich auch mit 16 bit klar komme, auf Kosten 
der Genauigkeit...
Persönliche Seite #2484110
Tom M. schrieb:
> Danke für eure Beiträge. Ich glaub' ich hab's gefunden: Ich verwende in
> der Routine 32 bit Variablen. Im Listing sehe ich calls zu Routinen wie
> __udivmodsi4 und __mulsi3. Das gehört wohl irgendwie zur avr-libc (oder
> ist es war avr-gcc spezifisches)?

Die Funktionsnamen folgen einer GCC-Nomenklatur, und diese Routinen sind 
in der libgcc implementiert. Diese beiden Routinen (32-bit 
Multiplikation und unsigned Division) stehen in Assembler und sind 
reentrant, wie alle anderen Arithmetik-Routinen in der libgcc auch. 
Ansonsten taugte so eine Bibliothek bestenfalls für die Tonne.

Neben reentrant-Fähigkeit muss der Zugriff auch atomar erfolgen.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 14 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.