4

FreeRTOS Notları #7: Event Groups

    Daha önceki notlarda bahsettiğimiz gibi gerçek zamanlı gömülü sistemler oluşabilecek olaylara(events) karşı bir cevap vermek zorundadır. Önceki notlarda tasklar arasında oluşan olaylara cevap vermek için aşağıdaki özelliklere sahip olan semaphore ve queue yapısını görmüştük.
  • Tek bir olayın oluşması için taskın blocked state’de beklemesine izin verir.
  • Olay gerçekleştiğinde tek bir taskın bloğunu kaldırırlar. Bu task event’ı bekleyen en yüksek öncelikli tasktır.
    Event Grupları ise olayların tasklar ile haberleşebilmesine izin veren başka bir FreeRTOS özelliğidir. Semaphore ve kuyruğun aksine;
  • Event Groups bir veya birden fazla olayın birleşimi için task’ı blocked state’de tutar.
  • Event Groups bir olayın veya birden fazla olayın birleşiminin gerçekleşmesini bekleyen bütün taskların bloğunu kaldırır.
    Event gruplarının bu benzersiz özellikleri tasklar arasındaki senkronizasyon, olayları birden fazla task’a yayınlama, bir taskın birden fazla olayın gerçekleşmesini beklemek için blocked state’de tutulması ve  bu olaylara karşı alınabilecek aksiyonların bitmesini beklemek için taskları blocked state’de tutmak event grupları daha kullanışlı yapar.
  Event grupları aynı zamanda uygulama tarafından harcanan RAM miktarını da azaltır(birden fazla binary semaphore yerine events group kullanarak).

Event Groups, Event Flags ve Event Bits

    Event flag(bayrak) bir olayın gerçekleşip gerçekleşmediğini gösteren bir boolean(1 veya 0) sayıdır. Event grup ise bu flaglerin oluşturduğu bir set, bir dizidir.
    Bir event flag sadece 1 veya 0 olabilir. Bu yüzden bir bayrağın durumu tek bir bit ile tutulabilir. Tüm bayrakların tutulduğu event group ise bir değişken içerisinde tutulabilir. Bu değişken FreeRTOS’da EventBits_t tipinde tanımlanır. Eğer EventBits_t değişkeninin herhangi bir biti 1 olarak set edilirse bu bite bağlı bir olay gerçekleşmiş demektir. EventBits_t değişkeninin içerisindeki event flagleri aşağıdaki gibidir.
    Eğer event grubun değeri 0x92 (binary 1001 0010) ise sadece 1.,4. ve 7. bit set edilmiş ve dolayısı ile bu bitlere bağlı olaylar oluşmuş demektir. Event gruop değeri 0x92 iken event flagleri aşağıdaki gibi olur.
    Buradaki bitlerin anlamını belirlemek yazılımcıya aittir. Örnegin;
  • Bit 0’ı networkten mesaj geldi anlamında tanımlayabilir.
  • Bit 1’i  network üzerinden mesaj gönderilmeye hazır anlamında tanımlayabilir.
  • Bit 2’yi ise network bağlantısını kesmek anlamında kullanabilir.
    Event grubun kaç bit olacağı configUSE_16_BIT_TICKS makrosuna göre belirlenir. Bu makro 1 olarak tanımlanırsa 8 bitlik, 0 olarak tanımlanırsa 24 bitlik bir event grup oluşturulur.
    Event gruplar da bir RTOS nesnesi olduğu için herhangi bir task ve interrupt içinden erişilebilir. Birden fazla task aynı event grubun bitlerini set edebilir ve birden fazla task aynı event grubun bitlerini okuyabilir.

xEventGroupCreate() Fonksiyonu

    FreeRTOS da event group oluşturabilmek için xEventGroupCreate() fonksiyonu kullanılır.

    Görüldüğü gibi bu fonksiyon bir parametre almaz. Eğer event grup oluşturulamadı ise NULL, oluşturuldu ise EventGroupHandle_t tipinde bir handle döndürür.

xEventGroupSetBits() Fonksiyonu

    Bu fonksiyon bir veya birden fazla event biti set etmek için kullanılır. Bu bit veya bitler set edildiğinde bu bitlere bağlı olayların gerçeklestiğini tasklara bildirmek için kullanılır.

  • xEventGroup: xEventGroupCreate() fonksiyonun döndürdüğü handle.
  • uxBitsToSet: Set edilecek bit veya bitlerin girildiği parametredir. Girilen parametre içeride bitwise OR işlemine tutulur. Yani sadece 1 olarak set edilen bitler değiştirilir. Zaten hali hazırda set edilmiş bitlere dokunulmaz. Örnegin; bu parametre 0x04 (0100) olarak girilirse üçüncü bit set edilir.
  • Return Değeri: fonksiyon tarafından değiştirilmeden önceki event değişkeninin değerini döndürür.
    Bu fonksiyonun interrupt-safe versiyonu olan xEventGroupSetBitsFromISR() fonksiyonu da bulunmaktadır.

