Forum: Mikrocontroller und Digitale Elektronik STM32 F746zg nucleo und ILI9488 TFT per SPI langsam ?


von Markus F. (dr-ice)


Angehängte Dateien:

Lesenswert?

Hallo,

ich habe an einem nucleo-746zg ein TFT mit einem ILI9488 Controller 
hängen. Das Display betreibe ich über SPI. Das funktioniert soweit auch 
ganz gut, allerdings ist es sehr langsam. Ich kann beim Löschen des 
Displays wirklich zugucken.

Vileicht hat ja jemand eine Idee, oder einen Kniff, mit dem STM32 bin 
ich relativ neu und die Einstellungen habe ich wahrscheinlich noch nicht 
alle verstanden. Ich habe mal die Treiberdateien angehangen.

Vielen Dank schon mal

Markus

von grundschüler (Gast)


Lesenswert?

Beitrag "Re: Stm32f103 Problem mit Spi2"

beim f103 0,11 sec für 240x320 - Bildaufbau mit 16bit-Farben. Das kannst 
du zum Vergleichen nehmen.

von Markus F. (dr-ice)


Lesenswert?

Das ist schon mal interressant, ich brauche zur zeit ca. 2 sec. für ein 
480x320 TFT bei maximalem Prozessortakt von 209MHz.

Gruß Markus

von Arduinoquäler (Gast)


Lesenswert?

Markus F. schrieb:
> Vileicht hat ja jemand eine Idee, oder einen Kniff, mit dem STM32 bin
> ich relativ neu und die Einstellungen habe ich wahrscheinlich noch nicht
> alle verstanden.

Tja wenn man so ein fertiges hardware-fernes (HAL-) Programmierteil
verwendet dann kommt sowas dabei raus.

Der Kniff besteht darin das SPI optimal auszunutzen und die
Anzahl der aufzurufenden Schichten zu verringern. Entweder
HAL oder schnell.

Markus F. schrieb:
> Ich habe mal die Treiberdateien angehangen.

"Angehängt". Oder "als Anhang beigefügt".

von pegel (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Entweder HAL oder schnell.

Bitte quäl weiter dein Ardudingsda.
Programmierer benutzen DMA.
HAL DMA.

von dasrotemopped (Gast)


Lesenswert?

>Entweder HAL oder schnell.

SPI mit CubeMX kann auch schnell sein.
Man muss nur DMA nutzen.

>maximalem Prozessortakt von 209MHz

Der CPU Takt sagt nichts über die SPI Taktung aus.
Und die ist entscheidend.


Gruß,

dasrotemopped.

von Markus F. (dr-ice)


Lesenswert?

Hi,

danke für die Antworten,
an HAL DMA habe ich schon gedacht, erste Versuche sind aber leider bei 
mir gescheitert. Wie gehe ich denn dabei richtig vor ?

Den gesamten Displayinhalt bekomme ich schlecht in den Speicher, also 
muss ich den Speicher aufteilen. Wie macht denn dabei eine Aufteilung 
Sinn ?
Wird das Ganze über DMA schneller, wenn ich nur Punkte setze ?

Wie konfiguriere ich den DMA für SPI richtig. Hat jemand ein Beispiel 
zur Konfiguration oder einen Ansatz für mich ?

Viele Fragen, trotzdem schon mal vielen Dank

Gruß Markus

von dasrotemopped (Gast)


Lesenswert?

da liegt der Hase im Pfeffer:
void ili9488_send_byte(int data)
{
  HAL_StatusTypeDef status = HAL_OK;
  //int timeout = 100;

  //status = HAL_SPI_Transmit(&ili9488_Spi, (uint8_t*) &data, 1, 
timeout);
  status = HAL_SPI_Transmit_IT(&ili9488_Spi, (uint8_t*) &data, 1);
  if(status != HAL_OK)
  {
    /* Execute user timeout callback */
    //LCD_TESTLED_SET;
  }
}

überträgt genau ein Byte. bei 480*320*16bit =307200 Aufrufe dieser 
Funktion für ein Bild.
Versuchs mal mit
HAL_SPI_Transmit_DMA(&ili9488_Spi, zeiger, res_x*2);
Aber Obacht, der DMA Transfer kann nicht ein Bild in einem Rutsch 
übertragen. Ich mache es zeilenweise, hat immer noch Overhead aber 
deutlich besser als mit der IRQ Variante pro Byte.

Gruß,
dasrotemopped.

von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

So geht DMA mit SPI. Den Rest macht CubeMX.
Danach geht dieser DMA Aufruf problemlos:
HAL_SPI_Transmit_DMA(&ili9488_Spi, zeiger, res_x*2);

