lpc236x serisini 60 Mhz hızında kullanabilmek

Başlatan mezire, 04 Ocak 2010, 09:53:44

mezire

arm7 Lpc23xx serisini kullanıyorum .

devre üzerinde 12Mhz. kristal kullanıyorum. PLL özelliğini kullanarak devremi 60Mhz hızında çalıştırmak istiyorum.  

12Mhz kristal ile işlemciyi 60MHz hızında PLL ile nasıl çalıştırabilirim. elinde örnek kod olan arkadaşlar yazarsa memnun olurum

controller

Bunun bir çok yöntemi var. PLL 275MHz - 550MHz aralığında çalışabilir. Genelde PLL 288MHz de çalıştırılır. Bu durumda CPU hızı 57.6MHz veya 72MHz olabilir (PLL bölücü değerinden dolayı). İlla 60MHz istirosan örnek;

MSEL = 20
NSEL = 1
CCLKSEL = 8

12MHz x 2 x 20 = 480 MHz PLL

CCLK = 480/8 = 60 MHz

Ayrıca bu hesaplamalar lpc23xx datasheet'inde ayrıntılı olarak var.
Hesabım OG tarafından haksız bir şekilde pasif yapılmıştır.


FullMetal

Yanlış hatırlamıyorsam NXP nin sitesinde bu iş için bir lilbrary vardı. Sen mesela 60 olarak belirliyorsun.  Programı derlerken gerekli ayarlamaları ona göre yapyor.

mezire

Cevap veren arkadaşlara teşekkür ederim.
Ancak bir türlü istediğim hızlar da sistemi çalıştıramadım.
Aşağıdaki fonksiyon kodlarını yabancı bir siteden buldum.
Olduğu gibi kullandım ama yine olmadı.
İsterseniz bu kodu bir inceleyin.
Kod problemli görünmüyor.
Sanırım gözden kaçırdığım başka şeyler var.
Sizler de çalışırsa kütüphanenize ekleyerek kullanabilirsiniz.
Çalıştıran arkadaşlardan buraya örnek yazmalarını rica ediyorum.
Ben "controller" isimli arkadaşın verdiği değerlerle şu şekil de kullandım;
  PLL_Init ( 20, 1, 8 );

Yanlış mı kullanıyorum acaba???

NOT: Kodların son hali aşağıdaki mesajlar da...

SpeedyX

ConfigurePLL ( 12, 1, 5 ); olarak dener misin?

mezire

