Ich programmiere gerade einen ATSAM Prozessor mit dem aktuellen Microchip Studio. Jetzt ist mir aufgefallen, dass die delay_us() und delay_ms() funktionen jeweils zu lang sind. der Fehler beträgt jeweils den Faktor 2,3. Ich habe schon meine Taktquelle geprüft, aber die ist korrekt. Das sehe ich anhand eines Timers und PWM. Das define CONF_CPU_FREQUENCY habe ich auch auf 48MHz gesetzt. An was könnte es noch liegen?
Matthias X. schrieb: > An was könnte es noch liegen? Das könnte daran liegen, dass der Prozessor mit einer anderen Frequenz als den von dir eingegebenen 48MHz läuft.
Matthias X. schrieb: > einen ATSAM Prozessor Und der genaue Typ ist geheim? Erstmal ein nachvollziehbares Minimal-Programm hier posten. Am besten ein ganzes Projekt, damit keine Unwägbarkeiten drin stecken können.
Matthias X. schrieb: > dass die delay_us() und delay_ms() funktionen jeweils zu lang sind. der Fehler beträgt jeweils den Faktor 2,3. Rufst Du die auch mit Werten von 100 oder mehr auf? Sonst wirken sich Nebeneffekte stärker aus. Also delay_us(1000) wartet 2300µs, während delay_us(100) 230 wartet? Das wären also ~ 20 MHz statt 48 MHz. Manchmal gibt es unterschiedliche Quellen (Clock-Source)s für unterschiedliche Aufgaben.
Rainer W. schrieb: > Das könnte daran liegen, dass der Prozessor mit einer anderen Frequenz > als den von dir eingegebenen 48MHz läuft. Matthias X. schrieb: > Ich habe schon meine Taktquelle geprüft, aber die ist korrekt. Das sehe > ich anhand eines Timers und PWM. Das define CONF_CPU_FREQUENCY habe ich > auch auf 48MHz gesetzt. Die Aussage könnte allerdings auch so interpretiert werden: "Einen Fehler bei mir kann ich ausschliessen"
Matthias X. schrieb: > Ich habe schon meine Taktquelle geprüft, aber die ist korrekt. Es kann an den Optinierungseinstellungen liegen.
Danke für die Antworten bisher. Es handelt sich um einen ATSAM51J20A. Ich nutze für die gesamte Peripherie und die CPU jeweils die GLCK1 als Quelle. Diese wird so erzeugt: 16MHZ Quartz->FDPLL0 (durch 6)(mal 18) = 48MHz GLCK->CPU Wobei ich gerade gesehen habe, dass die FDPLL folgende Bedinungen hat: 96 MHz to 200 MHz output frequency from a 32 kHz to 3.2 MHz reference clock Ich gehe zwar mit (16/6)MHz in die PPL. Aber ich will ja nur 48MHz am Ausgang haben. Eventuell läuft diese dann nicht stabil? Komisch, dass trotzdem meine ganzen Timer korrekt mit 48MHz laufen, aber die CPU nicht? Ich werde das prüfen. Mein zweiter Ansatz: Intern werden die Zyklenschleifen berechnet für die Delayroutine. Die eigentliche Delayrouting besteht nur aus diesen beiden ASM-Befehlen: 000021D8 subs r1, #1 000021DA bhi #-6 Wieviele Takte sollten die benötigen? Wenn ich das weis, dann kann ich prüfen ob die Berechnung der Schleifendurchgänge zu lange dauert oder die Taktfrequenz falsch ist.
> Wobei ich gerade gesehen habe, dass die FDPLL folgende Bedinungen hat: > 96 MHz to 200 MHz output frequency from a 32 kHz to 3.2 MHz reference > clock > Komisch, dass trotzdem meine ganzen Timer korrekt mit 48MHz laufen, aber > die CPU nicht? Core (CPU) und Peripherals können mit unterschiedlichen Takten laufen. https://next-hack.com/index.php/2020/02/12/overclocking-an-arduino-zero-or-any-atsamd21/
:
Bearbeitet durch User
Ich verwendet sowohl niedrige, als auch höhere Zahlen, z.B. delay_ms(10); delay_us(1000); ... Eigentlich sollte alles an der selben Taktquelle hängen. Siehe Bild. Es ist nur GLCK0 eingerichtet, diese bedient ja auch die CPU. Die gesamte Peropherie greift auf diese GLCK0 zu. Edit 1: um die PPL auszuschließen habe ich die GLCK auf die interne 48MHz Taktquelle geschalten. Das Verhalten bleibt aber gleich. Edit 2: Bei Delay_ms(10) will er die oberen ASM Befehle 160000 mal durchlaufen. Das wären korrekt wenn die Schleife 3 Takte benötigt. Also entweder sie benötigt in Wirklichkeit 7 Takte, oder es stimmt weiterhin etwas mit der Frequenz nicht. Wie kann ich die benötigten Takte prüfen? Könnte ein Befehl länger dauern wegen einer Pipeline, Compilereinstellungen, o.ä.?
Bruno V. schrieb: > Also delay_us(1000) wartet 2300µs, während delay_us(100) 230 wartet? Korrekt Wastl schrieb: > Die Aussage könnte allerdings auch so interpretiert werden: > "Einen Fehler bei mir kann ich ausschliessen" Das wollte ich damit nicht sagen. Ich wollte nur zum Ausdruck bringen, dass ich schon in diese Richtung gedacht habe, es geprüft habe und die Taktfrequent "eigentlich" stimmen sollte. Wie gesagt, eigentlich;) Arduino F. schrieb: > Es kann an den Optinierungseinstellungen liegen. Das war auch meine erste Vermutung. Ist aber bei DEBUG und RELEASE gleich. Wie gesagt, es sind nur die beiden genannten ASM Zeilen und die sind in beiden Einstellungen gleich.
Matthias X. schrieb: > An was könnte es noch liegen? _delay()-Zeugs basiert darauf, eine berechnete Zahl Taktzyklen sinnlos zu verheizen, indem halt die entsprechende Zahl Instruktionen ausgeführt werden. So weit, so gut. Während der Laufzeit diese Instruktionen sind Interrupts und DMA aber nicht gesperrt. Die können also zur Laufzeit der _delay-Routine weitere Laufzeit hinzufügen. Für Interrupts ist das natürlich sofort klar: die arbeiten ja schließlich ebenfalls Instruktionen ab. Bei DMA ist das vielleicht nicht sofort klar, aber die kann u.U. auch (direkt oder über Umwege) reingrätschen. Die Stelle zur Beeinflussung der Delay-Routine ist hier die Busbandbreite. Nur dann, wenn es einen L1-Codecache gibt und dieser auch aktiviert ist, kann man mit einiger Sicherheit davon ausgehen, dass zumindest DMA den Delay nicht störend verlängert. Die Interrupts aber bleiben. Deren Einfluß wird mit aktivem Code-Cache sogar größer, weil natürlich bei jeder ISR-Instanz dieser Cache gecleart und neu geladen werden muss.
Ups, ich meinte natürlich PLL. (Oder wie Atmel es genannt hat) @ Ob S. Danke. Aber es werden weder Interrupts, noch DMA verwendet. Ich werde als nächstes mal versuchen einen Timer mit CPU-Takt zu starten um zu prüfen wie wieviele Takte die ASM Befehle benötigen. Im zweiten Schritt werde ich mein Programm auf das Minimum reduzieren, schauen ob das verhalten noch so ist und anschließend hier veröffentlichen.
Matthias X. schrieb: > @ Ob S. > Danke. Aber es werden weder Interrupts, noch DMA verwendet. Warum nicht? Damit könnte man das sinnlose Delay wahrscheinlich komplett vermeiden...
Auf Cortex-M benutzt man für solche Delays eigentlich den Systick Counter, den jeder Cortex-M hat. Wenn der schon verwendet wird, dann irgend einen anderen Hardwaretimer. Instruktionen auf einem Cortex M4 zählen zu wollen ist hoffnungslos, der hat eine Pipeline und muss auch ab und an mal auf die Busports warten. Das funktioniert nicht so simpel wie bei einem AVR8 oder PIC.
Matthias X. schrieb: > Ups, ich meinte natürlich PLL. (Oder wie Atmel es genannt hat) Mit Atmel hat das nichts zu tun, genauso wenig wie "clock" eine Wortschöpfung von Atmel ist ;-) Als die Bezeichnung eingeführt wurde, hat an Atmel noch keiner gedacht. Die wurden erst 64 Jahre später aus der Taufe gehoben. https://en.wikipedia.org/wiki/Phase-locked_loop
:
Bearbeitet durch User
Wastl schrieb: > Rainer W. schrieb: >> Mit Atmel hat das nichts zu tun, ...... > > Ach! Echt jetzt? Ja, ganz echt ...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.