20
Oct
2020

Stage-d (final)

Görevler:

  • Yardımcı global fonksiyonların ve yapıların belirlenmesi ve tanımlanması
  • Test için fonksiyonların tanımlanması
  • Test

Bu kısımda Master’ın taleplerini application-layer’da kendimiz yazarak test edeceğiz. Uygulamanın şuanki hali için application-layer main dosyamızdır.

Yardımcı global fonksiyonlar, geliştirilen uygulamanın data parsing işlemlerini, dönüşüm işlemlerini ve bunun gibi sıklıkla uygulama katmanında ya da ara katmanlarda ihtiyaç duyulan fonksiyonlardır.

Bu fonksiyonları belirleyebilmek tecrübe ile sabittir. Çoğu zaman uygulamayı geliştirirken karşımıza çıkan ara işlemlerin başka fonksiyonların ya da modüllerin de kullanımına sunabilmek için bu fonksiyonları tanımlarız. Bu global fonksiyonlar ile daha temiz kod yazmış oluruz.

Uygulamamız için bu konuyu ele alalım şimdi. Objelerimizin farklı veri tiplerinde yani farklı boyutlarda değişkenleri bulunmakta. Object Control structı içerisindeki databuffer dizisi read talebinde objenin değerini; write talebinde ise objeye yazılacak değeri tutan dizidir. Bu giriş haberleşme protokolü tarafından da yapılabilir ya da bizim bu kısımda uygulayacağımız gibi manuel de yapılabilir.

Bir örnek üzerinden gidelim:

Toplam 4-byte uzunluğunda bir uint32_t değişken kontrol edilmek isteniyor olsun (write/read). Control Structı içerisindeki databuffer dizisine write talebi için master (haberleşme protokolü vs.) tarafından birer byte uzunluğunda değişkenin dataları yazılacaktır; read talebi için ise değişkenin 4-byte değeri birer byte olarak object control modülü tarafından yazılacaktır. Bu işlemleri yapmanın elbette bir çok yolu vardır. (Bitwise operatörler gibi.)

Bu işlemleri daha fonksiyonel hale getirmek istediğimiz zaman şu fonksiyonlara ihtiyaç duyulacaktır:

  • uint32_t değişkenin uint8_t [4] çevrimi
  • uint16_t değişkenin uint8_t [2] çevrimi
  • uint8_t [4] dizisinin uint32_t çevrimi
  • uint8_t [2] dizisinin uint16_t çevrimi

Bu çevrimleri fonksiyon haline getirirken union’dan faydalanacağız. Farklı tiplerin aynı adres üzerinden dönüşümünü sağlaması ile çok işimize yarayacaktır.

Yardımcı global fonksiyonları farklı bir modül içerisinde (.c ve .h dosyası) toplayabiliriz. Ancak bu uygulama için object control modülünü kullanıyorum. Aşağıdaki gibi union bildirimini object control header dosyasına ekleyerek başlıyorum. Bu union birimi maksimum iki double word uzunluğunda olacaktır.

Union for Byte-extraction

 

uint32_t değişkenin uint8_t [4] çevrimi ve uint8_t [4] dizisinin uint32_t çevrimi fonksiyonlarını aşağıda belirteceğim. Diğer fonksiyonları kendiniz yazınız.

1.  Get uint32_t Fonksiyonu:

Fonksiyona girilen uint8_t dizisi içeride üretilen union nesnesinin uint8_t dizisine kopyalanıyor. Daha sonra union dizisinin uint32_t tipindeki değeri geri döndürülüyor.

Soru (?): Fonksiyonun parametre olarak aldığı uint8_t dizisinin neden const olduğu sualini sorduğunuzu tahmin etmekteyim.

Gelen data[] dizisi aslında pointer olarak gönderiliyor. Parametre olarak gelen data pointerı gönderilen referansın kendisi olduğu için herhangi bir değişiklik yapmamamız gerekmektedir. Bunu önleyebilmek adına const ifadesini ekliyoruz. Bu sayede derleyici seviyesinde değiştirmeye karşı önlem almış oluyoruz.

Soru (?): Bir sonraki soru şu olsa gerek. Peki neden bu diziyi pointer olarak gönderiyoruz bu fonksiyona doğrudan değerleri göndermek de ana parametreyi korumaz mı?

Kesinlikle, evet korur. Ancak fonksiyonlara parametre gönderirken bu değerler kopyalanır. Aslını temsil etmez, sadece değerleri taşır. Bu taşıma işlemi CPU açısından daha fazla işlem yapmak demektir. Bir diziyi ya da değişkeni pointer ya da referans olarak göndermek kopyalama gerektirmediğinden bu işlemlerin daha hızlı gerçekleşmesini sağlayacaktır.
Ayrıca uint8_t dizisinin kopyalanmış veriler olarak olsa bile fonksiyon içerisinde de değişmemesini istiyoruz.

 

2. Set uint32_t Fonksiyonu

Bu fonksiyonda ise uint32_t değişkenin uint8_t dizisine yazılmasını istiyoruz. Fonksiyona parametre olarak gönderilen uint32_t değişkenini yine parametre olarak gönderilen data dizisine yazıyoruz. Bu yazma işleminde union kullanıyoruz.

Fonksiyondaki uint32_t value değişkeni kopyalanmış değer olmasına rağmen const olarak ifade edilmiştir. Yukarıda da söylediğim gibi bu değerin fonksiyon içerisinde dahi değişmesini istemiyorum ve bunu derleyici seviyesinde korumaya alıyorum.

 

 

 

 

 

 

Diğer fonksiyonları da yazdıktan sonra artık main.c dosyasında işlem yapmaya başlayabiliriz.

Bu uygulama için main.c dosyasını application-layer olarak kullanacağımızı söylemiştik.

Bazı değişkenleri burada tanımlayarak başlayabiliriz. Object modülünden index_objects struct array’i çalışma alanına extern etmemiz gerekmektedir. Bu extern ifadeyi objects.h dosyasına da ekleyebilirsiniz.

Değişkenler aşağıdaki gibi olacaktır:

Main.c Değişkenleri

index_objects struct dizisinin extern olarak eklenmesi gerektiğini unutmamalıyız.

obj_control adında nesne üreterek işlevleri gerçekleştirmeyi sağlayacağız.

Aynı struct üzerinden control adında bir pointer üretip nesne olarak üretilen obj_controlün adresine eşitleyerek daha rahat bir çalışma alanı oluşturmuş olacağız. Örnek olarak, obj_control pointerını parametre olarak kabul eden fonksiyonlara parametre gönderirken foo(&obj_control) yazmak yerine foo(control) yazmış olacağız.

Bunlara göre main fonksiyonu aşağıdaki gibi olacaktır:

Main Fonksiyonu

err adında oluşturduğumuz hata enumları ile ifade edilecek olan değişkenini kullanarak fonksiyonların dönüş değerleri (hata numaraları) kontrol ediliyor.

Oluşturduğumuz yardımcı fonksiyonlar ile data kopyalama işlemi gerçekleşiyor.

İki adet write ve read error test senaryosu ile testimizin bir kısmını gerçekleştirmiş oluyoruz. Tüm sistemi test etmek için farklı senaryoları kurunuz. Ayrıca Debug modunda çalıştırıp main fonksiyonunda kodu durdurarak control nesnesini ve içerisinde obj_arg nesnesini inceleyin.

İlk bölümü bitirmiş bulunmaktayız. Nemli, rutubetli ve dar olan embedded systems gezegeninde görüşmek üzere!

İlk bölümün tamamını içeren github repo linki:
https://github.com/mekzum/40ambar/tree/master/Section-1/stage-d