STM32'nin kullanacağı clock'a karar vermesi

Başlatan sytax333, 12 Ağustos 2018, 18:11:44

sytax333

Herkese iyi günler,

Benim uzun zamandır merak ettiğim bir konu var ancak internetteki dökümanlardan bunu bulamadım.

Örnek olarak herhangi bir STM32'yi alalım.

İki adet clock seçeneği var birisi HSE (External) diğeri HSI (Internal). Internal olan clock STM32F407'lerde 16MHz olduğunu okudum. Ben kendi projelerimde STM32F103C8T6 programlarken Ac6 ve eclipse tool chain'ini kullanıyorum. Burada dışarıdan bağladığım clock'u kullanmak için HSE_VALUE değerini 8000000 (8MHz) 'e PLL_M değerini ise 8'e çekiyorum. Bunu internette gördüğüm tutoriallarda böyle yaptıkları için yapiyorum. SystemCoreClock formülünüde anladım (SystemCoreClock = ((INPUT_CLOCK (HSE_OR_HSI_IN_HZ) / PLL_M) * PLL_N) / PLL_P = 168MHz çünkü STM32F4 çalışma clock'u)

Ancak anlamadığım konu ben stm32'ye HSE kullan yada HSI kullan demiyorum. Sadece yukarıda söylemiş olduğum 2 değeri giriyorum  başka herhangi bir değişiklik yapmıyorum.STM32 hangi clock'u kullanacağını nasıl belirliyor? Acaba kendi içinde bir if döndürüp bu değerin boş olup olmamasına mı bakıyor diye düşündüm ama bu değerleri ben değiştirmesemde defaultları var yani boş değiller.

Eminim çok basit bir açıklaması vardır. Beni bu konuda bilgilendirirseniz sevinirim.

Emre_Tuncay_

İlgili register in ilgili bitini 1 veya 0 yapmana göre HSE veya HSI kullanır.Bu registerin illaki başlangıç değeri vardır sen değiştirmezsen o değerde başlatır.

sytax333

Siz HSE yi kullanmak için ekstra olarak bir register'a bişi atıyor musunuz? Yoksa CubeMx kullanırken onu başta set edip geçiyor musunuz?

magnetron

STM32 başlarken HSI ile başlar
onu HSE'ye çeviren senin yazdığın kod

Aşağıda STM32 SPL den alınma fonksiyon HSE'yi start ediyor

void SetSysClockTo72(void)
{
  /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration -----------------------------*/  
  /* RCC system reset(for debug purpose) */
  RCC_DeInit();

  /* Enable HSE */
  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */
  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if (HSEStartUpStatus == SUCCESS)
  {
    /* Enable Prefetch Buffer */
    FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

    /* Flash 2 wait state */
    FLASH_SetLatency(FLASH_Latency_2);
 
    /* HCLK = SYSCLK */
    RCC_HCLKConfig(RCC_SYSCLK_Div1); 
  
    /* PCLK2 = HCLK */
    RCC_PCLK2Config(RCC_HCLK_Div1); 

    /* PCLK1 = HCLK/2 */
    RCC_PCLK1Config(RCC_HCLK_Div2);
    
    /* ADCCLK = PCLK2/4 */
    RCC_ADCCLKConfig(RCC_PCLK2_Div6); 
//#else
    /* PLLCLK = 8MHz * 9 = 72 MHz */
    RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
//#endif

    /* Enable PLL */ 
    RCC_PLLCmd(ENABLE);

    /* Wait till PLL is ready */
    while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)
    {
    }

    /* Select PLL as system clock source */
    RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

    /* Wait till PLL is used as system clock source */
    while(RCC_GetSYSCLKSource() != 0x08)
    {
    }
  }
  else
  { /* If HSE fails to start-up, the application will have wrong clock configuration.
      User can add here some code to deal with this error */    

    /* Go to infinite loop */
    while (1)
    {
    }
  }
}

sytax333

#4
O zaman HSE'yi kullanmak için benim yukarıda değiştirdiğim 2 satır dışında clock'la ilgili herhangi birşey yapmama gerek kalmıyor sanırım yanlış anlamadıysam.
--
Düzenleme: system_stm32f4xx.c dosyasında zaten default olarak HSE kullanıldığı yazıyor soylediğiniz gibi ayarların değişip değişmemesine bağlı.

Tagli

Projeyi CubeMX ile mi oluşturuyorsun? Ben hiç kullanmadığım için bilmiyorum ama eğer CubeMX kullanıyorsan, orada belirlediğin ayarlar (clock tree bölümünde grafiksel olarak belirlediklerin) sistem açılışında bir init fonksiyonu tarafından devreye sokuluyordur muhtemelen.

Ama normalde 8 MHz HSI ile başlar işlemciler (en azından benim kullandığım F103 ve F051 öyle idi). Clock source değişikliği için senin ilgili register'lara uygun değerleri yazman gerekir. Bunu yaparken de dikkatli olmalısın. İşlemlerin sıralaması bazı durumlarda önemli. Ayrıca bazı hatların azami hız sınırları var, bunları da göz önünde bulundurmalısın.

SystemCoreClock değeri CMSIS standartında tanımlı ve yazılım altyapısı için bir temel oluşturuyor. Ama ben CubeMX kullanmadığımdan, benim için bir anlamı yok. Yani bu değer donanımsal olarak bir anlam ifade etmiyor, yazılım kütüphaneleri bu değere bakarak işlemci hızını anlıyorlar sadece. Senin buna elle bir değer ataman yanlış olur. Sistem hızına müdahale eden işlemlerden sonra (register'lara yazmak veya kütüphaneden fonksiyon çağırmak), SystemCoreClockUpdate() fonksiyonunu çağırırsın. Bu da zaten system_stm32f4xx.c dosyasının içindedir. Bu ilgili register'ları tarayıp SystemCoreClock değerini tespit eder ve günceller. Yani SystemCoreClock bir çeşit gösterge değeri gibidir.

Bu arada ufak bir not: Sistem hızını değiştirdikten hemen sonra SystemCoreClockUpdate()'i çağırırsan hatalı sonuç alabilirsin. Bazen osilatör ayarları değiştirildiğinde yeni ayarların devreye girmesi çok az da olsa bir süre alıyor, atıyorum 1-2 ms (belki o kadar da değil). Sistem yeni değerlere oturmadan fonksiyonu çağırırsan SystemCoreClock hatalı bir değer alabilir (başıma gelmişti). Genelde sistemin istenilen değerlere oturup oturmadığını anlamana yarayacak bitler vardır ilgili register'larda.
Gökçe Tağlıoğlu