sayfa başı

3 Nisan 2019 Çarşamba

TAŞINIYORUZ !!



Evet taşınıyoruz. Goggle sites mahallesine taşınıyoruz. Oralar daha bir kolay ve ferah.
Yazıp çizmek daha zevkli. Buyrun buradan takip edin.
İlgili resim                    
                                       https://zafersatilmis.com/

1 Nisan 2019 Pazartesi

Baştan Sona Embedded Linux Kurulumu -2-

BBB İçin Çapraz Derleyici Kurulumu


Kaynak
Tarih
Versiyon
İşlem
Zafer SATILMIŞ
2019-04-01
0.1
Döküman oluşturuldu













Belli bir süre sonra sadece google sites üzerinden yazılarımı paylaşmayı düşünüyorum. O yüzden buradan da beni takip edebilirsiniz.

1.Amaç
Bu belgede BBB için gerekli çapraz derleyicinin(cross compiler) kurulumu ve kullanımı anlatılacaktır. Uboot, Kernel derlenmesi gibi konularda çapraz derleyicimizden faydalanacağımız için kurulumun doğru ve eksiksiz olması gerekiyor. Kurulum Ubuntu-64bit makine üzerinde gerçekleştirilmiştir.
2.Çapraz Derleyicinin Kurulması
2.1.Çapraz Derleyiciler Hakkında
Kendi işlemci mimarisinden farklı bir işlemci için kod üreten derleyicilere çapraz derleyici(cross compiler) denir. Bizim PC lerimizin mimarisi x86 ve bu yüzden BBB için ARM mimarisinde kod üretmemiz gerekiyor. Özetle çapraz derleyicinin görevi budur.
Çalışabilir bir çıktı alabilmek için derleyicinin yanında linker, debugger ve dump programlarına da ihtiyaç vardır. Bunların hepsini içeren programa ise toolchain denir. Bu sebeple bunları bir takım olarak indirip çalışır hale getirmemiz gerekir.
BBB için (64bit) Linaro GCC toolchain kullanmamız gerekiyor. Güncel sürümünü buradan kendiniz de görebilirsiniz.
2.2. Çapraz Derleyicinin İndirilmesi ve Kurulumu
İlk olarak bu bu sitede belirtilen adresten çapraz  derleyicinin güncel versiyonu indirilir. İndirme işleminden sonra tar dosyası istenilen dizine taşınır ve orada açılır. Ben derleyiciler için /opt/ dizinini kullanıyorum. Yanlışlıkla silinmesi ya da bozulması gibi durumların önüne geçmek için burayı kullanıyorum. /opt/ altında toolchain olarak bir klasör oluşturalım ve kurulumu buranın içinde yapalım. Ayrıca Uçan Linux kitabının yazarı olan Nazım Koç bilgilerini referans aldığım için isterseniz onun yapısı gibi bir yapı da oluşturabilirsiniz. Açıkçası ben o şekilde çalışıyorum.
wget -c https://releases.linaro.org/components/toolchain/binaries/6.4-2018.05/arm-linux-gnueabihf/gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz
Daha sonra tar açmak için aşağıdaki komutu koşalım
tar xf gcc-linaro-6.4.1-2018.05-x86_64_arm-linux-gnueabihf.tar.xz


Oluşacak dosya ismi çok uzun olduğu için arm isimli bir dizin ile link yapalım
ln -s gcc-linaro-arm-linux-gnueabihf-4.8-2014.04_linux arm
Bu adımlar sonrasında toolchain kurulumu tamamlanmış olması lazım. arm/bin dizini altında c ve c++ derleyicilerini görmiş olacaksınız. Bendeki görüntü şu şekilde:
Gerekli kütüphaneleri indirmek için ise aşağıdaki komutları koşmamız yeterli.
            apt-get install gcc-arm-linux-gnueabihf

 