Kodları iyileştirerek PLL_Init adında bir fonksiyon haline getirdim.
Aşağıdaki kod çalışıyor.
Ancak, NXP`nin kendi verdiği excel tablosundaki değerleri kullanarak işlem yapmama rağmen UART düzgün çalışmıyor.
Özetle şimdi de hızlanmış sistem de UART ayarını yapamıyorum.

void PLL_Init(DWORD PLL_MValue, DWORD PLL_NValue, DWORD CCLKDivValue)
{
   #define PLL_Feed()  PLLFEED = 0xAA; PLLFEED = 0x55 // Yapılan değişikliği uygular.
   #define PLL_Wait(Register, Flag)  while ((Register & Flag) == 0)
   
   // const DWORD SCS_OSCRANGE  = 0x10;
   const DWORD SCS_OSCEN     = 0x20;
   const DWORD SCS_OSCSTAT   = 0x40;
   const DWORD PLL_ENABLE    = 1 << 24;
   const DWORD PLL_CONNECT   = 1 << 25;
   const DWORD PLL_LOCK      = 1 << 26;

   if (PLLSTAT & PLL_CONNECT) // PLL bağlı ise kapat.
   {
       PLLCON = 1; // PLL Enable, bağlantı yok.
       PLL_Feed();
   }

   PLLCON = 0; // PLL Disable, bağlantı yok.
   PLL_Feed();

   // SCS |= SCS_OSCRANGE | SCS_OSCEN; // Ana osilatör 15~24MHz aralığında seçilerek aktif ediliyor.
   SCS |= SCS_OSCEN; // Ana osilatör aktif ediliyor.
   PLL_Wait(SCS, SCS_OSCSTAT); // SCS_OSCEN biti set edilene kadar bekle.

   CLKSRCSEL = 0x01; // Ana osilatör(XTAL) PLL saat kaynağı olarak seçiliyor.

   PLL_MValue--;
   PLL_NValue--;
   PLLCFG = PLL_MValue | (PLL_NValue << 16); // NSEL ve MSEL değerleri.
   PLL_Feed();

   PLLCON = 1; // PLL Enable, bağlantı yok.
   PLL_Feed();
   PLL_Wait(PLLSTAT, PLL_ENABLE); // PLL Enable oluncaya kadar bekle.

   CCLKCFG = CCLKDivValue - 1; // Clock bölücü set ediliyor.
   PLL_Wait(PLLSTAT, PLL_LOCK); // PLL kitleninceye kadar bekle.

   while (((PLLSTAT & 0x00007FFF) != PLL_MValue) && (((PLLSTAT & 0x00FF0000) >> 16) != PLL_NValue)); // Verilerin doğruluğunu çek et.

   PLLCON = 3; // PLL Enable, Connect.
   PLL_Feed();
   PLL_Wait(PLLSTAT, PLL_CONNECT); // PLL bağlanıncaya kadar bekle.
}

mezire

Deneyimlerini yazarsanız memnun olurum...

mezire

Alıntı yapılan: "SpeedyX"ConfigurePLL ( 12, 1, 5 ); olarak dener misin?

Denedim ama daha yavaş çalışıyor.

mezire

Aşağı da ki şekil de elde ettiğim hızlar da UART ve TIMER`lar düzgün bir şekilde çalışıyor.
Ama 24MHz`in üzerine çıkamadım.

PLL_Init(12, 1, 3); // 24MHz
PLL_Init(12, 1, 6); // 12MHz

SpeedyX

Alıntı yapılan: "mezire"Denedim ama daha yavaş çalışıyor.
Emin misin?

UART ve timerları nasıl kullanıyorsun?

Gelen frekansı doğru bölmüyorsun.
Biliyorsun 60mhz ile çalışmaz onlar.
12 ve 24MHz de o yüzden çalışıyorlar...

Örneğin 96 mhz de 115200bps için şöyle yapmıştım:


mezire

Sevgili SpeedyX,
12MHz kristal ile çalışırken 1 mikrosaniye ara ile kesme oluşturan bir timer kurmak için PR registerine 12 değerini yazmak gerekli.
Ancak, senin söylediğin değerler ile PLL ayarladığım da 1 mikrosaniyelik timer kesmesi için 12 yerine daha düşük bir değer girmek zorunda kaldım.
Bu durum sistemin yavaşladığını gösteriyor.
PLL ile ilgili keil forumları dahil bir çok site de araştırma yaptım.
Yazılmış hazır kodları da denedim. Ancak, bu işe kesin bir çözüm bulana rastlamadım.
Ör; Hem USB, hem UART, hem de kusursuz bir zamanlayıcıyı bir arada kullanabilmek için PLL ayarlarını varsayılan olarak bırakmak daha mantıklı görünüyor.
Özetle; En kararlı çalışma şekli için MSEL=12, NSEL=1 şeklinde kullanmaya devam edeceğim.
Yine de, kesin çözüm üreten arkadaşlar buraya yazarlarsa hepimiz için faydalı olacaktır.

NOT: MSEL ve NSEL değerleri PLLCFG registerine MSEL=11, NSEL=0 şeklinde yazılmalıdır. Yani, MSEL - 1 ve NSEL - 1 işleminden geçiriliyor.

malkocoglu

#12
Biraz gec kalmisim ama yine de cevap vereyim dedim...

LPC2368 errata'sina bakarsaniz PLL output'unun 290 MHz ustune cikamadigini gorursunuz.
Degerleri de ona gore secmeniz gerekli.

Ben 72 MHz'te calistirirken : MSEL = 72 (yani 71) , NSEL = 6 (yani 5) ve CCLKSEL = 4 (yani 3) secmistim.
Bu durumda 12/6 = 2 MHz. 2MHz * 72 * 2 = 288 MHz. 288 MHz / 4 = 72MHz cikar.
Sen MSEL degerini 60 icin ayarla en iyisi. Yeni cikan 2368'ler 72'de calisiyor gerci...