Konuyu Değerlendir
  • 0 Oy - 0 Ortalama
  • 1
  • 2
  • 3
  • 4
  • 5
Arduino ve Assembly Kod Entegresi
#1
Arduino ve Assembly Kod Entegresi nasıl olur?
Arduino IDE’sinde çalışırken genelde C’ye benzeyen bir lisanda kodlama yapılır. Buna ilaveten özel bir fonksiyon kullanarak Assembly lisanı da kullanılabilir. Arka planda da Arduino kodlarını işleyen GCC derleyicisi C-Kod ve assembly lisanda yazılmış kodların tümünü entegre edip Arduino’ya yüklediğimiz en son da kodlamayı tamamlar.
Aşağıda bu entegreyi gösteren ufak bir de örnek sunuyorum:
Alıntı: volatile byte benimNum = 10;
void setup() {
Serial.begin(9600);
Serial.print("ASMden önce...");
Serial.println(benimNum);
asm (
  "lds r16, (benimNum) \n" // benimNum değişkenini saymaç r16'ya yükle
  "inc r16 \n"             // r16 saymacını 1 artır
  "sts (benimNum), r16 \n" // r16 saymaç değerini benimNum değişkenine yükle
);
Serial.print("ASMden sonra...");
Serial.println(benimNum);
}
void loop() { }
Örnekte benimNum değişkeni tanımlanıp 10 değeri de atanıyor. Seri port hız ayarından sonra “ASMden önce…10” olarak bu değer Seri monitöre yazılıyor. Arkasından asm( ) komutuyla assembly diline geçiliyor. benimNumdeğişken değeri r16 saymacına yükleniyor ve saymaç bir artırılıyor. Sonra yeni saymaç değeri (11) tekrar benimNum değişkenine yükleniyor. Ve Seri monitöre bu yeni değer “ASMden sonra…11” olarak yazılıyor.
Bu basit örnekte önemli olan kodun ne yaptığı değil, kullanılan sözdizimidir:
  • Gördüğünüz gibi, standart Arduino değişken tanımı ve üç tane ‘Serial’ komutundan sonra gelen asm( ); komutu kullanılan dili assembly’ye geçiriyor. Yani asm(); Arduino kodunun bir fonksiyonu gibi davranıyor.

  • Her asm kod satırı “…” arasına yazılıyor.

  • Her satır tek bir ASM komutundan oluşuyor.

  • BLINK örneğindeki gibi “bekle:” tipinde etiketler hem altyordam hem de döngüler için kullanabiliyor.

  • Satır sonları kod listelemesini daha kolay okuyabilmek için \n kontrol karakteri ile sonlanıyor.

  • “…” dan sonra istenirse // kullanarak, Arduino kodundan olduğu gibi, açıklama yazılabiliyor.

  • asm( ); den sonra tekrar Arduino koduna geçilebiliyor.

  • Arduino kod … asm kod … Arduino kod sözdizimi istenildiği kadar tekrarlanabiliyor.
Burada gördüğünüz asm sözdizimi kuralları sizi assembly dilini denemeye başlatacak temel kurallardır. Fakat bunların ötesinde ve burada anlatmamıza imkan olmayan değişik bir sürü kural daha vardır. Unutmayın ki, Assembly dili her işlemci için değişik olup, işlemci yapısına göre de değişik komutlar içerir. Bundan dolayı bu dilde çalışmak özel bir yaklaşım gerektirir.
Daha geniş bir çalışma arzu edenler, “Official AVR-GCC Inline Assembler Cookbook” adlı sayfaları inceleyebilirler. Veya “Inline Assembler” terimini arayarak Internet’ten daha detaylı bilgi edinebilirler.
Assembly ile de BLINK Projesi
Buraya kadar takip edebildiyseniz, simdi BLINK projesini assembly dilinde yazmaya başlayalım:
  • Yakıp söndüreceğimiz led Arduino ana kartı üzerindeki LED13 dür.

  • Led yanıp sönme süresini 200ms olarak ayarlayacağız.

  • LED13’e ulaşabilmek için IOreg adres modunu kulanacağız.

  • LED13’ü yakıp söndürmek için EOR (dışlamalı veya operatörü) işleminden yararlanacağız.
