Leisungsvergleich ARM AVR

Gast #3638536
Lesenswert?

Mein 16Mhz-Atmega1284 füllt einen 320x240 SPI-TFT (153600Bytes) mit 
186.000 Bytes/sec.

Mein 100Mhz-LPC1768 schafft das mit 480.000 Bytes/sec.

Die Verarbeitung des Datenstroms eines OV7670-Bildsensors kann der AVR 
mit 115.000Bytes/sec, der ARM mit nur 35.000 Bytes/sec.

Verwendet wird jeweils der gleiche code:
1
Timer=0;
2
if(!(vsync)){while(!(vsync));}
3
while(vsync);
4
/*
5
while(zl_row<20*teilbild){
6
while(!href);//Warten auf href_h
7
while(href);
8
zl_row++;
9
}*/
10
//start frame
11
zl_row=240;
12
while(zl_row){
13
while(!(href));//Warten auf href_h
14
while(href){
15
// +++ px ++++
16
  while(!(pclk));
17
    SSP0DR=Value_Datenbus;
18
//    S0SPDR=Value_Datenbus;
19
//    SPDR=PIN(Value_Datenbus);
20
//    buffer[zl_pix]=Value_Datenbus;
21
  while(pclk);
22
  zl_pix++;
23
}//zl_row
24
zl_row--;
25
}//end frame
26
zl_performance=Timer;


Wodurch kommt es zum Leistungsabfall beim ARM gegenüber dem AVR? Mit dem 
SSP scheint es nichts zu tun zu haben. Auch das Schreiben in einen 
buffer klappt nicht besser. Wird der code beim ARM anders compiliert?
Gast #3638580
Lesenswert?

die Laufzeit dieses Codes ergibt sich doch größtenteils durch das Warten 
Flanken von pclk. Damit sollte die Laufzeit primär vom Timing deines 
Bildsensors bestimmt sein, nicht vom verwendeten µC (außer wenn er so 
langsam ist, dass er den Bildsensor nicht mehr richtig bedienen kann).

Wenn du einen Faktor 3 Unterschied in der Ausführungsgeschwindigkeit 
siehst: prüfe mal nach (Oszi), ob der Bildsensor jeweils gleich 
konfiguriert wurde und ob pclk jeweils die gleiche Frequenz hat. Wenn 
das nicht der Grund ist, würde ich als nächstes die Laufzeitmessung mit 
"Timer" überprüfen.
Gast #3638583
Lesenswert?

leluno schrieb:
> Verwendet wird jeweils der gleiche code:

Soll das heissen der ARM muss mit char und short Variablen 
zurechtkommen? Der ARM kann nur 32-bit Speicherzugriff effektiv 
ausführen.

Ansonsten kommt es schon auf den Compiler an. Es wäre aber auch möglich 
die paar Zeilen in Assembler zu schreiben, um sicherzugehen.
Gast #3638601
Lesenswert?

leluno schrieb:
> Verwendet wird jeweils der gleiche code

Mmmmhhh, findet im Hintergrund nix statt? Wie wird der Timer gefüttert? 
Überläufe ausgeschlossen?

Dein Vergleich hinkt also gewaltig. Um es richtig zu bewerten und zu 
kommnetieren (falls einer Lust hat) musst du schon beide vollständigen 
Projekte einstellen.

Aber ungesehen stinkt der avr dabei voll ab. Der arm läuft mit höherem 
Takt und hat einen besseren Befehlssatz. Ist halt so.
Gast #3638647
Lesenswert?

Tester schrieb:
> Dein Vergleich hinkt also gewaltig.

Es ist jeweils identischer code. pclk wird jeweils so eingestellt, dass 
gerade noch alle 153.600/2 pixel dargestellt werden. Alle interrupts 
sind abgestellt und werden nur für die Timer-Messung angestellt. Im 
Hintergrund läuft nichts. Die Einstellung des Sensors ist - bis auf den 
prescaler - identisch.

Ich versuche jetzt noch, die pclk-Auswertung über interupt zu machen.

 >Der ARM kann nur 32-bit Speicherzugriff effektiv
Das werde ich noch versuchen umzustellen, dass 32bit-Variablen 
wesentlich schneller als 8bit-Variablen verarbeitet werden, glaube ich 
aber nicht.
Gast #3638717
Lesenswert?

