Hallo,
ich stehe beim HAL-Treiber von ST zum STM32F407 gerade ein bisschen auf
dem Schlauch..
Ich möchte den Controller als Client über USB Daten empfangen lassen, in
diesem Fall eine Firmware, die der Controller dann über SPI auf ein
DAB-IC programmiert.
Grundsätzlich funktioniert das schon, jedoch möchte ich sicherstellen,
dass kein Buffer überläuft und nur neue USB-Daten nachkommen, wenn auch
Platz dafür ist.
In unzähligen Tutorials wurde immer auf die Funktion "CDC_Receive_FS"
verwiesen, die so lange NAK Pakete an den Host sendet, bis man sie
verlässt.
Ich hab das mal ganz aggressiv mit einer While-Schleife an einem Taster
versucht:
Der Host wartet dann geduldig, wie gewünscht.
Das Problem ist jetzt aber, dass die CDC_Receive_FS ja eine
Callback-Funktion aus einem Interrupt ist, sprich, alles andere im
Controller geht auch nicht weiter. Er könnte jetzt also auch nicht die
Zeit nutzen, um den Buffer zu verarbeiten.
Müsste man nicht irgendwo vorher schon prüfen, ob der Buffer weniger als
ein maximales USB-Paket rein bekommt und dann einen Schalter umlegen,
der immer mit NAK antworten lässt, bis wieder Platz ist?
Oder ist der Ansatz Blödsinn und ich setze falsch an?
Vielen Dank für Ideen/Einwände!
Mir scheint, du versuchst ein Problem zu lösen, das so nicht existiert.
Beim RX wirst du kaum einen Überlauf des Buffer provozieren können, so
lange der Rest deines Programms Ok ist.
Die serielle Übertragung ist in jedem Fall deutlich langsamer als USB
und du hast genügend Zeit deine Daten abzuholen, wenn du bei der
Software nicht völlig geschlampt hast.
Die Interupts sind auch kein Problem, da die USB-Interrupts mit sehr
hoher Priorität laufen und i.d.R. jeden anderen Interrupt unterbrechen
können.
Beim TX kannst du den Anschluss zwar flutem, aber du erkennst am
Rückgabe-Wert der Transmit-Funktion, ob ausreichend Platz im Puffer war.
Kai K. schrieb:> USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);>> USBD_CDC_ReceivePacket(&hUsbDeviceFS);
Ruf das halt nicht in dieser Funktion auf, sondern später, z.B. in einem
externen Interrupt wenn der Pin auf 0 gegangen ist.
Kai K. schrieb:> Müsste man nicht irgendwo vorher schon prüfen, ob der Buffer weniger als> ein maximales USB-Paket rein bekommt und dann einen Schalter umlegen,> der immer mit NAK antworten lässt, bis wieder Platz ist?
Der Controller sendet immer NAK-Pakete, bis du eben den Empfang
aktivierst (in der HAL über ReceivePacket). Mach das halt einfach
später, wenn du bereit bist, das Paket zu empfangen, und nicht im
Empfangs-Callback.
Harry L. schrieb:> Mir scheint, du versuchst ein Problem zu lösen, das so nicht existiert.
Mir scheint, du referierst gerade über ein Thema, von dem du zu wenig
verstehst.
Kai K. schrieb:> Müsste man nicht irgendwo vorher schon prüfen, ob der Buffer weniger als> ein maximales USB-Paket rein bekommt und dann einen Schalter umlegen,> der immer mit NAK antworten lässt, bis wieder Platz ist?> Oder ist der Ansatz Blödsinn und ich setze falsch an?
Nö, nö, deine Gedanken gehen schon in die richtige Richtung. Im Prinzip
kann man das so lösen, daß man den USB-Puffer erst dann als leer
(entleert bzw. abgearbeitet) kennzeichnet, wenn man die Daten auch
wirklich daraus entnommen hat.
Allerdings tut sich dabei je nach verbautem USB-Core ein kleines Problem
auf: Wenn der Core nur dann ein Interrupt-Flag setzt, wenn der Puffer
gefüllt wurde und nun bereit steht, dann kommen keine weiteren
Interrupts mehr, solange man den Puffer nicht als entleert kennzeichnet.
Wenn nun aber die ganze USB-Bedienung in einer ISR erfolgt, dann muß man
sich von woanders drum kümmern, daß man das als entleert setzen
irgendwann erledigt, sonst stockt ab da der Datenverkehr zum Bulk-Out
Endpunkt. Dito (bloß umgekehrt) die ganze Puffer-Geschichte beim
Bulk-In.
Bei Cores, die das Ein- bzw. Ausschalten des NAK_BI bzw. NAK_BO
ermöglichen, ist das alles kein Problem, aber gerade bei dem Zeugs, was
(soweit ich mich damit befaßt hab) bei ST verbaut wird, sieht das ein
bissel kröpeliger aus.
W.S.
W.S. schrieb:> aber gerade bei dem Zeugs, was> (soweit ich mich damit befaßt hab) bei ST verbaut wird, sieht das ein> bissel kröpeliger aus.
Das haben wir doch schon durch diskutiert, dass das nur bei deiner
skurrilen Programmierweise zum Problem wird, und du den NAKI-Interrupt
völlig zweckentfremdest. Bei sinnvoller Ablaufprogrammierung sieht das
bei allen USB-Cores gleich aus.
W.S. schrieb:> Mir scheint, du referierst gerade über ein Thema, von dem du zu wenig> verstehst.
Nö, du hast null Ahnung davon, wie die HAL funktioniert.
Die USB Hardware im STM32 sollte ein enable Bit für die jeweiligend EP
haben.
Bei "Puffer voll" schaltet der Interrupt Handler dieses Bit dann ab,
d.h. der EP erzeugt keine Interrupts mehr wenn Daten ankommen. Die USB
Hardware sendet dann NAK automagisch.
Auf der Seite wo der Puffer leer gemacht wird muss dann regelmäßig
dieses EP Enable Bit wieder angeschaltet werden.
HAL kann das AFAIK nicht von sich aus, aber ich habe mich jetzt auch
nicht durch die Doku gequält.
Vorsicht: Je nachdem wie HAL den USB Interrrupt programmiert hat, könnte
man im Interrupt Handler trotz deaktiviertem Bit landen, wenn andere EP
Interrupts getriggert wurden.