Aşağıdaki kodumuzu satır satır inceleyelim:
Alıntı: 001 /*  ASM diliyle BLINK
002      Bu program ATMEGA'nın PIN, DDR ve PORT yazmaçlarını kullanarak
003      PIN ayarları yapmayı gösteriyor.
004      Kod IOreg adresi tekniğini kullanıyor.
005
006      PINB  IOreg = 0x03     offset = 0x23
007      DDRB  IOreg = 0x04     offset = 0x24  
008      PORTB IOreg = 0x05     offset = 0x25
009      PINC  IOreg = 0x06     offset = 0x26
010      DDRC  IOreg = 0x07     offset = 0x27
011      PORTC IOreg = 0x08     offset = 0x28
012      PIND  IOreg = 0x09     offset = 0x29
013      DDRD  IOreg = 0x0A     offset = 0x2A
014      PORTD IOreg = 0x0B     offset = 0x2B
015
016      SAYMAÇLAR:  X: r27:r26          Y: r29:r28          ve Z: r31:r30
017 */
018
019 void setup() {
020   DDRB = DDRB | B00100000;      // d13 ÇIKTI olsun
021
022   asm  (
023     "jmp basla \n"
024     "bekle: \n"                 // 200ms geciktirme
025     "    ldi  r18, 17"    "\n"
026     "    ldi  r19, 60"  "\n"
027     "    ldi  r20, 204" "\n"
028     "1:  dec  r20"  "\n"
029     "    brne 1b"   "\n"
030     "    dec  r19"  "\n"
031     "    brne 1b"   "\n"
032     "    dec  r18"  "\n"
033     "    brne 1b"   "\n"
034     "    ret \n"
035    
036     "basla: \n"
037     "ldi r21, 0b00100000 \n"   // PORTB ayarı saymaç r21'e yükle (D13 on)
038   );
039 }
040
041 void loop() {
042   asm  (
043     "in r22, 0x3 \n"           // PINB (IOreg = 0x03) değerleri r22 ye yükle
044     "eor r22, r21 \n"          // LED13'ü pinini XOR'la
045     "out 0x5, r22 \n"          // PORTB saymacını güncelle (IOreg = 0x05)
046     "call bekle \n"
047   );
048 }
001-018: Program açıklamaları
019-021: SETUP kısmının başlangıcı. DDRB saymacı kullanarak D13 pinini OUTPUT (Çıktı) olarak ayarlıyoruz. DDRB saymacı dijital 8-13 pinlerini kontrol eder. Bu saymaç değerine ikili sabit B00100000 ile mantıksal OR (ve) işlemini uygulayınca D13 pinine rastgelen DDRB bit’ini 1 yapmış oluyoruz. Yani D13’ü çıkış olarak ayarlıyoruz.
022-040: Assembly dilinde kodumuzun ilk kısmı.
023: Satır 024-034 arasındaki bekle etiketli 200ms geciktirme kodunu işlemeden üzerinden basla etiketine atlıyoruz.
024-034: bekle adını verdiğimiz 200ms geciktirme kodu. Bunu AVR Gecikme Döngüsü Hesap Makinesi sayfasından aldık. Bu kodun bir alt yordam olarak çalışması gerektiğinden, siteden aldığımız kodun önüne bir etiket (“bekle: \n”) sonuna ise bir (” ret \n”) komutu ekledik. RET komutu kodun bu satırına gelindiğinde RETURN (geri dön) işlemiyle geciktirme kodunu çağıran yere geri döner.
035-036: basla etiketi. Önündekii boş satır sadece kolay okunsun diye.
037:  İkili sabit 0b00100000 değerini r21 saymacına bit maskesi olarak yüklüyoruz. PORTB saymacı dijital 8-13 pinlerini kontrol ettiğinden bu sabit değerdeki 1 bit’i D13 pinini belirtiyor. r21 saymacı tamamen bizim isteğimizle seçilmiş bir saymaç.
038: ASM kodun sonunu belirten “)” parantez.
039: SETUP sonu.
041-048: LOOP döngüsü.
042: LOOP içindeki assembly kodumuzun başlangıcı.
043: PINB (IOreg = 0x03) saymacındaki anlık pin durum değerlerini r22 saymacına okuyoruz.
044: EOR işlemi: r21’de sabit bit maske değeri 0b00100000 var. r22’de 8-13 dijital pinlerin anlık durumu var. EOR işlemi bittiğinde r22 deki değer r21’in içindeki 1 bit’in olduğu yerde aksine dönüyor. r21 değeri aynı kalıyor. Bunu tekrarladığımızda r22 değeri gene r21’in içindeki 1 bit’in olduğu yerde aksine dönüyor. Böylece EOR kullanarak d13 pin ayarını 0 ve 1 arasında değiştiriyoruz.
045: OUT komutu r22 saymacındaki değişmiş değeri PORTB saymacına (IOreg = 0x05) yazıyor. Yani D13 led’in yanıp sönmesi donanıma yansıtılıyor.
046: 200ms gecikme yapan bekle alt yordam çağrılıyor. 024-034’de anlatıldığı gibi, bekle bitince bu noktaya geri döner.
047: ASM kodun sonu.
048: LOOP döngüsü sonu.
— KOD SONU —
Gelecek Yapay Zeka İle Gelecek
Alıntı


Foruma Git:


Bu konuyu görüntüleyen kullanıcı(lar): 1 Ziyaretçi

Hakkımızda
    Yapay Zeka Forum , Yapay Zekayı Türkiye'ye tanıtmak ve bu alanda Türkçe kaynak sıkıntısını gidermek ve aynı zamanda Yapay Zekaya ilgi duyan tüm kişileri bir araya getirmek amacıyla kurulmuştur.

Yapay Zeka Forum


yapay zeka

,

yapay sinir ağı

,

yapay sinir ağları

,

derin öğrenme

,

makine öğrenmesi