Picproje Elektronik Sitesi

PICPROJE PROGRAMLAMA DERSLERİ => Arm Öğreniyoruz => Konuyu başlatan: z - 31 Ekim 2011, 17:57:22

Başlık: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 31 Ekim 2011, 17:57:22
Bu başlık da daha önceleri açtığımız BASIC kullanıcılarını C'ye alıştırma turları na benzer şekilde ilerleyecektir.

Amacımızın Keil ile ARM işlemcilere C kod yazmak olduğunu unutmayın.

Ancak bu kez katılımcı sayısı konusuna sınırlama getirmeyeceğim.

https://www.picproje.org/index.php/topic,35980.msg257667.html#msg257667 (https://www.picproje.org/index.php/topic,35980.msg257667.html#msg257667) başlığındaki konuları tekrardan anlatmayacağım.

Tartışmaya katılacak ASM ci arkadaşların ASM kodla örnek vermeleri yerine, hangi işlemleri yapmak istediklerini yazarak sormalarını, ve buna cevaben C kodlarını yazacağımızı hatırlatayım.

Örneğin  A ve B adındaki 8 bitlik değişkenlerimde saklanan iki sayıyı toplayıp sonucu 16 bitlik X değişkenine yazmak istiyorum dediklerinde

char A,B;
int X;
           
           // A ve B nin değer aldıklarını varsayın

           X= A+B; örneğini vereceğiz.


Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: muhendisbey - 31 Ekim 2011, 21:09:23
ASM'de register olarak kullandığımız 8 bitlik saklayıcılar (A. satırdan B. satıra şeklinde), C de neye tekabul ediyor değişkene mi?

C de CPU registerleriyle normalde işimiz olmaz.

C de değişkenler tanımlar ve işlemleri doğrudan bu değişkenler üzerinde yaparız.

Bir de C de bit düzeyinde işlem yapmak mümkün mü? Yani 3. bitin 1 olduğunu anlamak için sadece 3. biti nasıl öğrenebiliriz?

Eğer işlemcinizde bit bazında işlem yapan asm komutlar yoksa siz ne yapardınız? C de de aynısını yaparız.

Eğer işlemcinin bir bazında işlem yapan komutlar varsa C'de de bu anlamda komutlar vardır.

Örneğin ASM yazımınızda B.1, 8 bitlik değişkenin 1 nolu biti demek ise muhtemelen C de de B.1 yada benzerı yazım geçerli olacaktır.

Fakat en kötü ihtimal  if ((B>>3)&1) komutu, B nin 3.biti 1 ise karşılaştırmayı doğru kılacaktır.

Buradaki 3 kez sağa kaydırma, ARM işlemcide tek clock da yapılacağından zaman kaybı olmayacaktır.

(ARM işlemcinin Ram ve çevre birimi registerlerinin bazılarına bit bazında da erişilebilir.) (Sadece I/O Portlara mı  yoksa hepsine mi araştıralım)



Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: Klein - 01 Kasım 2011, 17:28:17
Aslında C'de doğrudan bit işleyen komutlar yok. Ama bu sorunu struct, union yapısı ile çözebiliriz.

union{
unsigned char structbyte;
struct{
    unsigned char bit_1 : 1;
    unsigned char bit_2 : 1;
    unsigned char bit_3 : 1;
    unsigned char bit_4 : 1;
    unsigned char bit_5 : 1;
    unsigned char bit_6 : 1;
    unsigned char bit_7 : 1;
    unsigned char bit_8 : 1;
  };
} test;

bu şekilde bir tanımlama ile bit kullanımı mümkün.
test.bit_1 = 0 , test.bit_2 = 1; 
ya da test.structbyte = 78;