Lothar schrieb:
> leluno schrieb:
>> Verwendet wird jeweils der gleiche code:
>
> Soll das heissen der ARM muss mit char und short Variablen
> zurechtkommen? Der ARM kann nur 32-bit Speicherzugriff effektiv
> ausführen.
Falsch. Der LPC1768 ist ein Cortex-M3 und der kann Byte(=8Bit), Halfword 
(=16bit), Word (=32bit) Zugriffe gleich schnell (alles in 2 Takten) 
durchführen. Unaligned-Zugriffe (=Halfword-Zugriffe auf ungerade 
Adressen & Word-Zugriffe auf Adressen die keine Vielfachen von 4 sind) 
gehen ebenfalls, brauchen nur einen Takt mehr.

Man kann also auch auf dem Cortex-M problemlos "char" und "short" 
verwenden. Der Code ist unvollständig und nichtssagend, da ist was 
außendrum falsch konfiguriert.

Tester schrieb im Beitrag #3638686:
> Der ARM pustet 2 AVRs weg, keine Sorge. Hier wird ja nur ein Ausschnitt
> gezeigt. Wohl nicht ohne Absicht: Trollfutter.
Nicht nur 2. Die Rechen-Leistung ist um Größenordnungen höher, Latenzen 
der Instruktionen und Interrupts (für Echtzeit) geringer, der Code 
kleiner.
Gast #3638724
Lesenswert?

Dr. Sommer schrieb:
> Die Rechen-Leistung ist um Größenordnungen höher, Latenzen
> der Instruktionen und Interrupts (für Echtzeit) geringer, der Code
> kleiner.

Wenn man's denn braucht + das Strombudget langt. Und auch nur die 
Leistung die nicht in ineffizientem Compiling versandet. Asm macht ja 
wenig Sinn bei den ARMs.
Gast #3638725
Lesenswert?

leluno schrieb:
> pclk wird jeweils so eingestellt, dass
> gerade noch alle 153.600/2 pixel dargestellt werden.

Damit auch ich es kapiere: Welche Frequenz hat pclk konkret beim 
Auslesen mit dem ATMega, welche Frequenz hat es beim Auslesen mit dem 
LPC? Nur nochmal zu Erinnerung: der Code wartet im wesentlichen immer 
nur auf pclk, die beiden µC warten nur unterschiedlich schnell.

leluno schrieb:
> Die Einstellung des Sensors ist - bis auf den
> prescaler - identisch.

Damit auch ich es kapiere: meinst du mit prescaler das, was im 
Datenblatt des Sensors als Pclk-Divider bezeichnet wird? Nach welchen 
Kriterien stellst du diesen Pclk-Divider ein? Hoffentlich nicht danach, 
dass über SPI die "richtigen" Daten empfangen werden, denn du prüfst 
nirgends, ob die SPI-Übertragung beendet ist. Wenn der ARM "zu schnell" 
läuft, machst du dir damit selbst die Daten kaputt.
Gast #3638738
Lesenswert?

Moby schrieb:
> Dr. Sommer schrieb:
>> Die Rechen-Leistung ist um Größenordnungen höher, Latenzen
>> der Instruktionen und Interrupts (für Echtzeit) geringer, der Code
>> kleiner.
>
> Wenn man's denn braucht + das Strombudget langt.
Kannst dir ja anschauen, z.B. beim EFM32, sogar hier im Wiki:
"Max. Verbrauch im aktiven Modus bei 32MHz: 5mA
Verbrauch im Sleep Modus mit Funktionen wie Displayansteuerung oder 
Sensorüberwachung: 1-2µA (inkl. RTC, Brown Out, RAM aktiv)
Ruhestrom: 20nA"
Sollte für die meisten Strombudgets reichen. Und was heißt brauchen - 
warum den Extra-Komfort der Rechenleistung ablehnen?

> Und auch nur die
> Leistung die nicht in ineffizientem Compiling versandet. Asm macht ja
> wenig Sinn bei den ARMs.
Nur dass der ARMv7M viel besser für C(++) geeignet ist als AVR, und 
effizientes Kompilieren viel einfacher ist. GCC kann das zB schon 
ziemlich gut. Und wenn es tatsächlich nicht langt, warum soll ASM "wenig 
Sinn" machen?

Moby schrieb im Beitrag #3638737:
> Noch so ein schöner Satz für die Sammlung!
> Speed als Problemfall.
Wie bei der NASA, die alte 8086er sucht(e) weil ihre Programme nicht mit 
höherer Prozessorgeschwindigkeit klarkam... Das Problem liegt natürlich 
im Programm, nicht am Prozessor.
Gast #3638743
Lesenswert?