Çapraz Derleyicinin Test Edilmesi
Derleyicimizi kurduk bir sorun olduğunu düşünmüyoruz ama yine de test etmek en güzeli. Ubuntu makinenizde daha öncesinden indirip kullandığınız gcc var ise arm için olan gcc ile karışmasını engellemek gerekiyor. Bunun için ilk olarak aşağıdaki komut koşulur:
export PATH=/opt/gomsis/toolchain/arm/bin:$PATH
which arm-linux-gnueabihf-gcc
Bu iki komuttan sonra aşağıdaki çıktıyı almanız gerekiyor. arm kelimesini görüyorsanız içiniz rahat olsun.
/opt/gomsis/toolchain/arm/bin/arm-linux-gnueabihf-gcc
Şimdi hello world uygulamasını derleme zamanı geldi. Eğer bu uygulamayı derleyip cihazda da çalıştığını görürsek o scp hello.out  root@192.168.7.2:/homezaman derleyici işi tamamdır. Çünkü derlenen uygulama sonrasında oluşacak output dosyası BBB bord için uygun olması gerekiyor.
Hızlıca vi ile açtığımız dosyaya hello world uygulamasını yazalım ve aşağıdaki komutları koşarak çapraz derleyici ile derleyelim. Daha sonrasında beaglebone usb kablosu ile pc bağlayalım. Beaglebone usb ile pc bağlandıktan sonra ssh ile scp komutu ile çıktı dosyamızı beaglebone gönderelim.(benim BBB ip: 192.168.7.2)
#include <stdio.h>
int main()
{
     printf("Hello, World!");
     return 0;
}
/opt/gomsis/toolchain/arm/bin/arm-linux-gnueabihf-gcc -C hello.c -o hello.out
scp hello.out  root@192.168.7.2:/home
Bu iki adım sonrasında BBB konsolundan /home dizininde hello.out dosyasını görmüş olacağız. Bu dosya ubuntu tarafında çapraz derleyici ile oluşturduğumuz çalışabilir dosyadır. (chmod 777 hello.out koşmak gerekebilir.)  Dosyayı çalıştırdığımızda Hello World çıktısını görmemiz lazım.
root@beaglebone:/home# ./hello.out
Hello, World!


                                Zafer SATILMIŞ-01.04.2019
                                    İZMİR

Baştan Sona Embedded Linux Kurulumu -1-


Giriş ve U-boot Kavramı



Kaynak
Tarih
Versiyon
İşlem
Zafer SATILMIŞ
2019-03-31
0.1
Döküman oluşturuldu













Belli bir süre sonra sadece google sites üzerinden yazılarımı paylaşmayı düşünüyorum. O yüzden buradan da beni takip edebilirsiniz.

Amaç


Bu belgenin amacı gömülü sistemler üzerinde Linux kurulumunda gerekli ön bilgileri vermektir. Sistem kurulumuna geçmeden önce ne tür sistem kurulumlarının olduğunu görmek ve linux kurulumunun gereksinimlerini aktarmak kurulum yapılırken neyin neden yapıldığını anlamamıza yardımcı olacaktır.   
Ön Bilgiler
Çalışmalar için gerekli donanım olarak BeagleBone Black kullanılmıştır. Linux sisteminin donanımdan bağımsız olduğunu bildiğimiz için sizler de istediğiniz donanım üzerinde bu anlatılanları gerçekleştirebilirsiniz.
Amaç olarak elimizdeki donanımda linux açılması için baştan sona tüm gereksinimleri yerine gerçekleştireceğiz. Gerekli kaynakların nasıl indirileceğini ve nasıl derleneceğini de adım adım yapmış olacağız. Bunun için adım adım aşağıdaki hedefleri tamamlayacağız.
  • Çapraz Derleyicinin Kurulması(cross compiler)
  • U-Boot İndirilmesi ve Derlenmesi
  • Çekirdeğin(Kernel) indirilmesi ve kurulması
  • Kök dosya sisteminin(root file system) kurulması
  • Açılışın gerçekleştirilmesi
Birçok gömülü linux kuruluş yöntemi vardır. O yüzden yukarıdaki adımlar seçilen yönteme göre değişiklikler gösterebilir. Fakat ana mantık aynı olduğu için bir yöntemi öğrendikten sonra diğer yöntemi kavramak çok kolay olacaktır.
Kuruluş yöntemlerini birbirinden ayıran fark Kernel ve RootFs bulunduğu yerlerdir. Örneğin Kernel NAND Flash, SD kart gibi bir yerde olabilir. RootFs için de farklı bir yer seçilebilir. Hatta Kernel gömülü bile olabilir.
Bunların yanında cihazın Kernel ve RootFs den önce çalışması gereken açılış yükleyicisi her zaman donanım üzerinde olmalıdır. SD kart, NAND Flash gibi bord üzerindeki alanlar en çok tercih edilenleridir. ARM sistemler için en çok kullanılan açılış yükleyicisi u-boot olduğu için gerekli çalışmaları u-boot kullanılarak yapılacaktır.
RootFs RAM üzerinde oluşturulan sistemlere Initramfs yapılı gömülü sistemler denir. RootFs uzak sunucuda ya da Kernel içinde ise buralardan alınıp RAM üzerinde açılır. 
 Açılış Yükleyicisi (u-boot)
