Arm 1: Stm32 Geliştirme Ortamının Linux’a Kurulumu ve Template Proje

Merhaba arkadaşlar uzun bir süredir blog yazamıyorum. Bunda iş değiştirmiş olmam ve adaptasyon süreci etkili olduğunu düşünüyorum. Bu sıralar evden çıkmadığımız zamanlarda tekrardan yazmak istedim. Twitter dan bir anket yapmıştım hangi konu üzerinde yazmaya devam ediyim diye en çok ARM oy almıştı o yüzden bir giriş niteliğinde olsun dite ARM mimarisine sahip olan STM32 serisi işlemciler için linux da çalışma ortamının kurulmasından bahsedeceğim. Peki neden linux üzerinde geliştirme yapacağız derseniz bu biraz size kalmış bir şey aslında işin detayına daha çok girmek istiyorsanız bir program derlenirken her aşamasına müdahil olmak istiyor olabilirsiniz benim gibi. Fakat bende iş hayatımda mecburiyetten windows üzerinde geliştirmeler yapıyorum çünkü üreticiler linux tarafına yeteri kadar destek vermiyor ve çok kapsamlı projelerde bazı şeylerin otomatik olması isteniyor. Biz burada farklı olarak herhangi bir IDE (Keil, IAR, TrueSTUDIO) kullanmadan geliştirmeler yapacağız. Kendi Makefile dosyamızı oluşturarak kodun her alanına elimizi sürmüş olacağız. Ayrıca hazır kütüphaneler gerekmedikçe kullanmak istemiyorum konunun anlaşılması açısından. Uzun zamandır Nxp kartlarında geliştirme yapıyorum fakat erişilebilirlik olarak sanırsam ST nin ekosistemi daha gelişmiş düzeyde bu nedenle elimde eski bir arkadaş olan STM32F407VG Discovery kartı vardı bütün geliştirmelerimi bu kart üzerinden yapacağım. O halde başlayalım 🙂

Compiler ve Stlink Kurulumu

C veya C++ yazdığınız kodun derlenmersi için “gcc-arm-none-eabi” ve bu derlenmiş dosyayı donanımın içerisine gömmek için ST firmasının geliştirdiği stlink kurulumu yapmamız gerekmektedir. Ben Debian kullanıyorum diğer dağıtımlar için komutlar farklılık gösterebilir.

Stlink kurulumu için gereksinimleri yüklüyoruz.

Yukarıda stlink uygulamasını git reposundan çektikten sonra build aldık ve “st-flash” uygulamasını /usr/bin klasörünün altına taşıdık ve her yerden erişebilecek hale getirdik.

Geliştirmeye başlamak için her şey hazır template projeyi buradan çekerek devam edelim.

Öncelikle kodumuzu derleyip cihaza atalım ve çalıştığından emin olarak başlayalım. Bunun için “make” komutu ile projemizi derleyelim. Daha sonra “make flash” komutu ile Stm32 mize kodumuzu yazalım. Eğer her şey doğru yapılmış ise board üzerindeki mavi led belirli aralıklar ile yanıp sönmesi gerekmektedir.

Daha sonra proje dosyamızın yapısını anlamaya çalışalım “src” klasörünün altında main.c dosyamız bulunmaktadır. Geliştirmelerimizi bu dosyadan yapacağız ilerleyen zamanlarda kendi kütüphane veye classlarımızı yazmaya başladığımız zamanda bu klasöre oluşturacağız. “build” klasöründe derlenen dosyaların binary halleri bulunmaktadır. Board un üzerinde yazdığımız dosyalar bunlardır. “inc” klasöründe projemizin ayağa kalkması için sonradan eklediğimiz dosyalar bulunmaktadır. Bunlar stm32 sistem dosyaları ve proje ayağa kalkarken başlangıç dosyaları bulunmaktadır. Ayrıca derleyici için linker dosyasıda bu klasörün altındadır. Son olarak “libraries” klsöründe ise kullanacağımız kütüphaneler yer almaktadır. Kütüphane seçimi yaparken karşımıza üç farklı seçenek çıkmaktadır. ARM firması tarafında geliştirilen “CMSIS” ve ST tarafından “HAL”, “Standart Peripherals Library”. Burada HAL daha yüksek seviyeli bir programlama sağlamaktadır ve donanım soyutlama katmanı oluşturmaktadır. Bu sayede geliştirdiğimiz kodu farklı donanımlar üzerinde çok fazla değişiklik yapmadan kullanabilme olanağı tanımaktadır. Biz başlangıç olarak CMSIS kütüphanesini kullanarak daha düşük seviye kodlama yapacağız. Böylece register seviyesinde nelerin döndüğünü anlamak daha kolay olacaktır.