Moby schrieb:
> Wenn man's denn braucht + das Strombudget langt.
PS: EFM32 braucht 150µA / MHz, ATmega88P (=stromsparversion) 300µA / 
MHz.
Tiefster Schlafmodus: EFM32 20nA, AVR 800nA.
Und aufgrund der höheren Effizienz des Cortex ist der EFM32 auch mit 
allen Operationen schneller fertig und kann schneller wieder schlafen 
gehen => Noch weniger Verbrauch.
Gast #3638750
Lesenswert?

Dr. Sommer schrieb:
> Falsch. Der LPC1768 ist ein Cortex-M3 und der kann Byte(=8Bit), Halfword
> (=16bit), Word (=32bit) Zugriffe gleich schnell (alles in 2 Takten)
> durchführen. Unaligned-Zugriffe (=Halfword-Zugriffe auf ungerade
> Adressen & Word-Zugriffe auf Adressen die keine Vielfachen von 4 sind)
> gehen ebenfalls, brauchen nur einen Takt mehr.

Was hat das damit zu tun? Bei einem char-Array braucht es dann auf dem 
LPC1768 für 4 byte mit char-Zugriff 2*1+(2+1)*3=11 Takte und ein 
long-Zugriff darauf braucht 2 Takte. Ist doch offensichtlich was 
schneller ist. Dazu kommt noch dass im hier nicht gezeigten AVR-Code 
vermutlich ALU-Instruktionen auf bytes drin sind, die beim ARM zusammen 
auf 4 bytes erfolgen können. Somit könnte der AVR-Code bei 
entsprechender Optimierung auf dem ARM um ein vielfaches schneller 
laufen.
Gast #3638757
Lesenswert?

Lothar schrieb:
> Dr. Sommer schrieb:
>> Falsch. Der LPC1768 ist ein Cortex-M3 und der kann Byte(=8Bit), Halfword
>> (=16bit), Word (=32bit) Zugriffe gleich schnell (alles in 2 Takten)
>> durchführen. Unaligned-Zugriffe (=Halfword-Zugriffe auf ungerade
>> Adressen & Word-Zugriffe auf Adressen die keine Vielfachen von 4 sind)
>> gehen ebenfalls, brauchen nur einen Takt mehr.
>
> Was hat das damit zu tun? Bei einem char-Array braucht es dann auf dem
> LPC1768 für 4 byte mit char-Zugriff 2*1+(2+1)*3=11 Takte und ein
> long-Zugriff darauf braucht 2 Takte.
Ich dachte es geht um einzelne Byte-Zugriffe. Aber auch die sind am ARM 
nicht langsamer als am AVR (also nicht ineffektiv) , nur der ARM kann 
zusätzlich (half-)word Zugriffe noch schneller...
> schneller ist. Dazu kommt noch dass im hier nicht gezeigten AVR-Code
> vermutlich ALU-Instruktionen auf bytes drin sind, die beim ARM zusammen
> auf 4 bytes erfolgen können. Somit könnte der AVR-Code bei
> entsprechender Optimierung auf dem ARM um ein vielfaches schneller
> laufen.
Ja. Aber der ARM ist definitiv nicht langsamer auf Bytes/Half-Words als 
ein AVR...
Gast #3638763
Lesenswert?

Lothar schrieb:
> ist immer um ein vielfaches schneller

Das ist aber auch in den meisten Bastler-Projekten zweitrangig.
Das Komplettpaket zählt. Robustheit. Ausgereiftheit. Erhältlichkeit. 
Preis. Vor allem aber: Einfache Anwendung.

Hab so einen Xmega128 in meiner Haussteuerung. Der hat sicher nicht 
wenig zu tun. Asm-optimiert zählt das Ding in seiner Haupschleife immer 
noch bis 60000H/Sek. Mein Gott, wohin bloß mit der Leistung? Ich krieg 
noch graue Haare. Da werd ich mir doch keine Gedanken über einen 
Plattformwechsel machen! Leistung ist doch sowieso völlig überbewertet. 
Oder man verbrät sie in eben Compilern und "schnellerem Warten" ;-)
#3638767
Lesenswert?

Dr. Sommer schrieb:
> Moby schrieb im Beitrag #3638737:
>> Noch so ein schöner Satz für die Sammlung!
>> Speed als Problemfall.
> Wie bei der NASA, die alte 8086er sucht(e) weil ihre Programme nicht mit
> höherer Prozessorgeschwindigkeit klarkam... Das Problem liegt natürlich
> im Programm, nicht am Prozessor.

Die Nasa hat die Chips für ihre Space Shuttle Diagnosesysteme gesucht. 
Der 8086 sitzt in dem Teil, das den Raketenantrieb vor dem Start 
überprüft.  Hat überhaupt nix mit Geschwindigkeit zu tun, sondern lag 
einfach daran, das die 20 Mio. USD für eine Neuentwicklung nicht 
genehmigt wurden.
Gast #3638832
Lesenswert?

