Forum: Mikrocontroller und Digitale Elektronik ARM Cortex M0 system timer


von chris_ (Gast)


Lesenswert?

Gibt es in den M0 Cortexen einen Standard Systemtimer.
Ich brauche die Zeit in Mikrosekunden vom Systemstart an.

von Cyblord -. (cyblord)


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

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?

von Cyblord -. (cyblord)


Lesenswert?

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
von Steffen R. (steffen_rose)


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

>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

von chris_ (Gast)


Lesenswert?

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.

von Won K. (Firma: Outside the Asylum) (the_sane)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von W.S. (Gast)


Lesenswert?

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
von eagle user (Gast)


Lesenswert?

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

von chris_ (Gast)


Lesenswert?

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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

>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 )

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

chris_ schrieb:
> Die "Clock-Distribution" ist mir da nicht ganz klar.

Dann zeig doch mal den Sourcecode, mit dem der Takt konfiguriert
wird.

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

Ich kann Dir die Konfiguration zeigen ...
Da steht 8Mhz, tatsächlich.
Die Frage ist: wie stelle ich sie um?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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
von Lothar (Gast)


Lesenswert?

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 ...

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

>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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Lothar (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Lothar (Gast)


Lesenswert?

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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von Lothar (Gast)


Lesenswert?

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

von chris_ (Gast)


Lesenswert?

>> 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?

von chris_ (Gast)


Angehängte Dateien:

Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

Die Zeiten für das Togglen sind dann

Tlow: 628us
Thigh: 832us

D.h die toggle-Frequenz liegt bei ca. 685kHz.

von Cyblord -. (cyblord)


Lesenswert?

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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

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.

von chris_ (Gast)


Lesenswert?

>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.

von chris_ (Gast)


Lesenswert?

> 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
Noch kein Account? Hier anmelden.