Forum: Mikrocontroller und Digitale Elektronik FIFO lösung für 1MBaud zu 0,32MBaud Problem


von Max (Gast)


Lesenswert?

Hallo,

ich verzweifel langsam bei dem Versuch eine 320kBit/s SPI-Übertragung 
von meinem xMega zu einem VS1053 über USB aufrecht zu erhalten...

Ich habe einen 4096Byte FiFo auf meinem xMega realisiert welcher zu 
Beginn mit 2048Byte gefüllt wird.
Anschließend wird eine 0xFF zum PC gesendet was das Senden von weiteren 
2048Bytes zum xMega auslöst.
Im direkten anschluss wird begonnen die vorhandenen 2048Byte über SPI zu 
schicken "zeitgleich" zum empfangen der angeforderten 2048Bytes.

Ist die Übertragung von 2048Bytes über SPI abgeschlossen wird gewartet 
bis die USB-Übertragung abgeschlossen ist (Was bei der fast 3x 
schnelleren CP2103 Baudrate von 926kBit/s nicht passieren sollte)

Leider verbringt der Prozessor an dieser Stelle trotzdem sehr viel Zeit 
mit warten so dass die MP3 nicht abgespielt wird.(MP3s mit < 100kBit/s 
funktionieren tadellos)

Ich vermute dass die Latenzen zu groß sind und Windows zu lange pennt eh 
es die Anforderung bemerkt.


Da ich bereits seit geraumer Zeit an diesem Problem knobel würde ich 
mich extrem über eine alternativlösung zur Umsetzung freuen.

Letztendlich geht es ja nur darum eine MP3 mit 320kBit/s über einen 
CP2103 welcher auf USBXpress eingestellt ist und auf 926kBit/s arbeitet 
zu meinem xMega128A1(32Mhz) zu senden welcher diese Weiterleitet über 
einen 8Mhz SPI zum VS1053 sendet.


Vielen Dank im Voraus

von Falk B. (falk)


Lesenswert?

@  Max (Gast)

>Ich habe einen 4096Byte FiFo auf meinem xMega realisiert welcher zu
>Beginn mit 2048Byte gefüllt wird.
>Anschließend wird eine 0xFF zum PC gesendet was das Senden von weiteren
>2048Bytes zum xMega auslöst.
>Im direkten anschluss wird begonnen die vorhandenen 2048Byte über SPI zu
>schicken "zeitgleich" zum empfangen der angeforderten 2048Bytes.

Wirklich? Also mit Interrupt. Poste mal Quelltext als Anhang.

>Ist die Übertragung von 2048Bytes über SPI abgeschlossen wird gewartet
>bis die USB-Übertragung abgeschlossen ist

Warum? Wenn das per Interrupt oder einen anderen Mechanismus 
erfolgt, welcher Multitasking ermöglicht, muss dort nicht so 
gewartet werden.

> (Was bei der fast 3x
>schnelleren CP2103 Baudrate von 926kBit/s nicht passieren sollte)

Bei 320kbit/s reichen 2048 Byte Vorsprung ca. 50ms.

>Ich vermute dass die Latenzen zu groß sind und Windows zu lange pennt eh
>es die Anforderung bemerkt.

50ms? Klingt mir zuviel SOOOO mies ist auch Windows nur selten.

>Da ich bereits seit geraumer Zeit an diesem Problem knobel würde ich
>mich extrem über eine alternativlösung zur Umsetzung freuen.

Der Ansatz ist richtig, die Umsetzung wahrscheinlich fehlerhaft.

von Max (Gast)


Lesenswert?