xEventGroupWaitBits() Fonksiyonu

   Bu fonksiyon event gruptan bit okumaya ve event bitler set edilene kadar taskları blocked state’de tutmaya yarar.

  • xEventGroup: xEventGroupCreate() fonskyionunun döndürdüğü event handle
  • uxBitsToWaitFor: Set edilmesi beklenen event bitleri girmek için kullanılan parametredir. Örneğin bu fonskiyonu çağıran task  bit 0 ve bit 2 nin set edilmesini bekliyor ise bu parametre 0x05 (0101) olarak girilmelidir.
  • xClearOnExit: Eğer bu parametre pdTRUE olarak girilirse bu fonksiyondan çıkılmadan uxBitsToWaitFor parametresine girilen bitler temizlenir.
  • xWaitForAllBits: Bu bit pdFALSE olarak girilirse set edilmesi beklenen bitlerden herhangi biri set edildiğinde bu fonksiyonun çağırıldığı task blocked state den çıkar. Eğer pdTRUE ise set edilmesi beklenen bütün bitler set edilmeden task blocked stateden çıkmaz.
  • xTicksToWait: Taskın blocked state’de ne kadar bekletileceğinin girildiği parametredir.
  • Return Değeri: Event grubun değerini döndürür. Eğer block süresi aşılırsa yine event grubun block süresi dolduğundaki değeri döndürülür.
    Bu fonksiyonun nasıl çalıştığını daha iyi anlamak için aşağıdaki tabloyu inceleyebiliriz.
    FreeRTOS da EventGroups ile ilgili diğer fonksiyonları incelemek için buraya tıklayabilirsiniz.

FreeRTOS da Event Groups Kullanımına Örnek

    Amaç: İki adet task tanımla. Tasklardan biri 3 bit event beklesin. Diğer task ise bir saniye aralıklar ile event üretsin. Event gruplarının nasıl çalıştığını görmek ve anlık olarak hangi event’ın gerçekleştiğini görmek için UART üzerinden stringler seriport ekranına gönderilsin.

  Event bekleyen taskı basitçe aşağıdaki gibi oluşturabiliriz.

    Yukarıdaki gibi bir task fonksiyonunu yazmadan önce main üzerinde aşağıdaki gibi bir event group handle’ı oluşturmamız gerekir.

    Bu handle’ı daha sonra event oluştururken kullanacağız.

    Yukarıdaki EventProcessTask() fonksiyonunda set edilmesi beklenen bitler 0. bit ,1. bit ve 2. bittir. Bu yüzden xEventGroupWaitBits() fonksiyonuna uxBitsToWaitFor parametresi olarak 00000111 binary sayısının hex karşılığı olan 0x07 yazılmıştır. xWaitForAllBits parametresi pdFALSE olarak girildiği için bu bitlerin hepsinin set edilmesini beklemeden tek bir bit set edildiğinde task blocked state den çıkacaktır. Daha sonra EventGroupValue değerinin hangi bitlerinin set edildiği if blokları ile kontrol edilip buna göre bir string UART üzerinden gönderilmiştir.

    Event üreten task fonksiyonu ise aşağıdaki gibidir.

    Burada bir switch-case yapısı ile birer saniye aralıklarla even bitleri set edilerek event’lar üretilemiştir. Bu task içerisinde her xEventGroupSetBits() fonksiyonu çağrıldığında diğer task çalışmaya başlayacaktır.

Tüm Kodlar (FreeRTOS ile)

CMSIS-RTOS ile EventGroups

    Bu yazıya kadar hep CMSIS-RTOS ‘un 1. versiyonunu kullanmıştık. Versiyon 1 de ise event groups ile ilgili API fonksiyonları bulunmamaktadır.Bunun yerine Signal events isimli bir başlık altında tasklar arasında event groups benzeri bir API fonksiyonları vardır fakat bu fonksiyolar da arka planda task bildirim(task notification) API fonksiyonlarını kullanır. O konuya bir sonraki notta değineceğiz. Bu yüzden bu notu burada sonlandırıyorum bir sonraki notta görüşmek üzere.

Kaynaklar

Mehmet Topuz

4 Comments

  1. Gömülü sistemler üzerine bu konu hakkında herhangi bir bilgiyi yabancı kaynaklardan bile edinmek çok zorken muhteşem bir içerik hazırlamışınız hocam. Elinize zihninize sağlık. Allah ilmimizi arttırsın.
    (Geçmiş yıllarda sürekli sağa sola sallayıp şevk kıran kayserili kaçak embedıdçıya selamlar. İçerik dediğin böyle olur bak. (O kendini biliyor :D))

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.