STM32F407 Cortex M4 şamataları

Başlatan bunalmis, 16 Ekim 2011, 17:14:50

memo333

Alıntı yapılan: fahri- - 02 Kasım 2011, 13:45:13
Hocam sırasımıdır ama;
Pic lerde data set değerlerimizi saklayabileceğimiz eeprom yapısı ARM larda yok sanırım. Bu durumu flash hafızayı kullanarak mı çözeceğiz yoksa harici eeprom mu kullanacağız?

FLASH kullanılıyor. Örnek programda mevcut f1ler için. ancak örnek programda iyileştirmeler yapılmalı, pek yeterli değil.
Gömülü Linux Notları --> http://linuxedu.xyz/

CLR

Alıntı yapılan: bunalmis - 02 Kasım 2011, 10:16:25
Linkini verdiğim programda init aşaması geçildikten sonra, bit atamalarını sadece tek makine cycle'ında yapıyor.

Örneğin 10 adet biti tek tek set yada reset edeceksen bu sadece 10 makine cycle'ı demek. Bundan daha hızlı bit manuplasyonu da olmaz. (Her clockta bir bit set yada reset)

Merhaba,

peki, önce Gpioa odr registerinin 10bitini, sonra Gpiob odr  registerinin 5 bitini set eder misin? Fakat pointerleri set edecekken hazırlamalısın yoksa bir anlamı kalmaz. Hız bakıyorsak herşey aynı anda olmalı.

Knowledge and Experience are Power

z

Alıntı yapılan: eemkutay - 02 Kasım 2011, 14:11:14
Merhaba,

peki, önce Gpioa odr registerinin 10bitini, sonra Gpiob odr  registerinin 5 bitini set eder misin? Fakat pointerleri set edecekken hazırlamalısın yoksa bir anlamı kalmaz. Hız bakıyorsak herşey aynı anda olmalı.

BitBand özelliğiyle hız kazanacaksam yöntemlerimi ben belirlerim.

#define PA10 (*(volatile unsigned short*) 0x424002A8)
#define PB5   (*(volatile unsigned short*) 0x42408294)

int main()
{
      while(1)
          {
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       

           }                                         
}
             
 
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

Alıntı yapılan: bunalmis - 02 Kasım 2011, 16:08:40

BitBand özelliğiyle hız kazanacaksam yöntemlerimi ben belirlerim.

#define PA10 (*(volatile unsigned short*) 0x424002A8)
#define PB5   (*(volatile unsigned short*) 0x42408294)

int main()
{
      while(1)
          {
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       

           }                                         
}
             


Merhaba,

Senin yöntemlerini kullansakta aşağıda tek biti bir cycle'da set ettiğini göremedim. Ayrıca bu kullandığın yapı kullanışlı değil, benim daha öncede söylediğim gibi hangi registerin bitini set etmek istiyorsan o registerin adresini girebilecek bir macro veya tanımlama ile yazman daha doğru olur.

#define BitSet(RegAdr,BitNo,Set_Reset) gibi mesela
#define BitSet(GpioaOdr,10,Set)   
#define BitSet(GpiobOdr,5,Reset)


[IMG]http://img43.imageshack.us/img43/9927/bitbanding.jpg[/img]

Knowledge and Experience are Power

z

Bahsettiğim yöntemle bitbanding işlemini en hızlı yaparsın. ASM ile yazsak ulaşacağımız hız aynen bu olur.

Ben derlediğimde aşağıdaki ekran görüntüsünden de anlaşılacağı üzere bir bit manuplasyonu tamı tamına 1 cycle alıyor.



Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

Senin yapıyor dediğin resimde de 1 cycle değil, iar'daki gibi 3 asm komutu sonunda set ediliyor,

1) 0x08000286'da Pa0'ın adresini alıyor
2) 0x0800028A'da set edeceği değeri yani 1'i diğer reg'e yazıyor
3) 0x08000294'te de gerçekten set ediyor

yani 1 biti set etmek için 3 asm komutu çalıştırması gerekiyor. 3 cycle gerekli yani.
Knowledge and Experience are Power

z

En kötümser durumda klasik manuplasyonla bir biti set etmek için

port adresini oku,
maskeleme verisini oku,
portu oku,
maskeleme verisi ile OR yap,
veriyi porta geri yaz

olmak üzere 5 adım gerekir.

Bitbanding işleminde ise en kötümser durumda

port adresini oku,
porta yazılacak veriyi oku (1)
bu veriyi porta yaz

olmak üzere 3 adım gerekir.

Dolayısı ile tartışmanın anlamı yok, bitbanding zamanlama açısından çok avantajlı.

En iyimser durumda ise bitbanding cycle başına 1 bit değişimi yapabilir. İki ayrı programda örnek verdim, inanmayan scopla pinlere bakar ve toggle etme frekansını ölçer.








Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

Mesele tartışmak değil, 1 cycle'da 1 biti set ediyor olsa çok kullanışlı olacaktı ama öyle değil maalesef, minimum 3 asm komutu çalıştırması gerekiyor dolayısıyla 3 cycle gerekli. Bunu scopla ölçmeye gerek yok, port pinlerinden registerlere yazmadan çıkacak değil.
Knowledge and Experience are Power

z

#338
Neden ısrar ediyorsun anlamıyorum. while döngüsünde 1 cycle da 1 bit set ediliyor işte. Bu en iyimser duruma denk geliyor.
Kendi derlediğin kodlara bakma benim derlediğim kodlara bak. Senin derleyici optimizasyon yapamamış yada sen yaptırmamışsın.

İnit aşamasına takılma ve while döngüsüne iyi dikkat et. Sadece 5 komut var. 5. cisi loop için diğer 4 tanesi de bit set reset işleri yapıyor.


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

İşte hata yaptığın noktada orası zaten, while içinde hep aynı yerde dönüyor diyorsun ama register adresleri ve bit değerleri değişmediği için aynı yerde dönüyor, yoksa 3 asm komutu işletmek zorunda kalacak derleyici.

   
Knowledge and Experience are Power

z

Alıntı Yapbunalmış hocam yanlış değerlendiriyorsunuz, işaretlediğiniz kısmın üstünde de işlemler var sizin bitler ile ilgili olarak. onları da dahil edin. en az 3 cycle
Peki sizleri kırmayayım.   

Alın size daha önce verdiğim kod. 1 cycle da 1 bit manüplasyonu.


#define PA10 (*(volatile unsigned short*) 0x424002A8)
#define PB5   (*(volatile unsigned short*) 0x42408294)

int main()
{
      while(1)
          {
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       
          }                                         
}   
 

Alın buda ikinci ve yavaş olanı.

#define PA10 (*(volatile unsigned short*) 0x424002A8)
#define PB5   (*(volatile unsigned short*) 0x42408294)

void Manuple()
{
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       
}   


int main()
{
      while(1)  Manuple
                                                   
}      
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Alıntı yapılan: eemkutay - 02 Kasım 2011, 20:01:29
İşte hata yaptığın noktada orası zaten, while içinde hep aynı yerde dönüyor diyorsun ama register adresleri ve bit değerleri değişmediği için aynı yerde dönüyor, yoksa 3 asm komutu işletmek zorunda kalacak derleyici.

Bunu zaten söyledik değilmi. En kötü durumda 3 Cycle olur diye.

int main()
{
      while(1)
          {
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PB5=0;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       

             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0;   // GPIOB_ODR da 5 nolu biti set et.
   
          }                                         
}

Oldumu? Gene Cycle başına 1 manüplasyon. İstersen C portunu ilave edeyim. Olmadı D pottunu.

Belli bir port sayısına kadar tek cycleda tek manüplasyonu yapılabilir. Görün artık bunu.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#342
Gerbay ARM asm yi bilirim.

Benim kodlarim oyle cikmaz. Cunku kodlarim immediate index adresleme kullaniyor.

ARM da cok farkli sekillerde yogurt yemeyi bilirim. Mesela verdigin yontem bunlardan birisi ve uzun yoldan yogurt yeniyor.

Elinizde ADR1 ve ADR2 omak uzere iki hedef adres ollsun. Ornegin R2 registerine ADR1 degerini yuklediginizde ADR2 ye ulasmak icin yapmaniz gereken tek sey  R2,#Ofset degerini kullanmak olacaktir. Ancak ADR1-ADR nin mutlak degeri kullanilacak komutlarin narrow yada wide olusuna gore belli bir aralikta olmak zorundadadir.
Fakat verdigim kisa kod (eemkutayin yazmami istedigi kod) gerek ASM kullanıcılarını C'ye alıştırma turları https://www.picproje.org/index.php/topic,36040.0.html
linkinde verdigim uzun program her cycle da bir bir manuplasyonu yapacak kapasitededir. Ofset degerleri secilen register adres uzakliklari icin uygundur.

Bir bitr atanabilecek deger ya 1 yada 0 olacagindan bunlari da R0 ve R1 icine koyarsaniz geriye store komutlari kullanmak kalir.

STR Rn,[R2,#ofset1]
STR Rn,[R2,#ofset2]
STR Rn,[R2,#ofset3]
STR Rn,[R2,#ofset4]
STR Rn,[R2,#ofset5]
STR Rn,[R2,#ofset6]
....
....
STR Rn,[R2,#ofset9]
STR Rn,[R2,#ofset10]
STR Rn,[R2,#ofset11]
STR Rn,[R2,#ofset12]
STR Rn,[R2,#ofset13]
STR Rn,[R2,#ofset14]
....
....
                               
Seklinde bir suru bit manuplasyon komutunu ardi ardina yazarak manuplasyon yapabilirsiniz.  Burada Rn yerine R0 yazarsaniz biti 0 lar, Rn yerine 1 yazarsaniz biti 1 yaparsiniz.         

Burada STR lerin her biri bir manuplasyon yapar. Cunku bitband adres alanina erisilmektedir. Ofsetlerin her biri de R2 nin otesinde bir baska adres. Bu sayede sadece ofseti degistirerek R2 ye deger atmaktan kurtulmus oluyorum.

Kisacasi ARM in nasil yogurt yedigini cok iyi biliyorum.   

Fakat bu demek değilki istenen her bitband islemini tek cycle da yapacak kod yazabilirim. Bunu belirtmistim. En kotu ihtimalle 3 cycle da yazarim. 
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

CLR

Alıntı yapılan: bunalmis - 02 Kasım 2011, 20:31:51

Bunu zaten söyledik değilmi. En kötü durumda 3 Cycle olur diye.

int main()
{
      while(1)
          {
             PA10=1; // GPIOA_ODR da 10 nolu biti set et.
             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PB5=0;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0; // GPIOA_ODR da 10 nolu biti sil.
             PB5=0;   // GPIOA_ODR da 10 nolu biti sil.       

             PB5=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=1;   // GPIOB_ODR da 5 nolu biti set et.
             PA10=0;   // GPIOB_ODR da 5 nolu biti set et.
   
          }                                         
}

Oldumu? Gene Cycle başına 1 manüplasyon. İstersen C portunu ilave edeyim. Olmadı D pottunu.

Belli bir port sayısına kadar tek cycleda tek manüplasyonu yapılabilir. Görün artık bunu.

Olmadı, boşu boşuna inat ediyorsun. Başlangıçta hazırlanmış registerler üzerinden işlem yapıyorsun ve bakın 1 cycle'da oldu diyorsun. Bunu bildiğin için "Belli bir port sayısına kadar tek cycleda tek manüplasyonu yapılabilir" diyosun. Bu bit banding özelliği değil, bu çok working registerli işlemci özelliğidir. İşlemcinin ana registerleri, işlem yapılacak register adreslerini ve bit değerlerini hafızada tutturuyor ve başka işlem yapmadığı için o registerler üzerinde işlem yapmak icap etmiyor ve while içinde döndürdüğü için sanki tek cycle'da işliyormuş gibi söylüyorsun. Oysa farklı farklı registerlerin adreslerini kullansan ve araya işlemcinin working registerlerini kullanmak zorunda olduğu kodlar girse ne demek istediğimi anlıyacaksın.
Knowledge and Experience are Power

z

Inat eden ben degilim sizsiniz. Cunku vermis oldugum orneklere inat eden sizsiniz.

Ozellikle belirtmeme ragmen her istediginiz bitbanding islemini tek cycle da yapacak kod yazamam 3 asm kod gerektirebilecek durumlar var dedim. Yapmami istediginiz A ve B portunda 10 ve 5 nolu bitleri manuple ettim degilmi?. Daha yuzlerce hatta binlerce ornek de yazabilirim. Bu orneklerin hepsi de tek cycle da bitbanding yapar.




Bana e^st de diyebilirsiniz.   www.cncdesigner.com