Moby schrieb:
> Hab so einen Xmega128 in meiner Haussteuerung.
Ist ja schön. Das hat aber nichts mit der Diskussion zu tun und ARM ist 
immer noch leistungsfähiger.

Hans-Georg Lehnard schrieb:
> Hat überhaupt nix mit Geschwindigkeit zu tun, sondern lag
> einfach daran, das die 20 Mio. USD für eine Neuentwicklung nicht
> genehmigt wurden.
Warum hätte man denn eine Neuentwicklung gebraucht wenn man stattdessen 
286er oder was andres neueres (verfügbares) verwendet hätte?
Gast #3638866
Lesenswert?

>if(!(vsync)){while(!(vsync));}
stimmt, wird geändert,

Lothar schrieb:
> für 4 byte mit char-Zugriff 2*1+(2+1)*3=11 Takte und ein
> long-Zugriff darauf braucht 2 Takte.

vom OV kommt nur ein 8bit-Signal, daher stellt sich die Frage der 
Übertragung  von 32 bit nicht.

Achim S. schrieb:
> Nach welchen
> Kriterien stellst du diesen Pclk-Divider ein?

Der OV bekommt ein CLKOUT-Signal, beim AVR 16Mhz, beim ARM 12Mhz. Den 
Prescaler habe ich solange verändert, bis der OV so langsam war, dass 
der Zeitraum 1Takt-PCLK ausreichend war, um die Spi-Datenübertragung 
abzuschließen: Beim AVR Prescaler 12=> 1,3Mhz - beim ARM Prescaler 32= 
0,375Mhz. Wenn ich den Prescaler weiter verringere, werden nicht mehr 
alle Pixel übertragen, weil die Zeit für den Datentransfer nicht mehr 
ausreicht.

Die Abfrage Übertragungsende habe ich weggelassen, da es den Code 
verkürzt und  da die Bedingung "ausreichend" Zeit für Spi ohnehin 
eingehalten werden muss. Der Prozessor kann an dieser Stelle im Code 
ohnehin nicht warten, da er sonst den nächsten Pixel-Takt verpasst.
Angehängte Dateien:
Gast #3638893
Lesenswert?

Detlef Kunz schrieb:
> Was soll ich dazu sagen?
> Das ist wie, wenn Opa Kause (60 Jahre unfallfrei) Sonntags im Porsche
> auf der Autobahn fährt.
> So ein Porsche ist nun mal nicht so schnell wie ein Trabi. ;)

Danke für die Beschreibung: so schön hätte ich es nicht auf den Punkt 
bringen können....
Gast #3638907
Lesenswert?

Mal abgesehen von der PCLK :-)

leluno schrieb:
> vom OV kommt nur ein 8bit-Signal, daher stellt sich die Frage der
> Übertragung  von 32 bit nicht.

Das heisst ja nicht dass man nicht die 8-bit puffern kann und wenn 
32-bit voll sind das zusammen abholt (spart 3 loops). DMA gäbe es dann 
notfalls auch noch.
Gast #3638931
Lesenswert?

> Falsch. Der LPC1768 ist ein Cortex-M3 und der kann Byte(=8Bit), Halfword
> (=16bit), Word (=32bit) Zugriffe gleich schnell (alles in 2 Takten)
> durchführen. Unaligned-Zugriffe (=Halfword-Zugriffe auf ungerade
> Adressen & Word-Zugriffe auf Adressen die keine Vielfachen von 4 sind)
> gehen ebenfalls, brauchen nur einen Takt mehr.

Das mag sein, aber bedenke, dass bei arithmetischen Operationen 
eventuelle Überläufe berücksichtigt werden müssen. Der ARM rechnet 
prinzipiell mit 32 Bit. Um die Bits los zu werden, die durch eventuelle 
Überläufe auf 1 gesetzt wurden, erzeugt z.B. der IAR Compiler bei 8-Bit 
Variablen massenhaft Shifts um 24 Bit nach links, gefolgt von Shifts um 
24 Bit nach rechts. Daher ist es beim ARM oft besser, auch für z.B. 
Schleifenzähler, bei denen 8 Bit reichen würden, gleich ein uint32_t zu 
verwenden.
Gast #3638961
Lesenswert?

Lothar schrieb:
> 8-bit puffern

Ich habe das doch probiert. Es macht keinen Unterschied, ob ich die 8bit 
erst in einen Buffer oder sofort in das SSP0DR-Register schreibe. Bei 
SSP0 ist DMA eingestellt, dürfte die CPU daher nicht belasten.

