- LiFePO4 Speicher Test         
Ergebnis 1 bis 10 von 17

Thema: Softwaretest mit Code Optimierung

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ersteinmal vielen Dank für Eure Informationen.

    Vorab: Ich muss glücklicherwiese nichts optimieren, weder aus Speichertechnischen noch aus Geschwindigkeitsgründen.

    Durch verschiedene Optionen möchte ich jedoch im Vorfeld schon "kritischen Code" erkennen, um eine möglichst "saubere"
    Software zu generieren.

    Das "volatile" ist natürlich zwingend erforderlich zum Beispiel bei meiner "SystemTickcount" Variablen.

    Meine Dummy Variable zum Lesen eines Registers um lediglich ein Interrupt Bit zu löschen muss dann auch "volatile" sein,
    sonst optimiert mir der Compiler die Zeile gänzlich weg, frei nach dem Motto: Was Du nicht benutzt, brauchst Du auch nicht

    Kritisch ist generell das Löschen von Interrupbits beim Cortex-M3. Das sollte man tunlichst nicht in der letzten Zeile tun.
    Das geht dann plötzlich nicht mehr und es wird ein Dauer oder doppelter Interrupt ausgelöst.

    Zur Zeit hängt die Software jedoch immer noch fest und ich bin noch auf der Suche.

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ich möchte das Thema nochmal aufgreifen, da ich neue "merkwürdige" Erkenntnisse gewonnen habe:

    Mein Code läuft jetzt mit Allen möglichen Optimierungen, das war ein gutes Stück Arbeit.
    Ein Fehler hat wirklich lange gedauert und dieser ist mir auch bisher nicht erklärlich. Vielleicht habt Ihr eine Erklärung dafür:

    Diese Zeile hat der Compiler wegoptimiert wenn *base nicht volatile ist */
    das darf er doch nur, wenn er wüste, dass da schon 0x83 drin steht, dem ist aber nicht so
    *(base + UART_LCR) = 0x83; /* DLAB = 1 , 8 bits, no Parity, 1 Stop bit */

    Dazu ein Ausschnitt aus dem Code zum Initialisieren der seriellen Schnittstelle:

    Code:
    /*----------------------------------------------------------------------------*/
    void uart_init(const U8 UartNo,const U32 baudrate)
    { volatile U8* base;
    
      base = (U8*) UART_BASE[UartNo];       /* base address of uart, Basisadreesen sind im Array abgelegt */
    
      *(base + UART_LCR) = 0x83;                /* <---- Zeilenklau Compiler      DLAB = 1 ,  8 bits, no Parity, 1 Stop bit */
      
      /* .............Werte für DLL und DLM setzen............. */
    
      *(base + UART_LCR) = 0x03;             /* <--- diese Zeile lasst der Compiler drin    DLAB = 0 ,  8 bits, no Parity, 1 Stop bit */
      
    }

    warum verschwindet die Zeile lediglich bei Optimierungsstufe -O3 ?

    Siro

    PS. Das ist LPCXpresso v7.9.2 [Build 493] [2015-09-14]
    Gnu-Compiler C/C++ GNU Toolchain Build Support 8.6.0.201502131403 org.eclipse.cdt.gnu.build.feature.group Eclipse CDT
    Geändert von Siro (03.12.2015 um 13:22 Uhr)

  3. #3
    shedepe
    Gast
    Sofern ich das auf die Schnelle sehe sind bereits alle Werte bekannt.

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo Siro,

    Ist doch für einen Automaten logisch! :-=

    Code:
    a = 0x83;
    a = 0x03;
    Da steht am Schluss immer 0x03 in a!

    Wie schon geschrieben wurde, ist das ohne volatile für den Compiler nur eine Variable im Speicher!
    Code:
    a = 0;
    a = 1;
    a = 2;
    a = 3;
    Da macht nur a =3; Sinn, die anderen Werte werden dauernd überschrieben ohne je gelesen zu werden.

    Die CPU, und der Compiler, behandeln bei dieser Architektur Register und Speicher genau gleich, da gibt es keinen Unterschied.
    Da muss man dann halt mit volatile "nachhelfen" und den Compiler beibringen, dass sich diese Speicherzellen auch ohne zutun des Programms änder können, bzw. das Setzen und anschliessende Löschen eines Bits etwas bewirken.

    Es gibt Architekturen, bei denen I/Os am einem separaten Bus hängen, da kann das der Compiler dann an der Adresse unterscheiden. z.B. der 8080 und auch die Nachfolger 8086 bis Pentium haben so einen separaten I/O-Bus. Beim 8080 gab es 256 I/O-Adressen, beim 8086 waren es dann 65KByte. Natürlich kann man aber auch bei dieser Familie I/Os im normalen Speicherbereich einbinden.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Jetzt, wo Du es so erklärst, fällt auch bei mir der Groschen (Centweise )

    Na klar, der Compiler sieht, dass ich einer Variablen einen Wert zuweise, nix damit mache und dann einen neuen Wert zuweise.
    Er kann den Sinn natürlich nicht erkennen, dass ich dies tue um an spezielle Register im UART heranzukommen.

    Das leuchtet mir jetzt auch ein und damit hat er recht und darf das wegoptimieren.
    Vielen Dank Peter

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    67
    Beiträge
    2.435
    Hallo,
    Zitat Zitat von Siro Beitrag anzeigen
    Jetzt, wo Du es so erklärst, fällt auch bei mir der Groschen (Centweise )
    Dann bist du jetzt reich

    Es gibt noch weitere Optimierungen, das wird dann auch die Reihenfolge der Befehle umgestellt, z.B. um die FPU besser auszunutzen, kann man, während die FPU gerade rechnet noch ein paar Integer-Befehle abarbeiten. Das hängt dann aber sehr von der CPU-Architektur ab. Bei manchen RISC-CPUs geht das so weit, dass das Return einer Subroutine VOR dem letzten Befehl stehen muss!

    Grundsätzlich muss man bei Funktionen, welche direkt I/Os bedienen mit der Optimierung sehr genau aufpassen! :Strom
    Meistens ist es am Besten diese separat auszulagern und ohne Optimierung zu übersetzen.
    Andernfalls kann schon eine neue Version des Compilers, mit verbesserter Optimierung, zu einem anderen Timing, und folglich zu Fehlern, führen.

    Noch etwas grundsätzliches zur Funktion eines Compilers:
    Zuerst wird eine lexikalische Prüfung vorgenommen, dabei wird im Prinzip die Rechtschreibung überprüft.
    Anschliessend folgt die syntaktische Prüfung, bei welcher festgestellt wird ob aus den Wörtern auch gültige Sätze gebildet wurden.
    Anschliessend bildet man eine Baumstruktur, welche den logischen Programmablauf darstellt und eigentlich Sprachunabhängig ist.
    Diesen Sprachabhängigen Teil nennt man Front End.

    An diesem Baum erfolgt dann die erste Optimierung, wie z.B. das wegoptimieren von unnötigen Variablen-Zugriffen und totem Code.

    Der Code-Generator (Back End) erzeugt dann aus dem Baum den eigentlichen Maschinencode. Dieser Teil ist dann CPU spezifisch.
    Hier wird dann weiter optimiert, vor allem da hin gehend, dass man viel benutzte Variablen möglichst in einem Register behält und erst am Ende der Berechnung in den Speicher schreibt (volatile verhindert auch diese Optimierung).
    Weitere Optimierungen sind z.B. bei einer Multiplikation mit 2, das Ersetzen durch eine Addition oder einen Links-Shift, je nachdem was halt schneller ist.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo Peter,
    ich wollt mich nochmal bedanken, für die zusätzlichen Informationen.

    Ich habe tatsächlich noch ein Problem gefunden. Ich habe eine "Inkontinenz" Inkonsistenz in meinem Code gefunden.
    Im Header habe ich einen 32 Bit und in C-Code Modul einen 16 Bit Wert declariert/definiert. Das merkt der Compiler nicht und beim IAR-Compiler wird funktioneller Code erzeugt
    der Gnu-Compiler hingegen erzeugt nicht funktionellen Code. Eindeutig meine Schuld , aber so unterschiedlich kann der erzeugte Code durch einen anderen Compiler halt werden.

    Obwohl die Sourcen im Projekt zur Verfügung stehen, guckt der Compiler sie sich nicht an und damit gibt es auch kein Warning. Schade eigentlich.


    Datei: FlowCalc.h
    extern volatile U32 flowfactor;

    Datei: FlowCalc.c
    U16 flowfactor = 256;

    mir fällt jetzt auch nichts ein, wie man solche Fehler vermeiden kann.
    Geändert von Siro (13.12.2015 um 16:00 Uhr)

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    19.05.2015
    Beiträge
    69
    Hallo Sisor,

    kann es sein, dass Du FlowCalc.h nicht in FlowCalc.c inkludierst?

    Also der GCC schreit normalerweise (oder spätestens bei -Wall) wenn eine Variable zuvor anders deklariert wurde, als sie dann später definiert wird.

    Gruss
    Chris

Ähnliche Themen

  1. PROGMEM und Optimierung
    Von Ceos im Forum C - Programmierung (GCC u.a.)
    Antworten: 6
    Letzter Beitrag: 09.10.2013, 07:15
  2. BASCOM Code-Optimierung - Was tut sich genau?
    Von Thomas E. im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 03.02.2012, 19:17
  3. Code Optimierung für Interrupt möglich?
    Von erik_wolfram im Forum C - Programmierung (GCC u.a.)
    Antworten: 15
    Letzter Beitrag: 13.09.2011, 22:21
  4. [ERLEDIGT] Fehler im Code? Optimierung nicht optimal? überfordert!
    Von erik_wolfram im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 30.03.2011, 17:27
  5. Code Optimierung
    Von Siro im Forum C - Programmierung (GCC u.a.)
    Antworten: 10
    Letzter Beitrag: 19.08.2010, 22:45

Berechtigungen

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

LiFePO4 Speicher Test