Ich habe mal die Zeit gemessen die für das Senden der 2048Bytes benötigt 
werden (C#->Stopwatch) und es ergab eine übertragungszeit von 
22ms(93090Bytes/sec). somit bleibt eine Zeit von 28ms für die Latenzen.

Kommt mir auch etwas viel vor allerdings kenne ich mich da nichtmehr so 
gut aus.

Das Warten nach der Übertragung von 2048Byte über SPI habe ich eingefügt 
um herauszufinden weshalb der Buffer ständig leer ist.

von Max (Gast)


Lesenswert?

Den quelltext werde ich heuteabend hier posten.

Die USART Übertragung läuft über High-Level-Interrupt und speichert in 
der ISR das jeweilige Byte nur in den FIFO.

SPI ist polled-basiert und sendet innerhalb der "main" Bytes aus dem 
FIFo.

von Max (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

habe nochmal ein Bisschen rumprobiert und kann nun Windows als Fehler 
ausschließen.
Es wird jede einzelne Anfrage sauber mit 2048Bytes beantwortet.

Anbei der Quellcode. Ist nicht gut kommentiert aber dafür auch nicht 
lang und intuitiv.

Die VS1053_Buffer.h brauche ich hier nicht posten. Es handelt sich um 
den Präprozessor-FIFO aus dem eigenen Hause mit 4096Bytes Größe:

http://www.mikrocontroller.net/articles/FIFO


Die Wichtigen Stellen sind wahrscheinlich das SPI-Senden:


while(1)
    {
      USART.DATA = 0xFF;

      PORTE.OUTSET = PIN4_bm;
      for(uint8_t i = 0; i < 64; i++)
      {
        while(!(PORTA.IN & 0x02)) {}
        for(uint8_t x = 0; x < 32; x++)
        {
          VS_transmitSDI(VS_Buffer_read(VSBuffer));
        }
      }
      PORTE.OUTCLR = PIN4_bm;
    }

sowie die transmitSDI Funktion

inline void VS_transmitSDI(uint8_t data)
{
  VSSPI.DATA = data;
  while(!(VSSPI.STATUS & SPI_IF_bm)) {}
}

Ich hoffe das ist aufschlussreich.

von holger (Gast)


Lesenswert?

>Ist die Übertragung von 2048Bytes über SPI abgeschlossen wird gewartet
>bis die USB-Übertragung abgeschlossen ist (Was bei der fast 3x
>schnelleren CP2103 Baudrate von 926kBit/s nicht passieren sollte)
>
>Leider verbringt der Prozessor an dieser Stelle trotzdem sehr viel Zeit
>mit warten so dass die MP3 nicht abgespielt wird.(MP3s mit < 100kBit/s
>funktionieren tadellos)

Die MP3 wird doch aber mit kurzen Aussetzern trotzdem abgespielt,
oder etwa nicht?

von Max (Gast)


Lesenswert?

ja, Abspielen kann ich mit dem gezeigten code MP3s bis 192kBit/sec ohne 
hörbare Ruckler oder ähnliches.
Aber theoretisch müssen auch 320kBit/s Mp3s machbar sein nur finde ich 
den Fehler nicht an dem es Scheitert :<

von holger (Gast)


Lesenswert?

>> (Was bei der fast 3x
>>schnelleren CP2103 Baudrate von 926kBit/s nicht passieren sollte)

Versuchs mal mit einem FT232RL.

von Falk B. (falk)


Lesenswert?

@  Max (Gast)

>    * MP3Example.c (2,9 KB, 6 Downloads) | Codeansicht

Da fehlen wichtige Teile, z.B. die FIFO-Sachen.
Was aber auffällt ist, dass du im blinden vertrauen Die Daten aus dem 
FIFO ziehst und einfach losschreibst. Das ist schlecht. Vor dem Senden 
von 32 Byte müssen wenigstens 32 Byte im FIFO sein, damm muss man prüfen 
und ggf. warten. Ausserdem kann und muss man Überlauf und Unterlauf des 
FIFO detektieren und ggf. signalisieren, das ist nicht nur für die 
Stabilität deiner Software wichtig, sondern auch für die Fehlersuche.


>habe nochmal ein Bisschen rumprobiert und kann nun Windows als Fehler
>ausschließen.
>Es wird jede einzelne Anfrage sauber mit 2048Bytes beantwortet.

In welcher Zeit? Wie gemessen? Mit dem Oszi.

>Anbei der Quellcode. Ist nicht gut kommentiert aber dafür auch nicht
>lang und intuitiv.

Richtig, nicht intuitiv ;-) Naja, geht schon, wenn gleich man nur raten 
kann, was PIN4_bm macht. Ist das das Handshake zum PC, dass der neue 
Daten senden soll? Das vermisse ich nämlich komplett.

>Die VS1053_Buffer.h brauche ich hier nicht posten.

Doch.

>http://www.mikrocontroller.net/articles/FIFO

100% identisch? Oder doch kleine Änderungen?

von Falk B. (falk)


Lesenswert?

Noch was, der FIFO aus dem Wiki ist NICHT interruptsicher, d.h. ein 
Zugriff aus dem UXC Interrupt kann genau in einen Lesezugriff 
reinfunken. Nicht gut!

Ergo. Einen WIRKLICH guten FIFO schnitzt man nicht mal so schnell.

von Denis (Gast)


Lesenswert?

@Falk Brunner

Alles was du gepostet hast ist überflüssig.

Der TE hat bereits geschrieben dass es sich bei dem FIFO um den 
verlinkten mit der einzigen Änderung dass die größe auf 4096 erhöht 
wurde.

Die kontrolle nach Überlauf etc ist ebenfalls überflüssig.
-Sendet man nur wenn daten vorhanden sind stockt die MP3
-Sendet man die 0x00 welche aus dem Fifo kommt wenn keine Daten 
vorhanden sind stockt die MP3

Welchen unterschied macht das jetzt genau?

Und wieso sollte man den Über/Unterlauf detektieren?
192kBit/s MP3s werden wohl sauber abgespielt
320kBit/s Mp3s nicht. Am Überlauf des Puffers wirds wohl nicht 
liegen....


Und zum schluss noch eine Quizfrage: Wozu dient PIN4_bm.
Beobachtung #1: Vor jeder SPI-Transaktion wechselt er seinen Zustand. 
Danach wieder zurück.
Beobachtung #2: Was ist im Datenblatt eines xMegas unter Portbelegung 
bei SPI für eine Funktion auf Pin4 festgelegt?
Antwort CS!!!!!


Der vom TE gepostete Code ist, bemessen an der komplexität des Problems, 
vollkommen verständlich.
Wer den Code nicht lesen kann ist i.d.R. nicht in der Lage zu helfen wie 
du eindrucksvoll bewiesen hast.


Und zur Interruptsicherheit:
Ein cli/sei im read und gut....


LG Denis

von Falk B. (falk)


Lesenswert?

@  Denis (Gast)

>Alles was du gepostet hast ist überflüssig.

Deine Meinung.

>Der TE hat bereits geschrieben dass es sich bei dem FIFO um den
>verlinkten mit der einzigen Änderung dass die größe auf 4096 erhöht
>wurde.

Und? Die Erfahrung in diesem Forum zeigt, dass man schnell was so hoppla 
hop als problemos abgehakt wird, und genau DORt dann der Fehler liegt.

>Die kontrolle nach Überlauf etc ist ebenfalls überflüssig.

Klar, alles nur was für Weicheier.

>-Sendet man nur wenn daten vorhanden sind stockt die MP3
>-Sendet man die 0x00 welche aus dem Fifo kommt wenn keine Daten
>vorhanden sind stockt die MP3

>Welchen unterschied macht das jetzt genau?

Das man diesen Zustand DEFINERT erkennt! Und nicht an stotternden MP3 
WAHRSCHEILICH was rückschließt.

>Und wieso sollte man den Über/Unterlauf detektieren?
>192kBit/s MP3s werden wohl sauber abgespielt

Das kann Zufall sein.

>320kBit/s Mp3s nicht. Am Überlauf des Puffers wirds wohl nicht
>liegen....

>Wer den Code nicht lesen kann ist i.d.R. nicht in der Lage zu helfen wie
>du eindrucksvoll bewiesen hast.

Na zum Glück hat DEIN Posting der Fehlersuche ungemein geholfen!

>Und zur Interruptsicherheit:
>Ein cli/sei im read und gut....

Aha, du kennst den Code des OP?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.