Auch für DMA brauche ich ausreichend Rechenzeit, um zumindest den 
Software-Single-Request aufzurufen. Diese Rechenzeit steht bislang nicht 
zur Verfügung.
Gast #3638993
Lesenswert?

ich sehe es dem Code auf die Schnelle nicht an: kannst du uns noch 
verraten, mit welchem Takt der SPI-Bus auf den beiden µC läuft?

Am liebsten sind mir bei solchen Angaben immer Werte, die man mal mit 
dem Oszi nachgemessen hat (damit man nicht irgendeine Prescaler- oder 
eine PLL-Einstellung übersieht, die sich auf den SPI-Takt auswirkt).
Gast #3639060
Lesenswert?

SSP0 läuft mit 25Mhz:
1
void lcd_ssp_init(void){
2
//0.15 0.17 0.18 ssp0/F x10
3
  pinSEL(0,16,0);
4
  pinDIRout(0,16);
5
  pinSET(0,16);
6
#if 1 //ssp0
7
  init_ssp0_1();
8
  ssp0_set_speed(2);
9
  //DMA:
10
  SSP0DMACR = 3;//176x
11
  LPC_SC->PCONP |= (1<<29);//Enable clock to DMA controller
12
#else....
13
void init_ssp0_1(void){
14
pinSEL(0, 15, 2);    // Attach SCK0 to I/O pad
15
pinSEL(0, 17, 2);    // Attach MISO0 to I/O pad
16
pinSEL(0, 18, 2);    // Attach MOSI0 to I/O pad
17
SSP0CR0 |= (DSS<<0);//8bits
18
SSP0CR0 |= (FRF<<4);//frame
19
SSP0CR0 |= (1<<CPOL);
20
SSP0CR0 |= (1<<CPHA);
21
SSP0CR1 = 0b0010;     // SOD = 0, MS = 0, SSEnable = 1, LBM = 0
22
SSP0CPSR = (PCLK_SSP / SCLK_SLOW) & ~1;//slow
23
SSP0CPSR = 250;
24
//SSP0CR0 = 0x0007;      /* Set mode: SPI mode 0, 8-bit */
25
//SSP0CR1 = 0x2;        /* Enable SSP with Master */
26
}
27
...
28
void ssp0_set_speed(char divider){// fast 2...254 slow
29
SSP0CPSR = divider;
30
}


Der SPI-AVR mit halbem Prozessortakt...
Beides ist in Ordnung, denn der Bildaufbau - ohne OV - ist ja o.k.


... Eine Idee habe ich noch. Am Pin 0.12 sitzt ein Taster. Der hat einen 
10k-Pullup. Möglicherweise verkürzt der die nutzbare Zeitspanne???
Gast #3639177
Lesenswert?

Der Pullup wars nicht. Ich habe CLKOUT mit dem CPU-Takt verbunden. Der 
Bildaufbau ist nun deutlich schneller als beim AVR. Mit dem ARM ist also 
alles in Ordnung. Was nicht funktioniert, ist die Änderung beim 
Prescaler. Vermutlich ein Problem beim SCCB-Bus. Für heute reichts. 
Vielen Dank für die Hilfe.
#3639536
Lesenswert?

leluno schrieb:
> Um den Leistungsvergleich abzuschließen, die Datenübertragung beim
> ARM
> läuft jetzt mit 12/7=1,7 Mhz im Vergleich zu 1,3Mhz beim AVR.
>
> So gewaltig ist der Unterschied also gar nicht.

Ich sag ja auch immer: Glaub keinem Vergleich, den Du nich selbst 
getürkt hast.
Also wo liegt hier wohl der die Irreführung? :)
Ich erinnere mal an Opa Krause. ;)

Und wenn die Art, wie die Messung gestartet wird, nicht geändert wurde, 
dann geht das bildlich gesprochen so:

Opa Kause will wissen wie lange er für den Weg von einer Ampel zur 
nächsten braucht.
Das macht er so:
Er fährt zur ersten Ampel, und startet dort schon mal die Stoppuhr.
Es ist gerade GRÜN, aber er will ja mit der ROT/GRÜN-Flanke losfahren, 
damit das ganze schön syncron ist.
Also wartet er bis ROT ist und färt los, sobald wieder GRÜN wird.
Dann Stoppt er die Zeit an der nächsten Ampel.
Sein Kumpel Willi mit seinem Trabi macht das gleiche. Allerdings kamm er 
erst in allerletzter Sekunde vor dem Start an der Ampel an (mann muss ja 
mal aufs klo).
Beide kommen genau zur selben Zeit an der nächsten Ampel an. Und doch 
hat Willi laut Messung eindeutig weniger Zeit gebraucht, ist also 
folgerichtig schneller. Also ist der Porsche doch nicht so schnell.
Gast #3639582
Lesenswert?