Gruß,

dasrotemopped.

von Markus F. (dr-ice)


Lesenswert?

@dasrotemopped

Vielen Dank, dann werde ich in der Richtung mal weitermachen, sieht ja 
eigentlich nicht aus wie Hexenwerk.

Gruß Markus

von Markus F. (dr-ice)


Lesenswert?

Hallo,

ich habe mal die Init angepasst, aber so ganz klappt es nocht nicht.
1
  /* DMA controller clock enable */
2
    __HAL_RCC_DMA2_CLK_ENABLE();
3
  /* Peripheral DMA init*/
4
  ili9488_dma.Instance =          DMA2_Stream3;
5
  ili9488_dma.Init.Channel =         DMA_CHANNEL_3;
6
  ili9488_dma.Init.Direction =       DMA_MEMORY_TO_PERIPH;
7
  ili9488_dma.Init.PeriphInc =       DMA_PINC_DISABLE;
8
  ili9488_dma.Init.MemInc =         DMA_MINC_DISABLE;
9
  ili9488_dma.Init.PeriphDataAlignment =   DMA_PDATAALIGN_BYTE;
10
  ili9488_dma.Init.MemDataAlignment =   DMA_MDATAALIGN_BYTE;
11
  ili9488_dma.Init.Mode =         DMA_NORMAL;
12
  ili9488_dma.Init.Priority =       DMA_PRIORITY_LOW;
13
  ili9488_dma.Init.FIFOMode =       DMA_FIFOMODE_DISABLE;
14
15
  HAL_DMA_Init(&ili9488_dma);
16
  HAL_SPI_Init(&ili9488_Spi);
17
18
  /* DMA interrupt init */
19
    /* DMA2_Stream3_IRQn interrupt configuration */
20
    HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 0);
21
    HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
22
23
    /* Peripheral interrupt init */
24
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
25
    HAL_NVIC_EnableIRQ(SPI1_IRQn);

passt das so, oder hab ich da irgendwas vergessen ?

Zum Probieren hab ich draw_full_rectangle geändert:
1
void gfx_ili9488_draw_full_rectangle(ili9488_coord_t start_x, ili9488_coord_t start_y, ili9488_coord_t end_x, ili9488_coord_t end_y, ili9488_color_t color)
2
{
3
  if(start_x>=end_x)
4
    return;
5
6
  color = COLOR_CONVERT(color);
7
8
9
  uint8_t groesse;
10
  groesse = abs((end_x-start_x)*(end_y-start_y));
11
  uint8_t Daten[groesse];
12
13
  /* Set up draw area  */
14
  ili9488_set_limits(start_x, start_y, end_x-1, end_y-1);
15
  /* Write into GRAM  */
16
  ili9488_send_command(ILI9488_CMD_MEMORY_WRITE);
17
  /* Fill GRAM with Pixelcolor to clear the Display  */
18
19
     for(int n=0;n<abs((end_x-start_x)*(end_y-start_y));n=n+3)
20
    {
21
      Daten[n]=(color);
22
        Daten[n+1]=(color >> 8);
23
        Daten[n+2]=(color >> 16);
24
    }
25
   HAL_SPI_Transmit_DMA(&ili9488_Spi, Daten, groesse);
26
27
  ili9488_wait_for_send_done();
28
  ili9488_deselect_chip();
29
}

Nochmal jemand einen Tipp ? Ich stehe gerade auf dem Schlauch.

Gruß Markus

von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

> aber so ganz klappt es noch nicht.
Sehr detaillierte Fehlerbeschreibung, aber das geht noch was genauer, 
oder ?

Die mit CubeMX generierte Initialisierung sieht etwas anders aus, mal 
verglichen ?
Das nucleo-746zg kann man per Mausklick mit aller Onboard Peripherie 
auswählen.


Gruß,

dasrotemopped.

von dasrotemopped (Gast)


Lesenswert?

>ili9488_deselect_chip();
du brauchst Hardware CS für SPI DMA

Pinmapping für ILI und SPI am STM32 ?

Gruß,

dasrotemopped.

von grundschüler (Gast)


Lesenswert?

du hast doch offensichtlich ein Problem mit deinem spi-code. Bevor du 
jetzt auf dma umstellst, wäre Fehlersuche und Fehlerbehebung angebracht.

Schau dir mal im Debugger an, wieviel - überflüssige - Takte dein code 
bei ili9488_send_byte(); macht.

von Arduinoquäler (Gast)


Lesenswert?

Markus F. schrieb:
> Wird das Ganze über DMA schneller, wenn ich nur Punkte setze ?

