Stm32f4 Discovery Hız Problemi

Başlatan xna, 07 Eylül 2013, 03:10:33

xna

Arkadaşlar Stm32F407vg bir uygulama yazarken alakasız bir hatadan birşey dikkatimi çekti

İşlemci hızımızı 168 mhz'e  GIPOD portları 100mhz' e ayarlasak bile
işlemci asla ve asla 100mhz ile portları sürmüyor
100 ü bırakın 10 mhz'ye bile çıkmıyor
acaba ben bir yerde bir hata yapmış olabilirmiyim diye
forum da yayınlalan bir kaç arkadaşımın örneklerinide aldım
ama sonuç yine aynı ve en basit hale getirip yine denedim ama malesef
bilgileri olan arkadaşlardan yardım bekliyorum teşekkürler..

Kodlar:
#include "STM32F4xx.h"
#include "stm32f4xx_gpio.h"


/*****************************************************************************************************
         CPU PLL ile 168Mhz de kosturulur
         AHB frekansy 168 Mhz
         APB1 frekansy 42 Mhz
         APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemXInit()
{
unsigned int i;
     for (i=0;i<0x00100000;i++);     // OSC oturtma ve kurtarma rutini
     RCC->CFGR |= 0x00009400;        // AHB ve APB hizlarini max degerlere set edelim
     RCC->CR |= 0x00010000;          // HSE Xtal osc calismaya baslasin
     while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
     RCC->PLLCFGR = 0x07402A04;      // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
     RCC->CR |= 0x01000000;          // PLL calismaya baslasin  (Rehber Sayfa 95)
     while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
     FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
     RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
     while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
     RCC->AHB1ENR |= 0x0000000F;     // GPIO A,B,C,D clock'u aktif edelim
     GPIOD->MODER  = 0x55550000;     // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
     GPIOD->OSPEEDR= 0xFFFFFFFF;     // GPIOD nin tum cikislari en yuksek hizda kullanacagiz           // Counter Enable

}

int main()
{
   SystemXInit();

    while(1)
    {
       //GPIO_ToggleBits (GPIOD, GPIO_Pin_14);
       //asm("nop");
       GPIO_SetBits(GPIOD, GPIO_Pin_11);
       //asm("nop");
       GPIO_ResetBits(GPIOD, GPIO_Pin_11);

    }
}

Klein

#1
aşağıdaki kod GPIO_SetBits() fonksiyonunun kodu.
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_PIN(GPIO_Pin));
  
  GPIOx->BSRR = GPIO_Pin;
}


her işlemin 1 periyot sürdüğünü varsayarsak  ki öyle değil.
Fonksiyonun çağırılması, işlemleri yapması ve geri dönmesi  5 saykıl.
programında 2 kez çağırıyorsun  toplam 10 periyot etti.
while döngüsü için  1, nop içinde 1,  toplam 12 periyot eder.
168 Mhz / 12 = 14Mhz eder.
Buna 2 saykıl süren işlemleri, Port değerinin Pin değerinin  registere atılması gibi işlemleri eklediğinde hızın 10MHz seviyelerinde olması gayet normal.





xna

Klein gecenin bu yarısı üşenmeyip bana yardımcı olmaya çalıştığın için teşekkür ederim bu herşeyden daha değerli

gözünden kaçmış ama hiç nop yok hepsi engelli

başında toggle ile denedim o fonksiyon daha yavaş

tam olarak çalışma hızı 3.23 mhz küsüratlarıda var ama yazmadım

şimdi direk port registerlarına yazmaya deniyorum hiç fonksiyon kullanmadan

onu yazdığım zaman sonucu burdan bildiririm , ilgin alakan için teşekkür ederim...

xna

Evet Arkadaşlar direk olarak GPIOD nin registerine yazınca

kısmen daha hızlandı ama bana çok komik geldi

bilgileri vereyim
(Kullandığım Compiler Gcc editör Coocox)

dongüyü bu şekilde kurarsanız hız: 15.277 mhz
(asm("nop"); lar kapalı)
dongu:
    //while(1)
    //{
       //GPIO_ToggleBits (GPIOD, GPIO_Pin_14);
       //asm("nop");
       //GPIOC->BSRR = BSRR_VAL;
       //GPIOC->BRR = BSRR_VAL;
       //asm("nop");
       GPIOD->ODR = 0x0800;//BSRR_VAL;
       //asm("nop");
       GPIOD->ODR = 0x0000;

       //GPIO_SetBits(GPIOD, GPIO_Pin_11);
       //asm("nop");
       //GPIO_ResetBits(GPIOD, GPIO_Pin_11);

    //}
    goto dongu;


döngüyü aşağıdaki gibi yaparsanız hızınız :3.231mhz
(asm("nop"); lar kapalı)
        GPIO_SetBits(GPIOD, GPIO_Pin_11);
       //asm("nop");
       GPIO_ResetBits(GPIOD, GPIO_Pin_11);

while ile goto arasında dişe dokunur bir fark yok
onların değerlerinide yazayım
while ile : 15.2761mhz
goto ile : 15.2770 mhz

bunlar benim tesbit edebildiklerim

şimdi yapacağım şey ise yukarıda yazdığım kodu komple ASM ile yazmak
ama pek umudum yok desem yeridir olsun olsun 20 mhz olsun

iyide bu işlemcinin Core = 168 mhz yani nerde bu güç
onuda geçtim D portu özellikle 100 Mhz gibi güzel bir hız ile sürülebildiği
yazıyor ama gelin görün ki 15 mhz ye zor ulaştım , muhtemelen bir yerde
hata yapıyorum ama göremedim

bu arada acaba Compiler'dan kaynaklanabilirmi ?
elinde keil yada iar olan arkadaşlardan destek bekliyorum
bi deneyebilirlerse onlardaki durum ne merak ettim...

Klein

#4
Portun 100Mhz olması porttan 100 MHz alabilirsin anlamında değil.  O  akım kapasitesi ile ilgili bir durum. Çıkışı  kodla değil PWM veya Timer gibi  bir donanımla sürersen gayet güzel 84Mhz çıkış alabileceğini görürsün.
Sorun kodlarında değil. Sorun 168MHz ve güç meselesine bakış açında. STM32F4 gayet güçlü bir alet.
Bu şekilde yaptığında çıkışın 15MHz olmasında hiç bir anormallik yok.

mesaj birleştirme:: 07 Eylül 2013, 05:38:50

Aşağıda D portunun 0. bitiniset eden ve resetleyen en basit kodun optimizasyonlar açıkken alınmış çıktısı var.
;;;249    while(1)
;;;250        {
;;;251    	GPIOD->ODR |= 0x0001;
000516  4807              LDR      r0,|L1.1332|
;;;252    	GPIOD->ODR &= 0xFFFE;
000518  f64f72fe          MOV      r2,#0xfffe
                  |L1.1308|
00051c  6801              LDR      r1,[r0,#0]            ;251
00051e  f0410101          ORR      r1,r1,#1              ;251
000522  6001              STR      r1,[r0,#0]            ;251
000524  6801              LDR      r1,[r0,#0]
000526  ea010102          AND      r1,r1,r2
00052a  6001              STR      r1,[r0,#0]
00052c  e7f6              B        |L1.1308|


Gördüğün gibi 8 komut  bir 2 iki periyotluk dallanma komutu işletiliyor. toplam 10 periyot.
168 MHz işlemci10 komutu işlettiğinde porttan 16.8MHz sinyal alırsın. Demekki senin kodunda 1 tane daha fazladan komut var hepsi o kadar. 


fatih6761

@Klein hocam XOR ile toggle yaparsanız daha hızlı olur. Kodu assemblyde yapıp bitbanding kullanmak da bir seçenek. Denemeye değer...

muhittin_kaplan

#6
Yptığım CYCLE Ölçümleri
frekansa göre hesaplanır artık.

DWT Usage: 5
ResetBit: 28
SetBit: 26
ToggleBit: 36
GPIOD->ODR &: 12

mesaj birleştirme:: 07 Eylül 2013, 13:07:07

GPIOD->ODR ^: 12 //EXOR işlemi

camby

Bu şekilde yazılımsal olarak daha yukarılara ( yanlış hatırlamıyorsam 70-80 mhz) çıkabiliyordu , fakat şimdi detayını hatırlamıyorum , klein hocanın gösterdiği gibi asm karşılığına dikkat etmek gerek yada direk asm yazmak gerek.

Bülent hoca, şamata sayfaların birinde de yazmıştı sanki..


Yazılımsal olarak I/O ları maksimum hızına çıkarmaya çalışmanın çok da bir anlamı yok , ama insan merak ediyor yine de işte ,  donanımsal birimler yüksek hızlarda bu Outputlara erişebiliyorlar , FSMC , PWM , SPI , USART vsvsvs.

Çevresel modülleri geçtim , en temel MCO birimi ile 168 MHz çıkış alabiliyorsunuz bir çıkıştan.

muhittin_kaplan

Hocam mco dan systemclock/2 aliyoruz sanki

camby

Max 84 mhz demesine karsin , Bolucu olmadan da cikis alinabiliyor hocam. Bir hata uzeri fark ettim ben de , gayet de guzel sinyal

z

#10
Asagidaki kodlari 3 seviyesinde speed optimizasyonu ile derlersen yaklasik olarak 84Mhz cikis sinyali alirsin.

#include "STM32F4xx.h"
 
/*****************************************************************************************************
         CPU PLL ile 168Mhz de kosturulur
         AHB frekansy 168 Mhz
         APB1 frekansy 42 Mhz
         APB2 frekansy 84 Mhz
*****************************************************************************************************/
void SystemInit()
{
unsigned int i;

          
     (*((int*)0xE000ED88))|=0x0F00000;     
          
     for (i=0;i<0x00100000;i++);     // OSC oturtma ve kurtarma rutini
          
     RCC->CFGR |= 0x00009400;        // AHB ve APB hizlarini max degerlere set edelim
     RCC->CR |= 0x00010000;          // HSE Xtal osc calismaya baslasin        
     while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
     RCC->PLLCFGR = 0x07402A04;      // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
     RCC->CR |= 0x01000000;          // PLL calismaya baslasin  (Rehber Sayfa 95)
     while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
     FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
     RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
     while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
     RCC->AHB1ENR |= 0x0000000F;     // GPIO A,B,C,D clock'u aktif edelim 
     GPIOD->MODER  = 0x55550000;     // GPIOD nin 15, 14, 13, 12, 11, 10, 9, 8 pinleri cikis tanimlandi (LEDler icin)
     GPIOD->OSPEEDR= 0xFFFFFFFF;     // GPIOD nin tum cikislari en yuksek hizda kullanacagiz      
}