Detlef Kunz schrieb:
> und wenn die Art, wie die Messung gestartet wird, nicht geändert wurde,
> dann geht das bildlich gesprochen so:

Du hast einen Fehler bei der Rücksetzung des Timers aufgezeigt. Das hab 
sogar ich verstanden und geändert. Die Frequenz von 1,7 Mhz wurde durch 
Veränderung des Prescalers ermittelt. Bei Prescaler 6 werden nicht mehr 
alle Pixel erfasst. Prescaler 7 ist ok. Daraus folgt 1,7Mhz.

Was erwartest du bei einer mit 25 Mhz betriebenen ARM-Peripherie im 
Vergleich zu einem mit 16 Mhz betriebenen AVR-System?

Dein Ton ist uenerträglich oberlehrerhaft.
#3640847
Lesenswert?

Was bei mir zwischendurch nicht gepasst hatte, waren 
Compiler-Optimierungen (-O2). Für das Projekt eingestellt, aber 
irgendwie hatte sich main.c ein -O0 eingefangen und lief damit 
schnarchlangsam - sowohl auf AVR als auch auf ARM. Der Unterschied 
nicht-optimiert zu optimiert war eine fast verdoppelte Transferleistung 
via SPI.
#3641370
Lesenswert?

Die hatte ich drin, weil ich alles mögliche ausprobiert habe, um das 
Dingen ordentlich ans Rennen zu bekommen.

Inzwischen sieht die Schleife so aus - immer noch Polling, da ich mit 
DMA nicht zu Rande komme. DMA SPI->Rx läuft, Tx nicht. Habe mich da von 
deiner Schleife mal inspirieren lassen. Ist aber nicht unbedingt 
schneller.
1
  while (!(VSYNC)); // wait for next frame
2
  while (VSYNC); // wait for frame start
3

4
  int rows=480;
5
  int border = ram_size;
6
  while (rows) {
7
      while(!(HREF)) ;  // wait for row
8
      while (HREF) {
9
        while(!(PCLK)) ;  // wait for pixel valid
10
        spi1_tx((GPIOB->IDR)>>8);
11
//        pixelcount++;
12
        border--;
13
        if (border) {
14
          while(PCLK) ;  // wait for pixel to end
15
        } else {
16
             border = ram_size;
17
             bank++;
18
             chip_select(bank);
19

20
             // Send WRITE command to chip
21
             spi1_tx(WRITE);
22

23
             // as default sequential mode, thus address has to be sent only at start
24
             address = 0;
25
             spi1_tx((address>>16));   //send even MoreMSByte address first
26
             spi1_tx((address>>8));   //send MSByte address first
27
             spi1_tx((address));      //send LSByte address
28
        }
29
      }  // of href
30
      if (linecount == 0) linecount = (ram_size-border) / 2;
31
      rows --;
32
   }  // of rows / image transfer done!
33

34
  pixelcount=(bank*ram_size)+(ram_size-border);
35
  sprintf(text, "Writing image succeeded! Wrote %u bytes, used %i RAM chips.\n", pixelcount, bank+1);
36
  uart_tx(text);
37
  sprintf(text, "Image dimension: %i x %i pixel. 10 bytes captured:\n", linecount, ((pixelcount/linecount)/2));
38
  uart_tx(text);
39

40
  chip_deselect();
Gast #3641642
Lesenswert?

Dirk K. schrieb:
> // as default sequential mode, thus address has to be sent
> only at start
>              address = 0;
>              spi1_tx((address>>16));   //send even MoreMSByte address
>              spi1_tx((address>>8));   //send MSByte address first
>              spi1_tx((address));      //send LSByte address

du hast sehr viel code in der Px-Schleife. Normalerweise muss man 
Speicherchips nur einmal adressieren und kann dann die bytes 
nacheinander schreiben. das Hochzählen der Adressen geht automatisch. 
Dadurch kannst du die Geschwindigkeit erhöhen. Je weniger Befehle in der 
px-Schleife, um so besser...

Die Darstellung auf dem TFT ist bei mir mit 1,7Mhz pclk durchaus 
akzeptabel. Ich bastel jetzt an der sd-Speicherkarte. Die 9er Version 
von Chan funktioniert. Bei der 10er bin ich gescheitert. Wenn das 
klappen sollte, könnte ich komplette Bilder auf die sd-Karte schreiben.
Gast #3641688
Lesenswert?