IAR derleyicisi bu şekildeki bit operasyonları için  işlemcinin komut setindeki bit operatörlerini kullanıyor. Belki derleyiciye göre değişiyordur.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: muhendisbey - 01 Kasım 2011, 23:43:49
hocam bunalmış hocamızın dediğini anladım ama sizin dediğiniz yöntemden tek bir satırı anlayamadım açıklayabilir misiniz?
Bir de bunalmış hocam işlemcide bit düzeyinde işlem varsa yada yoksa diye birşey belirtmiş. Böyle bir işlemci var mı ki bit düzeyinde işlem yapmasın?
Bu soruyu sorma amacım birçok kişi C de yazarken yazılımın çok şiştiğinden bahsetmiş forumlarda, bit düzeyinde yapılan işlemin hem düşük güç kontrolü açısından hem de yazılım boyutu açısından ekonomikliği bulunmakta. C kullanırken buna nasıl dikkat edebilirim maksadındaydı.

Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: Veli B. - 02 Kasım 2011, 02:15:23
ARM ailesinde bazı işlemciler "bit banding " olarak geçen bir manipulasyon desteği sunuyor(ör Cortex-M3/-M4) . Bit Banding piclerde ki BSF BCF gibi.
Örneğin ben Cortex M0 kullanıyorum ve Bit Banding desteklemiyor. Bu durumda Klein Üstadımın bahsettiği gibi aynı alanı gösteren bir union ve hedefi gösteren bir Struct ile alias oluşturup hedefin istediğimiz yerine ateş edebiliyoruz.

Üst seviye Cortexler için "Bit Banding" olarak aratırsanız detay bilgi bir haylice var. ARM da bununla ilgili bir makale de vardı sanırım.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 02 Kasım 2011, 04:48:12
Alıntı yapılan: muhendisbey - 01 Kasım 2011, 23:43:49
hocam bunalmış hocamızın dediğini anladım ama sizin dediğiniz yöntemden tek bir satırı anlayamadım açıklayabilir misiniz?
Bir de bunalmış hocam işlemcide bit düzeyinde işlem varsa yada yoksa diye birşey belirtmiş. Böyle bir işlemci var mı ki bit düzeyinde işlem yapmasın?
Bu soruyu sorma amacım birçok kişi C de yazarken yazılımın çok şiştiğinden bahsetmiş forumlarda, bit düzeyinde yapılan işlemin hem düşük güç kontrolü açısından hem de yazılım boyutu açısından ekonomikliği bulunmakta. C kullanırken buna nasıl dikkat edebilirim maksadındaydı.

Elbette yazılımla bit manuplasyonuna gerek duyan daha açık ifade ile donanımsal olarak bit işleme komutları olmayan işlemciler var.
Mesela, bit bazında işlem yapan makine komutları, PIC ve 8051 de var fakat, 8086 ve DSP lerde yok. CM3 işlemcilerin register üzerinde bit maniplasyonu yapan komutları var.
---------------------------
Mesela 8 bitlik bir portun 0. bitine 1 yüklemek için bit erişim komutu olmayan bir işlemci kullanıyorsan

porta daha önceden yüklenmiş olan veriyi tespit edip (bu portu okumak olabilir) ardından sonucu 0x01 ile OR layıp gerisin geriye porta yazabilirsin.

Aynı şekilde 0. biti o yapmak istiyorsan portu okuyup 0xFE ile AND leyip gerisin geriye porta yazabilirsin.

Eğer işlemcinin zaten bitmanuplasyon komutları varsa ya da erişmek istediğin alan Bit Band özelliğinde ise o zaman yukarıdaki uzun yönteme gerek kalmaz.

Derleyicinin hangisini tercih edeceğini hatta bu tercihi kendisi yapabilirmi yoksa biz mi zorlayacağız konusunu bilmiyorum. En kısa zamanda bu konuyu araştırıp örnekle açıklamak istiyorum.

Çok iyi düşünülerek yazılmış ASM programların çok iyi düşünülerek C ile yazılmış programlardan daha kısa ve hızlı olacağı konusunda sanırım hemfikiriz. Ancak ARM dünyasına geçtiğimizde bu işlemciyi genellikle büyük projelerde kullanmak isteriz.

Bu durumda amaç, kısa kod yazmak yerine projeyi gerçeklemek olmalıdır. Özellikle ve özellikle, hızlı koşmasının çok da şart olmadığı rutinleri C ile kodlama fikrini benimsemekte fayda var.

