Hallo Zusammen,
ich habe mal wieder ein kleines/großes Problem.
Ich habe mit einem STM32F103 ein schönes Projekt ans Laufen gebracht in
dem ich dank dem Forum die On Board USB Schnittstelle genutzt habe
Beitrag "USB des STM32 F103C8T6 nutzen"
und
Beitrag "STM32F103-USB-CDC von W.S."
Jetzt stellt sich für ein neues Projekt mal wieder die gleiche Frage,
nur diesmal habe ich einen M0 Kern ausgewählt, da der Prozessor außer
USB Daten empfangen und Kleinigkeiten steuern nicht wirklich was zu
Leisten hat.
Für den STM32F042 ergibt sich wieder mal das gleiche Problem.
1.) Ich verwende keine HAL und möchte es aus diversen Gründen auch
nicht.
2.) Ich möchte den Virtual-Com-Port nutzen und habe mir hierzu die
vermeintlich für diesen Prozessor richtige Library bei ST
heruntergeladen. Kann aber in der Verzeichnisstruktur nicht wirklich was
brauchbares finden (Ich kann zwar alle c und h files ordnungsgemäß
einbinden, finde aber immer noch keine "send" oder "receive" Routine
:-( )
3.) Hat vielleicht jemand etwas, was dem Beispielprojekt von W.S.
gleicht, aber für den M0 aufgebaut ist?
Für jede Hilfe bin ich mal wieder äußerst dankbar
Liebe Grüße
Hanna
Hallo Pegel,
danke für deine Antwort. Ich habe mir die auf der Seite zum download
angebotene Firmware heruntergeladen. Diese ist fast identisch zu der auf
der STM Seite verfügbaren. Das große Problem dabei:
Ich hab keinen blassen Schimmer was ich hierzu alles einbinden muss. Ich
dachte CDC wäre hier für Virtual Com Port mein Favorit, aber leider
finde ich hier keinerlei "sinnvolle" Funktionen:
SendByte, SendString etc.
Kann mir hier jemand auf die Sprünge helfen?
USB-Tutorial mit STM32: Virtueller COM-Port schon gelesen? Die USB
Peripherie vom F042 und vom F103 ist fast gleich. Du musst vermutlich
nur die Takt-Konfiguration anpassen (dieser Controller kann ja USB auch
ohne Quarz) und die Puffer-Größe ändern.
Siehe auch UART auf USB
Hanna schrieb:> Kann mir hier jemand auf die Sprünge helfen?
Wohl eher nicht.
Ich habe hier in diversen Threads den gleichen USB-Treiber, aber für
andere µC-Typen gepostet. Also für diverse LPC's, den NUC120 und auch
STM2F302.
Wenn du also einen solchen USB-Treiber für deinen Chip haben willst,
dann setze dich einfach mal daran, das betreffende Kapitel für den
USB-Periheriecore im Refmanual gründlich zu lesen und eine der
vorhandenen Treiberquellen nach deinem Gusto umzuarbeiten. Die
Gemeinsamkeiten sieht man ja beim Lesen der jeweils EINZIGEN Quelle.
Und wenn du den dann laufen hast, wäre es nett, ihn hier zu posten,
damit auch andere was davon haben. Ich selber komme sicherlich nicht in
absehbarer Zeit dazu, für den STM32F042 so einen Treiber zu schreiben.
W.S.
pegel schrieb:> Und alles ohne HAL.
Aber mit Standard Peripheral Library (dem Vorgänger der HAL) und ST USB
Device Library. Nur der CDC Teil ist selbst gemacht, aber der ist ja
vergleichsweise simpel...
pegel schrieb:> Hier gibt es ein kleines Projekt das man nur aufräumen muss...
Hab eben da mal reingeschaut. Das graust einen ja! Das ist ein buntes
Durcheinander von Quellen von ST, man sieht keinen Anfang und kein Ende.
Massen von .c und .h Dateien, dazu 550K an CMSIS, 1340K an StdPeripherie
und nochmal 180K an USB.
Das sieht alles so aus wie "darf's noch ein Löffel Code mehr sein?".
Oder eher eine ganze Schöpfkelle voll Code.
In main wird zwar der USB initialisiert, aber zu welchem Zwecke? Nur um
einen Wandler USB<-->UART herzustellen? Sowas kauft man in China für
zwofuffzig.
Wenn schon USB-VCP, dann sollte der dazu dienen, im µC einen
Kommunikationskanal bereitzustellen. Aber davon ist bei diesem Projekt
nichts zu sehen, in main landet man schlichtweg auf einer Mainloop, die
nur ne LED blinken läßt und eine echte Kommunikations-Schnittstelle in
der Firmware hab ich nicht entdecken können.
Ja, man müßte dort ganz erheblich aufräumen, das käme dann wohl einem
Kahlschlage gleich.
W.S.
Ich versuche, leider bisher vergeblich, den USB VCP Code von W. S. zum
laufen zu bringen. Der Code gefällt mir gut!
Es meldet sich ein USB CDC ACM-Device, wenn ich firmware.bin flashe,
welches ich im ZIP file gefunden habe. Code und Hardware laufen also.
Allerdings schaffe ich es nicht, den USB-Code in meinem Projekt
eingebettet zum laufen zu bringen. Verwenden tue ich den ARM-GCC. Gibt
es was zu beachten bei Verwendung des GCC, ausser dass _Nop() angepasst
werden muss? Bei mir wird soweit ich das durchblicke der USB-Interrupt
gar nie aufgerufen, warum auch immer...
Bevor ich jetzt noch Tage mit Fehlersuche verbringe: Hat jemand hier im
Forum den Code unter GCC am laufen und gibt es entsprechende Quellen?
Ich habe mal versucht den Code im Archiv unverändert zu übersetzen,
müsste dazu aber Linker-Skripte dazufügen und den armasm-Code anpassen.
Der Haken ist: USB zu benutzen ist einfach, es zu beherrschen und zu
entwickeln ist eine ganz andere Hausnummer. Wie beim Auto-fahren.
Wenn ich mir die Infos im Referenzhandbuch und das Tutorial von Niklas
anschaue, verstehe ich nur Bahnhof. Offensichtlich habe ich keinen
blassen Schimmer, wie USB funktioniert. Mit fehlt das Verständnis der
Fachbegriffe und mit den ganzen Bezeichnungen der Variablen und Settings
kann ich ungefähr nichts anfangen.
Dennoch bin ich froh darüber, dass Niklas und W.S. funktionierende
Beispiele veröffentlicht haben. Denn diese kann ich quasi 1:1 verwenden,
denn sie tun schon das, was ich benutzen möchte.
Ich kann da mit Hanna durchaus mitfühlen. Ich wäre auch damit
überfordert, die Libraries anzupassen. Da helfen 25 Jahre
Programmiererfahrung nicht automatisch weiter. Irgendwie habe ich auch
Hemmungen bei USB (2.0) tiefer einzusteigen, denn sicher wird bald die
nächste Sau durchs Dorf getrieben.
Es gibt nützlichere Hobbies, ich lerne zum Beispiel gerade, wie man mit
Sauerteig umgeht.
Stefanus F. schrieb:> Offensichtlich habe ich keinen> blassen Schimmer, wie USB funktioniert.
USB erfordert Literaturstudium, d.h. man sollte eins der einführenden
Bücher lesen.
Falls man die Spec selber lesen will: Die 1.1 Spec, die für "Full Speed"
µCs praktisch alles abdeckt, ist viel leichter zu lesen als die 2.0
Spec. Letztere hat durch den High Speed Mode viel an Übersichtlichkeit
verloren.
Aus den Quellen alleine wird man jedenfalls nicht schlau, denn das
sogenannte Endpoint 0 Handling ist nicht-trivial. Dort werden u.a. die
ganzen "magischen Bits" (Deskriptoren) zur Identifizierung und
Konfiguration übertragen.
Stefanus F. schrieb:> Wenn ich mir die Infos im Referenzhandbuch und das Tutorial von Niklas> anschaue, verstehe ich nur Bahnhof
Hm, sind die Begriffe nicht gut genug beschrieben? Zum
Überfliegen/Querlesen ist der Text natürlich nicht geeignet...
Jim M. schrieb:> Aus den Quellen alleine wird man jedenfalls nicht schlau,
Ich finde dass die Spec gar nicht so schlimm ist. Da gibt es viel
chaotischere (SD-Karten z.B.).
Das Hauptproblem ist eigentlich, dass die Spec natürlich auch das
beschreibt, was die Hardware tun soll, und man herausfinden muss,
welchen Teil davon der jeweils genutzte Mikrocontroller bereits
implementiert, und was man noch wie selbst programmieren muss.
Jim M. schrieb:> Dort werden u.a. die> ganzen "magischen Bits" (Deskriptoren) zur Identifizierung und> Konfiguration übertragen.
Die Deskriptoren sind aber alle ganz gut dokumentiert. Etwas lästig ist
dass man das Handling für mehrere Konfigurationen und alternative
Interfaces implementieren muss, obwohl die allermeisten Geräte das gar
nicht brauchen. Ich glaube Windows unterstützt das nichtmal...
Wollte nur rückmelden, der Code von W.S. geht jetzt wunderbar mit GCC
und ist wirklich schön schlank. Ich denke, wer "nur" einen virtuellen
COM-Port benötigt ist damit sehr gut bedient.
Das Problem war irgendeine Wechselwirkung mit HAL-Code. Ich habe den
jetzt komplett aus meinem Projekt rausgeworfen und alles auf "bare
metal" umgestellt. Das HAL-Zeug war für mich jedenfalls dermassen ein
undurchschaubarer Verhau von kaum lesbaren Files, eine vollständige
Abstraktion vom Controller brauche ich nicht, und am Ende musste ich
sowieso RM0008 lesen...
Switcher schrieb:> Das HAL-Zeug war für mich jedenfalls dermassen ein> undurchschaubarer Verhau von kaum lesbaren Files, eine vollständige> Abstraktion vom Controller brauche ich nicht
Komisch!
Ohne vorher jemals was mit USB auf µC gemacht zu haben, und als Neuling
mit HAL hat bei mir der VCP mit HAL nach <1h funktioniert.
Harry L. schrieb:> Komisch!> Ohne vorher jemals was mit USB auf µC gemacht zu haben, und als Neuling> mit HAL hat bei mir der VCP mit HAL nach <1h funktioniert.
Vermutlich mit cube generiert? In dem Falle: Äpfel, Birnen,
Honigmelonen...
Ja, der Cube-Code funktioniert schon. Aber gleichzeitig ist er dermassen
unübersichtlich und aufgebläht, dass er schwierig zu durchschauen ist.
Ich hatte z.B. das Problem, dass das I2C-System sich aufgehängt hat (Bug
in STM32F103). Es gibt dazu ein Erratum von ST und eine Prozedur, wie
das I2C-Subsystem wieder flott gemacht werden kann wenn es sich so
aufgehängt hat. Das Problem ist dann aber, dass sich das nicht mehr mit
HAL implementieren lässt. Und schon geht der Salat los...
Ausserdem finde ich den Aufwand, um z.B. mit HAL Bits in einem Port zu
setzen oder zu löschen schon reichlich absurd, wenn es auch mit einem
simplen GPIOx->BSRR = xxx geht.
Ist halb Geschmackssache.
Switcher schrieb:> Ja, der Cube-Code funktioniert schon. Aber gleichzeitig ist er dermassen> unübersichtlich und aufgebläht, dass er schwierig zu durchschauen ist.
Also zumindest für den USB-Teil kann man das so nicht ganz sagen.
Unübersichtlich vielleicht schon, aber wie viele USB-Frameworks hast du
schon gesehen? Die USB-Library von ST weist da schon gewisse
Ähnlichkeiten mit anderen Frameworks auf. Wenn einem die Struktur
bekannt ist, ist der Code schon gar nicht mehr so unübersichtlich.
Jim M. schrieb:> Falls man die Spec selber lesen will...> ...> Aus den Quellen alleine wird man jedenfalls nicht schlau, denn das> sogenannte Endpoint 0 Handling ist nicht-trivial.
Also, wie ich das sehe:
Dis Spezifikationen zu lesen, hatte mir eigentlich fast garnichts
gebracht, denn dort verliert man sich in Textwüsten, die bestenfalls als
Arsenal für die Advokaten der am USB beteiligten Firmen gegeneinander
geeignet sind.
Wichtiger sind einfach ein paar Grundsatz-Verständnisse. Allen voran,
daß der USB kein Bus ist, sondern eine Einzelverbindung eines Hosts zu
einem Device, und daß das Device nix selber zu sagen hat, sondern der
Host ist es, der allzeit ansagt, was das Device jetzt zu tun hat.
Deutlich wird das beim VCP an der Stelle, wo Daten zum Senden an den
Host asynchron herinkommen und dann bereitstehen.
Aktivität des Devices ("he, Host, ick will dir wat senden!") von der CPU
aus gibt es nicht. Punkt. Deshalb hatte ich dafür das Bit "Interrupt auf
NAK" des entspr. EP's jede 1 ms im Timer-Tick (des USB, nicht zu
verwechseln mit dem Cortex) frei gegeben und bei jeder Übertragung zum
Host hin wieder abgeschaltet, um nicht anschließend alle 11
Mikrosekunden einen Interrupt zu kriegen.
Blöd nur, daß dieses Verfahren ausgerechnet beim LPC4088 NICHT
funktioniert, obwohl der bis auf genau DIESES Detail den gleichen
USB-Core hat wie der LPC2478.
Bestenfalls kann das Device mit NAK sagen, daß es das (jetzt grad) nicht
tun kann. Und die eigentliche Kommunikation zwischen Host und Device
wird von der Hardware (der 'SIE') herzlich unabhängig von der CPU
erledigt, so daß man per Interrupt im Grunde nur die Ergebnisse der
Arbeit der Hardware präsentiert bekommt.
Der Endpoint 0 ist beim VCP eigentlich recht einfach zu verstehen. Der
EP0 kriegt nach Gusto des Hosts die Setup-Pakete übergeholfen und muß
eben selbige analysieren und das tun, was drinsteht - auch dann, wenn
der Host den gleichen Krempel dreimal hintereinander zu kriegen wünscht.
Das ist eigentlich alles.
Die eigentliche Schwierigkeit beim Device besteht aus 2 Problemen:
1. wie man im Interrupthandler mit der SIE zu verkehren hat. Das ist von
einem Peripheriecore zum anderen SEHR verschieden. Beim Core in den
STM32F103 ist das recht pervers per Toggeln gelöst, was mir zeitweise
den schieren Brechreiz ausgelöst hatte.
2. wie der für die diversen Pakete zu benützende RAM organisiert ist.
Jeder Endpunkt braucht seinen RAM-Bereich, in dem nicht nur man selber,
sondern auch die SIE herumfuhrwerkt. Auch das ist bei den STM32F103
recht kotzig gelöst, denn der dortige RAM ist 16 bittig im 32 bittigen
Grundraster ausgelegt, also lückig - und man darf nicht mal beliebig
byteweise drauf zugreifen. Siehe meine Kommentare in der Quelle.
Abgesehen von diesen beiden Punkten ist de eigentliche Rest doch recht
einfach und übersichtlich und bei allen µC gleich.
W.S.
@W.S.: magst du nicht mal einen kurzen Artikel dazu im Wiki schreiben?
Ich persönlich finde deinen Code sehr gut lesbar und aufgeräumt. Wäre
der ideale Einstig denke ich für viele USB- Anfänger, die sich nicht mit
HAL etc. rumschlagen wollen sondern "bare-metal" arbeiten.
Für "kurz" ist USB zu komplex. Was gefällt dir am bereits vorhandenen
Artikel, der genau darüber ist, nicht? Es wird sogar gezeigt wie man
das hakelige EPnR-Register elegant in den Griff bekommt.
TrollJäger schrieb:> magst du nicht mal einen kurzen Artikel..
Und was soll da drin stehen?
Ih habe hier schon ein paar Projekte einschließlich mMn. ausführlichem
PDF gepostet. Musterbeispiel: die Lernbetty. Und was hat man davon? Ich
sag's dir: man wird angepöbelt dafür. Anstatt zu lernen, wie man's macht
und anstatt sich damit mal wieder ein weiteres Stückchen Wissen und
Können anzueignen, kommen hier nur die ewigen Besserwisser, eben die
Beckmesser's a la Meistersinger in Nürnberg hoch und wissen alles besser
- ohne selbst je etwas geleistet zu haben außer Labern.
Meinst du, sowas läßt einen freudig zur Feder greifen?
Abgesehen davon wäre es wesentlich hilfreicher, wenn Andere sich so
eines Projektes bzw. eines Quellcodes annähmen und ihn auf andere
Architekturen umsetzten. Das Grundgerüst steht ja - und das Verstehen
des Ganzen sollte sich auch einstellen, wenn man mal etwas gründlicher
auf die Quelle geschaut hat und auch die anderen von mir geposteten
Quellen zum gleichen Thema als Vergleich gesehen hat.
Ich kann nicht auf allen Hochzeiten bzw. Controllern tanzen, schließlich
mache ich das hier ja auch nur in meiner Freizeit und als Einzelkämpfer
- und da kann ich mir nicht für jeden erdenklichen Chip ein Evalboard
bauen bzw. zulegen. Da sind auch Andere mal ein bissel gefordert.
Nochwas: Ein Artikel nur zu den Befindlichkeiten der STM32Fxxx ist
mMn. zu eng gesehen. Wenn schon, dann eher für eine breitere
Hardwarebasis. Mir ist es gelegentlich schon zuwider, hier sehen zu
müssen, daß für manche die Welt der 32 bittigen Controller nur aus den
Produkten von ST zu bestehen scheint, ohne daß man seinen Horizont auch
auf andere Typen ausweitet.
W.S.
W.S. schrieb:> 1. wie man im Interrupthandler mit der SIE zu verkehren hat. Das ist von> einem Peripheriecore zum anderen SEHR verschieden. Beim Core in den> STM32F103 ist das recht pervers per Toggeln gelöst,
Toggeln ist eine relativ sichere Methode, um Signale über verschiedene
Taktdomänen zu schicken. Man muß nur sicherstellen (z.B. per Handshake),
das der Sender nicht schneller toggelt, als das es der Empfänger
mitbekommt.
> der dortige RAM ist 16 bittig im 32 bittigen> Grundraster ausgelegt, also lückig - und man darf nicht mal beliebig> byteweise drauf zugreifen.
Das dürfte daran liegen, das STM den USB-Teil als IP-Core eingekauft
hat.
Ob das für alle STMs gilt, weiß ich nicht, aber für den, den wo ich USB
via HAL mal kurz angetestet habe (STMF4xx?).
Man erkennt es außerdem daran, das die Register-/Nutzungsphilosophie
anders ist, als die der restlichen Peripherie von STM.