“main.c” dosyasını inceleyerek devam edelim. Öncelikle “stm32f4xx.h” başlık dosyamızı kodumuza eklememiz gerekiyor. Bu dosya bize temelde cihaz çevre birimlerine erişmemiz için katman sağlamaktadır. Böylece biz hangi çevre biriminin register adreslerini bilmeden register isimleri ile geliştirme yapabiliyoruz. Dosya içerisinde bolca define ve structlar göreceksiniz çünkü donanıma kolay erişim sağlamamız için hazırlanmıştır. Aslında bu header dosyası cihazın reference manualine göre hazırlanmıştır yani biz bu arayüzü kullanmadan direkt olarak register adreslerini reference manualden de öğrenip o adrese yazma okuma işlemi yapabiliriz.

Gelelim kod da ne yapmak istediğimize basit olarak board üzerinde bulunan user ledlerini kontrol etmek istiyoruz. Mavi ledi belirli aralıklar ile blinky yaptırmak istiyoruz. Cihazın user manualinde o ledlerin hangi pinlere bağlı olduğu belirtilmektedir. Aşağıda görüldüğü gibi PD15 Mavi led e bağlıdır. Yani GPIOD portunun 15. pinini kontrol edersek ledi kontrol etmiş olacağız.

O halde öncelikle GPIOD Portuna clock sinyali ulaştırmamız gerekmektedir. Stm32 üzerinde birden fazla clock hattı bulunmaktadır. Hangisinin GPIOD portuna clock götürdüğünü bulmamız gerekiyor. Bunun için aşağıda ki resimde görüldüğ gibi (@reference_manual 65) bütün GPIO portlarına AHB1 hattı clock sinyali taşıyormuş. Bu clock hatlarının kontrolünü RCC (Reset and Clock Control) çevre biriminin kontrolü ile sağlanmaktadır. Yani RCC çevre biriminin AHB1 hattını enable eden registerına gideceğiz ve D portuna clock sinyali ulaştırması için uygun değer set edeceğiz.

Üstteki kod parçası RCC çevre biriminin AHB1ENR registerına erişerek 0x8 değerini set etmiştir. Peki nereden çıktı bu 0x8 değeri gelin onu inceleyelim. Reference manuelin 180. sayfasında AHB1ENR registerının her bir bitinin neyi kontrol ettiği yazmaktadır. Aşağıda görüldüğü gibi bu registerın 3. biti GPIOD yi kontrol etmektedir. Eğer bu bit değerine 1 yazabilirsek D portuna clock AHB1 üzerinden clock sinyali taşımız olacağız. O halde bu registera 0x00000008 yani 0b0000 0000 0000 0000 0000 0000 0000 1000 yazarsak D portu aktif olmuş olur. Peki neden “|=” operatörü ile yazma işlemi yaptık. Bunun nedeni ise diğer bitlerin değerini değiştirmeden sadece ilgili bite işlem yapmış olduk. Basit C operatör konuları gömülü sistemlerde sıklıkla kullanmaktayız.

Bir sonraki kod parçamız ise ilgili pini yani PD15 pinini çıkış olarak set etmektedir. Aynı şekilde bunun içinde GPIOD çevre biriminin MODER(Mode Register) registerına uygun bir değer yazarak PD15 i output olarak set edeceğiz.

Görüldüğü gibi ilgili registerın 30. ve 31. bitleri 15. pini kontrol etmektedir. Eğer bu bitlere 01 yazar isek PD15 pini output olarak set edilmiş olacaktır.

Daha sonra kodumuzda while(1) içerisine girerek sürekli yapmak istediğimiz işlemleri yazıyoruz. Biz led e toogle yaptırmak istediğimiz için aşağıdaki kodu yazdık.

