Gerçek zamanlı sistemler, çok çeşitli uygulamalar ve kullanım alanlarıyla karşımıza çıkar. Bu bölümde, bir mikrodenetleyici üzerinde gerçek zamanlı uygulamalar geliştirmek için bir Gerçek Zamanlı İşletim Sistemi (RTOS) nasıl kullanılacağına odaklanacağız.
İlk olarak, RTOS'un ne olduğuna dair genel bir bakış sunacağız ve gerçek zamanlı gereksinimleri olabilecek sistemlerin geniş yelpazesine göz atacağız. Ardından, gerçek zamanlı performans elde etmenin farklı yollarını inceleyecek ve donanım, firmware ve yazılım gibi çeşitli sistem türlerine dair genel bir çerçeve sunacağız. Son olarak, bir RTOS'un bir mikrodenetleyici uygulamasında ne zaman kullanılması gerektiğini ve ne zaman gereksiz olabileceğini ele alacağız.
Bu bölümlerde ilgili konulara değinirken aşağıdaki kaynaklardan sıkça yararlanacağız:
Brian Amos - Hands-On RTOS with Microcontrollers
Öyleyse başlayalım.
Gerçek Zamanlı Sistem Nedir?
Herhangi bir olaya karşı belirli bir sürede öngörülebilir ve kesin bir tepki verebilen bir sistem, "gerçek zamanlı" olarak kabul edilir. Peki, böyle bir sistem neden gerçek zamanlı olmak zorundadır? Eğer bir sistem, belirli bir zaman gereksinimini karşılamadığında başarısız sayılıyorsa, o zaman gerçek zamanlı olması gerekir. Ancak başarısızlık nasıl tanımlanır ve bunun sonuçları ne olabilir? Bu tanımlar ve sonuçlar, sistemin doğasına göre oldukça farklılık gösterebilir.
Gerçek zamanlı sistemlerde en önemli şeylerden biri, zaman gereksinimlerinin sadece hız açısından değil, bu gereksinimlerin karşılanmamasının doğuracağı sonuçlar açısından da geniş bir yelpazeye sahip olabileceğidir. Peki, zaman gereksinimleri ne kadar değişken olabilir ve bu farklılıklar nasıl yönetilir?
Zaman Gereksinimi
Zaman gereksinimlerinin ne kadar farklı olabileceğini göstermek için, birkaç farklı sistemi inceleyelim. Bu sistemler, analogdan dijitale dönüştürücülerden (ADC) veri okuma işlevine sahip. Örneğin, birinci sistemde bir lehim demirinin sıcaklığını kontrol eden bir kontrol sistemini ele alalım. Bu sistemde temel bileşenler, mikrodenetleyici (MCU), ADC, sensör ve ısıtıcıdır.
Mikrodenetleyicinin bu sistemdeki görevleri neler olabilir? Şöyle sıralayabiliriz:
Bir sıcaklık sensöründen ADC aracılığıyla veri almak,
Kapalı çevrim bir kontrol algoritması çalıştırmak (bu algoritma lehim demirinin ucundaki sıcaklığı sabit tutmayı amaçlar),
Gerekli olduğunda ısıtıcının çıktısını ayarlamak.
Burada önemli soru şu: Bir lehim demirinin sıcaklığını kontrol etmek için bu sistemin nasıl bir zaman aralığında çalışması gerekir? Yani, sensörden sıcaklık okuması, algoritmanın hesaplama süresi ve ısıtıcı ayarlamaları ne kadar sürede tamamlanmalıdır? Eğer bu süre aşılırsa, sistemde ne gibi aksaklıklar meydana gelir?
Lehim demirinin ucu sıcaklığını çok hızlı değiştirmediği için, mikrodenetleyicinin (MCU) saniyede sadece 50 ADC örneği (50 Hz) alması yeterlidir. Isıtıcıyı ayarlayan ve sıcaklığı sabit tutmaktan sorumlu kontrol algoritması ise daha da yavaş bir hızda, saniyede 5 kez (5 Hz) çalışır.
Bu durumda, ADC’nin bir donanım hattı ile tamamlanan dönüşümünü işaret ettiğini ve bu sinyalin MCU'ya, okumayı iç belleğine aktarması gerektiğini bildirdiğini varsayalım. Peki, MCU'nun bu veriyi ne kadar sürede alması gerekir? MCU, ADC'den iç belleğe veri aktarmak için en fazla 20 ms'ye sahiptir, çünkü bu süre içinde yeni bir okuma yapılması gerekmektedir. Ayrıca, MCU'nun ısıtıcı çıktısını güncellemek için gerekli hesaplamaları yapmak adına kontrol algoritmasını her 200 ms'de bir çalıştırması gerekmektedir (5 Hz). Bu örnekler çok hızlı süreçler gibi görünmese de, aslında gerçek zamanlı gereksinimlerin tipik birer örneğidir. Peki, sizce burada kritik olan nedir? MCU'nun belirlenen sürelerde işlem yapamaması, ısıtıcıyı yanlış ayarlayarak sistemde bir arıza yaratabilir mi? Hangi durumlarda bu tür bir zaman kaybı daha ciddi sonuçlar doğurabilir?
Şimdi, ADC okuma spektrumunun diğer ucunda, saniyede onlarca gigahertz hızında veri okuyan bir ağ analizörü veya osiloskop gibi yüksek bant genişliğine sahip bir cihazımız olabilir. Bu tür cihazlar, ham ADC verilerini genellikle frekans alanına çevirip, saniyede birçok kez yüksek çözünürlüklü bir ekranda grafiksel olarak gösterir. Böyle bir sistemin doğru çalışabilmesi için çok büyük miktarda işlem yapılması gerekir ve bu işlemler çok sıkı zaman gereksinimlerine uymalıdır.
Bu spektrumun ortasında ise genellikle hızlı hareket eden bir sistemde kararlılık sağlamak için PID kontrol döngülerini yüzlerce Hz'den onlarca kHz'ye kadar bir hızda çalıştırması gereken kapalı çevrim hareket denetleyicileri yer alır. Peki, "gerçek zaman" ne kadar hızlıdır? Görüldüğü gibi, ADC örneklerinde olduğu gibi bu sorunun cevabı duruma bağlıdır.
Bu noktada, osiloskop veya lehim demiri gibi sistemler zaman gereksinimlerini karşılamadığında ne olur? Performans düşüşü veya hatalı veri raporlanmasıyla karşılaşabiliriz. Örneğin, lehim demiri sıcaklık kontrolü düzgün sağlanamazsa, bileşenlere zarar verebilir. Test ekipmanında ise, zaman sınırlarına uyulmaması yanlış ölçümlerle sonuçlanabilir ve bu da bir hata olarak kabul edilir. Peki, bu hataların ciddiyeti nedir? Kimi insanlar için bu küçük bir sorun gibi görünse de, bu tür ekipmanlara güvenen kullanıcılar için oldukça büyük bir fark yaratabilir. Özellikle laboratuvar ekipmanları, ürün uygunluk kontrolü gibi kritik görevlerde kullanılıyorsa, hatalı ölçümler sonucunda yanlış değerler raporlanabilir. Şüpheli bir testin tekrarlanması mümkün olabilir, ancak sıkça yeniden test yapılması gerekiyorsa, bu ekipman güvenilmez olarak görülmeye başlanır ve satışlar düşebilir—tüm bunlar, bir gerçek zaman gereksiniminin sürekli olarak karşılanamamasından kaynaklanabilir.
Peki, daha tehlikeli senaryolarda ne olur? Örneğin, bir insansız hava aracının uçuş kontrolü veya endüstriyel süreç kontrolünde hareket denetimi gibi sistemlerde, kontrol algoritmasının zamanında çalıştırılamaması daha fiziksel ve yıkıcı sonuçlara yol açabilir, hatta bir çarpışma ile sonuçlanabilir. Bu durumda, sonuçlar potansiyel olarak ölümcül olabilir.
Düşünülesi: Neyse ki, bu tür başarısızlık senaryolarından kaçınmak için alınabilecek adımlar mevcuttur. Sizce bu adımlar neler olabilir? Zaman gereksinimlerini tutarlı bir şekilde karşılamak için hangi önlemler alınmalıdır?
Gerçek Zamanlı Sistem İçin Gereksinimler
Bir sistemin amacına uygun çalışmasını sağlamanın en basit yollarından biri, onu gereksinimleri karşılarken olabildiğince basit tutmaktır. Bu, basit bir görevi gereksiz yere karmaşık hale getirme eğilimine direnmek anlamına gelir. Örneğin, bir ekmek kızartma makinesi sadece bir dilim ekmeği kızartmak için tasarlandıysa, ona bir ekran ekleyip hava durumunu gösterme işlevi eklemeye gerek yoktur; sadece doğru süre boyunca ısıtıcıyı açmak yeterlidir. Bu basit görev, yıllardır hiçbir kod veya programlanabilir cihaz olmadan başarıyla yerine getirilebilmektedir.
Bir programcı olarak, karşılaştığımız bir sorunu hemen bir mikrodenetleyici (MCU) kullanarak çözmeye çalışmak gibi bir eğilimimiz olabilir. Ancak, bazı ürün fonksiyonları (özellikle elektromekanik bileşenler içeren ürünlerde) hiç kod yazmadan daha iyi bir şekilde çözülebilir. Örneğin, bir araba camı gerçekten de bir MCU'ya ihtiyaç duymadan motorları sürücüler aracılığıyla çalıştırabilir ve sensörlerden geri bildirim alarak onları kapatabilir. Bu görev, aslında birkaç mekanik anahtar ve diyot ile çözülebilir. Eğer bir geri bildirim raporlama mekanizması gerekiyorsa—örneğin, bir cam sıkıştığında bir hata raporlanması gerekiyorsa—o zaman daha karmaşık bir çözüm kaçınılmaz olabilir. Ancak bir mühendis olarak hedefimiz her zaman aynı olmalıdır: Sorunu olabildiğince basit bir şekilde çözmek, gereksiz karmaşıklık eklemeden.
Bir sorun yalnızca donanım ile çözülebiliyorsa, önce bu olasılığı ekip ile tartışmak gerekir. MCU'yu hemen devreye sokmadan önce bu seçeneği değerlendirin. Örneğin, bir sensör durumunu kontrol etmek basit bir while döngüsü ile yapılabiliyorsa, sensörü bu şekilde izlemek yeterli olabilir; hemen kesme hizmet rutinleri (ISR'ler) yazmaya gerek olmayabilir. Cihazın işlevi tek amaçlıysa, çoğu durumda tam teşekküllü bir RTOS kullanmak sistemi gereksiz yere karmaşıklaştırabilir—bu yüzden, böyle bir durumda RTOS kullanmaktan kaçının.
Düşünülesi: Peki, sizce hangi durumlarda karmaşıklık eklemeden problemi çözmek daha verimli olur? Hangi görevler için donanım yeterli olabilir ve hangi noktalarda yazılım müdahalesine ihtiyaç duyulabilir?
Gerçek Zamanlı Sistem Türleri
Gerçek zamanlı davranışı elde etmenin birçok farklı yolu vardır. Ayrıca, bu sistemlerin bir arada alt sistemler olarak çalışabileceğini de unutmamak gerekir. Bu farklı alt sistemler, bir ürün, kart ya da çip seviyesinde karşımıza çıkabilir. Burada biraz bazı kavramlara değinelim.
Donanım (Hardware)
Gerçek zamanlı sistemlerin en temel hali olan donanım, hala çok sıkı toleranslara ve/veya hızlı zaman gereksinimlerine sahip sistemler için en iyi çözümdür. Donanım, ayrık dijital lojik, analog bileşenler, programlanabilir lojik veya uygulamaya özel entegre bileşenler (ASIC) ile uygulanabilir. Programlanabilir lojik cihazlarının bir parçası olan programlanabilir lojik cihazlar (PLD'ler), karmaşık programlanabilir lojik cihazlar (CPLD'ler) ve alan programlanabilir kapı dizileri (FPGA'lar) bu çözümün çeşitli üyeleridir. Donanım tabanlı gerçek zamanlı sistemler, analog filtrelerden kapalı çevrim kontrolüne, basit durum makinelerinden karmaşık video codec'lerine kadar her şeyi kapsayabilir. Güç tasarrufu dikkate alınarak tasarlandığında, ASIC'ler bir MCU tabanlı çözüme göre daha az enerji tüketebilir. Genel olarak donanım, işlemleri paralel olarak ve anında gerçekleştirme avantajına sahiptir (elbette bu bir basitleştirmedir), oysa tek çekirdekli bir MCU yalnızca paralel işlem yapıyormuş gibi bir izlenim verir.
Peki, donanım tabanlı gerçek zamanlı sistemlerin dezavantajları neler olabilir? Genellikle aşağıdaki zorluklarla karşılaşılabilir:
Programlanabilir olmayan cihazların esnek olmaması,
Donanım geliştirme uzmanlığının, yazılım/firmware geliştiricilerinden daha az bulunabilir olması,
Büyük FPGA'lar gibi tam özellikli programlanabilir cihazların maliyeti,
Özel bir ASIC geliştirmenin yüksek maliyeti.
Bare-metal firmware
Bare-metal firmware, herhangi bir önceden var olan çekirdek ya da zamanlayıcı üzerine inşa edilmemiş yazılım olarak kabul edilir. Bazı mühendisler bu tanımı daha da genişletip, gerçek bir bare-metal firmware'in önceden hazırlanmış herhangi bir kütüphaneyi (örneğin, üreticinin sağladığı donanım soyutlama kütüphaneleri) kullanmaması gerektiğini savunur—bu görüş de bir ölçüde haklıdır. Bare-metal bir uygulamanın en büyük avantajı, kullanıcının kodunun tüm donanım üzerinde tam kontrol sahibi olmasıdır. Ana döngü kodunun kesintiye uğramasının tek yolu bir kesme sinyalinin tetiklenmesidir. Bu durumda, CPU'nun kontrolünü başka bir şeyin ele almasının tek yolu, mevcut ISR'nin (kesme hizmet rutini) bitmesi ya da daha yüksek öncelikli bir kesmenin tetiklenmesidir.
Bare-metal firmware, nispeten basit bir dizi görev ya da tek bir büyük görev olduğunda mükemmel bir seçenektir. Eğer yazılım belirli bir göreve odaklanır ve en iyi uygulamalar takip edilirse, belirli bir performans genellikle kolayca ölçülüp garanti edilebilir, çünkü ISR'ler arasındaki etkileşimler sınırlıdır (hatta bazı durumlarda ISR bulunmayabilir). Özellikle, fazla yüklenmiş veya ROM/RAM açısından sınırlı MCU'lar için bare-metal, bazen tek seçenek haline gelir.
Peki, bare-metal uygulamalar karmaşıklaştığında ne olur? Asenkron olaylarla başa çıkmak zorlaştıkça, bare-metal çözümler RTOS tarafından sunulan işlevselliklerle örtüşmeye başlar. Burada önemli bir nokta, kendi iş parçacığı güvenli sisteminizi oluşturmaya çalışmak yerine bir RTOS kullanarak, RTOS sağlayıcısının yaptığı tüm testlerden otomatik olarak faydalanmanızdır. Ayrıca, mevcut tüm RTOS'lerin uzun yıllardır kullanıldığını ve bu süreçte yazarlarının onları çeşitli uygulamalara uyumlu hale getirmek için sürekli işlevsellik ekleyip geliştirdiğini unutmamak gerekir.
Düşünülesi: Sizce, bare-metal bir çözüm ne zaman yeterli olur? RTOS gibi daha karmaşık çözümler ne zaman tercih edilmelidir? Örnek verebilir misiniz?
RTOS tabanlı firmware
Bir zamanlama çekirdeği üzerinde çalışan yazılımlar, RTOS tabanlı firmware olarak adlandırılır. Zamanlayıcının ve bazı RTOS önceliklerinin kullanılması, görevlerin işlemciyi tamamen kendilerine aitmiş gibi çalışıyormuş hissi vermesini sağlar. RTOS kullanarak, sistem en önemli olaylara yanıt verebilirken arka planda karmaşık görevler yürütülebilir.
Ancak, tüm bu görevlerin aynı anda çalışması bazı dezavantajlar da getirir. Verileri paylaşan görevler arasında bağımlılıklar ortaya çıkabilir ve bu bağımlılıklar doğru şekilde yönetilmezse, bir görevin beklenmedik bir şekilde bloklanmasına neden olabilir. Bu durumu yönetmek için bazı önlemler olsa da, bu durum kodu karmaşıklaştırabilir. Kesme sinyalleri genellikle kesmeleri olabildiğince hızlı bir şekilde işleyip, olabildiğince fazla işlemi bir göreve devretmek için görev sinyallemesini kullanır. Doğru bir şekilde yönetildiğinde, bu çözüm birçok karmaşık etkileşime rağmen sistemin duyarlı kalmasını sağlamak için mükemmel bir yöntemdir. Ancak yanlış yönetildiğinde, bu tasarım paradigmaları daha fazla zamanlama sapmasına ve daha az kesinliğe yol açabilir.
Nedir?: Firmware ve Software
RTOS tabanlı yazılım
Bir bellek yönetim birimi (MMU) ve merkezi işlem birimi (CPU) içeren tam bir işletim sistemi üzerinde çalışan yazılımlar, RTOS tabanlı yazılım olarak kabul edilir. Bu yaklaşım, farklı iç ve dış sistemler arasında birçok etkileşim gerektiren oldukça karmaşık uygulamaların geliştirilmesine olanak tanır. Tam bir işletim sistemi kullanmanın avantajı, beraberinde getirdiği hem donanım hem de yazılım yetenekleridir.
Donanım tarafında, genellikle daha yüksek saat hızlarında çalışan daha fazla CPU çekirdeği bulunur. Gigabaytlarca RAM ve kalıcı bellek mevcut olabilir. Harici donanım eklemek, çoğunlukla mevcut sürücüler sağlandığı sürece, bir kart eklemek kadar basit olabilir.
Yazılım tarafında ise, ağ yığınları, kullanıcı arayüzü geliştirme, dosya işlemleri gibi pek çok açık kaynak ve özel çözümler bulunur. Tüm bu yeteneklerin altında, çekirdek hala kritik görevlerin geleneksel bir işletim sisteminde olduğu gibi belirsiz bir süre boyunca engellenmesini önleyecek şekilde tasarlanmıştır. Bu nedenle, RTOS tabanlı firmware’de olduğu gibi, belirli bir performans elde etmek hala mümkündür.
RTOS tabanlı yazılımlara benzer şekilde, standart bir işletim sistemi (OS) bir geliştiricinin ihtiyaç duyabileceği tüm kütüphanelere ve özelliklere sahiptir. Ancak eksik olan şey, zamanlama gereksinimlerini katı bir şekilde karşılamaya odaklanmamış olmasıdır. Genel anlamda, geleneksel bir işletim sistemiyle oluşturulan sistemler çok daha az kesin ve öngörülebilir davranış sergiler (ve güvenlik açısından kritik bir durumda bu tür bir kesinlikten bahsedilemez). Eğer zamanlama gereksinimi çok sıkı değilse ve zaman sınırının kaçırılması ciddi sonuçlar doğurmuyorsa, dikkatli bir şekilde hangi yazılım yığınlarının çalıştırıldığına ve bu yığınların kaynak kullanımına özen gösterildiği sürece standart bir OS kullanılabilir. Bu tür bir gerçek zamanlı sistemin iyi bir örneği, Linux çekirdeğinin PREEMPT_RT yamaları ile yapılandırılmasıdır.
Şimdi, gerçek zamanlı bir sistem elde etmek için tüm seçenekler ortaya konduğuna göre, RTOS ile ne kastettiğimizi, özellikle de MCU tabanlı bir RTOS'tan ne anladığımızı tanımlama zamanı geldi.
Bu bağlamda, sizce standart bir işletim sistemi ile RTOS arasındaki en belirgin farklar nelerdir? Hangi durumlarda genel amaçlı bir işletim sistemi yeterli olabilir, hangi durumlarda ise RTOS tercih edilmelidir?
Bu bölümlük bu kadar, diğer bölümlere geçmeden önce sektöre yeni atılacak olan kişiler için şu siteyi ekte öneri olarak bırakıyorum:
Embedded
Ek olarak eğer kendinizi geliştirmek için bir roadmap arıyorsanız bu ilginizi çekecektir:
Roadmap
Dilerseniz Patreon Sayfam üzerinden bu çabamı maddi katkılarınızla destekleyebilirsiniz.
Diğer bölümde görüşmek üzere.
Çok güzel bir yazı olmuş ellerine sağlık
Şimdi ben sensörden belleğe daha hızlı aktarmak için DMA kullanabiliriz değilmi??