Gibt es in den M0 Cortexen einen Standard Systemtimer. Ich brauche die Zeit in Mikrosekunden vom Systemstart an.
chris_ schrieb: > Gibt es in den M0 Cortexen einen Standard Systemtimer. > Ich brauche die Zeit in Mikrosekunden vom Systemstart an. Stichwort: Systick. Den kann man so einstellen dass er jede µS einen Interrupt auslöst(SystemCoreClock/1000000). Im SysTick Interrupt kannst du dann eine Variable hochzählen und hast deine gewünschte Zeit.
Danke, habe ich gefunden: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0179b/ar01s02s08.html Seltsamerweise ist das nur ein 24Bit Timer. Wenn ich es richtig verstehe, sind die Adressen über alle M0 fest vergeben: SysTick Control and Status : 0xE000E010 Gibt es irgendwo Beispiel für die Konfiguration?
chris_ schrieb: > Wenn ich es richtig verstehe, sind die Adressen über alle M0 fest > vergeben: > SysTick Control and Status : 0xE000E010 Da es sich um ein Feature des Cores handelt ist das anzunehmen. Aber wer arbeitet denn mit der Adresse? Die sind alle per CMSIS definiert. > Gibt es irgendwo Beispiel für die Konfiguration? Bei Google massenhaft. Auch das Datenblatt dürfte sich darüber nicht ausschweigen. Im Prinzip setzt du nur den Compare-Wert für den Interrupt und die ClockSource.
:
Bearbeitet durch User
chris_ schrieb: > Gibt es irgendwo Beispiel für die Konfiguration? Was willst du bei den wenigen Registern groß konfigurieren? Ansonsten findest Du die Beispiele typischerweise bei den Prozessorherstellern, die diesen Cortex implementieren.
>Ansonsten findest Du die Beispiele typischerweise bei den >Prozessorherstellern, die diesen Cortex implementieren. Ja, das ist genau das Problem: Meine Hauptbeschäftigung ist momentan das Kämpfen mit den Tools. Ich verwende gerade ASF und vorher AtmelSTART, beide sind scheinbar nicht kompatibel. Mittlerweile habe ich das Modul in der ASF Konfiguration gefunden: ASF-Modul: Delay routines ( service ) systick
Wenn ich mir die Routinen dort anschaue
1 | void delay_init(void) |
2 | {
|
3 | cycles_per_ms = system_gclk_gen_get_hz(0); |
4 | cycles_per_ms /= 1000; |
5 | cycles_per_us = cycles_per_ms / 1000; |
6 | |
7 | SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk; |
8 | }
|
9 | |
10 | /**
|
11 | * \brief Delay loop to delay at least n number of microseconds
|
12 | *
|
13 | * \param n Number of microseconds to wait
|
14 | */
|
15 | void delay_cycles_us( |
16 | uint32_t n) |
17 | {
|
18 | while (n--) { |
19 | /* Devide up to blocks of 10u */
|
20 | delay_cycles(cycles_per_us); |
21 | }
|
22 | }
|
23 | |
24 | static inline void delay_cycles( |
25 | const uint32_t n) |
26 | {
|
27 | if (n > 0) { |
28 | SysTick->LOAD = n; |
29 | SysTick->VAL = 0; |
30 | |
31 | while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)) { |
32 | };
|
33 | }
|
34 | }
|
dann sehe ich, dass der Systemcounter beim Aufruf des Delays auf Null gesetzt wird. Mal ehrlich: wie bescheuert ist das denn? Der Systemcounter soll durchlaufen und nicht auf Null gesetzt werden. So viel zu fertigen Libraries.
chris_ schrieb: > Mal ehrlich: wie bescheuert ist das denn? Der Systemcounter soll > durchlaufen und nicht auf Null gesetzt werden. Das könnte daran liegen, daß das eine Delay-Routine und kein Systemcounter ist. chris_ schrieb: > So viel zu fertigen Libraries. Man sollte auch die richtigen raussuchen.
Won K. schrieb: > Das könnte daran liegen, daß das eine Delay-Routine und kein > Systemcounter ist. Systick ist aber per definitionem der Systemcounter. Den setzt man nicht für ein blödes Delay einfach auf 0. Mein Rat an chris_: ASF ist (meine Meinung) ein aufgeblähter Sack voller Makros und Funktionen. Da gibt es Funktionen, die gerade mal irgendein Bit in einem Steuerregister setzen oder löschen. Ansonsten ist das bloß obfuscation, was da betrieben wird. Man kann den ASF-Code hin und wieder nehmen um mal reinzugucken, wie sie dieses oder jenes Problem lösen. Man kann auch ein paar Dinge, die im Windschatten des ASF mitgeschleift werden (wie USB-Stacks oder die FAT-FS Implementierung, die letztlich die von elmchan ist), gut und gern in seinen Code integrieren. Ansonsten kommst du aber besser, wenn du den Controller einfach vom Datenblatt her verstehen lernst. Ist ein bisschen komplexer als ein AVR, aber nicht unendlich komplex. Fang mit der blinkenden LED an, also mit dem Beherrschen der Parallelports. Wenn du das geschafft hast, schau dir an, wie man die Systemtakte einstellt. Das ist bei SAMDxx mit seinen generic clocks erstmal ein Stück Arbeit, aber wenn man das verstanden hat, ist man ein ganzes Stück weiter. Irgendwo habe ich hier auch schon mal Codeschnipsel von mir gepostet, als ich mich durch den SAMD20 gewühlt habe. Kannst du als Anfang nehmen.
Jörg W. schrieb: > Ansonsten kommst du aber besser, wenn du den Controller einfach vom > Datenblatt her verstehen lernst. Endlich mal ein Satz, bei dem ich dir aus VOLLSTEM HERZEN zustimme. Den Beitrag von cyblord wegen CMSIS halte ich hingegen für weniger sinnvoll. Das CMSIS-Geprassel ist zwar nicht ganz so hirnrissig wie die ST-Lib, aber immer noch ein eigentlich unnützer Sack voll Obfuscation. So.
1 | /* SCS_BA = 0xE000E000 */
|
2 | /* Sysem Tick */
|
3 | #define SYST_CSR (*((volatile unsigned long *) (SCS_BA+0x00000010)))
|
4 | #define SYST_RVR (*((volatile unsigned long *) (SCS_BA+0x00000014)))
|
5 | #define SYST_CVR (*((volatile unsigned long *) (SCS_BA+0x00000018)))
|
6 | |
7 | /* initialisiert den SysTick mit 10 ms Tickzeit */
|
8 | void InitSystick (void) |
9 | { long L; |
10 | L = Quarzfrequenz / 100; // sollte 10 ms ergeben |
11 | SYST_CVR = SYST_RVR = L; |
12 | System_Tick = Ticks = Stunden = Minuten = Sekunden = 0; |
13 | SYST_CSR = ENA_TICK_INT | ENA_SYSTICK; |
14 | }
|
15 | |
16 | /******* Interrupt vom SysTick-Counter *************/
|
17 | |
18 | __irq void SysTick_Handler (void) |
19 | { SYST_CSR &= ~(COUNTFLAG); |
20 | ++System_Tick; |
21 | ++Ticks; /* Uhrzeit weiterstellen */ |
22 | if (Ticks >= 100) |
23 | { ++Sekunden; |
24 | if (Sekunden>59) |
25 | { Sekunden = 0; |
26 | ++Minuten; |
27 | if (Minuten>59) |
28 | { Minuten = 0; |
29 | ++Stunden; |
30 | }
|
31 | }
|
32 | Ticks = 0; |
33 | }
|
34 | }
|
Da der Systick Teil der CPU-Konstruktion von ARM ist und eben keine drangebeppte Peripherie eines Chipherstellers, sollte das auch so wie dargestellt klappen (Beispiel stammt aus ner Nuvoton-M051-Kiste). Aber: Der Systick ist m.W. ein Downcounter, dessen tieferer Zweck darin besteht, Interrupts für Uhr/RTOS auszulösen. Er ist kein Zähler für Mikrosekunden. Wer sowas brauchen will, sollte sich was anderes ausdenken, z.B. einen Timer. W.S.
:
Bearbeitet durch Moderator
chris_ schrieb: > Ich brauche die Zeit in Mikrosekunden vom Systemstart an. Manche Cortex-M haben ein Debug Modul namens DWT (Data Watchpoint and Trace). Da gibt's das Cycle Count Register DWT_CYCCNT (0xE0001004), das die CPU-Zyklen zählt. Perfekt ist es auch nicht, weil man es einschalten muss, aber immer noch besser als der SysTick. siehe: ARM® v7-M Architecture Reference Manual
Jörg Wunsch >Mein Rat an chris_: ASF ist (meine Meinung) ein aufgeblähter Sack >voller Makros und Funktionen. Da gibt es Funktionen, die gerade mal >irgendein Bit in einem Steuerregister setzen oder löschen. Ansonsten >ist das bloß obfuscation, was da betrieben wird. Ja, ich komme immer mehr dazu, Deinem Rat zu folgen. while(1) { gpio_set_pin_level(LED, 0); gpio_set_pin_level(LED, 1); } Ergibt 2.5 us HIGH 1.86 us LOW auf einem 48Mhz ATSAMD21G18. Das sind ja ähnlich schlechte Zeiten wie bei der ARDUINO-Funktion digitalWrite. Mache ich etwas falsch, oder ist die ASF so langsam?
chris_ schrieb: > Mache ich etwas falsch, oder ist die ASF so langsam? Bei welchem Takt ist das denn? Default clock ist (wimre) 2 MHz. Dafür wäre es so schlecht nicht, was du da hast. Ansonsten: schau doch einfach mal den generierten Assemblercode an.
>Bei welchem Takt ist das denn? Jetzt wo Du es sagst ... Ich habe das System mit AtmelSTART hier konfiguriert: Beitrag "Re: Arduino Zero mit ArduinoStart Konfigurieren" Die "Clock-Distribution" ist mir da nicht ganz klar. Ich glaube, die MCU läuft mit 8MHz. ( Wer's ausprobieren will: einfach die angegebene Konfiguration in den WebBrowser laden. Es gibt dann einen Tab, in dem die Clock-Verteilung angezeigt wird )
chris_ schrieb: > Die "Clock-Distribution" ist mir da nicht ganz klar. Dann zeig doch mal den Sourcecode, mit dem der Takt konfiguriert wird.
Ich kann Dir die Konfiguration zeigen ... Da steht 8Mhz, tatsächlich. Die Frage ist: wie stelle ich sie um?
chris_ schrieb: > Ich kann Dir die Konfiguration zeigen ... Dein Prozessor wird sicher keine bunten Bildchen ausführen, ich möchte schon den Sourcecode dafür sehen. ;-) p.s.: Für 8 MHz wären die Werte nicht so prickelnd, aber es würde mich nicht wundern, wenn das dann der Overhead von ASF ist. Ein ARM ist kein AVR, der innerhalb eines CPU/IO-Taktes ein Pin setzen oder löschen kann, aber ein wenig schneller könnte er schon sein.
:
Bearbeitet durch Moderator
Jörg W. schrieb: > Ein ARM ist kein AVR, der innerhalb eines CPU/IO-Taktes ein Pin > setzen oder löschen kann Selbstverständlich gibt es ARM die das können z.B. ein LPC800 mit 30 MHz verwendet die CPU Clock direkt als Peripheral Clock und hat bit-addressierbare GPIO-Register (kein Bit-banding). Damit kommen auch 30 MHz raus (kein sauberes Rechteck mehr allerdings) MOVS R0, #0 MOVS R1, #1 loop STRB R0, [PIN0BASE, #0] ; clear P0.0 STRB R1, [PIN0BASE, #0] ; set P0.0 B loop Nebenbei bemerkt, ich habe hier einen 72 MHz 8051 EFM8LB, der kann Pins mit 72 MHz toggeln. Wenn man das also braucht ...
Lothar schrieb: > Selbstverständlich gibt es ARM die das können z.B. ein LPC800 mit 30 MHz > verwendet die CPU Clock direkt als Peripheral Clock und hat Wenn ich mir dein Beispiel ansehe, sollte das mit dem SAMDxx auch so (ähnlich) gehen. Auch er kann CPU und Peripheral Clock bis maximal 48 MHz synchron takten. > Damit kommen auch > 30 MHz raus (kein sauberes Rechteck mehr allerdings) Glaube ich dir nicht. :-) Mit 30 MHz CPU-Takt kannst du in Software maximal 15 MHz am Ausgang erzeugen, da du zwei Befehle für eine volle Signalperiode brauchst. ;-) (Das ist noch ohne den Schleifenbefehl.) SAMDxx hat auch ein Pin-Toggle-Register, damit könnte man sogar einen symmetrischen Rechteck bauen (ein store und ein branch). Hat der TE aber nicht benutzt.
>Dein Prozessor wird sicher keine bunten Bildchen ausführen, ich >möchte schon den Sourcecode dafür sehen. ;-) Hallo Jörg, eigentlich bin ich ein Freund der bunten Bildchen, oder wie einer der Softwarearchitekten mal sagte: "Ein Bild sagt mehr als tausend Worte" Man kann direkt dieses File nehmen http://www.mikrocontroller.net/attachment/285487/ArduinoZero_ADC_SERIAL_EXAMPLE.atstart Dann in AtmelSTART laden ( => load project links unten ) http://start.atmel.com/ Deshalb ist es ja mehr als ein Bild. Man kann direkt konfigurieren. Scheinbar per trag&drop. Ich schaffe es, damit den 8MHz internal Clock mit der PLL zu verbinden. Aber das Ganze sieht dann irgendwie nach "zirkulärem" Kurzschluss aus.
chris_ schrieb: > eigentlich bin ich ein Freund der bunten Bildchen Ich nicht, weil die CPU eben keine Bilder ausführt. Das Ding ist doch nur ASF 2.0. Alles, was hinter den Bildchen passiert, sind wieder blackboxes. Da merkst du beispielsweise nicht, dass der dort benutzte delay-Kram dir den SysTick-Timer zerschießt (für jedes delay() wird der neu auf 0 gesetzt, was völlig tödlich ist, wenn du den noch anderweitig nehmen willst). Wie ich oben schon schrieb: das ist kein AVR mehr, aber das ist auch kein ARMv11 oder sowas. Die Details der Hardware kann man schon noch verstehen bei diesen kleinen ARMs. Bei den größeren benutzt man dann ein Betriebssystem und verlässt sich drauf, dass die OS-Hersteller ihre Arbeit ordentlich getan haben. Dann benutzt man aber die Hardware nicht mehr direkt, sondern nur noch über das API des OSes. Klar kann man nun diesen Atmel-START-Kram als „Mini-OS“ betrachten, aber ehrlich: dann kannst du lieber Arduino als API nehmen, das ist zumindest inzwischen hinreichend gut in der Praxis erprobt.
Jörg W. schrieb: > Mit 30 MHz CPU-Takt kannst du in Software maximal 15 MHz am Ausgang Hast recht. > SAMDxx hat auch ein Pin-Toggle-Register Hat der LPC800 auch, das ist aber nicht schneller weil z.B. für P0.4: MOVS R0, #10000B loop STR R0, [NOT0] B loop Aber wenn wir schon bei Bildern sind, mach doch mal Messungen am SAMDxx, habe gehört dort soll der Zugriff auf Pin-Toggle-Register zwei Zyklen dauern
Lothar schrieb: > Aber wenn wir schon bei Bildern sind, mach doch mal Messungen am SAMDxx, > habe gehört dort soll der Zugriff auf Pin-Toggle-Register zwei Zyklen > dauern Geht zumindest erstmal nicht aus dem Datenblatt hervor. Was mir beim Lesen auffällt ist, dass man DIR, IN und OUT auch direkt über den IOBUS der CPU lesen oder schreiben kann (braucht aber eine andere IO-Adresse). Das wäre allerdings nur dann schneller, wenn man den CLK_PORT_APB langsamer konfiguriert hat als den CPU-Takt. Muss mal gucken, wenn ich meinen SAMD20 mal wieder in den Fingern habe, kann ich das mal testen.
Jörg W. schrieb: > Das wäre allerdings nur dann schneller, wenn man den CLK_PORT_APB > langsamer konfiguriert hat als den CPU-Takt Haben die SAMDxx eine AHB-Lite/APB Bridge? Die braucht dann mehr als Null Zeit
Kannst doch selbst ins Datenblatt schauen. Da steht “AHB-APB BRIDGE”. Heißt das, dass beim Zugriff darüber Waitstates eingeschoben werden? Inwiefern das Teil eine zusätzliche Latenz einbringt, wäre ja nicht so tragisch.
Jörg W. schrieb: > Heißt das, dass beim Zugriff darüber Waitstates eingeschoben werden? Das nicht aber dann ist es schwer erklärbar wie die SAMDxx mit CPU-Takt/2 toggeln können sollen: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0226a/I144880.html
>> Mit 30 MHz CPU-Takt kannst du in Software maximal 15 MHz am Ausgang >Hast recht. >> SAMDxx hat auch ein Pin-Toggle-Register >Hat der LPC800 auch, das ist aber nicht schneller weil z.B. für P0.4: > > MOVS R0, #10000B >loop > STR R0, [NOT0] % 1 cycle ? > B loop % 2 cycles ? Wie das? Loop unrolling?
Hier die neue Konfiguration: http://www.mikrocontroller.net/attachment/286592/FastCpuClockSetup_48MHz.atzip Rein optisch sieht das Ganze in AtmelSTART etwas verworren aus: interner 8MHz Clock => Clock Generator 1 ==> PLL 48MHz ==> Clock-Generator 0 ==> CPU-Clock Warum das Ganze so kompliziert sein muss, weiß ich nicht.
Die Zeiten für das Togglen sind dann Tlow: 628us Thigh: 832us D.h die toggle-Frequenz liegt bei ca. 685kHz.
chris_ schrieb: > Hier die neue Konfiguration: > http://www.mikrocontroller.net/attachment/286592/FastCpuClockSetup_48MHz.atzip > > Rein optisch sieht das Ganze in AtmelSTART etwas verworren aus: > > interner 8MHz Clock => Clock Generator 1 ==> PLL 48MHz ==> > Clock-Generator 0 ==> CPU-Clock > > Warum das Ganze so kompliziert sein muss, weiß ich nicht. Ja da lob ich mir die grafische Darstellung im CubeMX. Da ist der Clocktree auch als Tree dargestellt und nebenbei praktisch genau so wie im Datenblatt. Absolut übersichtliche Sache.
Cyblord -. schrieb: > Da ist der Clocktree auch als Tree dargestellt und nebenbei praktisch > genau so wie im Datenblatt. Wie willst du etwas, was potenziell Rückführungen hat (wie im Bild zu erkennen), als Baum darstellen? Hast du schon mal Bäume gesehen, die rückwärts wieder in sich hinein wachsen? Das Diagramm ist so verkehrt nicht, allerdings helfen einem eben die bunten Bildchen nicht darüber hinweg, wenn man die Grundsätze dieser generischen Taktgeneratoren (GCLK) nicht verstanden hat. Nun, zumindest warnen sie einen offensichtlich sogar vor Missgriffen, wie eben völlig übertakteten PLLs hier. Man muss dann nur die Warnungen auch noch beherzigen.
>Ja da lob ich mir die grafische Darstellung im CubeMX. Hört sich gut an. Ich kenne CubeMX nicht, habe aber gerade mal gesucht: STM32CubeMX: STM32Cube initialization code generator Naja, für STM32. Ich habe leider einen SAMD20.
> Nun, zumindest warnen sie einen offensichtlich sogar vor Missgriffen, > wie eben völlig übertakteten PLLs hier. Das soll ja der große Vorteil dieser Konfigurationstools sein: Wenn sie geschickt gemacht sind, bewahren sie einem vor falscher Konfiguration und sorgen für eine gute Übersicht. Ich bin ja sowieso der Meinung, dass die wesentliche Arbeit in der Informatik der Umgang mit schlecht gemachter Software oder Tools ist. Da hat sich in den letzten 3 Jahrzehnten nichts geändert. Wie viele hundert Stunden habe ich schon mit der Konfiguration irgendwelcher Prozessorregister zugebracht? Ich weiß es nicht. Was ich aber weiß: ich bin es leid.
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.