Die DMA Jünger werden dich anlügen.

Oder sie werden nichtssagend ganz leise sein.
Nein, sie sind es schon.

von dasrotemopped (Gast)


Lesenswert?

Schau dir mal im Debugger an, wie viele - überflüssige - Takte dein Code
bei ili9488_send_byte(); macht.

Jeder Takt ist zu viel, weil ein DMA Transfer keine CPU Zyklen benötigt.
Darum beten die DMA Jünger ihn ja auch so an.

Die DMA Jünger werden dich anlügen.
Schon mal mit DMA selbst gearbeitet ? Hat deine CPU so was ?

Gruß,
dasrotemopped.

von Arduinoquäler (Gast)


Lesenswert?

dasrotemopped schrieb:
> Darum beten die DMA Jünger ihn ja auch so an.

Und DMA Jünger sind solche Freaks dass sie es schaffen bei
einzelnen DMA Byte-Transfers den Overhead einfach abzuschaffen.

Die schaffen das!

von dasrotemopped (Gast)


Lesenswert?

Den DMA mit
HAL_SPI_Transmit_DMA(&ili9488_Spi, Daten, groesse);
zu starten benötigt natürlich CPU Zyklen, der DMA an sich aber nicht. 
Effizient und effektiv wird es erst bei großen Datenmengen. Ein Farb-TFT 
ist da ein gerne genommener Anwendungsfall.

Man muss kein Freak sein, um mit der Maus in CubeMX die richtigen 
Häkchen zu setzen, RTFM reicht.

Darf ich vom Nickname auf deine CPU schliessen ?
Wie oft fällt im Datenblatt der Begriff DMA ?

Aber lieber zurück zum STM32 und ili9488.

Gruß,
dasrotemopped.

von john doe (Gast)


Lesenswert?

dasrotemopped schrieb:
> du brauchst Hardware CS für SPI DMA

Wieso denn das?


dasrotemopped schrieb:
> Den DMA mit
> HAL_SPI_Transmit_DMA(&ili9488_Spi, Daten, groesse);
> zu starten benötigt natürlich CPU Zyklen, der DMA an sich aber nicht.
> Effizient und effektiv wird es erst bei großen Datenmengen.

Das ist nicht richtig. Der DMA kann sehr wohl CPU Zyklen benötigen, denn 
sowohl CPU als auch DMA greifen über die Busse auf den Speicher bzw. die 
Peripherie zu und dabei kann es passieren, dass der DMA die CPU 
blockiert.

von dasrotemopped (Gast)


Lesenswert?

>kann es passieren, dass der DMA die CPU blockiert.

Das ist alles eine Frage der Speicherbandbreite und der Anforderungen 
der Anwendung. Zur Verfügung stehen internes, segmentiertes SRAM zur 
Erhöhung der parallel verfügbaren Speicherbandbreite.
Die Hardwareausstattung des STM32F746ZG laut Datenblatt :
L1-cache: 4KB data cache and 4KB instruction cache

SRAM: 320KB (including 64KB of data TCM RAM for critical real-time data) 
+ 16KB of instruction TCM RAM (for critical real-time routines) + 4KB of 
backup SRAM (available in the lowest power modes)

Multiple masters:
Cortex-Mx core AHB buses
DMA1 memory bus
DMA2 memory bus
DMA2 peripheral bus
Ethernet DMA bus
USB high-speed DMA bus
Chrom-ART Accelerator bus
LCD-TFT bus
siehe auch AN4031 / en.DM00046011.pdf

Die Speicherbandbreite reicht aus, um all diese Sachen mit Daten zu 
versorgen. Da sollte ein SPI Bus mit 25MHz@8bit= 3MByte/s doch 
reibungslos zu bedienen sein. Ein FIFO Buffer (siehe Screenshot weiter 
oben) vermeidet konkurrierende Zugriffe aufs RAM noch weiter.

>> du brauchst Hardware CS für SPI DMA
>Wieso denn das?
Einen GPIO Pin von der CPU umschalten zu lassen ist viel zu langsam für 
den DMA Controller. Und kostet natürlich auch wieder CPU Zyklen, das 
würde die Benutzung von DMA ad absurdum führen.

Gruß,

dasrotemopped.

von dasrotemopped (Gast)


Lesenswert?

@arduinoquäler
http://www.stm32duino.com/

komm auf die dunkle Seite, sie ist nicht stärker, aber schneller, 
verführerischer, mit DMA

von Markus F. (dr-ice)


Lesenswert?

Hallo und danke erst einmal an alle, die geantwortet haben.

