Kendimize ait RTOS Yazımı, Multitasking hakkında

Başlatan bunalmis, 08 Ekim 2011, 11:35:31

Erol YILMAZ

seri portu başka TASK lar kullanıyor mu ?

z

Her iki durum için de iki ayrı örnek olursa süper olur.

Zor olursa hayır tek task kullanıyor.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

RTOS kullananları burası açmadı galiba.

Baby RTOS'a aşağıda bahsettiğim eklenti yapılırsa pek çok proje gerçekleştirilebilir.

Şayet aktif taskımız, belli bir olayı bekleme noktasına geldiyse, şartlı bir döngü içinde olayın gerçekleşip gerçekleşmediğini zaman harcayarak test etmek yerine ben görevimi bitirdim ve artan zamanımı bir sonraki taska hibe ediyorum derse;

Bir sonraki task artık 1ms değil örneğin 1.5ms aktif olacaktır. Bu da daha çok işlem yapabilmesi demektir. Eğer yeni taskımız da işini ayrılan zamandan daha önce yapıp bir olayı bekleme aşamasına gelirse bu task da artan zamanını bir sonraki taska hibe edebilir.

Bu da gözle görülür bir performans artışına neden olur.

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

Alıntı yapılan: bunalmis - 09 Kasım 2011, 15:18:02
RTOS kullananları burası açmadı galiba.

Baby RTOS'a aşağıda bahsettiğim eklenti yapılırsa pek çok proje gerçekleştirilebilir.

Şayet aktif taskımız, belli bir olayı bekleme noktasına geldiyse, şartlı bir döngü içinde olayın gerçekleşip gerçekleşmediğini zaman harcayarak test etmek yerine ben görevimi bitirdim ve artan zamanımı bir sonraki taska hibe ediyorum derse;

Bir sonraki task artık 1ms değil örneğin 1.5ms aktif olacaktır. Bu da daha çok işlem yapabilmesi demektir. Eğer yeni taskımız da işini ayrılan zamandan daha önce yapıp bir olayı bekleme aşamasına gelirse bu task da artan zamanını bir sonraki taska hibe edebilir.

Bu da gözle görülür bir performans artışına neden olur.

Kesinlikle bu şekilde olmalı hocam :) 

Üstteki soru işareti için biraz düşünmek irdelemek lazım.

z

#34
Sorduğum soru klasik yöntemle tek cpu için yazdığımız program olsaydı bir iki dakikada kodları yazar bitirirdik.

RTOS'a geçince neyi düşüneceğiz? Eğer bu basit soru için bu kadar düşünürsek baba bir proje bizi çok yormazmı?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

TASK_A(){

while(1){
	if(kbhit() && getch()=='A'){
		delay_os_ms(10);
		if(kbhit() && getch()=='B'){
			out_led=1;
			delay_os_ms(100);
			out_led=0;
		}
	}
}
}

z

#36
TASK_A()
{ 
        while(1)
           {
               if(kbhit() && getch()=='A')
                 {
                    delay_os_ms(10);
                    if(kbhit() && getch()=='B')
                        {
                           out_led=1;
                           delay_os_ms(100);
                           out_led=0;
                        }
                   }
            }
}


Kodu anladım. Gerçi tam cevap olmadı galiba. Soruda klavyeden A harfi geldiğinde 10 ms içinde B harfi gelecekmi diyordum ama olsun. (Mevcut örnekte 10ms bekleyip ardından bakıyoruz) Buna ayrca kafa yoralım.

Yukarıdaki örnekte 10ms lik delayi başlattığımızda diğer tasklar sırayla işlemeye başlıyor. Delay başladıktan sonra 10ms dolduğunda o an işleyen task her neyse işi kesiliyor ve bahse konu delay rutininin bir alt satırına mı geliniyor?

Yoksa bu satıra tekrar geldiğimizde mesela 14 ms olabiliyormu?

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

#37
sorunuzun cevabı Rtos'un preemptive veya non-preemptive olmasına göre değişiyor.

Eğer ki 1 ms de 1 kere schedular çalışıyorsa(yani preemptive ise) ve bu görev diğer TASK'lardan öncelikli ise
elbette bu TASK en kötü 10+1 ms sonra çalışmaya devam eder.

Eğer ki non-preemptive bir RTOS ise bu görevin çalışması için o anda çalışmakta olan TASK ın sonlanmasını beklemek zorundayız.

emrahmrcn

Mesala schedular süreleri genelde 1mS oluyor(RoundRobin Algoritmasında). Bu sabitlenmiş süreyede kuantum süresi diyorlar, burada anlaşılacağı üzere performans direk kuantum süresi ile ilgili.
Benim yaradılışımda bir ayrıcalık varsa o da TÜRK olmamdır. M.K ATATÜRK

z

Round Robbin vs terimler yeni yeni sekillenmeye basladi. Asagidaki sitenin icerigi hosuma gitti.

http://www.bilgisayarkavramlari.com/2008/11/19/round-robin/


Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#40
STM32F için RTOS çalışması güzel gidiyor ve yakında Baby sıfatından kurtulacak.

Pis adını verdiğim RTOS'un özellikleri (Picproje İşletim Sistemi)

Her 1ms de Task geçişi,
Arta kalan zamanı bir sonraki Task'a hibe etme,
Düşük öncelikli Task'ların yüksek öncelikli Task'lar tarafından durdurulup çalıştırılması,
Tick rutinine kullanıcı kodu ekleyerek her 50 mikrosaniye de bir kritik zamanlı işlerin soft olarak kontrolu,
Tasklar arası veri aktarımı (Henüz yöntem belirlenmedi)
Interruptlar.

Şimdiden belirtmek gerekirse, C kütüphanelerinden hazır fonksiyonlardan bazıları çağrılırsa sistem muhtemelen çökecektir. Mevcut RTOS'larda bu durum nasıldır?

Bu özelliklere sahip PİS'in üstesinden gelemeyeceği bir uygulama ne olabilir?

Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

Alıntı yapılan: bunalmis - 11 Kasım 2011, 09:53:14Şimdiden belirtmek gerekirse, C kütüphanelerinden hazır fonksiyonlardan bazıları çağrılırsa sistem muhtemelen çökecektir. Mevcut RTOS'larda bu  durum nasıldır?

Neden çöker ?

z

Bu, tamamen kütüphane fonksiyonunun nasıl yazıldığına bağlı. Eğer sözkonusu kütüphane fonksiyonunda, stack haricinde ilave olarak global yada statik değişken kullanma yoluna gidilmişse;

Tasklardan birisi bu fonksiyonu çağırmışsa;
Fakat fonksiyon tamamlanamadan task geçişi olursa;
Sonra gelen tasklar da aynı fonksiyonu kullanırsa

reentry problemi oluşacağından sistem çöker.

Benimkisi varsayımdan ibaret. Eğer kütüphane fonksiyonları, RTOS çalışmasında da kullanılsın diye yazıldıysa zaten sorun olmaz.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

Hali hazır RTOSlarda;

Kullanıcı programları user modda çalışacak diye zorlama varmı?
Her ne kadar RTOS açık kod olduğu için engel olunamasa da kullanıcı programlarının Privileged seviyesinde kod yazımına izin veriliyormu?

Asla crash olmayan RTOS uygulamaları için bu tip sınırlamalar yapılmalı diye düşünüyorum.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#44
Baby RTOS çekirdegini, CM4 islemciyi CM3 gibi dusunup yazdigimdan Floating Point islemcinin varligini tamamen unutmuşum.
Haliyle Baby RTOS FPU uygulamalarında kullanılırsa sistem çökecekti.

Simdiki RTOS'da bu sorun giderildi ve yeni özellikler eklendi.

Task sayısı arttırıldıkça startup_stm32f4xx.s dosyasındaki Stack_Size değeri arttırılmalı. CM4 işlemci, CM3 işlemciye oranla
daha fazla hayati register içerdiğinden task geçişlerinde daha fazla stack alanı gerekiyor. Bu konu hatırda tutulmalı.

RTOS her 1 mili saniyede bir Task degistiriyor ilave olarak 2 temel fonksiyonu var.

1. fonksiyon, Delay(T) fonksiyonu,  milisaniye cinsinden Taskı beklemeye alıyor
2. fonksiyon ise Hibe()  fonksiyonu,  Task süresinin bitmesini beklemeden bir sonraki taska geçiş sağlar.

RTOS Cekirdeginin kaynak kodlari

//         STM32F Discovery kiti icin geliitirilmiş RTOS cekirdeği
//         www.picproje.org, Bülent Ünalmış   
        
#define Adres(Reg, adr) ldr Reg, =__cpp((unsigned)&adr)
#define STK_CTRL (*((volatile unsigned int*) 0xE000E010))  
#define STK_LOAD (*((volatile unsigned int*) 0xE000E014))  
#define STK_VAL  (*((volatile unsigned int*) 0xE000E018))  
 
char Task=0;
char HibeFlag=0;
 
struct T{int SP, Adr;};
struct T TaskTablo[TaskSayisi];
 
int PK[TaskSayisi][TaskSayisi];
unsigned int Dly[TaskSayisi];
 
void __asm RTOSInit()
{
        Adres(R0,TaskTablo[0])
        LDR     R1,=TaskSayisi
        MOV     R2,SP
        MOV     R3,#0X00       
L1     SUB     R2,R3
        LDR     R3,[R0,#0]
        STR     R2,[R0,#0]
        ADD     R0,#8
        SUBS    R1,#1
        BNE     L1
        Adres(R0,TaskTablo[1])
        LDR     R1,=TaskSayisi-1
L2      ;       LDR     SP,[R0]         // Bu komut hataliymis (errata)
        LDR     R3,[R0]
        MOV     SP,R3
        MRS     R2,FPSCR
        PUSH    {R2}      
        MOV     R2,#0
        PUSH    {R2}
        VPUSH   {S15}
        VPUSH   {S14}
        VPUSH   {S13}
        VPUSH   {S12}
        VPUSH   {S11}
        VPUSH   {S10}
        VPUSH   {S9}
        VPUSH   {S8}
        VPUSH   {S7}
        VPUSH   {S6}
        VPUSH   {S5}
        VPUSH   {S4}
        VPUSH   {S3}
        VPUSH   {S2}
        VPUSH   {S1}
        VPUSH   {S0}
        MRS   R2,XPSR
        ORR   R2,#0x01000000
        PUSH    {R2}    // PSR
        LDR     R2,[R0,#4]
        PUSH    {R2}    // R15 PC
        PUSH    {R2}    // R13 LR
        PUSH    {R12}   // R12 
        PUSH    {R3}    // R3
        PUSH    {R2}    // R2
        PUSH    {R1}    // R1
        PUSH    {R0}    // R0
        
        PUSH    {R4-R11}
       
        STR     SP,[R0]
        ADD     R0,#8
        SUBS    R1,#1
        BNE     L2   
             
        Adres(R0,TaskTablo[0])
        LDR     R3,[R0]
        MOV     SP,R3
        Adres(LR,TaskTablo[0]+4)
        LDR     LR,[LR]
        
        Adres(R0,Task)        
        STR     R1,[R0]
        Adres(R0,STK_CTRL)        
        LDR     R1,=0X00029040
        STR     R1,[R0,#0X04]       ; STK_LOAD=0X00029040
        LDR     R1,=0X00010007
        LDR     R2,[R0,#0X00]
        BIC     R2,R1
        ORR     R2,#7
        STR     R2,[R0,#0X00]
        NOP
        BX      LR
}
int SysTick_Handler_(int NSP,int SVC)
{
int i;
        TaskTablo[Task].SP=NSP;
        if (STK_CTRL & 0x00010000)
           {
             STK_CTRL&=~0x00010000; // Count Flagi silelim, 
             for(i=0;i<TaskSayisi;i++) 
               {
                 if(Dly[i]) Dly[i]--;
               } 
             
       if(HibeFlag==0)
               {            
             Task++; if (Task>=TaskSayisi) Task=0; // Sonraki taski harekete gecirelim
               }
             else if(HibeFlag==2)
               {
                 HibeFlag=0; // Ayni task devam etsin
               }
           }    
        else    // Hibe var
           {
             if(HibeFlag==1) 
               {            
             Task++; if (Task>=TaskSayisi) Task=0; // Sonraki taski harekete gecirelim
                 HibeFlag=2;
               }
           }
        return(TaskTablo[Task].SP);
}
   
void __asm SysTick_Handler()
{
        PRESERVE8
        PUSH  {R4-R11}
        MOV     R0,SP
        PUSH {LR}
        Adres(R1,SysTick_Handler_)
        BLX  R1
        POP  {LR}
        MOV     SP,R0
  POP  {R4-R11}
  BX  LR
}
 
void __asm SVC_Handler()
{
        B       SysTick_Handler
}
 
void __asm Hibe()
{
        Adres(R0,HibeFlag)   
        MOV     R1,#1
        STRB    R1,[R0]
        SVC     #0
        BX      LR
}
 
void Delay(unsigned int T)
{
        Dly[Task]=T;
        while(Dly[Task]) Hibe();
}
 
void PostaGonder(int VarAdr, int Alici)
{
        while(PK[Task][Alici]) Hibe();         // Alicinin Postakutusu dolu
        PK[Task][Alici]=VarAdr;                // Alicinin Posta kutusuna Posta atildi
} 
 
int PostaBekle(int Gonderen)
{
        while(PK[Gonderen][Task]==0) Hibe(); // Postacidan mektup bekle
        return(PK[Gonderen][Task]);              // Gelen verinin adresini oku
}
 
int PostaVarmi(int Gonderen)                      // Mektup almak isteyen bakar
{
        return(PK[Gonderen][Task]);              // Mektup gelmismi
}
 
void Selamlar(int Gonderen)                  // Sevgilim, mektubunu almistim
{                                                     // fakat diger hatunlar beni cok oyaliyor
        PK[Gonderen][Task]=0;               // ancak okuyabildim, opuyorum
}


Kart uzerindeki LEdleri yakip sonduren program icin SystemInit() fonksiyonumuz
#include "STM32F4xx.h"
 
/***********************************************************************
              CPU PLL ile 168Mhz de kosturulur
              AHB frekansi 168 Mhz
              APB1 frekansi 42 Mhz
              APB2 frekansi 84 Mhz
***********************************************************************/
 
void SystemInit()
{
unsigned int i;
         
        for (i=0;i<0x00100000;i++);         // OSC oturtma ve kurtarma rutini
        RCC->CFGR |= 0x00009400;         // AHB ve APB hizlarini max degerlere set edelim 
        RCC->CR |= 0x00010000;            // HSE Xtal osc calismaya baslasin        
        while (!(RCC->CR & 0x00020000));// Xtal osc stabil hale gelsin
//      RCC->PLLCFGR = 0x07405408;     // PLL katsayilarini M=8, N=336, P=2 ve Q=7 yapalim
        RCC->PLLCFGR = 0x07402A04;     // PLL katsayilarini M=4, N=168, P=2 ve Q=7 yapalim
        RCC->CR |= 0x01000000;            // PLL calismaya baslasin  (Rehber Sayfa 95)
        while(!(RCC->CR & 0x02000000)); // Pll hazir oluncaya kadar bekle
//      FLASH->ACR = 0x00000705;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
        FLASH->ACR = 0x00000605;        // Flash ROM icin 5 Wait state secelim ve ART yi aktif edelim (Rehber Sayfa 55)
        RCC->CFGR |= 0x00000002;        // Sistem Clk u PLL uzerinden besleyelim
        while ((RCC->CFGR & 0x0000000F) != 0x0000000A); // Besleninceye kadar bekle
        RCC->AHB1ENR |= 0x0000000F;   // GPIO A,B,C,D clock'u aktif edelim 
        GPIOD->MODER = 0x55000000;    // GPIOD nin 15, 14, 13, 12 pinleri cikis tanimlandi (LEDler icin)
        GPIOD->OSPEEDR= 0xFFFFFFFF;   // GPIOD nin tum cikislari en yuksek hizda kullanacagiz 
}


RTOS kullanarak 4 ledi farklı zamanlarda yakıp söndüren 4 adet task.
#define TaskSayisi 4
 
#include "STM32F4xx.h"
#include "RTOS.c"
#include "MyInit.c"
 
void Cpu1(void);
void Cpu2(void);
void Cpu3(void);
void Cpu4(void);
 
/****************************************************************      
        Startup kodundaki   Stack_Size      EQU     0x00000400
        satiri                     Stack_Size      EQU     0x00000800
        olarak degistirilmeli
****************************************************************/
 
int main()
{
//     Alttaki ilk satir
//     0.Task Cpu1 fonksiyonunu ve 512 byte Stack alanini kullanacak demektir

        TaskTablo[0].Adr=(int)&Cpu1; TaskTablo[0].SP=512; 
        TaskTablo[1].Adr=(int)&Cpu2; TaskTablo[1].SP=512;
        TaskTablo[2].Adr=(int)&Cpu3; TaskTablo[2].SP=512;
        TaskTablo[3].Adr=(int)&Cpu4; TaskTablo[3].SP=512;

        RTOSInit(); // Artik main satiri ile isimiz kalmadi tasklar kosmaya basladi
}
 
/****************************************************************      
        1. Task, yesil ledi 1 sn de flash eder
****************************************************************/
 
void Cpu1()
{
volatile int i;
        while(1)
          {
           GPIOD->ODR|=0x1000;
           Delay(1000);
           GPIOD->ODR&=~0x1000;
           Delay(1000);
          } 
}
 
/****************************************************************      
        2. Task, kavunici  ledi 2 sn de flash eder
****************************************************************/
 
void Cpu2()
{
volatile int i;
        while(1)
          {
           GPIOD->ODR|=0x2000;
           Delay(2000);
           GPIOD->ODR&=~0x2000;
           Delay(2000);
          } 
}
 
/****************************************************************      
        3. Task kirmizi ledi 1 sn de flash eder
****************************************************************/
 
void Cpu3()
{
volatile int i;
        while(1)
          {
           GPIOD->ODR|=0x4000;
           Delay(4000);
           GPIOD->ODR&=~0x4000;
           Delay(4000);
          } 
}
 
/****************************************************************      
        1. Task mavi ledi 1 sn de flash eder
****************************************************************/
 
void Cpu4()
{
volatile int i;
        while(1)
          {
           GPIOD->ODR|=0x8000;
           Delay(8000);
           GPIOD->ODR&=~0x8000;
           Delay(8000);
          } 
}


İyi RTOS'lar.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com