- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 12

Thema: Register für Variable reservieren

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.03.2010
    Beiträge
    161

    Register für Variable reservieren

    Anzeige

    Praxistest und DIY Projekte
    Hallo,
    ich würde gerne den folgenden Code auf Performance optimieren:
    Code:
    // Timer 0 Unterbrechung (100khz)
    ISR(TIMER0_COMP_vect) {
        static uint8_t prescaler;
        if (++prescaler==100) {
            prescaler=0;
            system_timer++;
        }
    }
    Ich glaube, dass es hier wegen der hohen Aufruf-Frequenz gut wäre, die Variable "prescaler" in ein Register zu legen. Ich habe die Variable außerhalb der Funktion (also global) verschoben und so deklariert:
    register uint8_t prescaler asm("r2");
    Das führt leider zu folgender Fehlermeldung:
    Fehler: expected »=«, »,«, »;«, »asm« or »__attribute__« before »asm«
    Wie macht man es richtig?

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    15.06.2008
    Ort
    Wien
    Beiträge
    162
    Ich machs immer so:
    Code:
    uint16_t var = 6518;
    asm ("" : "+r" (var));
    Wobei ich allerdings nicht denke, dass eine 8Bit Variable auf 2 Register verteilt wird. Das würde mMn keinen Sinn machen. (Bei Computer-Prozessoren kann eher das umgekehrte auftreten, also das z.b 4 8Bit Variablen auf 4 32Bit Register aufgeteilt werden, da es schneller ist, als ein 32Bit Register mit 4 8Bit Variablen zu verwalten)

    Das einzige was an deinem Code "optimiert" werden könnte ist statt system_timer++; ein Pre-Increment zu machen, also: ++system_timer;
    Ich nehme aber mal an das der Compiler das ohnehin tut (ohne es getestet zu haben). Dazu müsstest du dir den Assemblecode ansehen

    LG
    Nothing is impossible, the impossible just takes longer!

  3. #3
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von XBert
    Ich machs immer so:
    Was genau soll das bewirken?
    Das was s.frings gerne hätte ist es jedenfalls nicht.

    Zitat Zitat von s.frings
    Wie macht man es richtig?
    Kurze Antwort:
    "asm" in "__asm" ändern, oder gnu99 als Standard verwenden.

    Lange Antwort:
    Richtig macht man es gar nicht. Die potentiellen Probleme lohnen den Gewinn (läppische 4 Clocks in diesem Fall) fast nie. Wenn du diese Mini-ISR optimieren willst, dann implementiere sie direkt als Assembler-Funktion (mit der Variable im Speicher, nicht ausschließlich im Register). Der mögliche Gewinn ist höher, und das ohne die möglichen Nebenwirkungen.
    MfG
    Stefan

  4. #4
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Das sehe ich auch so, wenn schon ASM dann die ganze ISR. Einen Pumkt den man da verbessern kann ist schon mal das Sichern der Register - GCC legt da immer noch ein Zero Register an, auch wenn man es oft gar nicht nutzt.
    Oft kann man den Prescaler auch abwärts Zählen lassen von 100 nach 0, das geht auch etwas schneller.


    Vermutlich könnte man noch mehr Gewinnen, wenn man die Zeit gar nicht von Hand hochzählt, sondern direkt den Timer mit einem Passenden Vorteiler (z.B. 64) laufen läßt und dann ggf. zur Ausgabe umrechnet von den krummen Timer Ticks in µs.

  5. #5
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.03.2010
    Beiträge
    161
    Einen Krummen Timer möchte ich nicht haben, denn dann jittert mein Mikroskunden Zähler, was wiederum verheerende Auswirkungen auf andere Programmteile hätte (z.B. die Berechnung der Aktuellen Geschwindigkeit).

    Mir ist schon klar, daß meine ISR recht teuer ist, daber nach den obigen Kommentaren werde ich sie wohl unverändert lassen.

    Wenn ich könnte, würde ich den Quartz austauschen, so daß ich den Vorteiler nutzen kann, aber dann funktioniert die USB Schnittstelle nicht mehr.

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    49
    Beiträge
    1.146
    Zitat Zitat von s.frings
    Wenn ich könnte, würde ich den Quartz austauschen, so daß ich den Vorteiler nutzen kann, aber dann funktioniert die USB Schnittstelle nicht mehr.
    Du könntest ja auch für den Timer einen externen Takt (z.B. einen Oszillator) nutzen. Dann läuft Deinen USB-Schnittstelle und Du kannst trotzdem Deinen Code optimieren.

    Gruß,
    askazo

  7. #7
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Die ISR ganz in ASM könnte schon etwas bringen, und ist auch nicht so komliziert.

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Die ISR als
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    uint32_t volatile system_timer;
    
    ISR(...,ISR_NAKED)
    {
        static uint8_t prescaler;
        asm volatile (" ... " :: "s" (&prescaler), "s" (&system_timer));
    }
    und als asm ... ohne Gewähr (den quoten darfst selber )
    Code:
    push r24
    in r24,__SREG__
    push r24
    
    lds  r24, %0
    subi r24,-1
    cpi  r24,100
    brne 0f
    
    lds  r24, %1
    subi r24, -1
    sts  %1, r24
    lds  r24, %1+1
    sbci r24, -1
    sts  %1+1, r24
    lds  r24, %1+2
    sbci r24, -1
    sts  %1+2, r24
    lds  r24, %1+3
    sbci r24, -1
    sts  %1+3, r24
    ldi  r24,0
    0:
    sts  %0,r24
    
    pop r24
    out __SREG__,24
    pop r24
    reti
    Disclaimer: none. Sue me.

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.03.2010
    Beiträge
    161
    Danke SprinterSB, das war genau der Tipp, den ich gesucht hatte. Leider habe ich Deinen Beitrag zu spät gelesen - und daher das ganze anhand diverser Tutorials erarbeitet. Mein Forschungsergebnis entspricht fast exakt Deinem Vorschlag (was für ein Zufall )

    Guckst Du: https://www.roboternetz.de/phpBB2/vi...=498523#498523

  10. #10
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.03.2010
    Beiträge
    161
    Es hat sich inzwischen herausgestellt, dass die Verwendung von Register Variablen bei Verwendung der AVR libc unerwartete Seiteneffekte bewirkt hat.

    Das Problem ist, dass ich in "meinen" Sourcen zwar ein Register reserviert habe, aber die AVR libc weiss davon nichts. Spätestens wenn man nun z.B. mit printf etwas ausgibt, passieren seltsame Dinge.

    In meinem Fall kam erschwerend dazu, dass ich das Register in einer Interrupt-Routine beschrieben habe. Sobald irgendeine Library das Register anderweitig verwendet (was sehr wahrscheinlich ist), kommt es zu Fehlfunktionen.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress