Hallo,
ich stehe gerade auf dem Schlauch und vielleicht kann mir ja jemand
helfen.
Ich habe ein LPC Xpresso Board mit LPC1347 und versuche die
Arbeitsgeschwindigkeit nachzuvollziehen. Dafür habe ich die
Beispielfirmware "periph_systick" genommen in der ich zu Beginn des
Programms eine Endlosschleife eingefügt habe. Jeder Schleifendurchlauf
erzeugt einen Pintoggle.
int main(void)
{
/* Generic Initialization */
SystemCoreClockUpdate();
Board_Init();
while(1){
Board_LED_Toggle(0);
}
}
void Board_LED_Toggle(uint8_t LEDNumber)
{
Board_LED_Set(LEDNumber, !Board_LED_Test(LEDNumber));
}
void Board_LED_Set(uint8_t LEDNumber, bool On)
{
if (LEDNumber == 0) {
Chip_GPIO_WritePortBit(LPC_GPIO_PORT, 0, 7, On);
}
}
So weit so gut, die LED leuchtet. Die Frequenz an der LED habe ich
gemessen und stelle überrascht fest, dass ich auf maximal 400kHz komme,
obwohl die CPU nach meinem Verständnis mit 72MHz taktet.
Es kann doch nicht sein, dass eine einfache While Schleife mit einem
Toggle beinahe 100 CPU Takte verschlingt?
Oder irre ich mich in der Annahme, dass die CPU mit 72MHz läuft? Wird
die Prozessorgeschwindigkeit im Debug Modus heruntergesetzt?
Oder macht mir die Definition der GPIO Ports ein Strich durch die
Rechnung? Wo stelle ich die maximale Frequenz der GPIO Ports beim
LPCXpresso ein?
Ich habe eine Funktion gefunden, die den GPIO Block aber nur
initialisiert, jedoch nicht die Frequenz einstellt.
void Chip_GPIO_Init(LPC_GPIO_T *pGPIO)
{
Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_GPIO);
}
Ist da sonst noch irgendwo eine Einstellung?
Schau Dir mal das Disassembly z.B. im Debugger an. Da wird ein Function
call inklusive Rücksprung drin sein. Vielleicht hilft schon der
Optimizer etwas.
Wenn Du schnellen Code haben willst, must Du schon die GPIO Register
direkt beschreiben - oder einen Timer als PWM benutzen.
So wie die Fragestellung aussieht würde ich auch nicht davon ausgehen,
dass der Fragesteller weiß mit welcher Frenquenz die CPU läuft. Und die
Dokumentation zum LPC1347 hat er sich sicher auch nicht durchgelesen und
versucht etwas zu verstehen. Nur mal schnell Rumstochern und dann das
Forum arbeiten zu lassen finde ich etwas mutig...
@temp
So wie die Antwortstellung aussieht, ist diese aber auch nicht besonders
zielführend. Kluge Sprüche klopfen kann ich auch. Abgesehen mal davon,
habe ich niemanden gebeten meinen Code zu verbessern. Mich interessiert
nur die Ursache der Diskreptanz zwischen meinen Erwartungen und den
Messwerten. Eigentlich dachte ich, dass ein Forum dafür da ist und nicht
damit sich einige namenlose "Schlauköpfe" profilieren. Schäm dich.
Aus dem Manual ist mir durchaus bekannt, dass die Werte in den Registern
SYSPLLCTRL und SYSAHBCLKDIV für die Takterzeugung relevant sind. Die
Clock selection war meines Erachtens auch korrekt. Seltsamerweise haben
meine Veränderungen an MSEL und PSEL nicht zu erwarteten Ergebnissen
geführt, obwohl der Debugger die entsprechenden Zeilen anstandslos
abgearbeitet hat. Erst als ich das Projekt neu angelegt habe, konnte ich
mit dem main clock spielen. Entscheidend bei der Fehlersuche war das
Herausführen vom main clock an CLKOUT.
@Jim
Ich nehme an, dass die Codeausführung tatsächlich recht langsam ist und
nun kein Weg an Disassembler und Taktezählen vorbei führt. Danke für die
Tipps, ich werde die beherzigen.
Ich kann das auf meinem LPC1347 Board nachvollziehen. Der Takt wird
schon richtig über die PLL auf 72 MHz gestellt. Nur im Code sind ja
mehrere Unterprogrammaufrufe und da hängt es sehr an der Optimierung des
Compilers. Wenn ich für die chip und board lib Optimization -o3 und -lto
einschalte, für das Projekt auch -o3 dann komme ich auf 1,12 MHz. -lto
darf beim Hauptprojekt nicht eingeschaltet sein, dann werden die lib
Aufrufe wegoptimiert und der Pin toggelt nicht mehr.
Alexander schrieb:> So wie die Antwortstellung aussieht, ist diese aber auch nicht besonders> zielführend. Kluge Sprüche klopfen kann ich auch. Abgesehen mal davon,> habe ich niemanden gebeten meinen Code zu verbessern.
Och, weder ich noch andere haben versucht deinen Code zu verbessern.
Ausserdem ist das auch nicht deiner, wie du selbt geschrieben hast. Mal
abgesehen von den 10 Zeilen.
Alexander schrieb:> Mich interessiert> nur die Ursache der Diskreptanz zwischen meinen Erwartungen und den> Messwerten.
Sorry, wie kannst du überhaupt von was Erwartungen haben was du nicht
verstehst? Oder hast du die Lib die du verwendest analysiert und
verstanden. Wenn ja, würden sich die Fragen erübrigen. Den Hinweis die
GPIO Register sebst zu beschreiben hast du ja schon erhalten. Deine
Eierei an den Optimierungen ist doch nur ein Nebenkriegsschauplatz.
Gerade wenn es auf Highspeed bei GPIOs ankommt, ist jeder Aufruf einer
Funktion aus einer Lib großer Mist. Für das Toggeln des Bits 7 im Port 0
reicht bei deinem uC folgende Zeile:
1
while(1)
2
LPC_GPIO->NOT[0]=(1<<7);
3
4
wasalsAssemblerergibt:
5
6
4A01ldrr2,=0x50002300
7
2380movsr3,#0x80
8
6013strr3,[r2]
9
E7FDb0x00000290
Dazu muss man aber das Usermanual gelesen haben. Und wenn man das hat,
kommt man nicht auf die Idee schnelles GPIO-Handling mit
Bibliotheksfunktionen zu machen.
http://www.nxp.com/documents/user_manual/UM10524.pdf
Johannes S. schrieb:> -lto> darf beim Hauptprojekt nicht eingeschaltet sein, dann werden die lib> Aufrufe wegoptimiert und der Pin toggelt nicht mehr.
Oder Dein Oszi ist zu langsam - oder der Pin selber, bei 72 MHz sieht
man das eventuell nicht mal mehr im Oszi.
Jim M. schrieb:> Oder Dein Oszi ist zu langsam - oder der Pin selber, bei 72 MHz sieht> man das eventuell nicht mal mehr im Oszi.
Nö,
mit der Schleife ohne calls wie von temp beschrieben
1
while(1)
2
LPC_GPIO_PORT->NOT[0]=(1<<7);
tickert es für mein Oszi sicht- und messbar mit ziemlich genau 12 MHz.
Das es mit den C-calls langsamer läuft ist klar und würde mich auch
nicht stören, ich lasse selten LED per Software mit 800 kHz blinken.
Und das die Linker Optimierung nicht immer funktioniert habe ich schon
öfter gehabt, vor allem auch bei Code mit Debug Infos.
Nachtrag:
und auch meine mbed Variante mit bösem C++ läuft mir mit 2,2 MHz schnell
genug:
@temp
Bittogle war nicht das Ziel, sondern nur ein Mittel zum Zweck.
Ich bezweifle nicht deine Fachkompetenz, womöglich programmierst du auch
die USB Schnittstelle selbst. An deiner arroganten Art solltest du
jedoch nicht weniger arbeiten, als ich an meinen
Mikrocontrollerunkenntnissen.
An der Optimierung herumzueiern habe ich gar nicht vor, ich denke da
hast du unbewusst auf einen Beitrag von Johannes reagiert.
Deine kurze und knappe Antwort hätte es von vornherein auf den Punkt
bringen können:
"Der Code ist einfach schlecht und wenn man Wert auf die Performance
legt, sollte man nicht auf Standardbibliotheken setzen, sondern alles
selbst programmieren. GPIO Takt ist bei LPC1347 gleich dem main clock in
Verbindung mit dem System Clock Divider. Main Clock lasst sich wiederum
an CLKOUT Pin herausführen und einfach nachmessen. Nachzulesen auf Seite
12ff UM10524."
Ich danke allen für die Hilfe. Auch dir temp, obwohl mir deine Art zu
antworten nicht besonders schmeckt. Das Problem hat sich für mich
erledigt.
auf so Provokationen solltest du hier gar nicht eingehen,
Programmiersprachen, OS, 8 oder 32 Bit µC und noch einiges sind
Religionen hier und die Diskussionen versauen dann nur die Threads. Und
gerade die selbstgekrönten Assemblergötter lauern nur auf solche Themen.
Ich habe das jedendsfalls so verstanden das es nur ein Test war und dann
die Enttäuschung das da soviel Overhead reinkommt. Aber so ein Beispiel
taugt mMn nicht zur Beurteilung der Leistung, ein paar Takte mehr oder
weniger liefern sofort grob unterschiedliche Frequenzen. Interessanter
an dem LPC1347 ist die gute Peripherie wie die vielen 32 Bit Timer und
USB incl. Ansteuerung dazu im ROM.