Uhl schrieb:
> Das war mir schon recht neu.
Steht aber im Datenblatt. ;-)
1 | 13.7 Clocks after Reset
|
2 |
|
3 | On any reset the synchronous clocks start to their initial state:
|
4 | * OSC8M is enabled and divided by 8
|
5 | * GCLK_MAIN uses OSC8M as source
|
6 | * CPU and BUS clocks are undivided
|
> Bei den AVRs habe ich einfach
> einmalig die Fuses gesetzt und dann war das damit erledigt.
Weil sie den Takt nicht zur Laufzeit umschalten konnten (war ein
Problem mit deren Flash-Implementierung). Bei den Xmegas ging das
auch zur Laufzeit, gar nicht so unähnlich zu den SAMDs.
> Das ist auch das größere Problem. Die ARMs sind doch schon recht
> verschieden gegenüber den AVRs.
An den Xmegas sind sie etwas näher dran als an den alten AVRs, aber
komplexer sind sie natürlich trotzdem.
> Ich finde für den ARM (Atmel) überhaupt keine einleuchtenden und gut
> strukturierten Anleitungen.
Für die älteren findet man wenigstens noch Appnotes (SAM3/4), aber
deren Peripherals wiederum wirken wie aus der Zeit der Dinosaurier:
schwerfällig, mit Features überfrachtet, umständlich.
Dann irgendwann hat sich Atmel drauf versteift, allen ihr ***es ASF
aufzudrängeln, und nun sind die entsprechenden „Appnotes“ oft nur
noch ein Wiederkäuen der ASF-API-Dokumentation. :-((
> Ich kenne die Programmierung von ARMs derzeit nur auf dem Raspberry Pi.
Das ist aber auch 'ne ganz andere Nummer als so ein Cortex-M0+.
Wenn du mit den SAMDs weitermachen willst, solltest du als erstes
versuchen, das ganze Taktsystem zu verstehen. Zentrales Element
sind dabei die „generic clock generators“ (GCLK), über die läuft das
alles. Die kann man auf verschiedene Weise an Taktquellen binden,
miteinander verketten, die Ausgänge für Timer oder anderweitig als
Takt benutzen.
Das Verständnis dabei etwas verkomplizierend ist, dass es davon acht
Stück gibt. Man hat diesen aber nicht acht komplette Registersätze
spendiert, sondern die GENDIV- und GENCTRL-Register enthalten ein
Feld, welches den Generator benennt, für den die getroffenen
Einstellungen gelten sollen. Dadurch muss man diese beiden Register
immer komplett mit allen Bits auf einmal beschreiben.
Bei mir sieht die Initialisierung auf den extern angeschlossenen
16-MHz-Quarz sowie die Aktivierung des 32-kHz-Quarzes derzeit so aus:
1 | #define WAIT_GCLK_SYNC() while(GCLK->STATUS.bit.SYNCBUSY)
|
2 | #define WAIT_XOSC32K_READY() while((SYSCTRL->PCLKSR.bit.XOSC32KRDY) == 0 )
|
3 |
|
4 | //…
|
5 | SYSCTRL->XOSC32K.bit.STARTUP = 6; /* ≈ 1 s */
|
6 | SYSCTRL->XOSC32K.bit.XTALEN = 1; /* this is a crystal */
|
7 | /* Auto amplitude control – see errata, does not work */
|
8 | SYSCTRL->XOSC32K.bit.AAMPEN = false;
|
9 | /* 32KHz output Enable/Disable */
|
10 | SYSCTRL->XOSC32K.bit.EN32K = true;
|
11 | SYSCTRL->XOSC32K.bit.ONDEMAND = false;
|
12 | SYSCTRL->XOSC32K.bit.RUNSTDBY = true;
|
13 |
|
14 | SYSCTRL->XOSC32K.bit.ENABLE = true;
|
15 |
|
16 | /* Check the XOSC32K Clock source is ready to use */
|
17 | WAIT_XOSC32K_READY();
|
18 |
|
19 | /* Generic clock generator 1: use XOSC32K without prescaler */
|
20 | GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(0);
|
21 | WAIT_GCLK_SYNC();
|
22 | GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_XOSC32K |
|
23 | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE;
|
24 | WAIT_GCLK_SYNC();
|
25 |
|
26 | /* Enable RTC clock as GCLK[1] */
|
27 | GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(1) | GCLK_CLKCTRL_ID_2;
|
28 | PORT->Group[1].PMUX[23 / 2].bit.PMUXO = PORT_PMUX_PMUXE_H_Val;
|
29 | PORT->Group[1].PINCFG[23].bit.PMUXEN = 1;
|
Die Initialisierung der DFLL habe ich im Moment auch noch nicht
probiert. Mit dieser kann man aus dem 32-kHz-Takt (aber nur aus
diesem!) den zentralen Takt von 48 MHz erzeugen. Aber Achtung,
der Flash ist nicht so schnell! Wenn man die CPU mit 48 MHz
werkeln lassen will, muss man dem Flash Waitstates aufbrummen.
Wie viele, hängt noch von der Betriebsspannung ab. Damit ist ein
CPU-Takt von 48 MHz eigentlich nur dann interessant, wenn man
(zumindest teilweise) Code aus dem RAM ausführen möchte (sowas ging
beim AVR nicht, beim ARM geht das). Hat man das nicht vor, kann
man die Taktfrequenz lieber so limitieren, dass der Flash ohne
Waitstates betrieben werden kann, dann spart man Energie.
An was man sich beim ARM (nicht nur von Atmel) auch gewöhnen muss
ist, dass die peripheren Takte standardmäßig größtenteils nach dem
Reset abgeschaltet sind (damit die Baugruppen keinen Strom brauchen).
Nur das nötigste ist initial eingeschaltet, damit man die Kiste
erstmal in Schwung bekommen kann.