Leider muss ich die nächsten Tage erst einmal etwas anderes bearbeiten, 
ich lese aber hier mit und freue mich über alle Tipps und Vorschläge.

Gruß Markus

von Arduinoquäler (Gast)


Angehängte Dateien:

Lesenswert?

Ich hab schon seit einigen Monaten ein TFT mit ILI9488
hier herumliegen, es hat 4 inch Diagonale und es hat
den RaspBerry Connector mit SPI.

Anlässlich dieses Threads hab ich das TFT endlich mal
in Betrieb genommen. Grundlage für meine Tests ist ein
ATxMega128A1 der mit 32 Mhz läuft, die SPI im 2x
Speed Mode mit 16 Mhz. Damit erreiche ich das Löschen
des gesamten 480x320 Feldes in weniger als 280msec.

Und da ist kein DMA dabei. Siehe Film ....

Markus F. schrieb:
> ich brauche zur zeit ca. 2 sec. für ein
> 480x320 TFT bei maximalem Prozessortakt von 209MHz.

von Arduinoquäler (Gast)


Lesenswert?

Zu Erklärung vielleicht noch:

Gegen Ende des Demo-Video wird das TFT achtmal mit verschiedenen
Farben gelöscht und zwischen jedem Löschen noch 20 msec gewartet.
Also braucht das Löschen eigentlich nur etwa knapp 260 msec.

von Rolf (Gast)


Angehängte Dateien:

Lesenswert?

Arduinoquäler schrieb:
> Grundlage für meine Tests ist ein
> ATxMega128A1 der mit 32 Mhz läuft, die SPI im 2x
> Speed Mode mit 16 Mhz. Damit erreiche ich das Löschen
> des gesamten 480x320 Feldes in weniger als 280msec.
Ich habe hier ein ILI9341 mit einer Auflösung von 320x240, betrieben im 
16 Bit-Farbmodus.
Dort komme ich auf eine effektive Datenrate von 2,8 MByte/s auf der SPI.
Genutzt wird ein STM32F4 180 MHz, SPI läuft mit 22,5 MHz und natürlich 
mit DMA. Wenn DMA läuft kann die CPU sich wieder um andere Dinge 
kümmern.

dasrotemopped schrieb:
>>> du brauchst Hardware CS für SPI DMA
>>Wieso denn das?
> Einen GPIO Pin von der CPU umschalten zu lassen ist viel zu langsam für
> den DMA Controller. Und kostet natürlich auch wieder CPU Zyklen, das
> würde die Benutzung von DMA ad absurdum führen.
/CS braucht man, wenn man noch andere Dinge am SPI hat.
An meinem Display brauchte ich /CS um aus dem read mode wieder 
rauszukommen.
Wichtig ist einen GPIO-Pin um zwischen Kommando und Datenmodus 
umzuschalten.
Da kommt man nicht drumrum. Oder hat jemand eine Idee, wie man das dem 
STM-SPI-Modul mit überlassen kann?

DMA lohnt sich nur für die Daten (nicht für die Kommandos) und auch nur, 
wenn man viele davon hat, also beim Bildschirm löschen, Rechteck füllen, 
orthogonale Linien zeichnen oder Fonts ausgeben. Bei einem einzelnen 
PutPixel bringt DMA nix.

Rolf

von Arduinoquäler (Gast)


Lesenswert?

Rolf schrieb:
> Dort komme ich auf eine effektive Datenrate von 2,8 MByte/s auf der SPI.

Dann dazu noch kurz die Datenrate meiner Anordnung
ohne DMA und 16 MBit/sec SPI:

260msec, 16 Bit, 480x320 Pixel ....

ergibt eine Datenrate von grob 1.18 MBytes/sec auf dem
vergleichsweise "schwachbrüstigen" ATxMega128.

von Stefan (Gast)


Lesenswert?

Rolf schrieb:
> SPI läuft mit 22,5 MHz
Theoretisches SPI Maximum: 22,5 MHz / 8 Bit = 2,8125 MByte /s
realer Wert: 2,778 MByte /s (wenn die Displayausgabe stimmt)

real/max = 98,8 %


Arduinoquäler schrieb:
> 16 MBit/sec SPI
Theoretisches SPI Maximum: 16 MBit/s = 2 MByte/s
realer Wert: 1,18 MByte/s

real/max = 59 %


Laufen da auf dem ATxMega128 noch irgendwelche Tasks?

von dasrotemopped (Gast)


Lesenswert?

>Damit erreiche ich das Löschen des gesamten 480x320 Feldes
>in weniger als 280msec. Und da ist kein DMA dabei. Siehe Film ....
Gutes Ergebnis. Das heisst aber, das der DMA Controller im Xmega128
ungenutzt rumliegt ?