leluno schrieb:
> die Datenübertragung beim ARM
> läuft jetzt mit 12/7=1,7 Mhz im Vergleich zu 1,3Mhz beim AVR

leluno schrieb:
> Was erwartest du bei einer mit 25 Mhz betriebenen ARM-Peripherie im
> Vergleich zu einem mit 16 Mhz betriebenen AVR-System?

Wie wäre es wenn du beide systeme mit der gleichen takt frequenz 
betreibst? dann wäre der vergleich meiner meinung nach viel sauberer. 
Eine höhere Taktfrequen bedeutet ja zwangsläufig, das ein höherer 
datendurchsatzt erreicht werden kann (unabhängig davon, wie viel höher 
der Durchsatzt dann wirklich ist). Wenn du es aber mal mit der gleichen 
Taktfrequenz testets, und der ARM dann langsamer ist, ist das ergebnis 
wirklich ernüchternd.
So wie es jetzt ist sage ich: Der ARM ist bei der Datenübertragung 
400kHz schneller. Und 400kHz sind nunmal 400kHz.
#3641707
Lesenswert?

Bei 640x480x2Byte (etwa 610 kByte) muss ich die Speicherchips von 
128kByte halt nach 128kByte umschalten ;) Den meisten Code überspringe 
ich ja und das klappt ohne Umschalten auch sehr gut und fix.

Ich verliere 8 Byte, offenbar ist das Umschalten der Speicherchips 2 
PCLK zu langsam. Auslagern kann ich das nicht, und SPI-RAM funktioniert 
nun mal so, dass ich den Befehl WRITE, die Adresse und dann die Daten 
sende - also anstatt 1 Byte sequentiell über die Leitung zu schicken, 
laufen da 5. Nehme ich da irgendwo CS weg, ist der Befehl zu Ende und 
der Chip wartet auf einen neuen Befehl.
In einer vorher laufenden Schleife kann ich immerhin schon mal auf 
Sequential Mode umstellen und kann mich auf umschalten + Daten senden 
beschränken.

Mit DMA und Puffer dürfte sich da was machen lassen. Aber der DMA zickt 
natürlich auch. Wäre ja zu einfach, würde eine Peripherie mal 
funktionieren wie beschrieben. ;) So lernt man jedes Protokoll, jeden 
Baustein wirklich gut kennen. Wenn man dann nicht irgendwo stecken 
bleibt, macht das sogar Spaß :)
Gast #3641709
Lesenswert?

Ich kann beim AVR mit einer Pixel-Clock-Frequenz von 1,7Mhz nichts 
anfangen, weil er die einkommenden Daten nicht mehr verarbeiten kann. 
Ohne Frage ist der ARM auch beim Spi-Transfer wesentlich schneller. Der 
Vorteil erhöht sich noch wenn die CPU-Rechenleistung von 100Mhz zum 
Tragen kommt. Trotzdem ist auch der AVR - insbesondere der M1284 - nicht 
schlecht.
Gast #3641973
Lesenswert?

Dirk K. schrieb:
> Ich verliere 8 Byte, offenbar ist das Umschalten der Speicherchips 2
> PCLK zu langsam. Auslagern kann ich das nicht,

Wenn du zeilenweise ansteuerst, müsste das gehen, weil bei !href ja eine 
Schreibpause eintritt.
1
zl_href = 124;
2
while(href)
3
{...
4
zl_href--;
5
}
6

7
cs_chip1_h,cs_chip2_l, write_cmd, zl_href = 124
8

9
zl_href = 124;
10
while(href)
11
{...
12
zl_href--;
13
}
14
...

die Dauer der Befelsfolge beim Umschalten bestimmt dann die 
Schreibgeschwindigkeit. Wenn du den chip nicht adressierst, müsste er 
bei 0 anfangen.
#3641999
Lesenswert?

Danke für den Vorschlag, da hätte ich vielleicht auch drauf kommen 
können, mich auf 102 Zeilen pro Modul zu beschränken - das hilft gegen 
die verlorenen Pixel :)
1
Reading COM11 again from OV7670: [143] -> Prescaler 16, frequency 500 kHz.
2
Select first RAM chip.
3
Writing image succeeded! Wrote 614400 bytes, used 5 RAM chips.
4
Image dimension: 640 x 480 pixel. 10 bytes captured:
5
[101]: 153   [102]: 187   [103]: 186   [104]: 202   [105]: 95   [106]: 223   [107]: 137   [108]: 220   [109]: 88   [110]: 222

Die Schleife sieht jetzt auch besser aus, weniger krampfhafte 
Stützkonstrukte (border ...).
1
  int rows=480;
