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?
deine Frage kann ich dir leider nicht beantworten
aber wenn du einen ARM F4 mit DCMI-Interface für die Camera benutzt,
sind 4,6 MByte/sec zu schaffen wenn er die Daten nur aufs Display
schaufeln muss
(nur als Info, wenn du was schnelleres brauchst)
Gruss Uwe
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.
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.
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.
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.
leluno schrieb:>>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.
Für solche Zwecke eignen sich besonders die int_fastx_t Typen.
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.
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.
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.
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.
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.
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.
Moby schrieb:> Na ja schön. Ist/war? ausgerechnet der Spitzensparmeister bei den Arms.
Den man sinnvollerweise nimmt wenns um Stromspar geht?! Und
freundlicherweise hab ich ihn mit dem Stromspar-AVR verglichen.
Moby schrieb im Beitrag #3638677:
> Ein AVR ist für viele Fälle eben die bessere Lösung.
Ein moderner 8051 wie der FT51 ist immer um ein vielfaches schneller als
jeder veraltete AVR :-)
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...
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" ;-)
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.
Und nun? Bekommen wir den vollstaendigen Code zu sehen??
Schon die 2. Zeile sieht etwas ungelenk aus:
1
if(!(vsync)){while(!(vsync));}
kurz: if (A) while (A) ;
das ist: while (A) ;
Was soll das? Compiler-Optimierungs-Plausibilitaetscheck??
Wer das mach, der tut auch noch Schlimmeres...
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?
>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.
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. ;)
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....
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.
> 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.
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.
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).
voidssp0_set_speed(chardivider){// 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???
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.
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.
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.
Detlef Kunz schrieb:> 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.
Hihi, das find ich gut :)
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.
leluno schrieb:> Was erwartest du bei einer mit 25 Mhz betriebenen ARM-Peripherie im> Vergleich zu einem mit 16 Mhz betriebenen AVR-System?
Ich bin von dem Erkenntnisgewinn beeindruckt.
leluno schrieb:> Dein Ton ist uenerträglich oberlehrerhaft.
Nunja, ein Exchef meinte, ich wär überheblich.
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.
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
introws=480;
5
intborder=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));
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.
leluno schrieb:> die Datenübertragung beim ARM> läuft jetzt mit 12/7=1,7 Mhz im Vergleich zu 1,3Mhz beim AVRleluno 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.
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ß :)
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.
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.
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:
Die Schleife sieht jetzt auch besser aus, weniger krampfhafte
Stützkonstrukte (border ...).
1
introws=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
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);
Dirk K. schrieb:> if ((rows % 101)==0) {
falls die Umschaltung der banks zeitkritisch ist, kannst du diese
Abfrage auch einsparen, indem du den code 5mal wiederholst.
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.
>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.
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.
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.
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.