Çok optimize sonuç verecek ASM yazım, fazlasıyla zahmetli ve mevcut seçenekleri kimi zaman tek tek yazıp elemeyi gerektirdiğinden, mecbur kalmadıkça tercih edilmemelidir.



Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 02 Kasım 2011, 06:25:54
Bit Banding

CM4 işlemcimizde çevrebirimlerinin registerleri ile SRAM alanı üzerinde bit işlemleri yapılabilmekte. (Ancak bu işlemlerin doğrudan işlemci ile yapılması gerekiyor. DMA ile yapamıyoruz.) Word olarak erişilen alanı ister word data yükleyerek değiştirebiliyoruz istersek bit banding yaparak. (Word alias konusuna bir ara değinelim, unutturmayın)

Hedef alanda bir biti değiştirmek için Bu bitin bit band alanındaki adresini hesaplamamız gerekiyor.
bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4)

Örneğin RAM'ın ilk adresi olan 0x20000000 da 2.biti (0 dahil sayarsak 0,1,2) 1 yapalım.

Bit_Band_Base = 0x22000000,  Byte_Offset = 0x0000 * 0x32,  Bit_Number = 2

Bit_Word_Addr=0x22000000 + 0*32 + 2*4 =0x22000008

Bunu test etmek için aşağıdaki programı Keilde deneyin. A ve P değişkenlerini Watch1 de gözleyin.

#include "STM32F4xx.h"
unsigned short A;

void SystemInit()
{
}

unsigned short* Bit_Adr(int Wadr,char BitNum)
{
      return((unsigned short*)(0x22000000 + ((Wadr - 0x20000000)<<5) + (BitNum<<2)));
}

int main()
{
unsigned short* P;
     A=0;
     P=Bit_Adr((int)&A,2);
    *P=1;
   
}

Yukarıdaki program A=0 ataması ardından Anın 2.bitini set etmektedir.  Basit bir bit manuplasyonu için fazlaca uzun bir işlem mi dersiniz? 
Devam edeceğiz.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 02 Kasım 2011, 07:08:25
Memoryde  MyTarget adındaki 16 bitlik adresde bit manuplasyonu yapmak için;

P pointerimize  P=((unsigned short*)(0x22000000 + ((MyTarget - 0x20000000)<<5))); yükleyelim.   P bizim MyTarget adresinde 0. biti referans gösterir.  n.pozisyondaki biti set etmek istersek word pointera 2*n eklemek ( adresi 4*n byte ilerletmek) yeterli olacaktır.   

#include "STM32F4xx.h" unsigned short A;

void SystemInit()
{
}   

unsigned short* Bit_Adr(int Wadr,char BitNum)
{
    return((unsigned short*)(0x22000000 + ((Wadr - 0x20000000)<<5) + (BitNum<<2)));
}   


int main()
{
unsigned short* P; 

     A=0;
     P=Bit_Adr((int)&A,0);


    *(P+0x000)=1;      // 0. Biti set et
    *(P+0x002)=1;      // 1. Biti set et 
    *(P+0x004)=1;      // 2. Biti set et 
    *(P+0x006)=1;      // 3. Biti set et 
    *(P+0x008)=1;      // 4. Biti set et 
    *(P+0x00A)=1;      // 5. Biti set et 
    *(P+0x00C)=1;      // 6. Biti set et 
    *(P+0x00E)=1;      // 7. Biti set et 
    *(P+0x010)=1;      // 8. Biti set et 
    *(P+0x012)=1;      // 9. Biti set et 
    *(P+0x014)=1;      //10. Biti set et 
    *(P+0x016)=1;      //11. Biti set et 
    *(P+0x018)=1;      //12. Biti set et 
    *(P+0x01A)=1;      //13. Biti set et 
    *(P+0x01C)=1;      //14. Biti set et 
    *(P+0x01E)=1;      //15. Biti set et 
    *(P+0x020)=1;      //16. Biti set et   (!!! MyTarget'i takip eden adrese duhul ettik !!!)
    *(P+0x022)=1;      //17. Biti set et 
    *(P+0x024)=1;      //18. Biti set et 
    *(P+0x026)=1;      //19. Biti set et 
    *(P+0x028)=1;      //20. Biti set et 
    *(P+0x02A)=1;      //21. Biti set et 
    *(P+0x02C)=1;      //22. Biti set et 
    *(P+0x02E)=1;      //23. Biti set et 
    *(P+0x030)=1;      //24. Biti set et 
// .....
// .....     
}   