2
  while (rows) {
3
      while(!(HREF)) ;  // wait for row
4
      while (HREF) {
5
        while(!(PCLK)) ;  // wait for pixel valid
6
        spi1_tx((GPIOB->IDR)>>8);
7
        pixelcount++;
8
        while(PCLK) ;  // wait for pixel to end
9
      }  // of href
10
      if (linecount == 0) linecount = pixelcount / 2;
11
      if ((rows % 101)==0) {
12
           bank++;
13
           chip_select(bank);
14

15
           // Send WRITE command to chip
16
           spi1_tx(WRITE);
17

18
           // as default sequential mode, thus address has to be sent only at start
19
           address = 0;
20
           spi1_tx((address>>16));   //send even MoreMSByte address first
21
           spi1_tx((address>>8));   //send MSByte address first
22
           spi1_tx((address));      //send LSByte address
23
      }
24
      rows --;
25
   }  // of rows / image transfer done!

War irgendwie der Idee aufgesessen, die Speicherchips randvoll zu 
schreiben - ist ja aber Quatsch. :)

Ohne Adressierung geht es nicht. Der Chip erwartet: <cmd> - <address> - 
<data>: http://ww1.microchip.com/downloads/en/DeviceDoc/25142A.pdf
Gast #3642047
Lesenswert?

Dirk K. schrieb:
> pixelcount++;
>         while(PCLK) ;  // wait for pixel to end
besser:
while(PCLK) ;  // wait for pixel to end
pixelcount++;

> spi1_tx((address>>16));   //send even MoreMSByte address
>            spi1_tx((address>>8));   //send MSByte address first
>                  //send LSByte address

besser:
spi1_tx(0);
spi1_tx(0);
spi1_tx(0);
#3642059
Lesenswert?

An der Stelle ist das alles nicht mehr zeitkritisch - habe da ja locker 
8 oder mehr PCLK "blank pause", da kann der STM32F103 so richtig 
rumrechnen ;) Dass da drei Mal 0 als Adresse übertragen wird, ist schon 
klar - das macht den Kohl da aber nicht fett, da die Shifts in einem 
Takt laufen und die serielle Übertragung per SPI die eigentliche Bremse 
ist.
Gast #3642068
Lesenswert?

>Was erwartest du bei einer mit 25 Mhz betriebenen ARM-Peripherie im
>Vergleich zu einem mit 16 Mhz betriebenen AVR-System?
Die Peripherie hat ja prinz. nichts mit dem Kern zu tun (wobei die SPI.. 
vom AVR aber extrem schlecht ist).
Aber m.E. liegt ganz oben schon ein Fehler vor, denn mit SPI ein 
Grafik-Display anzusteuern, ist einfach grässlich.
Gast #3643269
Lesenswert?

MCUA schrieb:
> mit SPI ein Grafik-Display anzusteuern, ist einfach grässlich

???????
Einfach anzuschließen, billig, vollwertiger Ersatz für Text-Lcd, super 
geeignet für die Darstellung von Funktionen und Graphen, Anzeige von 
Fotos mit noch akzeptabeler Geschwidigkeit. Bei genügend Speicher für 
die Zeichen-lib - ab Atmega32 - immer  zu empfehlen.

Beim aktuellen Projekt ersetzt das Lcd lediglich einen 
153.600-Byte-Speicher, der die praktische Eigenschaft hat, den 
Speicherinhalt optisch anzuzeigen. Es geht nur um einen Zwischenschritt, 
da die Bilder (mindestens 4x 153.600 Bytes) letztlich auf eine sd-card 
müssen.
Gast #3756906
Lesenswert?

Dirk K. schrieb:

> Ohne Adressierung geht es nicht. Der Chip erwartet: <cmd> - <address> -
> <data>: http://ww1.microchip.com/downloads/en/DeviceDoc/25142A.pdf

"If operating in Sequential mode, after the initial data
byte is shifted in, additional bytes can be clocked into
the device. The internal Address Pointer is automatically
incremented."

Seite 5, Kapitel 2.4 Write Sequence

Alles andere wäre sehr ungewöhnlich.
#3757416
Lesenswert?

Rainer, wo ist der Widerspruch?!

Sofern du CS wieder wegnimmst, ist der aktuelle Befehl beendet. Du 
startest wieder mit Befehl, wenn du den Chip anwählst.

Und der verlangt eine Adresse.

Die Adresse wird nur einmal gesetzt beim Adressieren des Chips. Steht 
alles doch da. Nach der Initialisierung schubse ich rein die Daten rüber 
und verlasse mich auf Autoinkrement.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren