-         

Ergebnis 1 bis 5 von 5

Thema: FIFO Ringbuffer Assembler

  1. #1

    FIFO Ringbuffer Assembler

    Anzeige

    Hallo zusammen
    ich Suche Quellcode für einen Ringbuffer in Assembler bzw. Codesnipsel oder sonstigen Hilfen dazu.
    Habe mich bereits selbst daran versucht, doch bisher ist es mir noch nicht gelungen. Wie kann ich auf Erreichen des Pufferende nachfragen?

    Ich verwende einen ATMega32.
    Bin für jede Hilfe dankbar.

  2. #2
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    08.07.2006
    Ort
    Karlsruhe/München
    Alter
    27
    Beiträge
    587
    Ich weiß zwar nicht was ein Ringbuffer ist; jedoch weiß ich dach es im Wiki eine Fifo-Lib gibt. Diese arbeitet aber meines Wissens nicht sehr ökonomisch, aber es ist sicher eine gute Anleitung wie man es Programmieren kann...

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied Avatar von drew
    Registriert seit
    06.04.2005
    Beiträge
    150
    Hallo ebby,
    eigentlich mache ich eher 'C' aber ich kann mal das Prinzip beschreiben:
    Für einen Ringpufferpuffer musst du erst mal Speicher für die Daten reservieren. Dann brauchst einen Merker, für die Stelle in Deinem Speicher an die Du das letzte mal geschrieben hast und einen Merker, für die Stelle in Deinem Speicher, von der Du das letzte mal gelesen hast. Das wars auch schon.
    Jetzt musst Du nur noch jedesmal, wenn Du was in den Ringpuffer rein schreibst Deinen "SchreibeMerker" um eins erhöhen und wenn Du was Rausliest, Deinen "LeseMerker" um eins erhöhen.
    Wenn Du jetzt noch nach dem Erhöhen von einem Merker den Merker wieder auf dan Anfang von Deinem Speicher setzt, wenn der Merker zu groß ist, bist Du fertig.

    Das Erreichen des Pufferendes kannst Du erkennen, indem Du Deinen Merker mit der Endaddresse Deines Puffers (Startaddresse +Länge des Puffers) vergleichst.

    Ich versuchs mal in pseudo 'C' vielleicht hilft es Dir...

    Speicher reservieren:
    ------------------------
    uint8 Puffer[GROESSE];
    uint8 *LeseMerker;
    uint8 *SchreibeMerker;

    Init:
    ----
    LeseMerker=&Puffer[0];
    SchreibeMerker=&Puffer[0];

    Schreiben:
    -----------
    SchreibeMerker++;
    if( SchreibeMerker>=&Puffer[GROESSE] )
    { SchreibeMerker=&Puffer[0]; }
    *SchreibeMerker=ZuSchreibenderWert;

    Lesen:
    ------
    LeseMerker++;
    if( LeseMerker>=&Puffer[GROESSE] )
    { LeseMerker=&Puffer[0]; }
    AusgelesenerWert=*LeseMerker;

    Drew

    PS.: Du kannst das ganze noch erweitern, in dem Du beim Lesen die beiden Merker vergleichst und so herausfinden, ob Du von einer Stelle liest, in die auch schon was geschrieben wurde, oder nicht (Overflow Error).


  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    1.892
    Am einfachsten dürfte das mit indizierten Lese und Schreibbefehlen mit Auto Inkrement gehen.

    Code:
    LDI XL,low (Startadresse)          ;X Register mit Startadresse füttern
    LDI XH,high (Startadresse)
    ....
    LDI R16,konstante
    CALL Schreibloop
    .....
    
    Schreibloop:
    ST X+,R16                              ; Den Wert von R16 im Speicherplatz ablegen und X um 1 erhöhen
    LDI R17,low (maxAdress)           ; R17 und R18 auf das Ende des Ringpuffers einstellen
    LDI R18,high(maxAdress)
    CP R17,XL                                 ; Vergleichen ob das Ende des Ringpuffers erreicht ist
    CPC R18,XH
    BRCC ENDE                      ; Das Ende ist nicht erreicht -> nächster Wert
    LDI XL,low (Startadresse)            ; Das Ende ist erreicht  -> wieder am Anfang beginnen
    LDI XL,high (Startadresse)
    ENDE:
    Return                        ; Wieder in die aufrufende Routine zurück gehen.
    Die Ausleseroutine kann analog z.B. mit dem Y Register erfolgen.
    In die Schreibroutine müsste noch eine Überwachung, das der Schreibzeiger, den Lesezeiger nicht überholt. -> Nach dem Schreiben darf der Schreibzeiger nicht gleich dem Lesezeiger sein.
    Das würde Datenverlust zur Folge haben ( Buffer Overflow )
    Wenn der Lesezeiger den Schreibzeiger erreicht hat ist der Ringpuffer wieder geleert.

    Du kannst natürlich auch die aktuellen Schreib- und Leseadressen in einem RAM Speicherplatz ablegen, damit die Routine zerteilen und bei Bedarf den Schreib- bzw. Lesebegfehl ausführen.
    Wenn Du das X und Y Register exklusiv für die Indizierung der Adressen nutzen kannst (wie im Beispiel oben), bleibt Dir das Laden und Abspeichern der Adressen in das RAM erspart.

    Ich hoffe ich hab das einigermassen Verständlich rübergebracht, wenn nicht poste mal wo es hakt.

  5. #5
    Danke für die Antworten
    habe jetzt einen ersten Versuch hin. Allerdings ohne Überwachung des Schreibzeigers. Habe einfach den Ringbuffer relativ groß gemacht. Die Daten dürften schnell genug gelesen werden.

Berechtigungen

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