Şayet her bir bit değişkenin adresini sabitlersek bu durumda pointer üzerinde toplama işlemi yapmaya gerek kalmaz ve

Bit değişkenlerimiz A0,A1,A2,A3... B0,B1,B2,B3... gibi isimler alabilir.

Bunların herbirisinin adresi belli olduğundan;

B1=A1;  B7=A6 & B3; vs vs işlemler, klasik yazılımla yapılacak bit manüplasyon işlemlerine kıyasla  son derece hızlı yapılacaktır.

(Yukarıdaki örnek programı aynen kullansanız dahi Keil çok optimize kodlar üretmektedir)
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: taneryilmaz - 02 Kasım 2011, 11:13:20
merhab abunalmış hocam bu konuya ben de dahil olmak istiyorum . burada siz ben den bir program isteseniz ben de asm sini yazsam   sonra sizde  C ye çevirseniz olur mu ?
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 02 Kasım 2011, 11:29:35
ARM asm yazacaksan olur.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: muhendisbey - 05 Kasım 2011, 14:39:24
C de alt program nasıl yazılır? ve bu alt programlar ana programa nasıl dahil edilir?
bunun için 200ms lik gecikmeyi ana program içinde kullanmaya örnek verebilir misiniz?

Bir diğeri tablo alt program, bunu nasıl C de yaparız?
Bunun için de seven segment display 0-9 sayıcı örneği verebilir misiniz?
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 05 Kasım 2011, 15:01:28
Alt program dediginiz sey C deki fonksiyolar.

Ornegin CALL TOPLA gibi bir asm satirini C'de

TOPLA(); diye kullaniriz.

-------------------

200ms lik gecikme rutinini eger asm de zaman kaybeden kodlari calistirarak gercekliyorsaniz C de de bunu

for(i=0;i<10000;i++); gibi i nin volatile ekiyle tanimlandigi kodla yada benzeri ile gerceklestiririz.

Isin icine CPU clk frekansini da dahil edip 10000 gibi bir sayiyi CPU CLK degerine gore modifiye eden fonksiyonu  yazmak da mumkundur.

Eger 200ms yi timer ile yaptirdiysaniz C de mantik ayni.

--------------------

Tablolari C de array olarak tanimlariz. Eger amaciniz bir tabloya fonksyonlarin adreslerini yerlestirmek ve bir indise gore bu fonksyonlari cagirmak ise
fonksiyon adreslerini array icine yazmaniz yeterli. Bu konuda ornegi bir baska mesajimda verecegim.


Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: muhendisbey - 25 Kasım 2011, 20:46:55
Hocam UART ile iletişim kurmak istesek, buna uygun porta göre bağlantımız yapılmış olsun. Mesela iletmek istediğim bir metin olsun "bunalmis" mesela bunu nasıl göndeririz? Sıfırdan kütüphane oluşturmak mı gerekir, yoksa bunu sağlayacak yapı Keil içerisinde var mı?
Bunu şu açıdan da soruyorum bluetooth üzerinden porta çıkış vermeye uğraşıyorum.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: muhendisbey - 25 Kasım 2011, 20:48:13
Bir de yazmayı unutmuşum yukarıda diğer mesajda yanıtlayacağınız sorumu cevaplayabilirseniz memnun olurum.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: yamak - 05 Ocak 2012, 19:36:00
Hocam şimdi ben C de program yazarken bir değişken tanımlıyorum bu değişkenlerle işlem yaparken aslında arm işlemcimizin r0-r12 registerları ile işlem yapıyoruz değil mi?Eğer durum böyle ise değişken tanımladığımız bu r0-r2 registerlarının arasından hangisi ile işlem yapılacağı nasıl belirleniyo.Bir de bir çevre-birimine ait bir register a bir değer atayacağımız zaman ilk olarak r0-r12 registerlarına kaydedilip daha sonra mı o registera kaydoluyo yoksa direkt olarak mı kaydediliyo.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: yamak - 05 Ocak 2012, 21:36:27
Hocam bu derleyiciyle alakalı bişey değil mi? Yani derleyiciyi kim yazdıysa onun belirlediği kurallar.
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: cooldoubtless - 06 Ağustos 2012, 02:35:05
BUNALMIŞ HOCAMIZ DISCOVERY KİT HAKKINDA ÖRNEKLER VERİRKEN

