Elektronik Devreler Projeler Elektronik ve biraz daha fazlası İletişim - Araçlar - Dikkat - Topluluk
Elektronik / Elektronik Kaynakları/

RTOS’a Giriş: OSA RTOS

Sponsorlu Bağlantılar

Mikrodenetleyicilerde adım adım ilerlerken RTOS adıyla sıkça karşılaşmaya başlıyorsunuz. Bu yüzden benim de bir kaç haftadır gündemimi meşgul eden RTOS’lara, hiç bu konulara girmemiş/girememiş bir kişi gözünden anlatmak ve ilk adımların nasıl atılacağını göstermek istiyorum.

Öncelikle RTOS’a biraz değinmek gerekirse, ki kısa değinmenin haksızlık olduğunu düşünsem de, açılımından da anlaşılacağı üzere bir işin, tam belirtilen zaman aralıklarında yapılması ilkesi taşıyan, içerisinde bu amacı gerçekleştirmek üzere birimler barındıran, küçük işletim sistemleri desek sanırım yanlış olmaz. Peki RTOS’a ne için ihtiyaç duyarız?

– Spagetti kod yazımı, yani sonsuz for, binlerce if/else’den kurtulmak,
– Kodların bakımını daha kolay yapabilmek ve kodun bölümlerini daha keskin belirleyebilmek,
– Bizim için acil olan işlemleri, tam belirlenen sürede yaptırabilmek,
– Görünürde paralel işlem yapabilmek için.

Normal kod yazdığımızı düşündüğümüzde işlemlerimizi bir sıraya sokar, bir kesme yardımıyla bu işlemleri sırasıyla yürütürüz. Elbette kısa kod parçaçıkları yazdığımızda bunu kontrol etmesi ve yönetmesi bizim için kolaydır, fakat onlarca kontrol mekanizması işin içine girdiğinde sistemin takibi ve bakımı oldukça zorlaşır ve işin içinden çıkılamaz noktaya gelinir. İşte bu noktada RTOS işin içine girer. Burada unutulmaması gereken iki konu vardır, RTOS sisteminize artı bir hız katmaz, işleyiş organizasyonu ve yönetimi katar. Tasarlanan RTOS sistemleri kurulduğu sistemden bağımsızdır ve bunun için neredeyse tüm RTOS’ların farklı mikrodenetleyicilerle de rahatça çalıştığı görülür.

RTOS tercihleri konusunda ise oldukça fazla alternatifiniz var. İnternette “RTOS” diye aradığınızda bedava veya ücretli binlerce RTOS ile karşılaşıyorsunuz. Ben ise bedava olduğu ve 8 bitlik mikrodenetleyicilerde kolay bir biçimde kullanmak için OSA RTOS’u tercih ettim. İlgili sistemi incelemek ve indirmek için buraya tıklayabilirsiniz. Bu yazıda yaptığım örneğin ise yapım aşamalarını aşağıdaki videodan izleyebilirsiniz(1080p ve tam ekran izlemenizi öneririm). RTOS kullanımına geçmeden önce OSA RTOS’un yardım dosyasını çok dikkatli bir şekilde okumanızı şiddetle tavsiye ediyorum. Gerçekten en ince ayrıntısına kadar özenilerek hazırlanmış bir kaynak.

Karşılaştıracağımız örnek her ne kadar RTOS’un gücünü göstermede yetersiz olacaksa da karşılaştırma örneğimizde RC0-3 bacaklarından sırasıyla 200-400-600 ve 800ms’lik kare dalgalar üretelim. C18’de derleyeceğim kodları öncelikle klasik metotla yazalım.

// www.FxDev.org

#include < p18f2520.h >

// Fuse ayarlamaları, ayrıntılı bilgi için C18 help dosyasına bakılmalı
#pragma config OSC      = HSPLL
#pragma config FCMEN    = OFF
#pragma config IESO     = OFF
#pragma config PWRT     = ON
#pragma config BOREN    = ON
#pragma config BORV     = 1
#pragma config MCLRE    = ON
#pragma config LPT1OSC  = OFF
#pragma config PBADEN   = OFF
#pragma config STVREN   = OFF
#pragma config DEBUG    = OFF
#pragma config WDT      = OFF
#pragma config LVP      = OFF

int i,flag;

void PIC_Init(void)
{
    LATC            = 0x00;
    TRISC           = 0x00;

    T1CON           = 0x80;     // 16bit mode
    TMR1H           = 0xD8;     // 1ms'de bir kesme için değerler yükleniyor
    TMR1L           = 0xF0;

    INTCON = 0;
    INTCONbits.PEIE = 1;
    PIR1bits.TMR1IF = 0;        // Timer1 kesme bayrağı siliniyor
    PIE1bits.TMR1IE = 1;        // Timer1 kesmesi aktif
    T1CONbits.TMR1ON= 1;        // Timer1 çalıştırılıyor
    INTCONbits.GIE  = 1;        // Kesmeler açılıyor
}

void main(void)
{
    PIC_Init();                     // Pic için genel ayarlar yapılıyor

    for(;;)
    {
        if(flag)
        {
            flag=0;
            i++;
            if((i%100)==0) {LATCbits.LATC0^=1;}
            if((i%200)==0) {LATCbits.LATC1^=1;}
            if((i%300)==0) {LATCbits.LATC2^=1;}
            if((i%400)==0) {LATCbits.LATC3^=1;}
        }
    }
}

/*//////////////////////  Kesme Rutinleri \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
void kesme(void);       // Kesme fonksiyonu tanımlanıyor
                        // Ayrıntılı bilgi için C18 User Guide Interrupt Kısmına bakılmalı
//----------------------------------------------------------------------------

// Yüksek öncelikli kesme vektörü
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
  _asm
    goto kesme         //Kesmeye atla
  _endasm
}
#pragma code

#pragma interrupt kesme
void kesme(void)
{
    if (PIR1bits.TMR1IF)
    {
        PIR1bits.TMR1IF = 0;
        TMR1H           = 0xD8;     // 1ms'de bir kesme için değerler yükleniyor
        TMR1L           = 0xF0;
        flag=1;
    }
}

Şimdi de aynı işlemi OSA RTOS kullanarak yazalım.

// www.FxDev.org
// OSA RTOS Örneği
#include < p18f2520.h >
#include < osa.h >

// Fuse ayarlamaları, ayrıntılı bilgi için C18 help dosyasına bakılmalı
#pragma config OSC      = HSPLL
#pragma config FCMEN    = OFF
#pragma config IESO     = OFF
#pragma config PWRT     = ON
#pragma config BOREN    = ON
#pragma config BORV     = 1
#pragma config MCLRE    = ON
#pragma config LPT1OSC  = OFF
#pragma config PBADEN   = OFF
#pragma config STVREN   = OFF
#pragma config DEBUG    = OFF
#pragma config WDT      = OFF
#pragma config LVP      = OFF

void PIC_Init(void)
{
    LATC            = 0x00;
    TRISC           = 0x00;

    T1CON           = 0x80;     // 16bit mode
    TMR1H           = 0xD8;     // 1ms'de bir kesme için değerler yükleniyor
    TMR1L           = 0xF0;

    INTCON = 0;
    INTCONbits.PEIE = 1;
    PIR1bits.TMR1IF = 0;        // Timer1 kesme bayrağı siliniyor
    PIE1bits.TMR1IE = 1;        // Timer1 kesmesi aktif
    T1CONbits.TMR1ON= 1;        // Timer1 çalıştırılıyor
}

void Task_1(void)
{
    for(;;)
    {
        OS_Delay(100);
        LATCbits.LATC0^=1;
    }
}

void Task_2(void)
{
    for(;;)
    {
        OS_Delay(200);
        LATCbits.LATC1^=1;
    }
}

void Task_3(void)
{
    for(;;)
    {
        OS_Delay(300);
        LATCbits.LATC2^=1;
    }
}

void Task_4(void)
{
    for(;;)
    {
        OS_Delay(400);
        LATCbits.LATC3^=1;
    }
}

void main(void)
{
    PIC_Init();                     // Pic için genel ayarlar yapılıyor
    
    OS_Init();                      // RTOS ilk ayarları yapılıyor

    OS_Task_Create(1,Task_1);       // 1. task oluşturuluyor, öncelik 1
    OS_Task_Create(2,Task_2);       // 2. task oluşturuluyor, öncelik 2
    OS_Task_Create(3,Task_3);       // 3. task oluşturuluyor, öncelik 3
    OS_Task_Create(4,Task_4);       // 4. task oluşturuluyor, öncelik 4
    
    OS_EI();                        // Kesmeler açılıyor
    OS_Run();                       // RTOS çalıştırılıyor
}

/*//////////////////////  Kesme Rutinleri \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\*/
void kesme(void);       // Kesme fonksiyonu tanımlanıyor
                        // Ayrıntılı bilgi için C18 User Guide Interrupt Kısmına bakılmalı
//----------------------------------------------------------------------------

// Yüksek öncelikli kesme vektörü
#pragma code InterruptVectorHigh = 0x08
void InterruptVectorHigh (void)
{
  _asm
    goto kesme         //Kesmeye atla
  _endasm
}
#pragma code

#pragma interrupt kesme
void kesme(void)
{
    if (PIR1bits.TMR1IF)
    {
        PIR1bits.TMR1IF = 0;
        TMR1H           = 0xD8;     // 1ms'de bir kesme için değerler yükleniyor
        TMR1L           = 0xF0;
        OS_Timer();
    }
}

Her iki kodu da derlediğimizde aşağıda göreceğiniz üzere, yer konusunda aralarında bariz bir fark oluşmamaktadır.

rtos-karsilastirma

Fakat bu örnekte tam olarak belli olmasa da öncelik atayabilme, işi zamanında tamamlama, büyüyen kod öbeklerinde anlaşılabileceği gibi sistemin takip edilebilirliğinin kolay olmasından RTOS tercihimiz olacaktır.

Örneğin elinizde 10ms’de bir ADC’den örnek alan, alınan değeri 0.5ms’de bir PI, PID’den geçiren ve tüm sonuçları 200ms’de bir bilgisayara aktaran, 50ms’de bir ise sistemin tepkisini değiştiren yazılım parçaları bulunsun. Bunu if/else’ler ile oluşturmaktansa RTOS’un bize sunduğu Task’larla yapmak hem kolay hem de anlaşılır olacaktır. Dahası sürelerin kesin ve görevlere kolaylıkla öncelik atanabilmesi de cabası.

RTOS ile ilgili giriş yazımı kapamadan önce, ileriki RTOS örneklerimde kullanacağım OSA RTOS‘un 10F’ten 24F’e, AVR ve STM’e kadar mikrodenetleyici ve C18, C30, CCS C, Hi-Tech, WinAVR gibi çok farklı derleyiciler için rahatça kullanılabildiğini belirtmek isterim.

İleride daha komplike örnekler ve OSA RTOS’un derin görevlerini de ele almayı düşünüyorum.
Herkese çalışmalarında başarılar dilerim.

Dip Not: Kodları Rus’lar yazdığı için de müzik onlara özel..

Sponsorlu Bağlantılar
  • Welat

    Öncelikle bu güzel paylaşımınız için çok teşekkür ederim.
    Ben de birkaç aydır RTOS ile ilgili araştırma yapıyorum ama maalasef böyle güzel anlatan bi kaynak bulamadım.
    http://www.freertos.org/ diye bi site buldum fakat pek bi şey anlamadım oradan.

    Ben CCS-C derleyicisini kullanıyorum, eğer bununla ilgili bir örnek paylaşırsanız çok sevinirim.
    Çoğu üniversitede ve sanayide, pek çok kişi CCS-C kullanıyor.

    Allah’a emanet olun.

  • FxDev

    @Welat: Yorumunuz için öncelikle teşekkür ederim, maalesef sitemde çok ekstrem durum oluşmadıkça CCS C ile ilgili örnek paylaşmayacağım. İleri seviye PIC uygulamalarında Hi-Tech, C18 ve C30 uygulamaları kullanmanızı öneririm.

  • Burak

    Paylaşımınızı gerçekten çok değerli buldum.Ancak videoya ulaşamadım rica etsem videonun gizlilik ayarlarını açık yapabilir misiniz? Veyahut özelden link gönderir misiniz?

    Çalışmalarınızda kolaylıklar dilerim.

  • misafir

    Bir sorum var bu işletim sistemini Arduino da(uno) çalıştırabilirmiyiz ona özel başka işletim sistemleri var mı? Cevaplayabilirseniz sevinirim…