Hallo zusammen! Ich möchste mit einem STM32F7 (Ich habe ein STM32F746ZG-Nucleo Board) Daten aufnehmen und im RAM speichern. Das ganze soll mittels 16Bit Paralleler Schnittstelle funktionieren. Dafür habe ich ein ganz normales GPIO Register als Input Pins deklariert. Ein ADC liefert mit die Daten und ein Timer startet einen DMA request welcher die Daten des GPIO in ein 1000er Array schreibt. Der DMA schreibt immer nur 16 Bit Blöcke, ist das fertig, wird umkonfiguriert auf die nächsten 16Bit im Array und schreibt wieder die 16Bit aus dem GPIO register ins Array. u.s.w. Code: . . . hdma_tim1_up.XferCpltCallback = &DMATransferComplete; //Interrupts hdma_tim1_up.XferHalfCpltCallback = NULL; hdma_tim1_up.XferErrorCallback = NULL; uint16_t data[1000]; uint16_t transCounter=0; uint8_t errFlag=0; . . . void DMATransferComplete(DMA_HandleTypeDef *hdma) { //This means the DMA transfer has finished transCounter++; if (transCounter<1000) { //haben wir schon 1000 werte ? if (HAL_DMA_Start_IT(&hdma_tim1_up, (uint32_t)&GPIOD->IDR, (uint32_t)&data[transCounter], 1) != HAL_OK) { errFlag = 1; } } } . . . Das Problem ist nun, dass ich damit auf etwa 90ksps komme. Und das trotz dessen, dass ich den STM32F7 auf 288MHz raufgetaktet habe. Wie kann das sein ? Was dauert hier so lange ? Ein test das ganze ohne Timer, ohne DMA einfach freilaufend in einen loop zu schreiben machte es schon erheblich schneller. Scheinbar ist es sinnlos einmal einen 16Bit block per DMA zu schicken und ihn dann neu zu konfigurieren. Die Problemstellung besteht dennoch: Im 1MHz (besser 10MHz) stehen 16Bit an die in einen Array rein sollen. Geht das ernsthaft nicht mit einem STM32F7 Cortex M7 ?! Besten Dank schonmal wenn ihr mir helfen könnt. Eure Erfahrung ist meistens Goldwert Gruß, Simon
S------- R. schrieb: > Scheinbar ist es sinnlos einmal einen 16Bit block per DMA zu schicken > und ihn dann neu zu konfigurieren. Ja, sehr. Ganz normal in Software 1 16bit-Wert in den RAM zu schreiben dauert ca 2 Takte. Den DMA zu konfigurieren, Cache zu leeren (invalidate), den Interrupt zu betreten, die DMA-Flags zu verarbeiten, den Cache nochmal leeren dauert viel länger. S------- R. schrieb: > Geht das ernsthaft nicht mit einem > STM32F7 Cortex M7 ?! Doch, aber du darfst nicht jedes 16bit-Wort einzeln verarbeiten. In einer Schleife direkt einlesen sollte gehen, dann bleibt aber nicht mehr viel Rechenzeit für anderes. Hier sollte man darauf achten effizienten Code zu schreiben und die Compiler-Optimierungen zu nutzen. Ist die Frequenz, mit der die Werte ankommen, fix? Kannst du den Timer nicht auf genau die Frequenz einstellen, den Timer direkt die DMA-Transfers auslösen lassen, und per DMA 1000 Werte auf einmal abfragen? Gibt es eine Art Trigger-Eingang? Vielleicht lässt sich mit Input-Capture o.ä. das Einlesen automatisch starten. Alternativ lässt sich vielleicht mit dem FSMC etwas machen. Muss es parallel sein? Bei 10 MHz ist ggf. QSPI auch hilfreich...
:
Bearbeitet durch User
S------- R. schrieb: > Was dauert hier so lange ? Da wird u.a. jedes Mal ein Interrupt aufgerufen, und das dauert auf einem Cortex-M. Man muss mit dem DMA in größeren Blöcken arbeiten, damit es effizient wird. Also DMA mit großen Blöcken (1KB zum Bleistift), und dann jeweils Trigger via Timer oder externem Pin. So wird nur alle 512 Werte (bei 1KB Daten) der Interrupt Handler aufgerufen.
Stell dir vor du möchtest 1000 Brötchen kaufen, organisierst dir einen LKW, holst damit jedes Brötchen einzeln und wunderst dich warum dies langsamer ist, als jedes Brötchen einzeln mit einem Kleinwagen zu fahren.
Danke für eure schnellen Antworten. Niklas G. schrieb: > Ja, sehr. Ganz normal in Software 1 16bit-Wert in den RAM zu schreiben > dauert ca 2 Takte. Den DMA zu konfigurieren, Cache zu leeren > (invalidate), den Interrupt zu betreten, die DMA-Flags zu verarbeiten, > den Cache nochmal leeren dauert viel länger. OK - verstanden. Macht auch Sinn. Niklas G. schrieb: > Doch, aber du darfst nicht jedes 16bit-Wort einzeln verarbeiten. In > einer Schleife direkt einlesen sollte gehen, dann bleibt aber nicht mehr > viel Rechenzeit für anderes. Hier sollte man darauf achten effizienten > Code zu schreiben und die Compiler-Optimierungen zu nutzen. Das Problem ist, dass ich eben nur im festen MHz Rhythmus neue Werte bekomme. stehen diese an muss ich sie einlesen. Habe gerade die bekannten -O1/2/3 flags getestet - es macht bereits einiges aus. Hätte ich nicht gedacht bei diesem wenigen "trivialen" Code. Niklas G. schrieb: > Ist die Frequenz, mit der die Werte ankommen, fix? Kannst du den Timer > nicht auf genau die Frequenz einstellen, den Timer direkt die > DMA-Transfers auslösen lassen, und per DMA 1000 Werte auf einmal > abfragen? Gibt es eine Art Trigger-Eingang? Vielleicht lässt sich mit > Input-Capture o.ä. das Einlesen automatisch starten. > Alternativ lässt sich vielleicht mit dem FSMC etwas machen. Ja, ist fix. Ein "Burst" wäre zwar toll aber kann warten. Den DMA auf größere Blöcke zu setzten funktioniert nicht denn das geschieht ohne Trigger. Das geht zwar richtig schnell aber nicht im schönen. von mir gewünschten Abstand. Deshalb muss ich den praktisch jedes mal neu starten. Trigger Eingang wäre vorhanden und soll auch genutzt werden. Ich habe nur zu Testzwecken einen internen Timer genommen welcher den DMA startet und bin eben dort schon auf Probleme gestoßen. FSMC Schnittstelle ist interessant, genauso wie die DCMI Schnittstelle (Display) Problem ist nur, dass ich es partout nicht schaffe diese als stinknormales Paralleles Interface zu nutzen und sich ST darüber auch richtig ausschweigt. Weiterhin ist es für mich fraglich ob die schneller sind. Niklas G. schrieb: > Muss es parallel sein? Bei 10 MHz ist ggf. QSPI auch hilfreich... Hab ich extra wegen der Geschwindigkeit und den viele IOs des STMs genommen ;) QSPI hätte der auch - hmmm
S------- R. schrieb: > Das geht zwar richtig schnell aber nicht im schönen. von mir > gewünschten Abstand. Deshalb muss ich den praktisch jedes mal neu > starten. Du kannst einen Timer auf die gewünschten 10MHz stellen und direkt die DMA-Transfers auslösen lassen (ohne ISR). S------- R. schrieb: > Trigger Eingang wäre vorhanden und soll auch genutzt werden. Kommt der Trigger denn mit 10MHz? Oder hast du irgendeine Form von Takt oder Strobe-Signal, welches angibt, wann ein neuer 16bit-Wert anliegt? Es müsste mit Timern möglich sein, auf dieses zu reagieren und direkt einen DMA-Transfer auszulösen. S------- R. schrieb: > Habe gerade die bekannten -O1/2/3 flags getestet - es macht bereits > einiges aus. Hätte ich nicht gedacht bei diesem wenigen "trivialen" > Code. Ja, ohne Optimierungen ist wie angezogene Handbremse. Der Compiler fügt dann jede Menge ziemlich nutzlosen Code ein, sodass selbst simpler C-Code stark verlangsamt wird.
S------- R. schrieb: > Weiterhin ist es für mich fraglich ob die schneller > sind. FSMC ist auf jeden Fall schneller als Port-IO.
Es sollte möglich sein, den DMA so zu konfigurieren, dass du den Channel, der vom Timer getriggert wird benutzt, dann stellst du beim Timer ein, dass bei jedem UpdateEvent ein DMA Transfer ausgelöst wird. Beim DMA wird dann MADDR auf den Array Start gelegt, PADDR auf das GPIO IDR, PINC auf 0 und MINC auf 1. Dann den Count im DMA richtig einstellen, Timer Frequenz richtig einstellen und starten und es sollte bei jedem Timer Update Event ein Wert vom GPIO in das Array eingelesen werden. Ich bin im HAL von ST nicht so bewandert, schreibe meinen Code normalerweise direkt auf Register Level. Auch mit dem F7 hab ich noch nichts gemacht, aber sollte, denke ich, ja ähnlich sein wie bei den F4 mit denen ich Erfahrung habe. Die Erklärung ist jetzt mal nur so prinzipiell, wenn du willst, könnte ich es auch etwas genauer ausarbeiten, hoffentlich ist es so wenigstens halbwegs klar.
S------- R. schrieb: > Das ganze soll mittels 16Bit Paralleler Schnittstelle funktionieren. > Dafür habe ich ein ganz normales GPIO Register als Input Pins > deklariert. Genau dafür haben die eine FSMC-Schnittstelle.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.