Forum: Mikrocontroller und Digitale Elektronik lpc2148 PLL-Fehler


von simon91 (Gast)


Lesenswert?

Hallo,
ich hab mir vor kurzem das Olimex-Dev-Board LPC-P2148 zugelegt. Nun hab 
ich mir folgenden PLL-Init-Code zusammengestellt, der aber leider nicht 
funktioniert, da bei meinem Testprogramm (siehe unten) nicht wie 
vorgesehen die LEDs im Sekundentakt, sondern nur etwa alle 5 Sekunden, 
wechseln. Ich schließe daraus, dass der PLL nicht aktiviert wird, kann 
aber leider keinen Fehler in meinem Code finden. Für eure Hilfe bedanke 
ich mich schon einmal im voraus.

PLL-INIT:
1
#define FOSC  12000000
2
#define PLL_M 5
3
#define PLL_P 2
4
#define CCLK  (PLL_M * FOSC)
5
6
void arch_init(void) {
7
8
  // CCLK = FOSC*PLL_M = 12000000*5 = 60000000
9
  PLL0->CFG = (PLL_M-1)|((PLL_P-1)<<5);
10
  // PLL aktivieren
11
  PLL0->CON = 0x01;
12
  PLL0->FEED = 0xAA;  //PLL Feed-Sequenz
13
  PLL0->FEED = 0x55;
14
  // Änderungen werden übernommen
15
  while ( !( PLL0->STAT & PLOCK ) );
16
17
  // PLL aktivieren/mit Taktgeber verbinden
18
  PLL0->CON = 0x03;
19
  PLL0->FEED = 0xAA;  //PLL Feed Sequence
20
  PLL0->FEED = 0x55;
21
22
23
  MAMCR=0x0;
24
25
  #if   CCLK < 20000000
26
    MAMTIM = 1;
27
  #elif CCLK < 40000000
28
    MAMTIM = 2;
29
  #elif CCLK >= 40000000
30
    MAMTIM = 3;
31
  #endif
32
33
  MAMCR=0x2;
34
35
36
  VPBDIV=0x1;
37
38
}


Test-Programm:
1
int main(void) {
2
3
  uin32_t i = 0;
4
5
  arch_init();
6
7
  GPIO0->DIR |= (1<<10);
8
  GPIO0->SET  = (1<<10);
9
  GPIO0->DIR |= (1<<11);
10
  GPIO0->SET  = (1<<11);
11
12
  while(1) {
13
    GPIO0->SET = (1<<11);
14
    GPIO0->CLR = (1<<10);
15
    for(i = 60000000;i>0;i--)
16
      NOP();
17
    GPIO0->SET = (1<<10);
18
    GPIO0->CLR = (1<<11);
19
    for(i = 60000000;i>0;i--)
20
      NOP();
21
  }
22
23
  return 0;
24
}

von (prx) A. K. (prx)


Lesenswert?

Woran ist ersichtlich, dass es im Sekundentakt abgehen müsste? Die 
Warteschleifen benötigen garantiert mehr als 1 Takt pro Iteration. Wenn 
NOP exakt ein NOP ist, komme ich auf mindestens 4 Takte (NOP=1, 
Subtraktion=1, Sprung>=2).

von simon91 (Gast)


Lesenswert?

Ok,
ich hab mir nun den Code des Disassamblers heraus geschrieben:
1
 370:  nop      (mov r0,r0)
2
 374:  subs  r3, r3, #1  ; 0x1
3
 378:  bne  370 <main+0x4c>

Demnach dauert das Ganze 3 Takte. Ich hab jetzt die Schleife auf 
20000000 geändert. Die Folge: es dauert ungefähr 1.5s.

von simon91 (Gast)


Lesenswert?

Wenn ich hingegen i=12000000 (der Takt des Quarzes) eingebe, erfolgt das 
Blinken genau im Sekundentakt. Da dieses Ergebnis aber durch die 
Ausführungszeit der Schleife verfälscht ist, frag ich nun andersrum: wie 
kann ich zuverlässig feststellen ob der PLL funktioniert?

von (prx) A. K. (prx)


Lesenswert?

simon91 wrote:

> Demnach dauert das Ganze 3 Takte.

Der Branch braucht mindestens 2. Je nach Speicherart und MAM-Einstellung 
auch mehr.

von simon91 (Gast)


Lesenswert?

Ja, ok das die branch-instruction mehr als einen Takt braucht ist klar.
Ich bin nun selbst darauf gekommen wie ich den PLL testen kann:
Ich hab nun einfach ein Timer-Interrupt geschrieben das die LEDs im 
Sekundentakt an- bzw. ausmacht und es funktioniert. Das es mit der 
Schleife nicht funktionieren kann ist mir nun auch klar (man lernt 
immerwieder etwas neues).
Danke für die Hilfe

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.