- RTOS nasıl çalışır?
- RTOS'ta sık kullanılan terimler
- Arduino FreeRTOS Kitaplığını Kurmak
- Devre şeması
- Arduino FreeRTOS Örneği - Arduino IDE'de FreeRTOS görevleri oluşturma
- Arduino IDE'de FreeRTOS Görev Uygulaması
Gömülü cihazların içinde bulunan işletim sistemine RTOS (Gerçek Zamanlı İşletim Sistemi) denir. Gömülü cihazlarda, zamanlamanın çok önemli bir rol oynadığı durumlarda gerçek zamanlı görevler kritiktir. Gerçek zamanlı görevler Zaman Belirleyicidir, herhangi bir olaya yanıt süresinin her zaman sabit olduğu anlamına gelir, böylece belirli bir olayın belirli bir zamanda meydana geleceği garanti edilebilir. RTOS, uygulamaları çok hassas zamanlama ve yüksek derecede güvenilirlikle çalıştırmak için tasarlanmıştır. RTOS ayrıca tek bir çekirdekle çoklu görev yapmaya yardımcı olur.
RTOS, genel amaçlı işletim sistemi ile RTOS arasındaki fark, farklı RTOS türleri vb. Hakkında daha fazla bilgi edinebileceğiniz gömülü sistemlerde RTOS'un nasıl kullanılacağına dair bir öğretici zaten ele aldık.
Bu eğitimde FreeRTOS ile başlayacağız. FreeRTOS, kullanımı bu mikro denetleyicilerle sınırlı olmamakla birlikte, 8/16 bit mikro denetleyicilerde çalıştırılacak kadar küçük olan gömülü aygıtlar için bir RTOS sınıfıdır. Tamamen açık kaynaklıdır ve kodu github'da mevcuttur. RTOS'un bazı temel kavramlarını biliyorsak, FreeRTOS'u kullanmak çok kolaydır, çünkü kodlamanın arka uç kısmını bilmeden doğrudan kodda kullanılabilen iyi belgelenmiş API'lara sahiptir. Tam FreeRTOS belgeleri burada bulunabilir.
FreeRTOS, 8-bit MCU üzerinde çalışabildiğinden, Arduino Uno kartında da çalıştırılabilir. Sadece FreeRTOS kitaplığını indirmeli ve ardından API'leri kullanarak kodu uygulamaya başlamalıyız. Bu eğitim, tamamen yeni başlayanlar içindir, aşağıdaki konular, bu Arduino FreeRTOS eğitiminde ele alacağız:
- RTOS nasıl çalışır?
- RTOS'ta sık kullanılan bazı terimler
- FreeRTOS'u Arduino IDE'ye Yükleme
- Örnekle FreeRTOS Görevleri nasıl oluşturulur
RTOS nasıl çalışır?
RTOS çalışmasına başlamadan önce, Görevin ne olduğunu görelim. Görev, yürütülecek CPU üzerinde programlanabilen bir kod parçasıdır. Bu nedenle, bir görevi gerçekleştirmek istiyorsanız, çekirdek gecikmesi veya kesintiler kullanılarak planlanmalıdır. Bu çalışma, çekirdekte bulunan Scheduler tarafından yapılır. Tek çekirdekli bir işlemcide, zamanlayıcı, görevlerin belirli bir zaman diliminde yürütülmesine yardımcı olur, ancak farklı görevler aynı anda yürütülüyor gibi görünüyor. Her görev kendisine verilen önceliğe göre çalışır.
Şimdi bir saniyelik aralıklarla yanıp sönen LED için bir görev oluşturmak ve bu görevi en yüksek önceliğe almak istiyorsak RTOS çekirdeğinde ne olacağını görelim.
LED görevinin yanı sıra, çekirdek tarafından oluşturulan bir görev daha olacak, bu boşta kalma görevi olarak bilinir.. Boş görev, yürütülebilecek bir görev olmadığında oluşturulur. Bu görev her zaman en düşük öncelikte, yani 0 öncelikte çalışır. Yukarıda verilen zamanlama grafiğini analiz edersek, yürütmenin bir LED görevi ile başladığı ve belirli bir süre çalıştığı ve ardından kalan süre boyunca boşta kalan görevin bir tik kesintisi oluşana kadar çalıştığı görülebilir. Daha sonra çekirdek, görevin önceliğine ve LED görevinin toplam geçen süresine göre hangi görevin yürütülmesi gerektiğine karar verir. 1 saniye tamamlandığında, çekirdek boşta olan göreve göre daha yüksek önceliğe sahip olduğu için yürütmek için led görevi tekrar seçer, ayrıca LED görevinin boşta kalma görevini önlediğini söyleyebiliriz. Aynı önceliğe sahip ikiden fazla görev varsa, bunlar belirli bir süre boyunca sıralı olarak çalışacaklardır.
Çalışmayan görevin çalışma durumuna geçişini gösteren durum şemasının altında .
Her yeni oluşturulan görev Hazır durumuna geçer (çalışmama durumunun bir parçası). Oluşturulan görev (Görev1) diğer görevlerden en yüksek önceliğe sahipse, o zaman çalışma durumuna geçecektir. Bu çalışan görev diğer göreve öncelik verirse, yeniden hazır durumuna geri döner. Aksi takdirde, görev1, engelleme API'si kullanılarak engellenirse, CPU, kullanıcı tarafından tanımlanan zaman aşımına kadar bu görevle meşgul olmayacaktır.
Görev1, API'leri Askıya Alma kullanılarak çalışma durumunda askıya alınırsa, Görev1 Askıya alındı durumuna geçecek ve zamanlayıcı tarafından tekrar kullanılamayacaktır. Görev1'i askıya alınmış durumda devam ettirirseniz, blok diyagramda görebileceğiniz gibi hazır durumuna geri dönecektir.
Bu, Görevlerin nasıl çalıştığı ve durumlarını nasıl değiştirdiğiyle ilgili temel fikirdir. Bu eğiticide, FreeRTOS API kullanarak Arduino Uno'da iki görev uygulayacağız.
RTOS'ta sık kullanılan terimler
1. Görev: Yürütülecek CPU üzerinde programlanabilen bir kod parçasıdır.
2. Zamanlayıcı: Hazır durum listesinden çalışma durumuna kadar bir görev seçmekten sorumludur. Zamanlayıcılar genellikle tüm bilgisayar kaynaklarını meşgul edecek şekilde uygulanır (yük dengelemede olduğu gibi).
3. Önleme: Halihazırda yürütülmekte olan bir görevi işbirliği olmaksızın çalışma durumundan çıkarmak amacıyla geçici olarak kesintiye uğratma eylemidir.
4. Bağlam Değiştirme: Önceliğe dayalı preemptionda, zamanlayıcı çalışan görevlerin önceliğini her sistem kesmesinde hazır görev listesi önceliğiyle karşılaştırır. Listede önceliği çalışan görevden daha yüksek olan herhangi bir görev varsa, bağlam anahtarı gerçekleşir. Temel olarak, bu süreçte farklı görevlerin içeriği kendi yığın belleğine kaydedilir.
5. Planlama ilkeleri türleri:
- Önleyici Çizelgeleme: Bu tür çizelgelemede görevler, öncelikler dikkate alınmadan eşit zaman diliminde çalışır.
- Öncelik Tabanlı Önleme: Önce yüksek öncelikli görev çalıştırılır.
- İşbirliğine Dayalı Zamanlama: Bağlam değiştirme yalnızca çalışan görevlerin işbirliği ile gerçekleşecektir. Görev, görev verimi çağrılana kadar sürekli olarak çalışacaktır.
6. Çekirdek Nesneleri: Görevin bazı işleri gerçekleştirmesi için sinyal vermek için senkronizasyon işlemi kullanılır. Bu işlemi gerçekleştirmek için Kernel nesneleri kullanılır. Bazı Çekirdek nesneleri Olaylar, Semaforlar, Kuyruklar, Muteksler, Posta Kutuları vs.'dir. Bu nesnelerin nasıl kullanılacağını ilerideki eğitimlerde göreceğiz.
Yukarıdaki tartışmadan, RTOS konsepti hakkında bazı temel fikirlere sahibiz ve şimdi FreeRTOS projesini Arduino'da uygulayabiliriz. Öyleyse, Arduino IDE'ye FreeRTOS kitaplıklarını kurarak başlayalım.
Arduino FreeRTOS Kitaplığını Kurmak
1. Arduino IDE'yi açın ve Sketch -> Include Library -> Manage Libraries'e gidin . FreeRTOS'u arayın ve kitaplığı aşağıda gösterildiği gibi kurun.
Kitaplığı github'dan indirebilir ve.zip dosyasını Sketch-> Kitaplığı Dahil Et ->.zip dosyası ekle'ye ekleyebilirsiniz .
Şimdi, Arduino IDE'yi yeniden başlatın. Bu kitaplık, aşağıda gösterildiği gibi Dosya -> Örnekler -> FreeRTOS'ta da bulunabilen bazı örnek kodlar sağlar.
Burada çalışmayı anlamak için kodu sıfırdan yazacağız, daha sonra örnek kodları kontrol edip kullanabilirsiniz.
Devre şeması
Arduino'da FreeRTOS kullanarak Yanıp Sönen LED görevi oluşturmak için devre şeması aşağıdadır:
Arduino FreeRTOS Örneği - Arduino IDE'de FreeRTOS görevleri oluşturma
Bir FreeRTOS projesi yazmak için temel bir yapı görelim.
1. İlk olarak, Arduino FreeRTOS başlık dosyasını aşağıdaki gibi ekleyin
#Dahil etmek
2. Yürütme için yazdığınız tüm işlevlerin işlev prototipini verin.
void Task1 (void * pvParameters); void Task2 (void * pvParameters); .. ….
3. Şimdi, void setup () işlevinde görevler oluşturun ve görev zamanlayıcıyı başlatın.
Görev oluşturmak için, xTaskCreate () API belirli parametrelerle / argümanlarla kurulum işlevinde çağrılır.
xTaskCreate (TaskFunction_t pvTaskCode, const char * const pcName, uint16_t usStackDepth, void * pvParameters, UBaseType_t uxPriority, TaskHandle_t * pxCreatedTask);
Herhangi bir görev oluşturulurken iletilmesi gereken 6 argüman vardır. Bakalım bu argümanların ne olduğunu
- pvTaskCode: Görevi uygulayan fonksiyona basitçe bir göstericidir (aslında, sadece fonksiyonun adı).
- pcName: Görev için açıklayıcı bir ad. Bu FreeRTOS tarafından kullanılmaz. Yalnızca hata ayıklama amacıyla dahil edilmiştir.
- usStackDepth: Her görevin, görev oluşturulduğunda göreve çekirdek tarafından tahsis edilen kendi benzersiz yığını vardır. Değer, bayt sayısını değil, yığının tutabileceği kelime sayısını belirtir. Örneğin, yığın 32 bit genişliğinde ise ve usStackDepth 100 olarak aktarılırsa, RAM'de 400 baytlık yığın alanı (100 x 4 bayt) ayrılacaktır. Bunu akıllıca kullanın çünkü Arduino Uno'da sadece 2Kbyte RAM vardır.
- pvParameters: Görev girdi parametresi (NULL olabilir).
- uxPriority: Görevin önceliği (0 en düşük önceliktir).
- pxCreatedTask: Oluşturulmakta olan göreve bir tutamaç vermek için kullanılabilir. Bu tutamaç daha sonra API çağrılarında görev önceliğini değiştiren veya görevi silen (NULL olabilir) göreve başvurmak için kullanılabilir.
Görev oluşturma örneği
xTaskCreate (görev1, "görev1", 128, NULL, 1, NULL); xTaskCreate (görev2, "görev2", 128, NULL, 2, NULL);
Burada, Task2 daha yüksek önceliğe sahiptir ve bu nedenle ilk önce yürütülür.
4. Görevi oluşturduktan sonra, vTaskStartScheduler () kullanarak void kurulumunda zamanlayıcıyı başlatın ; API.
5. Void loop () işlevi, herhangi bir görevi manuel ve sonsuz olarak çalıştırmak istemediğimiz için boş kalacaktır. Çünkü görev yürütme artık Zamanlayıcı tarafından gerçekleştiriliyor.
6. Şimdi, görev işlevlerini uygulamalı ve yürütmek istediğiniz mantığı bu işlevlerin içine yazmalıyız. İşlev adı, xTaskCreate () API'sinin ilk bağımsız değişkeniyle aynı olmalıdır.
void task1 (void * pvParameters) { while (1) { .. ..// mantığınız } }
7. Kodun çoğu, çalışan görevi durdurmak için gecikme işlevine ihtiyaç duyar, ancak RTOS'ta CPU'yu durdurduğu ve dolayısıyla RTOS da çalışmayı durdurduğu için Delay () işlevinin kullanılması önerilmez. Bu yüzden FreeRTOS, görevi belirli bir süre engellemek için bir çekirdek API'sine sahiptir.
vTaskDelay (const TickType_t xTicksToDelay);
Bu API, gecikme amacıyla kullanılabilir. Bu API, belirli sayıda onay için bir görevi geciktirir. Görevin bloke kaldığı gerçek süre, tik oranına bağlıdır. Sabit portTICK_PERIOD_MS , tıklama oranından gerçek zamanı hesaplamak için kullanılabilir.
Bu, 200 ms'lik bir gecikme istiyorsanız, bu satırı yazmanız yeterlidir.
vTaskDelay (200 / portTICK_PERIOD_MS);
Bu nedenle, bu eğitimde, üç görevi gerçekleştirmek için bu FreeRTOS API'lerini kullanacağız.
Kullanılacak API'ler:
- xTaskCreate ();
- vTaskStartScheduler ();
- vTaskDelay ();
Bu öğretici için oluşturulacak görev:
- Dijital pin 8'de 200ms frekansla LED yanıp sönüyor
- Dijital pin 7'de 300ms frekansla LED yanıp sönüyor
- Numaraları seri monitörde 500 ms frekansla yazdırın.
Arduino IDE'de FreeRTOS Görev Uygulaması
1. Yukarıdaki temel yapı açıklamasından Arduino FreeRTOS başlık dosyasını dahil edin. Ardından işlev prototipleri yapın. Üç görevimiz olduğundan, üç işlevi ve prototiplerini yapın.
#include void TaskBlink1 (void * pvParameters); void TaskBlink2 (void * pvParameters); void Taskprint (void * pvParameters);
2. void setup () işlevinde, saniyede 9600 bitte seri iletişimi başlatın ve xTaskCreate () API kullanarak üç görevi de oluşturun. Başlangıçta, tüm görevlerin önceliklerini '1' yapın ve planlayıcıyı başlatın.
geçersiz kurulum () { Serial.begin (9600); xTaskCreate (TaskBlink1, "Task1", 128, NULL, 1, NULL); xTaskCreate (TaskBlink2, "Task2", 128, NULL, 1, NULL); xTaskCreate (Taskprint, "Task3", 128, NULL, 1, NULL); vTaskStartScheduler (); }
3. Şimdi, görev1 LED'inin yanıp sönmesi için aşağıda gösterildiği gibi üç işlevi de uygulayın.
void TaskBlink1 (void * pvParameters) { pinMode (8, OUTPUT); while (1) { digitalWrite (8, HIGH); vTaskDelay (200 / portTICK_PERIOD_MS); digitalWrite (8, DÜŞÜK); vTaskDelay (200 / portTICK_PERIOD_MS); } }
Benzer şekilde, TaskBlink2 işlevini uygulayın. Task3 işlevi şu şekilde yazılacaktır:
void Taskprint (void * pvParameters) { int counter = 0; while (1) { counter ++; Serial.println (sayaç); vTaskDelay (500 / portTICK_PERIOD_MS); } }
Bu kadar. Arduino Uno için bir FreeRTOS Arduino projesini başarıyla tamamladık. Bu eğitimin sonunda bir videoyla birlikte tam kodu bulabilirsiniz.
Son olarak, dijital pin 7 ve 8'e iki LED bağlayın ve kodu Arduino kartınıza yükleyin ve Seri monitörü açın. Aşağıda gösterildiği gibi görev adı ile 500 ms'de bir sayacın çalıştığını göreceksiniz.
Ayrıca, LED'leri gözlemleyin, farklı zaman aralıklarında yanıp sönüyorlar. XTaskCreate işlevindeki öncelik bağımsız değişkeniyle oynamaya çalışın. Numarayı değiştirin ve seri monitör ve LED'lerdeki davranışı gözlemleyin.
Şimdi, analog okuma ve dijital okuma görevlerinin oluşturulduğu ilk iki örnek kodu anlayabilirsiniz. Bu sayede sadece Arduino Uno ve FreeRTOS API'leri kullanarak daha ileri projeler yapabilirsiniz.