Forum: Mikrocontroller und Digitale Elektronik Taktfrequenz ATXmeaga128A1


von Matthias L. (mcl024)


Lesenswert?

Hallo Zusammen,

mit dem folgenden Code stelle ich die CPU frequenz auf 32MHz ein.
1
   //Oscillator auf 32Mhz einstellen PIN1 = OSC_RC32MEN wird gesetzt 
2
   OSC.CTRL = 0x02;
3
   
4
   // Wenn Oscillator stabil wird das Flag RC32MRDY
5
   // gesetzt und 32Mhz können benutzt werden
6
   while(!(OSC.STATUS & OSC_RC32MRDY_bm));
7
   // I/O Protection
8
   CCP = 0xD8; 
9
   // Clock auf 32Mhz einstellen
10
   CLK.CTRL = 0x01;

Wenn ich CCP = 0xD8 auskommentiere dann funktioniert nichts mehr bzw. 
läuft die CPU nicht mehr mit 32MHz. Woran liegt das?

von Gerhard G. (xmega)


Lesenswert?

Hallo,

mit dem Byte 0xD8 wird das Configuration Change Schutz-Register (CCP) 
freigegben. Dann kann erst gewünschte Konfiguration für die Vorteiler
usw. eingestellt werden.

Gruß xmega

von Horst (Gast)


Lesenswert?

XMega A Manual, Kapitel 3.12

von Matthias L. (mcl024)


Lesenswert?

Danke. Woher weiss ich welche Register davon betroffen sind?

von Thomas B. (nichtessbar)


Lesenswert?

Horst schrieb:
> XMega A Manual, Kapitel 3.12

RTFM...

von Matthias L. (mcl024)


Lesenswert?

Mhh irgendwie werde ich daraus nicht ganz schlau.

Mit der folgenden Oszi_Init möchte den ClkPer4 = 64MHz, ClkPer2 = 64MHz 
und ClkCPU = ClkPer = 32Mhz einstellen.
1
//Oscillator auf 32Mhz einstellen PIN1 = OSC_RC32MEN wird gesetzt 
2
OSC.CTRL = 0x02;
3
   
4
// Wenn Oscillator stabil wird das Flag RC32MRDY
5
// gesetzt und 32Mhz können benutzt werden
6
while(!(OSC.STATUS & OSC_RC32MRDY_bm));
7
   
8
OSC.CTRL &=~ OSC_PLLEN_bm;  // PLL ausschalten
9
OSC.PLLCTRL  = OSC_PLLSRC_RC32M_gc | OSC_PLLFAC3_bm;  // Quelle und Multiplikator 8 einstellen 
10
OSC.CTRL  |= OSC_PLLEN_bm;    // PLL einschalten
11
while(!(OSC.STATUS & OSC_PLLRDY_bm));  // Warten bis PLL Ready
12
  
13
CCP = 0xD8; 
14
CLK.PSCTRL = 0x01;   // Prescaler C auf 2 stellen
15
CLK.CTRL = 0x04;     // Main Clk Source auf PLL stellen

funktioniert aber leider nicht. Der Takt könnte so bei 1MHz liegen.
Was mache ich falsch?

von Matthias L. (mcl024)


Lesenswert?

Hat das noch keiner eingestellt? Oder stelle ich mich wieder zu blöd an?

von Matthias L. (mcl024)


Lesenswert?

Also ich habe jetzt noch ein bisschen rumprobiert. Wenn ich nach der 
ersten while schleife CLK.CTRL = 0x01 schreibe dann läuft er auch mit 
32MHz, als wenn er den Rest kopmlett ignoriert, also die PLL.

von Horst (Gast)


Lesenswert?

Matthias Laubnitz schrieb:
> CCP = 0xD8;
> CLK.PSCTRL = 0x01;   // Prescaler C auf 2 stellen
> CLK.CTRL = 0x04;     // Main Clk Source auf PLL stellen

Lies mal "3.12.1 Sequence for write operation to protected I/O 
registers" aus dem XMega A Manual.
Du hast nach CCP = 0xD8 4! Takte Zeit, das Register zu ändern. Daraus 
folgt a) ggf. mehrfach CCP = 0xD8 und b) Optimierung des Compilers 
einschalten.

von Horst (Gast)


Lesenswert?

Korrektur: PSCTRL gehört nicht zu den CCP geschützten Registern, also 
CCP vor CTRL setzen.

von Matthias L. (mcl024)


Lesenswert?

Hey danke für deine Antwort. Habe nun mal folgenden Code mit 
Optimierungslevel -os und -o1 getestet.
1
//Oscillator auf 32Mhz einstellen PIN1 = OSC_RC32MEN wird gesetzt 
2
  OSC.CTRL = 0x02;
3
   
4
  // Wenn Oscillator stabil wird das Flag RC32MRDY
5
  // gesetzt und 32Mhz können benutzt werden
6
  while(!(OSC.STATUS & OSC_RC32MRDY_bm));
7
   
8
  OSC.CTRL &=~ OSC_PLLEN_bm;  // PLL ausschalten
9
  OSC.PLLCTRL  = OSC_PLLSRC_RC32M_gc | OSC_PLLFAC3_bm;  // Quelle und Multiplikator 8 einstellen 
10
  CLK.PSCTRL = 0x01;   // Prescaler C auf 2 stellen
11
  OSC.CTRL  |= OSC_PLLEN_bm;    // PLL einschalten
12
  while(!(OSC.STATUS & OSC_PLLRDY_bm));  // Warten bis PLL Ready
13
  
14
  CCP = 0xD8; 
15
  CLK.CTRL = 0x04;     // Main Clk Source auf PLL stellen

Bei -Os läuft die CPU scheinbar gar nicht und bei -o1 läuft sie sehr 
langsam.

von Horst (Gast)


Lesenswert?

Was heißt "langsam"?

von Matthias L. (mcl024)


Lesenswert?

Korrektur: Bei -o1 scheint alles so zu laufen wie ich es möchte, also 
ClkPER und ClkCPU.

Doch bleibt er jetzt in der Init für das SDRAM hängen. Woran liegt denn 
das schon wieder?
1
void sdram_init(void)
2
{
3
/* Initialize EBI. */
4
  EBI_Enable( EBI_SDDATAW_4BIT_gc,
5
              EBI_LPCMODE_ALE1_gc,
6
              EBI_SRMODE_ALE12_gc,
7
              EBI_IFMODE_3PORT_gc );
8
9
  PORTE.OUT |= (1<<PIN5);   // Dieser Punkt wird nicht erreicht
10
11
12
  /* Initialize SDRAM. (PER2X clock is 2MHz giving a 500ns clock cycle.) */
13
  EBI_EnableSDRAM( EBI_CS_ASIZE_8MB_gc,   /* 8 MB address space. */
14
                   SDRAM_ADDR,             /* Base address. */
15
                   false,                  /* 2 cycle CAS Latency. */
16
                   true,                   /* 12 Row bits. */
17
                   EBI_SDCOL_10BIT_gc,     /* 10 Column bits. */
18
                   EBI_MRDLY_2CLK_gc,      /* 2 cycle Mode Register Delay. (min 2CLK) */
19
                   EBI_ROWCYCDLY_1CLK_gc,  /* 1 cycle Row Cycle Delay. */
20
                   EBI_RPDLY_1CLK_gc,      /* 1 cycle Row to Pre-charge Delay. (min 37ns) */
21
                   EBI_WRDLY_2CLK_gc,      /* 2 cycle Write Recovery Delay. (1CLK + 7ns)*/
22
                   EBI_ESRDLY_1CLK_gc,     /* 1 cycle Exit Self Refresh to Active Delay. (min 67ns) */
23
                   EBI_ROWCOLDLY_1CLK_gc,  /* 1 cycle Row to Column Delay. (min 15ns) */
24
                   0x001F,                 /* 31 cycle Refresh Period (max 15.625us). */
25
                   0x00C8 );               /* 200 cycle Initialization Delay (min 100us). */
26
27
}
28
29
30
void EBI_Enable( EBI_SDDATAW_t sdramDataWidth,
31
                 EBI_LPCMODE_t lpcMode,
32
                 EBI_SRMODE_t sramMode,
33
                 EBI_IFMODE_t interfaceMode )
34
{
35
  /* These fields fill up the whole register, so we don't have to protect any bits with masks. */
36
  EBI.CTRL = (uint8_t) sdramDataWidth | lpcMode | sramMode | interfaceMode;
37
}

aus dieser Funktion kommt er nicht mehr raus.

von Matthias L. (mcl024)


Lesenswert?

Hat jemand das SDRAM auf dem X-Plained Board mit 64MHz Clk am laufen?

von Matthias L. (mcl024)


Lesenswert?

Ich habe die Init nun ein wenig verändert und auf die 64MHz angepasst. 
Habe ich noch etwas vergessen? Kann es erst heut abend testen.
1
/* Initialize SDRAM. (PER2X clock is 64MHz giving a 15,625ns clock cycle.) */
2
  EBI_EnableSDRAM( EBI_CS_ASIZE_8MB_gc,   /* 8 MB address space. */
3
                   SDRAM_ADDR,             /* Base address. */
4
                   false,                  /* 2 cycle CAS Latency. */
5
                   true,                   /* 12 Row bits. */
6
                   EBI_SDCOL_10BIT_gc,     /* 10 Column bits. */
7
                   EBI_MRDLY_2CLK_gc,      /* 2 cycle Mode Register Delay. (min 2CLK) */
8
                   EBI_ROWCYCDLY_1CLK_gc,  /* 1 cycle Row Cycle Delay. */
9
                   EBI_RPDLY_3CLK_gc,      /* 3 cycle Row to Pre-charge Delay. (min 37ns) */
10
                   EBI_WRDLY_2CLK_gc,      /* 2 cycle Write Recovery Delay. (1CLK + 7ns)*/
11
                   EBI_ESRDLY_5CLK_gc,     /* 5 cycle Exit Self Refresh to Active Delay. (min 67ns) */
12
                   EBI_ROWCOLDLY_2CLK_gc,  /* 2 cycle Row to Column Delay. (min 15ns) */
13
                   0x001F,                 /* 31 cycle Refresh Period (max 15.625us). */
14
                   0x1900 );               /* 6400 cycle Initialization Delay (min 100us). */

von Matthias L. (mcl024)


Lesenswert?

Also nochmal zum Anfang. Der Takt ist nun wie möchte mit 32/64MHz bei 
-O1. Nur reagiert jetzt alles etwas komisch als wenn Teile komplett weg 
optimiert werden.

Meine Frage an Euch ist nun ob es auch eine Möglichkeit gibt den 
gewünschten Takt ohne Optimierung einzustellen.

von Hagen R. (hagen)


Lesenswert?

so mache ich das:
1
// Taktsystem konfigurieren
2
    // externen 16MHz Quarz einschalten
3
    OSC.XOSCCTRL = OSC_XOSCSEL_XTAL_16KCLK_gc | OSC_FRQRANGE_12TO16_gc;// | OSC_X32KLPM_bm;
4
    OSC.CTRL |= OSC_XOSCEN_bm;
5
    while (!(OSC.STATUS & OSC_XOSCRDY_bm));
6
    // PLL Source = 16MHz ext. Quarz * 8 = 128 MHz  
7
    OSC.PLLCTRL = OSC_PLLSRC_XOSC_gc | (8 << OSC_PLLFAC_gp);
8
    OSC.CTRL |= OSC_PLLEN_bm;
9
    while (!(OSC.STATUS & OSC_PLLRDY_bm));
10
    // CLK-Prescaler A/1 B/2 C/2 -> 128MHz -> 64MHz -> 32MHz
11
    CCP_Write(&CLK.PSCTRL, CLK_PSADIV_1_gc | CLK_PSBCDIV_2_2_gc);
12
    // PLL nun als Systemclock auswählen
13
    CCP_Write(&CLK.CTRL, CLK_SCLKSEL_PLL_gc);
14
    // 2MHz und 32MHz RC abschalten
15
    OSC.CTRL &= ~(OSC_RC32MEN_bm | OSC_RC2MEN_bm | OSC_RC32KEN_bm);
16
    // nun CLK Einstellungen schützen
17
    CCP_Write(&CLK.LOCK, CLK_LOCK_bm);

wichtig ist nachfolgende Funktion:
1
void CCP_Write(volatile uint8_t* address, uint8_t value) {
2
3
  AVR_ENTER_CRITICAL_REGION();
4
  volatile uint8_t* tmpAddr = address;
5
#ifdef RAMPZ
6
  RAMPZ = 0;
7
#endif
8
  asm volatile(
9
    "movw r30,  %0"        "\n\t"
10
    "ldi  r16,  %2"        "\n\t"
11
    "out   %3, r16"        "\n\t"
12
    "st     Z,  %1"       "\n\t"
13
    :
14
    : "r" (tmpAddr), "r" (value), "M" (CCP_IOREG_gc), "i" (&CCP)
15
    : "r16", "r30", "r31"
16
    );
17
18
  AVR_LEAVE_CRITICAL_REGION();
19
}

Gruß Hagen

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.