//  FLASH->ACR = 0x00000705;           // Flash ROM icin 6 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55) Yazmamız gereken asıl kod bu fakat çipte bug var
   
    FLASH->ACR = 0x00000605;           // Flash ROM icin 6 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55) Mecburen bunu yazacağız.

gibi bir açıklama yapmış ancak burada neden 0x0605 değerini kullandığımızı ben anlayamadım çipte bug olması ne demek ve de neden bu değeri(PREFETCH bitini) etkiliyor? Diğer konular kilitli olduğundan buraya yazmak zorunda kaldım özür dilerim...
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: camby - 04 Kasım 2012, 17:13:32
Alıntı yapılan: z - 02 Kasım 2011, 06:25:54

#include "STM32F4xx.h"
unsigned short A;

void SystemInit()
{
}

unsigned short* Bit_Adr(int Wadr,char BitNum)
{
      return((unsigned short*)(0x22000000 + ((Wadr - 0x20000000)<<5) + (BitNum<<2)));
}

int main()
{
unsigned short* P;
     A=0;
     P=Bit_Adr((int)&A,2);
    *P=1;
   
}


Hocam bu yapı ile istediğim portun bitine Bitband kullanarak yazabiliyorum ancak kafama takılan bir nokta var.

P pointer'ına sizin örneğinizde yüklenen değer 0x22000008 , benim örneğimde de 0x422201A0 gibi bir değer ( GPIOC->ODR, Bit8 ) ve sorunsuz çalışıyor gibi.

Ancak P pointerını unsigned short olarak tanımladık yani 16bit. Fakat 32 bitlik adresleri P pointer'ı ile kullanıyoruz , değeri hesapladığımız fonksiyondan 16 bit short bir değerle dönüyoruz.

Burada kaçırdığım bir şey mi var acaba diye sormak isterim size ?

mesaj birleştirme:: 04 Kasım 2012, 17:13:58

Alıntı yapılan: camby - 04 Kasım 2012, 17:13:32
Bu yapı ile istediğim portun bitine Bitband kullanarak yazabiliyorum ancak kafama takılan bir nokta var.

P pointer'ına sizin örneğinizde yüklenen değer 0x22000008 , benim örneğimde de 0x422201A0 gibi bir değer ( GPIOC->ODR, Bit8 ) ve sorunsuz çalışıyor gibi.

Ancak P pointerını unsigned short olarak tanımladık yani 16bit. Fakat 32 bitlik adresleri P pointer'ı ile kullanıyoruz , değeri hesapladığımız fonksiyondan 16 bit short bir değerle dönüyoruz.

Burada kaçırdığım bir şey mi var acaba diye sormak isterim size ?

mesaj birleştirme:: 04 Kasım 2012, 17:15:21

Burada düzenleme yapılamıyor sanırım bu sayede öğrenmiş oldum : )
Başlık: Ynt: ASM kullanıcılarını C'ye alıştırma turları
Gönderen: z - 04 Kasım 2012, 17:41:00
Pointerin tipi ile point edilen yere yazılacak verinin uzunluğu anlaşılmalı.

ARM işlemcide memory 32 bit adreslenir. Dolayısı ile pointerler fiziksel olarak 32 bit deger saklar. Pointerin short int tanımlanması 32 bitlik ile adreslenen alana 16 bitlik veri yerleştirilmesine izin verir.

0x01
0x0001
0x00000001
0x0000000000000001

Yukarıda 1 sayısını görüyorsun. Bunların memorye yerleşimi 32 bitlik pointer ile yapılır fakat her biri memory de farklı uzunlukta alan kullanır.