Hallo,
ich würde gerne meine aktuelle Bare-Metal Applikation mit DMA- und
Ethernettransfer um einen Massenspeicher erweitern.
Dazu sind erst einmal folgende Dinge notwendig:
-File-System um auf den Massenspeicher zuzugreifen
-Treiber für USB und evtl. SD
-einen Stack für den USB Host.
Die Ansprüche sind erst einmal nicht sehr hoch. Bei der Datenrate wären
ca. 100 MB/s wünschenswert, notwendig sind jedoch nur zwischen 10-50
MB/s.
Auf dem MicroZed Board werden Daten generiert, welche aktuell über
Ethernet versendet werden, jedoch zusätzlich/alternativ auf eine externe
Festplatte geschrieben werden sollen.
Vor Linux scheue ich mich momentan deshalb, da ich eine recht
performante Anwendung mit eigenem TCP/IP Stack auf Basis einer
Bare-metal Anwendung erstellt habe. Es besteht die Möglichkeit, ein
Filesystem + USB Treiber mittels eines Linux auf einem der beiden Kerne
zum Laufen zu bringen und auf dem zweiten Kern die Bare-Metal Anwendung
laufen zu lassen - finde ich jedoch etwas umständlich.
nun habe ich bereits einen bare-metal driver gefunden, dieser
initialisert das Processing System des Zynq jedoch ausschließlich als
DEVICE, nicht als HOST:
1
/* Set the USB mode register to configure DEVICE mode.
2
*
3
* XUSBPS_MODE_SLOM_MASK note:
4
* Disable Setup Lockout. Setup Lockout is not required as we
5
* will be using the tripwire mechanism when handling setup
6
* packets.
7
*/
8
ModeValue=XUSBPS_MODE_CM_DEVICE_MASK;
9
10
XUsbPs_WriteReg(InstancePtr->Config.BaseAddress,
11
XUSBPS_MODE_OFFSET,ModeValue);
12
13
XUsbPs_SetBits(InstancePtr,XUSBPS_OTGCSR_OFFSET,
14
XUSBPS_OTGSC_OT_MASK);
ModeValue = 0 setzt den USB Mode als DEVICE MODE
ModeValue = 1 setzt den USB Mode als HOST MODE, nur leider ist schon das
im Board Support Package fest codiert, eine Konfiguration als DEVICE
wird nicht vorgesehen.
es wird jedoch immer wieder angesprochen, dass auch der Host Mode
unterstützt werden würde:
ich denke jedoch, dass es nicht so ohne weiteres möglich ist? Leider
gibt es absolut nichts gescheites im Netz zu finden!
Alternativ würde auch eine käuflich erwerbbare Version in Frage kommen,
falls hier jemand mehr weiß?
Wäre schön wenn mir jemand einen möglichen Lösungweg nennen könnte, da
ich aktuell nicht weiter komme.
Vielen Dank!
Grüße
Julian
Moin Julian,
Julian B. schrieb:> Die Ansprüche sind erst einmal nicht sehr hoch. Bei der Datenrate wären> ca. 100 MB/s wünschenswert, notwendig sind jedoch nur zwischen 10-50> MB/s.
Auch bei den 50 MByte/s ist Sense mit USB 2.0, ne. Da müsstest du schon
in Richtung USB3.0 gehen oder gar SATA in Betracht ziehen. Oder Daten
komprimieren...
> Filesystem + USB Treiber mittels eines Linux auf einem der beiden Kerne> zum Laufen zu bringen und auf dem zweiten Kern die Bare-Metal Anwendung> laufen zu lassen - finde ich jedoch etwas umständlich.
Gerade die Ketzerei hätte ich jetzt am ehesten noch begangen.
Denn USB und effiziente DMA in Bare Metal hochzuziehen und ans Limit zu
trimmen ist gehörig komplex, unter dem Aspekt dass auch noch ATA-Layer
und Filesystem zu implementieren sind. Da gibts schon eine Menge Code,
aber bis das alles so zusammenspielt...
Aber auch die Linux-Seite würde noch keine Garantie für deine
Durchsatzanforderungen bieten. Ich bin nicht up to date, wie gut Xilinx
die Kernelseite abgedeckt hat, mein letzter Statuscheck war noch in der
"Steinzeit".
Hi Strubi :)
ok 50MB ist auch das maximum was übertragen werden soll, mit Abstrichen
sind 10-25MB immernoch sehr toll. Darunter allerdings macht es nur noch
wenig Sinn.
Wäre es auch möglich einen bestehenden Stack auf den Zynq zu portieren?
Und dies auch ohne Filesystem, oder bedingt die USB-Host Funktion
unbedingt ein Filesystem?
Gibts irgend etwas um "schnell" mal eine einfache Linux Applikation mit
Filesystem und USB-Host-Funktionalität zum Laufen zu bekommen, ohne dass
ich hier Wochen umsonst verschwende und schließlich das Thema doch
verwerfen muss?
Hi Julian,
> Wäre es auch möglich einen bestehenden Stack auf den Zynq zu portieren?> Und dies auch ohne Filesystem, oder bedingt die USB-Host Funktion> unbedingt ein Filesystem?>
Nee, wenn du nur Sektoren/Blöcke schreiben willst, reicht die
Implementierung einiger USB-SCSI-Kommandos, wenn das USB I/O für deine
HW bereits abgehakt ist. Die Header dazu findest du im Linux-Source
(siehe struct sg_io_hdr_t, wenn ich nicht falsch liege)
Es gibt sonst auch ganz bekloppte Leute, die spiffs (spi flash
filesystem) für andre Medien missbrauchen. Geht sehr gut "bare metal".
> Gibts irgend etwas um "schnell" mal eine einfache Linux Applikation mit> Filesystem und USB-Host-Funktionalität zum Laufen zu bekommen, ohne dass> ich hier Wochen umsonst verschwende und schließlich das Thema doch> verwerfen muss?
Wenn "mal schnell", dann wohl so: Linux mit USB-Host-Unterstützung auf
den Zynq braten, USB-Stick einstecken und 'dmesg' checken.
Dann bleibt das Problem nur noch, wie du effizient (typischerweise auch
per memory to memory dma) die Daten zwischen den Cores austauschst.
Weiss aber nicht, ob Xilinx für sowas schon Kerneltreiber-Templates
bereitgestellt hat.
Strubi schrieb:> Wenn "mal schnell", dann wohl so: Linux mit USB-Host-Unterstützung auf> den Zynq braten, USB-Stick einstecken und 'dmesg' checken.> Dann bleibt das Problem nur noch, wie du effizient (typischerweise auch> per memory to memory dma) die Daten zwischen den Cores austauschst.> Weiss aber nicht, ob Xilinx für sowas schon Kerneltreiber-Templates> bereitgestellt hat.
Danke mal wieder für deine Hilfe, Strubi.
Also ich habe jetzt die XAPP1078 zum laufen bekommen, viel mehr selbst
nachgebildet, ich kann also ein neues VHDL Design abändern, Petalinux
abändern und den Code abändern und es läuft soweit alles.
Gibt aber bis ich zu USB komme noch einige Baustellen, die ich angehen
muss, bevor das eigentliche Thema USB hoch kommt. Nun läuft Linux unter
Core0 und baremetal unter core1.
linux wird gebootet. die baremetal-app liegt auf addr 0x30000000 im RAM,
wird diese Adresse ins OCM bei 0xFFFFFFF0 geschrieben, wird die app
gestartet.
Aufgrund des Linux OS kann nur noch mit global timer und private
interrupts gearbeitet werden. Core1_nIRQ wird in der demo app verwendet.
nun wollte ich Core1_nFIQ zusätzlich implementieren, bekomme ihn aber
nicht verbunden/ausgelöst, hier meine Initialisierung:
1
staticintSetupIntrSystem(INTC*IntcInstancePtr,
2
XPlIrq*PeriphInstancePtr,
3
u16IntrId,
4
XPlIrq*PeriphInstancePtr2,
5
u16IntrId2)
6
{
7
8
intStatus;
9
10
11
XScuGic_Config*IntcConfig;
12
13
/*
14
* Initialize the interrupt controller driver so that it is ready to
das modul IRQ_gen0 (0x78600000) ist verbunden mit core1_nIRQ,
das modul IRQ_gen1 (0x78700000) ist verbunden mit core1_nFIQ.
Wird an Addr 0x78600000 löst das modul einen interrupt aus, der wieder
quitiert werden muss, ebenso IRQ_gen1.
Funktioniert aber nicht. Ich muss beide Interrupts auslösen, dann wird
nur der nIRQ ausgelöst und quitiert, nFIQ bleibt gesetzt. Wenn nFIQ aber
nicht gesetzt ist, löst auch nIRQ nicht aus.
Woran liegt das???
ich hab nun die interrupt - thematik mal auf eis gelegt, war nur ein
Randproblem.
nun starte ich petalinux auf core0 und baremetal auf core1. funktioniert
auch. wenn ich aber auf core1 meine lwip anwendung laufen lasse bekomme
ich keine tcp verbindung hin! :(
wie im anhang zu sehen ist, kommuniziert das fpga (192.168.202.10) mit
dem host (192.168.202.86), dieser meldet sich dann zwar auf die erste
anfrage zurück, danach sollte jedoch auch eine verbindung ausgelöst
werden. daran hängt es aber gerade eben! der "connected_callback" wird
in lwip nicht ausgelöst, obwohl ich "tcp_connect()" ausführe und die
beiden timer (fast & slow) auch zur richtigen zeit kommen.
woran kann das liegen?
hat der zweite kern keinen zugriff mehr auf die hardware durch das
petalinux? ist das aus xapp1078 modifizierte BSP auch hier modifiziert
worden?(offiziell wurde die uart output() funktion verändert und der
private timer anders initialisiert.
dies dürfte jedoch keinen effekt auf lwip oder ethernet haben?
https://gist.github.com/imrickysu/8c9bb9a0a0c40f24d718
bitte noch einmal um hilfe, denn ansonsten scheint alles wunderbar zu
funktionieren!
Hi Julian,
sorry, das muss ich passen. Sieht fast so aus, als ob Xilinx es immer
noch bisschen auf ihre eigene Weise machen, wegen solcher Scherereien
flog damals bei mir der Zynq in die Ecke.
Die Crux bei Linux ist halt schnell, dass es sehr komplex wird, wenn die
board-supply-Packages nicht durchdacht sind/das machen sollen, was der
User will. Hast du mal versucht, am Device-Tree (*.dts) rumzudrehen? Das
wäre typischerweise die eleganteste Methode, Resourcen zu kontrollieren.
Sollt ja ein aktuelles Kernel sein...
Ansonsten hilft vermutlich nur HW-Debugging, aber fang bloss nicht mit
OpenOCD an, das Linux-Kernel zu debuggen (Albtraum garantiert).
Gruss,
- Strubi
Hi Strubi,
du bist auch der einzige der hier aktiv ist, oder? :P
vielen DAnk für deine antworten!
ich habe den ethernet controller in .dts komplett entfernt, dann wird er
nicht mehr initialisiert und antwortet bei umkonfiguration auch nicht
mehr darauf. linux scheint also die verbindung zum eth0 verloren zu
haben.
dennoch scheine ich keinen zugang zum hardwaretreiber zu haben. die BSP
sind auch leider zu undurchsichtig auf treiberebene, ich kann leider
nicht erkennen wo der haken ist.
ich bekomme zum beispiel den error-callback nachdem die timeouts für das
senden der SYN-segmente erreicht ist. prinzipiell funktioniert also ja
zumindest etwas. das SYN wird aber physikalisch nie übertragen, generell
keine TCP protokolle. am anfang lediglich ARP protokolle.
komme so leider nicht weiter und weiß nicht in welche richtung ich nun
gehen soll :/