Bu işlem ise gene GPIOD çevre biriminin bu sefer de ODR(Output Data Register) registerına erişerek PD15 pinine 1 ve 0 sinyali gönderecektir. “^=” bu işlem ise Xor alarak sürekli çıkışı değiştirmektedir.

Son olarak da ledin yanıp söndüğünü görmek için belirli bi süre beklememiz gerekmektedir. Hazır bir kütüphane kullanmadığımız için delay fonksiyonumuz henüz yok bu sebeple rastgele bir süre boyunca işlemciyi bekletiyoruz.

Bu işlemler sadece kartımıza düzgün kod yükleyip çalıştığından emin olmak içindi. Bu süreçten sonra bütün çevre birimleri benzer mantık ile registerlar sayesinde kontrol edilebilmektedir. En basit GPIO çevre biriminin registerları bile detaylıdır çıkış tipinden hızına kadar bütün ayarlamalar yapılabilmektedir. Aslında biz hazır register tanımlamalarını kullanmadan da programlama yapabiliriz. Aynı örneği birde bu şekilde kodlayarak aslında yapılan işin ne olduğunu anlamak önemli.

Yukarıda görüldüğü gibi eğer reference manualden açıp register adreslerini öğrenirsek aynı işlemi kendi tanımlamalarımız ilede yapabiliriz. Bu şekilde geliştirme yapmak tabikide daha zor fakat işleyişin nasıl olduğunu anlamak adına çok önemlidir. Ve bu mantığı anladığınız zaman üreticiden bağımsız bir şekilde yazılım geliştirmeyi öğrenmiş olursunuz.

Arm yazılım geliştirme yazımın sonuna geldiniz bundan sonra daha düzenli bir şekilde adım adım bütün çevre birimlerini anlatmak istiyorum. Bir sonraki yazıda görüşmek üzere.

6 Replies to “Arm 1: Stm32 Geliştirme Ortamının Linux’a Kurulumu ve Template Proje”

  1. Ali Tahir says: Reply

    Faydalı bir içerik olacaktır. Kaleminize sağlık. Libopencm3 kütüphanesine olan yaklaşımınız nedir? Ürün geliştirme açısından ele alacak olursak hangi kütüphane üzerinde geliştirme yapmayı tavsiye edersiniz?

    1. saffetblt says: Reply

      Yorumunuz için teşekkür ederim daha önce kullanmadım Libopencm3 kütüphanesini fakat dediğim gibi bu işi register seviyesini anladıktan sonra istediğiniz kütüphaneyi kullanabilirsiniz. Ben şahsen CMSIS kütüphanesini tercih ediyorum fakat iş hayatında hazır bsp ler üzerinden geliştirmede yapıyorum eğer üretici bana böyle bir imkan vermiş ise tabikide kullanıyoruz. Fakat her zaman bu imkan olmayabiliyor o zamanda oturup kendimiz tek tek yazyoruz 🙂

  2. Hocam çok faydalı bilgiler paylaşıyorsunuz lütfen ara vermeyin. Teşekkürler…

    1. Teşekkür ederim uygun oldukça her fırsatta yazmaya çalışıyorum 🙂

  3. Hocam selamlar, ben gelistirmelerimi hal kütüphanesi üzerinden yapıyorum, takıldığım yerde ref. manual’i açıp gerekirse detaya inebiliyorum, ya da yazılan fonksiyonlarda neler yapılmak istendiğini gayet rahat anlıyorum. Sizce hal kullanimi ilerde dezavantaj yaratır mı ? Tasarimciyi kisitliyor mu ? Profosyonellerin eğilimi ne yönde ?

    1. Merhaba Hal kütüphanesini tabiki de kullanabilirsin hiçbir sorun yok bence. Dediğin gibi alt tarafta neler olduğunu anlıyorsanız işinizi çok hızlandırır. Profesyonel hayatta bazen üreticiler böyle kütüphaneler sağlamıyorlar kendimiz yazmak zorunda kalıyorum. Bazende Hal dan bile daha hazır kütüphaneler veriyorlar o zaman da onu kullanıyorum. Fakat her zaman temelde ne olduğunu bilmem önemli.

Leave a Reply