Forum: Mikrocontroller und Digitale Elektronik STM32F1xx DMA - FSMC (LCD)


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Erik Z. (erik_wolfram)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe mir grade ein STM32F103VET Board mit TFT von Pollin zugelegt.
Das LCD besitzt einen ILI9325 Display-Controller und ist über 16 Bit 
FSMC angebunden. Hierzu habe ich mir entsprechende Bibliotheken 
zusammengeführt um die volle Funktionalität zu erzielen.

Soweit so gut:
Ich kann Texte schreiben, Graphen zeichnen und Bildchen anzeigen. (Alles 
was man sich so wünscht). Touch gibts auch!

Aber:
Funktionen wie "LCD_Clear" benötigen ca.32 ms für die 320x240 Pixel. 
Damit ist keine vernüftige Bildrate umzusetzen. Der Grund dafür ist 
recht einfach - in sämmtlichen Bibliotheken wird eine for-Schleife für 
die 320x240=76800 Pixel genutzt und jedes mit einer entsprechenden Farbe 
gefüllt. Mit einer Taktfrequenz von 72 MHz weiß man dann schnell wo die 
32 ms herkommen.


Da ich ein großer Fan von DMA bin dachte ich mir, dass ich diesen doch 
nutzen könnte um die Pixel im Hintergrund und wesentlich schnell zu 
füllen. Ebenso könnte man so schnell kleine Bildchen/Icons aus einem 
Puffer ausgeben.

Leider scheitere ich momentan an dieser Aufgabe: Der DMA scheint ein 
Timing-Problem mit dem FSMC zu haben - zwar kommen Daten an - diese sind 
jedoch fehlerhaft. Die ersten 10-20 Pixel sind müll, während die 
nachfolgenden Pixel eine kontinuierliche, falsche Farbe haben (rot statt 
gelb).
Der Code dafür sieht so aus:
1
  uint16_t ColorDMA = Color;
2
3
  LCD_SetCursor( 0, 0 );
4
  LCD_WriteRAM_Prepare(); /* Prepare to write GRAM */
5
6
  RCC_AHBPeriphClockCmd( RCC_AHBPeriph_DMA1, ENABLE );
7
8
  DMA_InitTypeDef DMA_InitStructure;
9
10
  DMA_StructInit( &DMA_InitStructure );
11
12
13
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &(ColorDMA);
14
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
15
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
16
17
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) 0x60020000;
18
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_MemoryDataSize_HalfWord;
19
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
20
21
  DMA_InitStructure.DMA_M2M = DMA_M2M_Enable;
22
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;//DMA_DIR_PeripheralSRC;
23
24
  DMA_InitStructure.DMA_BufferSize = 3000;      // max 65535
25
26
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
27
  DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
28
29
  DMA_DeInit( DMA1_Channel1 );
30
  DMA_Init( DMA1_Channel1, &DMA_InitStructure );
31
32
  DMA_ITConfig( DMA1_Channel1, DMA_IT_TC, ENABLE );
33
34
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
35
36
  DMA_Cmd( DMA1_Channel1, ENABLE );
37
38
  while(!(DMA_GetITStatus(DMA1_IT_TC1)));
39
  DMA_ClearFlag(DMA1_FLAG_TC1);

Der Code sollte eigentlich die ersten 3000 Pixel in der vorgebenen Farbe 
füllen. Stattdessen sind die ersten 10-20 Pixel schwarz und die 
restlichen rot statt gelb.


Was mir auch vollständig unerklärlich ist: warum nutzt keine der 
Bibliotheken den DMA für solche Funktionen? Eigentlich liegt das doch 
auf der Hand... Laut STM32 Datenblättern sollte der DMA auf FSMC 
zugreifen können...

Ich hoffe hier kann mir jemand helfen!

Gruß Erik

von Philipp K. (philipp_k59)


Bewertung
0 lesenswert
nicht lesenswert
Erik Z. schrieb:
> Was mir auch vollständig unerklärlich ist: warum nutzt keine der
> Bibliotheken den DMA für solche Funktionen? Eigentlich liegt das doch
> auf der Hand...

das liegt nicht auf der Hand wenn man mit 5Leitungen SPI und DMA optisch 
vergleichbar schnell wie FSMC mit mindestens 16 Steuerleitungen ist.

Gerade so kleine Displays sind sowieso nicht allzuschnell im Refresh das 
man unbedingt FSMC nutzen muss.. Als Übung ist das bestimmt hilfreich!

von Erik Z. (erik_wolfram)


Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe es nun zum Laufen bekommen. Mit der Suche nach AN2790 bekommt 
mann neben einer PDF eine Bibliothek welche entsprechende Funktionen 
bereit stellt.
Außerdem ist dort das Timing für das LCD genau beschrieben (bzw. genaue 
Werte für mein Display).
Lediglich bei den Adressen der FSMC-Schnittstelle ist in dieser 
Bibliothek eine Einschränkung da der Ausgang A0 verwendet wird. Wird der 
Ausgang A16 verwendet muss für die Bank1 0x60000000 das 16-Bit (A16) 
eingeschoben werden:
0x60000000 | (0x00000001<16) -> 0x60020000
Die Bänke sehen dann so aus:
Bank1 (NE1) 0x60000000
Bank2 (NE2) 0x64000000
Bank3 (NE3) 0x68000000
Bank4 (NE4) 0x6C000000

Das hierß für mich, dass ich auf die Struktur LCD verzichte und 
LCD_REG16 und LCD_DATA16 manuell setze:
#define LCD_REG16     (*((volatile uint16_t*)0x60000000))
#define LCD_DAT16     (*((volatile uint16_t*)0x60020000))
Die RAM-Addresse für den DMA geht ohne Pointer:
#define LCD_RAM_ADDR     ((uint32_t)(0x60020000))


Jetzt konnte ich das ganze so machen wie es angedacht war. Per DMA 
benötigt ein "LCD_Clear" knapp 15 ms @ 72 MHz OHNE Prozessorlast. Das 
entspricht ca. 66,7 FPS für das Füllen des kompletten Displays. (Vorher 
31,25 FPS mit 100% Prozessorlast)
Für meine Anwendung sollte das auf jeden Fall reichen, da ich das 
Display nur partiell neu füllen möchte. (Graph für einen Datenlogger)

Gruß Erik

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.