Moin,
vielleicht kann mir jmd bei der Suche nach einem passenden
Mikrocontroller helfen: er sollte mindestens 32kB internen RAM, 128kB
Flash oder mehr (auch intern) besitzen, sowie einen USB 2.0 Full-Speed
Device, welcher per DMA die Daten im internen RAM ablegen kann - der
Speicher für die DMA sollte größer 8kB sein im RAM; und ein externes
Memory-Interface wird benötigt (16Bit breiter Datenbus).
Es kommen insgesamt immer 9kB Daten über USB an, und erst dann kann der
Prozessor mit den Daten auch was anfangen. Daher wäre es schön, wenn der
Prozessor erst danach damit beschäftigt wird.
Bezüglich der DMA-Geschichte: ist es richtig, dass man diese nur einmal
am Anfang einstellt und dann läuft der Transfer der Daten von alleine ab
(die ganze Zeit), oder muss der Transfer immer wieder per Hand aktiviert
werden?
Das Gehäuse kann alles sein, außer ein BGA, da ich das nicht selbser
löten kann (bzw. keine Erfahrungen habe bezüglich Bügeleisen etc...)
LG
Jörg
Soweit ich erkennen kann lassen sich per Fullspeed USB sowieso nur 64
Byte pro Frame übertragen, isochron 1KB. Insofern dürfte die Grösse des
USB-RAMs nicht der entscheidende Aspekt sein und es sollten genug
Möglichkeiten bestehen, die Daten rechtzeitig ins normale RAM zu
verlagern.
Controller mit mindestens 32KB RAM, externem Speicherinterface und USB
gibt es jedenfalls einige. In den STM32F103/105 Reihen beispielsweise.
reicht mir ein 70MHz Prozessor wenn über USB eine Datenrate von 8MBit/s
zu erwarten ist?
Diese Daten müssen anschließend umsortiert werden (ein kompletter
Datenblock hat 600Bit und insgesamt gibt es von diesen 16 Stück);
Sortierung sieht so aus, dass von jedem dieser 16 Blöcke nacheinander
alle ersten Bits, alle zweiten Bits, dritten Bits etc. an das externe
Memory Interface übergeben werden müssen...
Die Geschwindigkeit mit der diese Daten an das ExtMemInt weitergeben
werden müssen beträgt für jedes Bit 1µs; d.h. alle 1µs wird von jedem
dieser 16en Blöcke ein Bit weitergeben.
Eigentlich nicht soviel, aber ich weiß nicht wieviel Performance-Verlust
man durch die Verwendung des USB Interfaces bekommt.
LG
Jörg
Jörg schrieb:
> reicht mir ein 70MHz Prozessor wenn über USB eine Datenrate von 8MBit/s> zu erwarten ist?
Nö. Mit diesem ganzen Zirkus drum herum und vermutlich streng synchronem
pausenfreiem Bus nicht. Da klingt das für mich eher nach FPGA. Eventuell
geht es aber auch mit XMOS.
die Datenpakete über USB kommen im kontinuierlichen Stream an, das ist
richtig. Im Prinzip einschalten und nicht mehr aufhören...
Dachte mir schon dass es mit einem ARM7 knapp werden würde, aber ein
ARM9 mit 180 MHz (100MHz externes Businterface) reicht auch nicht mehr?
Auf einem ARM7 mit 70MHz hatte ich es schon mal am laufen allerdings
ohne USB-Zeug (in diesem Fall lagen die DAten in einem Dualport RAM, was
jetzt nicht mehr möglich ist)...
Mit FPGA oder XMOS kenn ich mich gar nicht aus...
Hab's nicht probiert, aber 12Mb/s = 1,5MB/s = 0,4MW/s traue ich dem
Controller schon zu, immerhin muss der Prozessor die normalerweise nicht
Bit für Bit einzeln verarbeiten. Erst zusammen mit der Bitpflückerei
wird das zum Thema.
Hallo Jörg,
über den Daumen könnte da die Leistung der AVR32UC3 von Atmel reichen.
Da gibt es Typen mit USB-Hardware und externem Speicherinterface.
Gruß, DetlevT
Detlev T. schrieb:
> über den Daumen könnte da die Leistung der AVR32UC3 von Atmel reichen.> Da gibt es Typen mit USB-Hardware und externem Speicherinterface.
Ob ein 66MHz AVR32 wirklich so viel schneller ist als ein 100MHz
Cortex-M3 (LPC1700)? Weder USB noch Bus sind hier m.E. das zentrale
Problem, sondern das Bitgepfriemel frisst die Leistung. Die
USB-Interrupts und Blocktransfers kommen da nur noch oben drauf.
Was mit weiterhin zu unklar ist um es abschätzen zu können: die externen
Buszyklen. Müssen die exakt alle 1µs ablaufen, komplett ohne erlaubtem
Jitter? Das schafft ohne externe Synchronisation nicht einmal DMA. Wie
hast du das in der bisherigen Lösung gemacht?
das ganze lief damals ohne Betriebssystem (da kein USB) und die
Synchronisation, dass die Signale über das externe MemInterface
rausgingen, war lediglich ein TimerInterrupt (der daraus resultierende
Jitter war zu vernachlässigen).
Der Jitter zwischen den "gleichzeitig" auf den Weg zu bringenden Daten
durfte nicht zu groß sein, und das war mit dem MemInterface gut zu
händeln.
Mit dem Bitgefriemel hat es gerade so geklappt - war aber zeitlich sehr
knap; also irgendwelche kurzen zusätzlichen Interrupts etc. waren nicht
drinnen. Der Dualport RAM (16Bit Datenbus) war allerdings auch sehr
schnell mit; ich glaub ich hatte einen Waitstate (mit USB wird dieser
Vorgang des Datenschaufelns in den internen RAM wahrscheinlich nicht so
schnell gehen)
>Das schafft ohne externe Synchronisation nicht einmal DMA
welche externen Syn-Möglichkeiten würde es hier denn noch geben? Wenn
extern ein Sync-Signal anliegt wie z.B. Midi-Timecode oder ähnliches
muss das von der CPU auch erstmal per Interrupt wahrgenommen werden...
Wenn ein Jitter von ein paar Takten zulässig ist, dann ist ein
Bustransfer über Timer-getriggertes DMA wohl auch kein Problem und
frisst kaum Zeit.
Ist das externe nun wirklich ein Bus, oder sind das bloss 16 Leitungen
und du hast bisher einen Bus verendet? DMA direkt auf den Port gibt's ja
auch.
Interrupts sollten dann auch kein Problem sein, solange die Gesamtlast
noch verdaut wird. Das darf natürlich keine Just-in-Time Produktion
werden, sondern es müssen genug umgepfriemelte Daten für den DMA auf
Halde liegen, um sich auch ab und zu mal um den USB Interrupt kümmern zu
können.
>Timer-getriggertes DMA wohl auch kein Problem
rentiert sich hier der Einsatz von DMA, wenn im Interrupt nur insgesamt
16Bits (1Bit pro Leitung des Datenbusses) übertragen wird, und im
nächsten Interrupt dann das zweite Bit... ?
Also nochmal von vorne, so wie ich den Kram verstanden habe:
(1) Alle Millisekunde kommen 9KB Daten über USB rein.
(2) Zwischen (1) und (3) sitzt jemand, der deine 9KB vom Kopf auf die
Füsse stellt, indem er die Bits im Speicher neu sortiert.
(3) Alle Mikrosekunde werden 16 Bit parallel irgendwo ausgegeben, egal
ob Bus oder Port. Die Daten kommen aus einem 9KB Puffer im RAM.
Deinen Interrupt alle Mikrosekunde sehe ich hier nicht. Sondern einen
DMA-Kanal, der in für ihn gemächlichem Mikrosekundenraster
umgepfriemelte Daten aus dem Speicher rausschaufelt.
Rechenzeit entsteht in (1) und (2). In (1) weil das USB per Interrupt
bedient werden will um die eingelaufenen Daten abzufischen bevor das
USB-RAM überläuft. Hauptschleife macht (2) und sorgt dafür, dass dem DMA
die Daten nicht ausgehen.
RAM-Bedarf: 3 Puffer zu je 9KB. Einer läuft grad rein, einer wird
verwurstet, einer läuft grad raus. Vielleicht geht auch weniger als 9KB
pro Puffer.
Den USB-Transfer werd ich Isochron machen, da es ein Stream ist - sprich
wenn etwas falsch angeliefert wordern ist, ist es halt so (ähnlich wie
bei Audio, Video etc.)
>(1) Alle Millisekunde kommen 9KB Daten über USB rein.
genau - dieser Stream läuft die ganze Zeit ununterbrochen
>(2) Irgendwo zwischen (1) und (3) sitzt jemand, der deine 9KB vom Kopf>auf die Füsse stellt, indem er die Bits im Speicher neu sortiert.
richtig, ein Controller (welcher muss noch gefunden werden); dieser ist
natürlich auch dafür zuständig die neu sortierten Daten wieder
rauszuschicken (16Bit Port). Jede µs werden insgesamt 16bits (1Bit pro
Leitung der 16Bit-breiten-Leitung) rausgeschickt.
>Deinen Interrupt alle Mikrosekunde sehe ich hier nicht. Sondern einen>DMA-Kanal, der in für ihn gemächlichem Mikrosekundenraster>umgepfriemelte Daten aus dem Speicher rausschaufelt.
Muss dieser Transfer immer wieder von mir persönlich losgetreten werden
(wahrscheinlich gibt es einen DMA-Timer-Interrupt)? Also ein Interrupt
der die DMA veranlässt die 16bit Daten rauszuschieben... Dieser Transfer
passiert ja ohne das der Prozessor etwas mitbekommt. Ist es auch möglich
der DMA zu sagen, dass sie im Speicher von Position A nach B wandern
soll? Sprich zuerst die 16Bit Daten rausschicken, die sich an Position A
im Speicher befinden und anschließend die Daten rausschicken die sich an
Position A+16Bits befinden?? Kann man hier bei der Init der DMA einen
Bereich angeben der nacheinander abgefrühstückt werden soll?
Des Weiteren würd ich mal vermuten das ein DMA Transfer für den
ankommenden USB Stream sinnvoll sein wird, um Leistung einzusparen vom
Prozessor.
Ist es eigentlich ratsam bei USB ein O/S einzusetzen? Oder ist es
schneller wenn mann vom jeweiligen Chiphersteller den Source bekommt für
die USB-Treiber Implementierung? Hab bei Atmel gesehen, dass die c-Files
dafür zur Verfügung stellen - weiß nicht wie das bei den LPCs ist?
Jörg schrieb:
> Den USB-Transfer werd ich Isochron machen,
Wenn du schon über die Quelle keine Kontrolle hast, dann darüber wohl
auch nicht. Zumal du m.W. diese Datenrate mit Fullspeed nur isochron
schaffst.
> Muss dieser Transfer immer wieder von mir persönlich losgetreten werden> (wahrscheinlich gibt es einen DMA-Timer-Interrupt)?
Wie schon angedeutet kann jeder einzelne DMA-Transferzyklus- eines
16-Bit Wortes automatisch per Timer-Event losgetreten werden. DMA-Quelle
ist Speicher, inkrementierend, DMA-Ziel kann ein Port sein, kann
externer Speicher sein, inkrementierend oder nicht. Wenn das mal
eigerichtet ist, dann läuft das die ganzen 9KB autark durch, ohne
Beteiligung der CPU.
> Also ein Interrupt der die DMA veranlässt die 16bit> Daten rauszuschieben...
Begriffsproblem? Der Begriff "Interrupt" steht gemeinhin für eine
Unterbrechung des Prozessors. Die gibt's hier nicht. Nur alle
Mikrosekunde ein für einen Takt vom DMA blockiertes RAM.
> Dieser Transfer> passiert ja ohne das der Prozessor etwas mitbekommt.
Ja.
> Position A+16Bits befinden?? Kann man hier bei der Init der DMA einen> Bereich angeben der nacheinander abgefrühstückt werden soll?
Genau das ist DMA.
> Des Weiteren würd ich mal vermuten das ein DMA Transfer für den> ankommenden USB Stream sinnvoll sein wird, um Leistung einzusparen vom> Prozessor.
Je nach Implementierung des USB-Moduls. Ich habe mal kurz bei dem vom
STM32 reingesehen. Da landen die Daten in einem internen
Dual-Port-Memory aus dem der USB-Interrupt sie rausholen muss. Diesen
Transfer kriegt die CPU schneller zustande als der DMA-Controller.
A. K. schrieb:
> Ob ein 66MHz AVR32 wirklich so viel schneller ist als ein 100MHz> Cortex-M3 (LPC1700)? Weder USB noch Bus sind hier m.E. das zentrale> Problem, sondern das Bitgepfriemel frisst die Leistung. Die> USB-Interrupts und Blocktransfers kommen da nur noch oben drauf.
Sehe ich auch so. Ein 16-Bit Päckchen braucht 32 Shift-Befehle, die
jeweils einen Takt brauchen. Bei 66MHz wäre der Controller damit also
etwa zur Hälfte ausgelastet. Vielleicht noch 20% Rechenleistung für die
Schleife. Bleiben 30% für die Reaktion auf den USB-Interrupt und die
Programmierung des DMA, der die bereits behandelten Daten rausspeichert.
Käme auf einen (Simulations-) Versuch an, ob man mit der Zeit auskommt.
Ich halte das aber für möglich.
Jörg schrieb:
> Ist es eigentlich ratsam bei USB ein O/S einzusetzen?
Nein, das denke ich nicht.
> Oder ist es> schneller wenn mann vom jeweiligen Chiphersteller den Source bekommt für> die USB-Treiber Implementierung?
Ebendies. ST hat Code für den USB-Support. Inwieweit der hier direkt
geeignet ist oder etwas umgebaut werden muss weiss ich nicht. Das wird
bei Atmel, NXP und TI nicht anders sein.
PS: Wenn ich hier STM32 erwähne, dann weil ich die besser kenne als die
LCP1700. Prinzipielle Unterschiede in der Vorgehensweise dürfte es dabei
nicht geben, vielleicht arbeitet NXP beim USB etwas anders, aber das
ändert wenig am Arbeitsprinzip insgesamt. Die 100MHz eines LPC1700
könnten jedoch nützlich sein.
Detlev T. schrieb:
> Sehe ich auch so. Ein 16-Bit Päckchen braucht 32 Shift-Befehle, die> jeweils einen Takt brauchen.
Bischen mehr ist es, denn die Daten kommen aus Speicher und müssen
wieder in Speicher zurück. Wahrscheinlich lässt sich das zeitsparend mit
dem Transfer der Daten aus dem USB-RAM verbinden, womit auch noch einer
der 3 Puffer entfällt. Dann liegt der Hauptteil der CPU-Last im
USB-Interrupt.
Entscheidend ist also, ob ein Controller diese Last schafft. Die
DMA-gesteuerte Ausgabe ist für die Abschätzung dagegen kaum relevant.
Jörg schrieb:
>>(2) Irgendwo zwischen (1) und (3) sitzt jemand, der deine 9KB vom Kopf>>auf die Füsse stellt, indem er die Bits im Speicher neu sortiert.>> richtig, ein Controller (welcher muss noch gefunden werden);
Ich rieche da ein mögliches Missverständnis. Mit 1-3 waren Abläufe im zu
findenden Controller gemeint und mit dem "sitzt jemand" ein Stück
Programm.
Zur Abschätzung der USB-Leistung vielleicht ganz interessant: Mit einem
AT91SAM7 (48 MHz) hab ich mit Bulk Transfers ca. 800-900 kiB/s
geschafft. Dabei wurden immer 10 kiB Puffer gesendet. Ohne Optimierung
waren die Interrupts zu lange, anscheinend war der damit also ganz schön
beschäftigt.
hast recht - die LPC2917/01 oder LPC2919/01 sind leichter zu bekommen
bei der gleichen Frequenz.... bekomm ich auf jeden Fall bei Digikey (das
is erstmal in Ordnung, da für eine Platine eh mehr anfällt).
>Zur Abschätzung der USB-Leistung vielleicht ganz interessant: Mit einem>AT91SAM7 (48 MHz) hab ich mit Bulk Transfers ca. 800-900 kiB/s>geschafft.
Danke für diesen Leistungsvergleich.
>Ohne Optimierung waren die Interrupts zu lange, anscheinend war der damit >also
ganz schön beschäftigt.
welche Optimierung sprichst du hier vor allem an?
Abgesehen von der Frage zur USB-Performance dürfte die Bitschubserei
erst mit mindestens 17 freien Registern optimal arbeiten. Was ARMs und
AVR32 schlechter stellt als beispielsweise MIPS oder PowerPC.
welche unterschiede sind das die du bezüglich der PowerPCs ansprichst?
Könnt ich noch durch das Umschalten auf Thumb-Mode etwas an performance
gewinnen was die Bitschubserei angeht?
Jörg schrieb:
> welche unterschiede sind das die du bezüglich der PowerPCs ansprichst?
Vielleicht habe ich die Bitschubserei auch nicht richtig verstanden.
Aber was bei mir rüberkam sind 16 Register als Datenquelle und eines als
Ziel. Die 16 werden nacheinander geschoben und nach jeder solchen Aktion
wird das rausgeschobene Bit ins Zielregister reingeschoben. Ergibt an
Registern 16 für rein, 1 für raus, 2 für Adressen als Minimum.
Nun haben AVR32 und ARM aber nur 16 Register, davon 13 frei verwendbar.
MIPS und PowerPC haben insgesamt 32 Register. Ich habe nur nicht parat,
ob die den dafür nötigen rotate-with-carry/add-with-carry Befehl kennen.
Der Thumb-Mode bringt nichts.
Jörg schrieb:
> welche Optimierung sprichst du hier vor allem an?
Compileroptimierung. Zum Debuggen wollte ich eigentlich -O0, aber damit
hat dann kein USB funktioniert. Schlussendlich bin ich bei -O2 gelandet.
Ich weiß jetzt nicht, wieviel das tatsächlich ausmacht, aber der
Controller langweilt sich auf jeden Fall nicht, wenn er mit Daten
zugeballert wird.
Karl schrieb:
> Compileroptimierung. Zum Debuggen wollte ich eigentlich -O0, aber damit> hat dann kein USB funktioniert. Schlussendlich bin ich bei -O2 gelandet.
Das ist klar, der Unterschied ist gewaltig. Dazu kommt evtl. noch die
Platzierung, denn die SAM7 können mangels Flash-Bandbreite nativen ARM
Code nicht ungebremst im Flash ausführen, sondern müssen auf RAM
ausweichen.
Hier könnte zwar nicht Thumb, wohl aber Cortex mit gegenüber ARM7 oder
ARM9 erheblich kleinerem Interrupt-Overhead punkten, jedenfalls bei IRQ
in C und nicht FIQ in Assembler.
Wenn die einzelnen Interrupts eher kurz sind (ist das der Fall gewesen?)
und man sowas auf ARM7/9 macht, dann könnte das ein Fall für FIQ in
Assembler sein.
>Registern 16 für rein, 1 für raus, 2 für Adressen als Minimum
das mit den Registern stimmt, wusste bloß nicht dass die anderen beiden
Architekturen mehr Register zur Verfügung haben.
> hat dann kein USB funktioniert. Schlussendlich bin ich bei -O2 gelandet.
was wird hier alles optimiert gegenüber dem -00?
Jörg schrieb:
> was wird hier alles optimiert gegenüber dem -00?
Bei -O0 liegen beispielsweise alle Parameter und Variablen im RAM statt
in Registern, sie werden bei jeder Verwendung erneut geladen und/oder
gespeichert. Allein dieser Unterschied ist exorbitant.
Es gibt noch jede Menge mehr Optimierungen unterschiedlicher Bedeutung.
Puh, das ist alles schon ein paar Jährchen her. Die Interrupts waren,
ähm, mittellang, in C und AFAIR im Ram, aber nicht als FIQ. Und als es
dann lief war es auch ok, weil die restliche Anwendung dank DMA wenig
Rechenzeit gebraucht hat. Das USB-Monster zu bändigen war schon genug
Arbeit ;)
Wenn man die häufigen Teile als FIQ und in Assembler macht, könnte das
in der Tat deutlich schneller werden. Außerdem haben die Cortex M3 auch
noch deutlich höhere Taktfrequenzen.
A. K. schrieb:
> MIPS und PowerPC haben insgesamt 32 Register. Ich habe nur nicht parat,> ob die den dafür nötigen rotate-with-carry/add-with-carry Befehl kennen.
Hab mal nachgesehen. MIPS hat nicht, PowerPC hat.