Mit DMA würde SPI nicht viel schneller, aber die CPU Last ist deutlich 
geringer und der uC könnte sich um das Ranschaffen der nächsten 
Datenpakete kümmern.
Hier mal ein Beispiel mit STM32F4 und ili9341 im SPI Modus:
https://www.youtube.com/watch?v=qSf7YtFZIsA
Abwechselnd wird mit und ohne DMA ein neues Bild geschrieben. Der 
Unterschied im Bildaufbau ist gering, aber die CPU Last ohne DMA ist 
100%, mit DMA muss die CPU sich nur um den Start des DMA Prozesses 
kümmern.
In den Kommentaren ist auch ein Link zum Sourcecode, falls es jemand 
interessiert. SPI und ili9341 ist aber nur ein Nebenschauplatz bei dem 
Projekt.

Beim Xmega128 mit 32 MHz/8bit kann die CPU intern bist zu 32MB/s 
schieben, das heisst, SPI ist mit 2 MB/s im Verhältnis ein Flaschenhals 
für die CPU.
Beim STM32F4 mit 180MHz/32bit wird das Verhältnis noch schlechter, so 
das DMA schon fast zur Pflicht wird.

>GPIO-Pin um zwischen Kommando und Datenmodus
>umzuschalten... hat jemand eine Idee, wie man das dem
>STM-SPI-Modul mit überlassen kann?
Nicht mit SPI. Die Lösung ist ein SSD1963 am i80/SRAM Speicherinterface. 
Ist mit STM32F4 und Xmega128 möglich. Da bestimmt nur die beschriebene 
Speicheradresse im externen RAM ob das Daten oder Command Flag gesetzt 
ist.

Gruß,
dasrotemopped.

von Arduinoquäler (Gast)


Lesenswert?

dasrotemopped schrieb:
> Gutes Ergebnis. Das heisst aber, das der DMA Controller im Xmega128
> ungenutzt rumliegt ?

So ist es. Ich wollte das Display in Betrieb nehmen und dabei
zeigen was gegenüber der erschreckenden Datenrate  beim STM32
(siehe Eingangs-Post) herauszuholen ist. Ohne DMA.

Stefan schrieb:
> Laufen da auf dem ATxMega128 noch irgendwelche Tasks?

Nein, nur der 1 msec Timer Interrupt. Man bedenke dass die
SPI nicht nur die Daten rausschaufeln muss sondern der
Prozessor muss auch jedes Byte einzeln in das SPI Datenregister
schreiben, und das "ge-handshaked". Eine teilweise Entrollung
der Schleife (4 Transfers) macht das Ganze noch etwas flotter,
aber viel mehr ist nicht zu holen. Auch ein 16-Bit Schleifen-
Inkement braucht seine Zeit.

von Arduinoquäler (Gast)


Lesenswert?

Ich würde ja die DMA-Jünger befriedigen wollen die so sehr
darauf schwören, auch weil es mich (rein theoretisch)
interessiert, aber ich fürchte es geht in diesem Fall nicht.

Die DMA Maschine beim ATxMega braucht entweder eine feste
Quelladresse oder einen kontinuierlichen Speicherbereich zum
Lesen. Im Falle eines TFTs mit SPI müssen jedoch für das
einzelne Pixel 16-Bit Worte geschrieben werden, also
alternierend Low Byte / High Byte. Das kann die DMA Maschine
aber nicht leisten. So wäre ein DMA-Transfer fürs TFT nur
möglich wenn die Farbe schwarz ist, dann kann man einfach
die erforderliche Zahl Nullen schicken, oder die gewählte
Farbe hat im Low und High-Anteil den gleichen Wert. Nicht
sehr warscheinlich und auch nicht sehr praktisch .....
Einziger Ausweg wäre einen Buffer in der Grösse des Displays
bereitzustellen wo die Lösch-Daten schon drinstehen, aber
die müssten auch erst mal (für jede Farbe) da drinstehen und
der Buffer müsste immer da sein.

Wäre die SPI-Maschine auf 16 Bit ausgelegt dann bestünde
Hoffnung.

Vielleicht fällt jemand noch etwas ein was ich beim ATxMega
übersehen habe.

von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