U-boot açılış yükleyici tüm ARM cihazlar için ortak olmuştur. Firmalar kendi borduna göre u-boot için güncellemeler yaparak kullanımı kolaylaşmıştır.
u-boot iki programdan oluşur. MLO ve uboot.bin MLO ufak bir koddur ve sistemi tek başına açamaz. MLO bordun ROM bulunan basit bir program ile kolaylıkla yüklenir. MLO ayağa kalktığında gerekli adresleri atayıp çevre birimlerin ayağa kalkmasını sağlar. Ayrıca MLO tarafından esas açılış yükleyicisi olan uboot.bin yüklenir.
uboot.bin yükleminden sonra açılış yükleyicisi (u-boot) tamamlanmış olur. Ağ üzerinden ya da yerel cihazlardan Kernel, RootFs dtb, yüklenebilir. U-boot kullanılan bord göre farklı özellikler içerebilir. Tüm özellikler borda ait konfigürasyon dosyasında bulunur. O yüzden u-boot derlemeden önce uygun konfigürasyon dosyası bilinmelidir.
MLO ve uboot.bin dışında ayrıca mkimage programı da gereklidir. u-boot derlendiğinde bu üç dosya oluşur. MLO ve uboot cihazın açılış yükleyicisi için gereklidir. mkimage ise uboot.bin uygulamasının gerekli dosyaları tanıması için dosyaların başına 64 byte bilgi yazar. Bu başlık bilgisi olmadan uboot.bin ilgili dosya üzerinde işlem yapamaz. U-boot dan sonra yüklenmesi gereken Kernel imajı için mkimage ile Kernel imajı olan zImage kodunun başına 64 byte bilgi yazılmalıdır. 
Son Söz
U-boot konusu önemli ve derin konudur. Bordun açılışında önem teşkil ettiği için bu kısımda hata yaşamadan ilerlenmelidir.

19 Mart 2019 Salı

C++ Referanslar

Referanslar


C++ bazı yönleri ile göstergelere(pointer) benzeyen başka bir değişken tipini içerir. Bir değişkeni tanımlanırken & sembolünü kullanılırsa referans türünden bir değişken tanımlanmış olur. Aşağıda referans tanımlamaya bir örnek verilmiştir.
int x;
int& r = x;
Yukarıdaki örnekte referansa ilk değer verilmesi keyfi değildir. Referanslar tanımlarken aynı türden bir değişken ile ilk değer verilerek tanımlanmak zorundadır. Göstergelerde bu zorunluluk söz konusu değildir. Bu yüzden göstergeler ile referansları birbirinden ayıran en büyük özelliklerden biri budur. Örneğin aşağıdaki kod derleme anında hata verir.
int a = 5;
int &r;
Derleyicinin vereceği hata: 'r' declared as reference but not initialized
Referans tanımlanmasında ilk değerini aldığı değişkenin yerine geçer. Bu  yüzden referansa bir nevi takma ad görevini görür.
int x;
int& r = x;
x değişkenine artık r referansı ile de ulaşılabilir. Referansın tanımlanmasından sonra x ve r birbirine bağlanmıştır. Bu bağ r referansının tüm ömrü boyunca devam edecektir. Yani referansa bundan sonra başka bir değişken atanamayacak. Bu durum referanslar ile göstergeleri birbirinden ayıran diğer önemli özellikten biridir. Aşağıdaki örnek kod bloğunda r referansı tanımlanırken a değişkeni ile ilk değer alıyor ve bundan sonraki r referansına atamalar tıpkı a değişkenine yapılan atamalar gibi sadece değer atamasıdır.
#include <iostream>
 
int main()
{
   int a = 5, b = 4;
   int &r = a; // r referansı tanımlanıyor
   std::cout << "a: " << a << " r: " << r << std::endl; // a'nın değeri ve r'nin değeri gösteriliyor
   
   r = b; // r referansına b değişkeninin değeri atanıyor. bu a = b; işlemi ile aynıdır.
   
   std::cout << "a: " << a << " r: " << r << std::endl; // a'nın değeri ve r'nin değeri gösteriliyor
}
r = b; atamasının farkı anlaşıldıktan sonra çıktı olarak a: 5 r: 5 ve a: 4 r: 4 sonuçlarını görürüz. Görüldüğü gibi r hem a değişkenin içeriğini tutuyor ve r yapılan atamalar a ya yapılmış oluyor. Bu yönüyle referanslar göstergelere benzer.