int main()
{
    while(1)
    {
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
      GPIOD->ODR=0xffff; 
      GPIOD->ODR=0x0000;               
    }
}
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

xna

Degerli Z Senin yazdığın kodların çalışma hızı : 18.283 mhz

benim tespitlerim sonucu farklı düşündüğüm yerler var diye düşünüyorum

her ne kadar PDF ler önümüzde olsada bu 168 mhz bizim kullanabileceğimiz hızlar değil

bu hız donanım hızı , PWM , USB , Timer , CCP gibi nodüllerin kullanabileceği hızlar

bu sebeple yazılım ve tasarım esnasında pic ve avr lerde olduğundan daha iyi hesaplanması gerekmekte

çünkü pic ve avr de  bi döngüde kaç mhz alacağını işlemci hızınla yakalayabiliyorsun ama ARM işlemcilerde

malesef öyle değil yukarıdada yazdığım gibi biz şu basit döngüyü ASM ile yazsak bile elimize gelecek olan HIZ

En fazla 20Mhz yani 5 te 1 , demekki ARM larla işlem yaparken PIC ve AVR mantığımızıda bir kenara koymamız gerekiyor

2 gündür dünyanın 4 bir yanındaki forumları araştırdım çoğu insan benim düştüğüm hataya düşmüş , yani GPIOD 100 mhz ise