Um mal wieder auf die Frage des TO zurückzukommen.
Hier mal das Nucleo-F746ZG einmal ohne DMA, aber dafür alle 3 Bilder von 
SDcard gelesen und das zweite Beispiel transferiert die selben 3 Bilder 
aus dem Flash per SPI DMA ans Display. Der RAM Verbrauch bleibt bei 
beiden Varianten gering, da immer nur maximal eine Bildzeile im RAM 
zwischengespeichert wird. Das sollte auch ein Xmega packen (Kapitel 
2.2):
http://www.atmel.com/Images/Atmel-8046-Using-the-XMEGA-DMA-Controller_Application-Note_AVR1304.pdf
Die Daten müssen natürlich in der Bytereihenfolge vorliegen, so wie es 
der Framebuffer des Displays sie erwartet. Umschichten beim SPI Transfer 
ist nicht möglich. Beim Xmega und beim STM32 ist der SPI Modus durch das 
Display festgelegt. Ich habe 16 bit Farbtiefe, aber 8 bit SPI und es 
geht offensichtlich, und das schnell.

Gruß,

dasrotemopped.

PS:
Ein Microprozessor bearbeitet Datenströme, ein Microcontroller steuert 
Datenströme. Das muss man bei der Konzeptionierung seiner Programme und 
Hardware immer bedenken. Das Lesen des Eingabedatenstroms vom externen 
Speicher und die Weiterleitung an ein externes Display per DMA lässt den 
Microcontroller als Dirigent auftreten, der DMA Controller ist der, der 
die Arbeit erledigt, hoch spezialisiert und effizient. Die 
Leistungsfähigkeit des Microcontrollers ist dann unwichtig.

von Rolf (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Ich wollte das Display in Betrieb nehmen und dabei
> zeigen was gegenüber der erschreckenden Datenrate  beim STM32
> (siehe Eingangs-Post) herauszuholen ist. Ohne DMA.
Der STM kommt auch ohne DMA auf eine ordentliche Datenrate.
Aber definitv nicht mit der HAL.
Man sollte die HAL einfach als eine Beispielimplementierung betrachten, 
die von ängstlichen Javaprogrammieren entworfen wurde.
Man betrachte nur mal die ganzen Sicherheitsabfragen, bevor da was 
passiert.

Beim ILI-TFT muß ja auch ständig zwischen 8- und 16-Bit, data und 
command, single- und DMA-Transfer umgeschalten werden, da kommt man mit 
der HAL auf keinen grünen Zweig.

Ich habe die HAL-Funktionen als Startpunkt genommen. Dann habe ich 
Schritt für Schritt die überflüssigen Codeteile entfernt.

> Nein, nur der 1 msec Timer Interrupt.
Der läuft bei mir auch, für die Zeitzählung.
Und die Bytezählung habe ich in die SPI-Transferfunktionen mit 
reingenommen.


Arduinoquäler schrieb:
> Im Falle eines TFTs mit SPI müssen jedoch für das
> einzelne Pixel 16-Bit Worte geschrieben werden, also
> alternierend Low Byte / High Byte. Das kann die DMA Maschine
> aber nicht leisten.
Da war ich ganz froh, das der STM32 das kann (16 Bit SPI und 16 Bit 
DMA). Sonst wären da auch ein paar Krücken nötig gewesen.


Rolf

von dasrotemopped (Gast)


Lesenswert?

>Beim ILI-TFT muß ja auch ständig zwischen 8- und 16-Bit, data und
>command, single- und DMA-Transfer umgeschalten werden, da kommt man mit
>der HAL auf keinen grünen Zweig.

Kann ich nicht nachvollziehen. Ich nutze ausschliesslich CubeMX/HAL und 
irgendwas umschalten 8/16 bit beim ili-TFT mache ich auch nie. Und 
langsam kommt mir das jetzt auch nicht vor. Aber ich lasse mich durch 
Gegenbeispiele gerne überzeugen.

Gruß,
dasrotemopped.

von Arduinoquäler (Gast)



Lesenswert?

Arduinoquäler schrieb:
> Ich hab schon seit einigen Monaten ein TFT mit ILI9488
> hier herumliegen, es hat 4 inch Diagonale und es hat
> den RaspBerry Connector mit SPI.

So .... jetzt zum feierlichen Sonntag Nachmittag ein bisschen
Übung auf dem STM32F407 (Discovery).

Display Löschen dauert hier 117 msec bei 21.xxx Mhz SPI Clock.
Ergibt etwa 2.62 MByte/sec wenn ich richtig gerechnet habe.

Ach ja: ohne DMA.
Ach ja: ohne HAL, aber mit "Arduinoquäler-Optimierung"

Wenn ich wieder Zeit habe werde ich das Ganze noch mit DMA
machen.

von Arduinoquäler (Gast)


Lesenswert?

Der auf dem Foto sichtbare blaue Connector ist übrigens für
die 16-Bit Displays (SSD1963, ILI9325, ILI9341...). Da macht
so ein Display noch etwas mehr Freude / Speed. Sogar ohne DMA.

von Markus F. (dr-ice)


Lesenswert?

@Arduinoquäler,

finde ich klasse, wie schnell das bei Dir geht. Würdest Du mich 
teilhaben lassen und einen Source hochladen ?

Ich würde mich freuen.

Ich bin leider nicht zu besonders viel gekommen, ich habe einen 
Bandscheibenvorfall und kann mich kaum bewegen.

Gruß Markus

von dasrotemopped (Gast)


Angehängte Dateien:

Lesenswert?

>ein bisschen Übung auf dem STM32F407
der zieht gleichauf mit meinem STM32F429
>Ach ja: ohne DMA
die etwa 3 MB/s sollten weder Xmega noch STM32 in Verlegenheit bringen

auch hier wird klar, das das SPI Display im wesendlichen davon abhängt, 
das der SPI Kanal immer gut mit Daten versorget wird und möglichst hoch 
getaktet ist. Allerdings ist keine CPU damit überfordert.
Eigendlich ist die Warheit, das die CPUs sich bei dem ili9341/9388 
Display langweilen und könnten noch viel mehr zusätzlich machen.
Im Video habe ich da mal ein Beispiel:
das ili9341 am SPI2 benutze ich nur als Debug/Status Anzeige,
der eigendliches Spass ist auf dem externen LTDC VGA Ausgang.
800x480@16bit mit 30fps. Das ili9341 wird auch mit 30 fps aktualisiert, 
aber nicht Vollbild. Auf dem Monitor rechts oben ist  übrigens der 
framecounter eingeblendet, DMA wird natürlich ;) benutzt, aber das 
Optimum ist noch lange nicht erreicht. Aber da das ganze nur Hobby ist 
geht es langsam vorran.