Referansların Kullanımı

Referanslarını nasıl tanımlanması gerektiğini gördük. Şimdi referansların kullanımına değinelim. Referanslar tanımlandığı değişkenin yerine geçtikleri için tıpkı o değişken gibi kullanılabilir. Değer atama, adresini alma ya da diğer işlem operatörleri ile kolayca kullanılabilir. Göstergelerden farklı olarak referansların kullanımında herhangi bir operatör yardımı gerekmez. Ama göstergelerde içerik ataması yapılırken * operatör kullanılması gerekiyor. Örneğin p bir gesterge olsun(int *p;) ++p; operatörün adresini arttırırken ++(*p) ise göstergenin gösterdiği değişkenin değerini bir arttırıyor. Kimi zaman bu durumlar göstergelerde zorluklara ve hatalara yol açıyor. Fakat referanslarda kullanım daha kolay. Aşağıda buna ait bir örnek görülmektedir. Örnekte referansın kullanımına dikkat edilerek incelenmelidir.
#include <iostream>
 
int main()
{
   int a = 5, b = 4;
   int &r = a; // r referansı tanımlanıyor
   int *p; // p pointer tanımlanıyor
   int *p2; // p2 pointer tanımlanıyor
   
   r = b; // referansa b değeri ya ni a ya b değeri atanıyor.
   
   p = &a; //p göstergesine a nın adresi atanıyor
   
   /*p2 göstergesine r referansının tanımlandığı değişkenin adresi atanıyor.
     refereans a değişkenine tanımlandığı için aslında a'nın adresi atanıyor
     Adres kullanımında da tıpkı normal değişkenler gibi kullanıldı*/
   p2 = &r;    

  return 0;
}

Const Referanslar

Referanslar tanımlandığı değişkenin yerine geçip nasıl atama ya da diğer operatörlerle rahatça kullanıyorsak tıpkı değişkenler gibi const olarak da tanımlanabilir. Const olarak tanımlanmasının kullanım yerine göre farklı amacı ve faydaları olabilir. Const kullanım örneklerine geçmeden önce aslında referansların bir const pointer olduğunu görmemiz gerekir. Referanslar adresi değiştirilemez bir const pointer gibidir.
  int a = 5, b = 4;
   int &r = a; // r referansı tanımlanıyor
   int * const p = &a; // const p pointer tanımlanıyor
   /* hatalı, kendisi const olarak tanımlandığı
      için adresi p pointer yeni adres atanamaz     
    */
   p = &b;

Referansa bağlanan değişken tıpkı yukarıdaki örnekteki const pointer gibi değiştirilemiyordu. Referansı const olarak tanımlarsak bu sefer de değer ataması işlemi yapamayız. Bu durum referansı sadece okunabilir bir değişken yapar. Aşağıdaki kodu derlemek istediğimizde derleyiciden hata alırız.
#include <iostream>
 
int main()
{
   int a = 5, b = 4;
   const int &r = a; // r referansı tanımlanıyor

   r = b; // hatalı. const referans, değer atanamaz

   b = r; // referans sadece okundu.

   return 0;
}
Alınan hata: [Error] assignment of read-only reference 'r'
Bu örnek ile const referansların kullanım amacı ve faydası ortaya çıkmış oldu. Const referanslar sadece okuma amaçlı olarak kullanılır. Bu sayede kullanıcının referansın taşıdığı değişkenin içeriğini bozması engellenmiş olur. Hata alımı derleme zamanında rahatlıkla görülür.
Const referanslar ayrıca iki farklı şekilde de kullanılır. Bir değişmezin değerini atama ve farklı türden değişkenin değerini atama işlemlerinde de kullanılabilinir.
#include <iostream>
 
int main()
{
   double d = 35.5;
   const int &r = d;  // farklı türden değişken atanıyor
   
   const int &r2 = 66;  // sabit bir değer atanıyor.
   
   std::cout << "r: " << r << " r2: " << r2 << std::endl; // r'nın değeri ve r2'nin değeri gösteriliyor

   return 0;
}
Yukarıdaki kod örneği hata almadan derlenir ve çıktı olarak r: 35  r2: 66 üretir.

Referansların Parametre Olarak Kullanılması

Referanslar parametre olarak kullanılırken tıpkı göstergeler gibi kullanılır. Parametre değişkeni referans olan fonksiyon aynı türden bir nesne ile çağrılmalıdır. Bu kurala uyarak yapılan çağrıda referans çağrımda kullanılan nesnenin yerine geçer. Referansların özelliklerinden dolayı fonksiyona nesnenin kendisi değil adresi aktarılmış olur. Bu durum tıpkı göstergelerde olduğu gibi hız ve yer kazancı sağlar. Bu çağırma türü call by referance olarak adlandırılır. Aşağıda örnek bir kullanım gösterilmektedir.
#include <iostream>