ben bunu 100mhz ile sürebilirim diye düşünmüş , Ancak öyle değil PWM ile çıkabileceğiniz en fazla HIZ 84 Mhz teoride pratikte denemedim

Capture Compare Modulünden işlemciye gireceğiniz yada Timerlara gireceğiniz hız en fazla 100Mhz Teoride , evet bilinen en hızlı port
Kamera portu ve kamera ile entegre DMA modunda çalışmadır ve 168 mhz hızı bir tek o kaynak kullanabiliyor oda grafik hızlandırma birimi ile benim tespitlerim bunlar ...

z

Son verdigim kodlari karta yukleyip D portunun ornegin 15 nolu pinini scop ile gozleyip peryodu olctunmu?

Benim scop yalan soylemiyorsa 11.9 ns.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

xna

Evet Sayın Z Karta yükleyip Osiloskop ile ölçtüğüm sonucu yazdım , yani kafamdan

yada başka bir şekilde ölçüm şekli yapmadım , Senin osiloskop'un markası nerdir ?

hem ns hem frekans olarak vermiyomu , yani sen ekrana baktığında kaç MHZ olduğunu

yazmıyormu ? , gerçi artık üzerinde fazla durmuyorum , yeni analiz yapıp yazılımı ona göre

optimize etmeyi düşünüyorum , donanımı daha fazla kullanmak lazım olabildiğince yazılımsal

eylemlerden kaçınmak lazım , ve mümkün olduğunca yazılımsal kontrollerden uzak durmak lazım

yani buton okumak için bile portlarla muhattap olmamak lazım , herşeyi interruptlara bırakmak ciddi hız kazandırır...

z

Elimdeki scop HP54603B.

Frekansi 84.30.... 84.75 gibi aralikta farkli degerler olarak gosteriyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com