Gruß,
dasrotemopped.

von Arduinoquäler (Gast)


Lesenswert?

dasrotemopped schrieb:
> die etwa 3 MB/s sollten weder Xmega noch STM32 in Verlegenheit bringen

Diese Aussage verstehe ich allerdings nicht ....

Dann noch dieses:

Stefan schrieb:
> Theoretisches SPI Maximum: 22,5 MHz / 8 Bit = 2,8125 MByte /s

Dann bin ich ja mit meiner Nicht-DMA-Implementierung nicht weit
vom möglichen Maximum entfernt, solange man mit der SPI-Datenrate
bei 21..22 Mhz bleibt:

Beitrag "Re: STM32 F746zg nucleo und ILI9488 TFT per SPI langsam ?"

Liebe DMA-Jünger:
Bleibt also anzunehmen/vorauszusagen dass durch das "langsame"
SPI hier sich die Datenrate mit DMA nicht wesentlich steigern
lässt. Insbesondere auch deshalb weil DMA-Transfers sich für
kleine Datenmengen nicht lohnen wird weil der Overhead zuviel
Zeit verschlingt.

von john doe (Gast)


Lesenswert?

Arduinoquäler schrieb:
> Liebe DMA-Jünger:
> Bleibt also anzunehmen/vorauszusagen dass durch das "langsame"
> SPI hier sich die Datenrate mit DMA nicht wesentlich steigern
> lässt. Insbesondere auch deshalb weil DMA-Transfers sich für
> kleine Datenmengen nicht lohnen wird weil der Overhead zuviel
> Zeit verschlingt.

Die Datenrate steigt sicherlich nicht, aber sehr wohl lohnt sich DMA 
schon oft bei kleinen Datenmengen.
Bei 20MHz SPI kann eine 180MHz-MPU während eines 16-Bit-Transfers (ein 
Pixel) schon etliche Befehle ausführen. Erst recht gilt das für die 
216MHz F7 oder gar die 400MHz H7 MCUs.
Der Overhead bei DMA beschränkt sich ja meistens auf das Setzen vom CS, 
der Anfangsadresse sowie der Menge der Daten. Zum Schluss dann noch ein, 
zwei Befehle im IRQ.
Rechnen lohnt sich also, insbesondere wo etliche SPI-ICs auch nur 10MHz 
oder weniger verkraften.

von Arduinoquäler (Gast)


Lesenswert?

john doe schrieb:
> Bei 20MHz SPI kann eine 180MHz-MPU während eines 16-Bit-Transfers (ein
> Pixel) schon etliche Befehle ausführen.

Ja das könnte der Fall sein wenn ich (als Prozessor-Kern) nicht
schon drauf warte das nächste Graphik-Paket an das SPI zu senden.

Im Nachhinein:

Wen man sich die Sourcen des im Eingangsbeitrag geposteten Treibers
anschaut dann kann einem schon das blanke Entsetzen packen. Für
jedes Bitchen setzen eine eigene Funktion ..... geschrieben von
einem (vermutlich) Java-Programmierer der von 8-Core xxxGHz Pentiums
verdorben ist. Schlimmster "Fehler" (das kann man natürlich auch
anders sehen): Die Pixel werden im 24-Bit-Modus geschrieben. Würde
man sich auf 16 Bit Farbauflösung beschränken (was die Displays ja
klaglos hergeben) könnte man alleine dadurch ca 30% Verarbeitungszeit
sparen. Korinthenkacker können jetzt philosophieren wie sinnvoll
24 Bit Farbe auf einen Mikrocontroller-Display ist ....

von dasrotemopped (Gast)


Lesenswert?

>sich die Datenrate mit DMA nicht wesentlich steigern lässt
richtig, SPI mit 25MHz bleibt auch mit DMA SPI mit 25MHz

>kann eine 180MHz-MPU während eines ... Transfers ... schon
>etliche Befehle ausführen
genau das ist der Punkt. Die CPU von einfachen Datenschiebeaufgaben
zu befreien und anderweitig nutzen.
Ich denke, mein Beispiel mit dem VGA Ausgang zeigt deutlich, das DMA die 
Aufgabenteilung im System optimiert. DMA was DMA am besten kann und CPU 
was CPU am Besten kann.
Und allgemein muss man feststellen, das selbst bei "kleinen" Systemen 
die beste Lösung nicht automatisch eine schnellere CPU ist, sondern zu 
prüfen, ob man schon alles aus der Plattform herausgeholt hat. Auch ein 
Singlecore uC kann Multitasking mit guter Performance.

Bleibt nur zu hoffen, das ein Blick in den Quellcode dem TO genug Hilfe 
ist um seine Performanceprobleme zu beheben. Aber mein Code zum ili9341 
und sein Code zum ili9488 sind ja fast gleich strukturiert, es fehlt nur 
eine etwas mehr Hardware optimierte Implementierung der SPI Nutzung 
(Hardware CS und DMA). Grundsätzlich funktioniert die Ansteuerung des 
ili9488 ja.

Gruß,

dasrotemopped.

von Stefan K. (stefan64)


Lesenswert?

Arduinoquäler schrieb:
> Dann bin ich ja mit meiner Nicht-DMA-Implementierung nicht weit
> vom möglichen Maximum entfernt, solange man mit der SPI-Datenrate
> bei 21..22 Mhz bleibt

Der Sinn von DMA ist nicht nur, die Hardware-Übertragung zu 
beschleunigen, sondern die CPU während der Übertragung für andere 
Aufgaben benutzen zu können.

Gruß, Stefan

von Arduinoquäler (Gast)


Lesenswert?

Stefan K. schrieb:
> sondern die CPU während der Übertragung für andere
> Aufgaben benutzen zu können.

Arduinoquäler schrieb (schon) im Beitrag #4883559:
> Ja das könnte der Fall sein wenn ich (als Prozessor-Kern) nicht
> schon drauf warte das nächste Graphik-Paket an das SPI zu senden.

von Markus F. (dr-ice)


Lesenswert?

Hallo zusammen,

ein wenig habe ich heute mit einem Kollegen daran weiterarbeiten können.
Die größte Optimierung, die wir erreicht haben, kam durch das schreiben 
der 3 Farb-Bytes direkt hintereinander und des Löschen des Displays mit 
einem Zeilenweisen Buffer.

Vielen , vielen Dank für die Hinweise von Euch, manchmal steht man 
einfach ein bisschen auf der Leitung.

Jetzt geht es nach und nach an die Optimierung z.B. der Textausgabe.

Viele Grüße

Markus

von Johannes S. (Gast)


Lesenswert?

Die Funktion die am häufigsten aufgerufen wird ist send_byte() und 
arbeitet mit dem aufwändigen ST HAL. Den muss man aber nicht gleich 
komplett wegwerfen, es reicht soetwas wie ein fastWrite() dazuzubauen. 
Hier ist ein Beispiel wie das bei der mbed lib gemacht wurde:
https://developer.mbed.org/users/Sissors/code/BurstSPI/file/bc069279eb37/BurstSPI_STM32F4.cpp
Probiert mal aus einfach den Teil aus dem fastWrite in das send_byte zu 
packen, der spi Pointer muss dabei durch eure globale ili9488_Spi 
Struktur ersetzt werden. Und weil vom Display nichts zurückgelesen wird 
ist der ClearRX Teil nicht nötig.

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
Noch kein Account? Hier anmelden.