void func (int &r)
{
   r = 66;
}
int main()
{
   int z = 35;
   
   func (z);
   
   std::cout << z;

   return 0;
}

Örnekte görüldüğü gibi parametresi referans olarak tanımlanmış func fonksiyonu çağrılırken z nesnesinin kendisi kullanılmıştır. Adres ya da herhangi bir operatör kullanılmamıştır.  func fonksiyonuna z’nın değeri değil adresi verilir. Fonksiyon içinde r artık z’nin yerine geçer. Bu durumda r’ ye atanan 66 değeri aslında z’ ye atanmış olur.
Fonksiyon çağrılırken nesnenin sadece ismi kullanıldığı için C++ dilinde bu şekilde çağrımın call by value ya da call by reference olup olmadığını anlamak için fonksiyonun bildirimini yada tanımlamasını görmek gerekir. Örneğin aşağıdaki örnekte z nesnesi iki fonksiyon için argümandır ve fonksiyonların çağrılma biçimleri aynıdır. Fakat fonksiyonların paremetreleri farklı olduğu için işlevleri farklıdır.
#include <iostream>

void foo(int v)
{
   v = 27;
}

void func (int &r)
{
   r = 66;
}
int main()
{
   int z = 35;
   
   foo (z);    
   func (z);
   
   std::cout << z;

   return 0;
}

Diğer bir konu ise referans parametrelerinde const kullanılması. Const referans kullanıldığında ilgili referansa herhangi bir atama yapamadığımızı hatırlamak gerekir. Hatta ata yapılmak istendiğinde hatanın derleme zamanında alındını da biliyoruz. Const referansa atama yapılamadığından bu tür parametreler fonksiyon içinde sadece okuma amaçlı kullanılır. Referans tanımlanmasında fonksiyonu kullanacak kişiye bu değişkenin sadece okuma amaçlı kullanılacağını ve değerinin değişmeyeceği bilgisini vermiş oluruz. Kendi kodlarımızı yazarken bu kurala uyarak kodumuzun okunabilirliğini arttırmış oluruz.
Yukarıda verilen bilgilerin tümü referans aktarılan sınıflar için de geçerli. Bir sınıfı bir fonksiyona argüman olarak gönderdiğimizde aslında sınıfın adresini göndermiş oluruz. Bu sayede sınıf ne kadar büyük olursa olsun yalnızca sınıfın adresi gönderilir.

Referansların Geri Dönüş Değeri Olarak Kullanılması

Bir fonksiyonun geri dönüş değeri referans olarak tanımlanabilir. Bu biçimce kullanımlarda tıpkı geri dönüş değeri gösterge olan fonksiyonlardaki gibi dikkatli olmalıyız. En çok yapılan hata yerel bir değişkeni göstergeyi geri dönüş değeri olarak kullanmaktır. Aynı tehlike referanslar için de geçerlidir. Geri dönülecek değer fonksiyon bitiminden sonra da hala aktif oluyor olması lazım. Bu duruma örnek olarak global değişkenler ya da static değişkenler verilebilir. Aşağıda örnek kullanımı gösterilmiştir.
#include <iostream>

int gValue = 66;

int & getGlobalValue (void)
{
   int &r = gValue;    
   return r;
}
int & getStaticValue(int v)
{
   static int s;
   int &r = s;

   s = v;        
   return r;
}
int main()
{
   int z;
   int p;
   
   z = getGlobalValue();
   std::cout << z <<std::endl;
   
   p = getStaticValue(z);
   std::cout << p <<std::endl;
   
   getGlobalValue() = getStaticValue(0);
   
   std::cout << gValue <<std::endl;

   return 0;
}
Yukarıdaki örnekte özellikle getGlobalValue() = getStaticValue(0); satırını anlamadan geçmeyin. Referanslar bir değişkenin yerine geçtiğini unutmayın.
Kod yazarken referansmı yoksa gösterge mi kullanılmalı ikilemine girmemek için aklınızda şu kuralı tutun: Referans kullanımı mümkün ise referans kullan, aksi durumda gösterge kullan. Yani kısaca gösterge kullanmanın çok fazla bir artısı yok ise hiç düşünmeden referans kullanın.

İyi Çalışmalar. 22.03.2019-İzmir