ARM SAMC20 externen Quarz erkennen

Gast #6875179
Lesenswert?

Hallo,
hat eventuell schon mal jemand bei dem SAMC20, oder natürlich auch gerne 
bei einem ähnlichen Derivat, wärend der Laufzeit versucht zu erkennen, 
ob ein externer Quarz vorhanden ist?

Ich stelle es mir wie folgt vor:
- Reset/Power on
- der interne Takt ist ausgewählt
- Konfiguration und Start des "External Multipurpose Crystal Oscillator"
- Warte darauf, dass der externe Takt fertig ist
- Wenn die "Clock Failure Detection" angesprochen hat, arbeite mit dem 
internen Takt, ansonsten mit dem externen

Könnte das so klappen?

Ich habe hauptsächlich probleme mit dem Warten; das XOSCRDY-Bit war 
trotz fehlendem Quarz gesetzt.

Über sachdienliche Hinweise würde ich mich sehr freuen.

Gruß
Simon
Gast #6875291
Lesenswert?

Simon schrieb:
> Ich habe hauptsächlich probleme mit dem Warten; das XOSCRDY-Bit war
> trotz fehlendem Quarz gesetzt.
???
Ich kenne nur den D21.
Aber dass das XOSCRDY-Bit gesetzt ist, ist sehr verwunderlich.
Funktioniert denn die Oszillator-Umschaltung auf XOSC?
Prüfe das mal nach.
Evtl. könntest du - mit internem Takt - XOSC auf einen Zähler geben und 
so die ungefähre XOSC-Frequenz bestimmen. Wenn kein Quarz, dann keine 
oder völlig falsche Frequenz.
Gast #6875375
Lesenswert?

Elektrolurch schrieb:
> Evtl. könntest du - mit internem Takt - XOSC auf einen Zähler geben und
> so die ungefähre XOSC-Frequenz bestimmen. Wenn kein Quarz, dann keine
> oder völlig falsche Frequenz.

Herzlichen Dank für den Hinweis, vielleicht werde ich das so machen.

Ich habe es noch einmal probiert, leider wird das XOSCRDY-Bit immer 
gesetzt.

Der externe Takt wird auch nur für die Timer etc. genutzt, der Kern 
läuft weiter mit dem internen Takt.
Ich konnte die genutzten Timer trotz des fehlenden Quarzes mittels des 
GCLK->GENCTRL[2] betreiben, die Frequenz scheint nur nicht zu stimmen.

folgendendes funktioniert jetzt, zumindest wenn kein Quarz bestückt ist.
1
static void clock_init()
2
{
3
  bool xosc_fail;
4
  OSCCTRL->XOSCCTRL.reg = OSCCTRL_XOSCCTRL_STARTUP(0xC) | OSCCTRL_XOSCCTRL_AMPGC | OSCCTRL_XOSCCTRL_GAIN(0x4) | OSCCTRL_XOSCCTRL_XTALEN | OSCCTRL_XOSCCTRL_ENABLE | OSCCTRL_XOSCCTRL_CFDEN;
5
  while (!(OSCCTRL->STATUS.reg & OSCCTRL_STATUS_XOSCRDY)){};
6
  if (OSCCTRL->STATUS.reg & OSCCTRL_STATUS_XOSCFAIL)
7
  {
8
    xosc_fail = true;
9
  }
10
  else
11
  {
12
    xosc_fail = false;
13
  }
14

15
  OSCCTRL->OSC48MDIV.reg = OSCCTRL_OSC48MDIV_DIV(0);
16
  MCLK->CPUDIV.reg = MCLK_CPUDIV_CPUDIV_DIV1;
17

18
  GCLK->GENCTRL[0].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC48M;
19
  
20
  if (xosc_fail == false)
21
  {
22
    GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(1) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_XOSC;
23
  }
24
  else
25
  {
26
    GCLK->GENCTRL[2].reg = GCLK_GENCTRL_DIV(2) | GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSC48M;
27
  }
28
}
Ich hätte nur Bedenken, dass es vielleicht nicht immer richtig 
funktioniert.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren