Taktfrequenz ATXmeaga128A1

OP #2512111
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?
OP #2512218
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?
Gast #2513364
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.
OP #2513583
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.
OP #2513644
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.
OP #2514586
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). */
#2516228
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

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