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

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

z

Benim acaip multitaskingim geldi. http://ww1.microchip.com/downloads/en/AppNotes/00585b.pdf deki aciklamalardan cekirdek yazmaya calisacagim.
Sorularimi da burda soracagim. Fakat daha guzel bir dokuman biliyorsaniz link verebilirmisiniz?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#16
Bir kac tane tasktan olusan bir program yaziyor olalim.

Interuptlar bu tasklarin disinda ayri bir taskmidir?

Bu tasklarin biribirine gore onceliginin olmasi ne demektir? Interrupt task ise oncelikle bunlarin onceliginden mi bahsedilmek isteniyor?

Taskdan taska gecisim,  timer tickle olusturulmus zaman araligi belirlemiyormu? Eger oyleyse task onceligi anlamsiz olmuyormu?

Tasklara ayrilan surelerin birbirinden farkli olmasi istenen bir seymidir?

Bir task kendine ayrilan zamandan daha once isini bitirirse diger taska gecilmelimidir? Gecilmeliyse bunun dezavantaji varmidir?

Gecilmeliyse timer icerigi modifiye edilmelimidir?

Bir task kendine ayrilan zamandan daha once isini bitirirse arta kalan zaman bir sonraki taska hibe mi edilir?

Tasklar 1,2,3,4 gibi numaralanmis olsun. Tasklar 1,2,3,4,1,2,3,4 diye isleme alinmazlar mi? Bu siralama hic bozulmazmi bozulursa kim nicin bozar?


Tasklarin donanimsal registerlerle oynama gibi bir luksu olabilirmi?

Yoksa bunlar ayri bir tasktan mi talep edilir? Boyleyse bu isleri cok yavaslatmaz mi?

Tasklar boyle bir lukse sahipse sistemin crash olmamasi program (tasklari) yazanin yukumlulugundemidir?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

ErsinErce

#17
Creating a Multitasking Kernel for the COP8 Microcontroller
http://www.national.com/an/AN/AN-1099.pdf

Writing Operating System
http://faculty.kfupm.edu.sa/ics/salah/091/ics531/resources.html
http://faculty.kfupm.edu.sa/ics/salah/091/ics531/handouts/ch47.pdf

JamesM's kernel development tutorials
http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html

Multitasking Fundamentals       //// bu slaytlar konuya sizin yaklaştığınız gibi yaklaşıyor
http://www.ida.liu.se/~TDDC31/files/OS_TDDC31_Le2.pdf

netten bunlar çıktı

merak edenler için keyword multitasking fundamentals

z

#18
Aslinda oncelikle su soruyu sorayim. Belki de gavurun ne yaptigiyla ilgilenmeye gerek kalmaz.

3 ayri islemci ile proje yapmis olalim.

1. islemci, ortam sicakligini olcuyor olsun.
2. islemci, PID ile isiticinin voltajini ayarlasin.
3. islemci 1. ve 2. islemcilerle rs232 uzerinden haberlessin ihtiyac duyulan veri trafigini yonetsin, ayrica ekranda ortam sicakligini, isitici voltajini gostersin.

Simdi bu 3 islemciye yazilacak kodlar birbirinden tamamen bagimsiz 3 ayri proje demektir.

Eger ben bu 3 projeyi tek bir proje gibi yeni bastan yazip tek bir islemci icine gommek yerine,

Tek bir islemci icine 1. 2. 3. islemci kodlarini tamamen bagimsiz fonksiyonlar seklinde yazsam,
Bu fonksiyonlari F1, F2,F3 olarak isimlendirsem.

F1 calismaya baslasa timer int geldiginde F1 durdurulup F2 calismaya baslasa, gene timer int gelince F2 durup F3 calissa ve bu boyle dongude kalsa

Bu projenin cekirdek kodlarini yazsam os mu yazmis olacagim.

Burada adi gecen F1, F2 ve F3 task mi olacak?

F1, F2 ve F3, mesela ortak kullanilan F4 fonksiyonunu cagirsa bu F4 fonksiyonuna bu os camiasinda ozel bir ad veriliyormu?

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

emrahmrcn

Doğru yaklaşımlar... Yazdıklarınız aslında çekirdek temel işlemleri. Bir OS temeli. Bu sorular OS öğrenmek için çok güzel ,önce neden OS yazılması gerekliliğine takılmak lazım ki hangi nedenlere bağlı olarak OS ler yazılmış. Yani bazı problemler olmuş ve çözümler gerekmiş..

Alıntı yapılan: bunalmis - 06 Kasım 2011, 01:13:51
Aslinda oncelikle su soruyu sorayim. Belki de gavurun ne yaptigiyla ilgilenmeye gerek kalmaz.

3 ayri islemci ile proje yapmis olalim.

1. islemci, ortam sicakligini olcuyor olsun.
2. islemci, PID ile isiticinin voltajini ayarlasin.
3. islemci 1. ve 2. islemcilerle rs232 uzerinden haberlessin ihtiyac duyulan veri trafigini yonetsin, ayrica ekranda ortam sicakligini, isitici voltajini gostersin.

Simdi bu 3 islemciye yazilacak kodlar birbirinden tamamen bagimsiz 3 ayri proje demektir.

Eger ben bu 3 projeyi tek bir proje gibi yeni bastan yazip tek bir islemci icine gommek yerine,

Tek bir islemci icine 1. 2. 3. islemci kodlarini tamamen bagimsiz fonksiyonlar seklinde yazsam,
Bu fonksiyonlari F1, F2,F3 olarak isimlendirsem.

F1 calismaya baslasa timer int geldiginde F1 durdurulup F2 calismaya baslasa, gene timer int gelince F2 durup F3 calissa ve bu boyle dongude kalsa

Bu projenin cekirdek kodlarini yazsam os mu yazmis olacagim.

Burada adi gecen F1, F2 ve F3 task mi olacak?

F1, F2 ve F3, mesela ortak kullanilan F4 fonksiyonunu cagirsa bu F4 fonksiyonuna bu os camiasinda ozel bir ad veriliyormu?
Benim yaradılışımda bir ayrıcalık varsa o da TÜRK olmamdır. M.K ATATÜRK

z

#20
Alıntı yapılan: gerbay - 06 Kasım 2011, 17:58:55
hocam preemptive multitasking de yüksek öncelikli task bir event ya da device beklerken bir sonraki task a geçilir. sizin bahsettiğiniz olay "round-robin" diye geçiyor. mesela windows, linux gibi sistemler round-robin kullanırlar.

VxWorks, Integrity gibi "hard real-time" RTOS lar default olarak preemptive scheduling yaparlar ama "round-robin scheduling yap" diye konfigüre edilebilirler..

Burda bir taskin yuksek oncelikli olmasi ne demek?  Bu soru hala cevapsiz kaldi

Bir ornekle aciklayabilirmisin?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#21
Nihayet ilk RTOS cekirdegimi yazdim. Aslinda dilim RTOS demeye varmiyor ama ARM cipi icinde istediginiz kadar CPU olusturabiliyorsunuz.

Her bir CPU icin bagimsiz kod yazabiliyor ve bunlari kosturabiliyorsunuz. Tabiki su anda bir bebek rtos dan bahsediyoruz. Tasklar arasinda veri alisverisine bu asamada hic kafa yormadim.

Ilk deneme programimda STM32F kitimizdeki Arm islemci icine 4 cpu gomdum. Her bir cpu, kart uzerindeki 4 ledden sadece birisi ile ilgileniyor. 1ms lik zaman araliklarinda aktif oluyorlar. Asagidaki scop goruntusunde 2 CPU nun ledleri on off eden sinyalleri var.



Baby RTOS'un ve 4 CPU nun acik kodlari asagida.

/*
                Baby RTOS, STM32F-Discovery kiti uzerindeki ARM çip 
                uzerınde birden fazla CPU ile calisma yapmak icin gelistirilmektedir.
                PICPROJE - Bülent ÜNALMIŞ
*/
#include "STM32F4xx.h"
#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))  
#define CpuSayisi 4

void Cpu1(void);
void Cpu2(void);
void Cpu3(void);
void Cpu4(void);

struct Regs{int R4,R5,R6,R7,R8,R9,R10,R11,R13;};
     
struct Regs CpuReg[CpuSayisi]; 
int CpuNo;
int STK=-1;
int Radr;

/*****************************************************************************************************
              CPU PLL ile 168Mhz de kosturulur
              AHB frekansý 168 Mhz
              APB1 frekansý 42 Mhz
              APB2 frekansý 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 
} 

void __asm JMP(int Adr) 
{ 
             BX  R0 
}

int __asm PSR()
{
             MRS  R0,XPSR
             ORR  R0,#0x01000000
             BX  LR
}

int __asm CStack()
{
             MOV  R0,R13
             BX  LR
}

/*****************************************************************************************************
             STS TICK COUNTER AHB FREKANSINDA (168 MHZ) KOSACAK
*****************************************************************************************************/

void RTOSInit()
{
             CpuNo=0;
             STK_LOAD= 0X00029040;    // 165E6/1000=168000 TICK TIME 1 mili saniye
//           STK_LOAD= 0X00029040>>1; // 165E6/1000=168000 TICK TIME 500 mikrosaniye
             STK_VAL  = 0X00029040;   // TIMER GERIYE DOGRU BU DEGERDEN BASLASIN
             STK_CTRL&=~0x00010000;   // Count Flagi silelim, 
             STK_CTRL|= 0x00000007;   // int enb ve count enb yapalim, clk kaynagini AHB yapalim
             JMP(Radr);
}

void __asm SysTick_Handler()
{
              Adres(R3,CpuNo);  ;  R3=Cpu No Adres
              LDR  R1,[R3]   ;  R1=Cpu No
              MOV    R2,#36          
              MUL    R2,R1 
              Adres(R0,CpuReg[0])
              ADD    R2,R0
              STR  R4, [R2,#00] ; R4
              STR  R5, [R2,#04] ; R5
              STR  R6, [R2,#08] ; R6
              STR  R7, [R2,#12] ; R7
              STR  R8, [R2,#16] ; R8
              STR  R9, [R2,#20] ; R9
              STR  R10,[R2,#24] ; R10
              STR  R11,[R2,#28] ; R11
              STR  R13,[R2,#32] ; SP
 
              ADD  R2,#36
              ADD  R1,#1   ; CpuNo++
              MOV  R0,#CpuSayisi
              CMP  R1,R0
              STRLT R1,[R3]   
              MOVGE R1,#0
              STRGE R1,[R3]
              LDREQ   R2,=__cpp((unsigned)&CpuReg[0])
 
              Adres(R0,STK_CTRL)
              LDR  R1,[R0,#0X00]
              BIC  R1,#0X00010000
              STR  R1,[R0,#0X00] 
              LDR  R4, [R2,#00] ; R4
              LDR  R5, [R2,#04] ; R5
              LDR  R6, [R2,#08] ; R6
              LDR  R7, [R2,#12] ; R7
              LDR  R8, [R2,#16] ; R8
              LDR  R9, [R2,#20] ; R9
              LDR  R10,[R2,#24] ; R10
              LDR  R11,[R2,#28] ; R11
              LDR  R13,[R2,#32] ; SP
              BX  LR
}
 
void CpuInit(int No, int Adr, int Stack)
{
int* P;
            if (STK==-1)
              { 
                STK=CStack(); 
                Radr=Adr|1;
              }
            else 
             {
                STK-=Stack;
                CpuReg[No].R13=STK; 
                P=(int*) STK; 
               *P=0; P++; // R0
               *P=0; P++; // R1
               *P=0; P++; // R2
               *P=0; P++; // R3
               *P=0; P++; // R12
               *P=Adr|1 ; P++; // Return Adres
               *P=Adr|1 ; P++; // PC
               *P=PSR() ;      // PSR
             } 
}

int main()
{
          CpuInit(0,(int)&Cpu1,0x100);
          CpuInit(1,(int)&Cpu2,0x100);
          CpuInit(2,(int)&Cpu3,0x100);
          CpuInit(3,(int)&Cpu4,0x100);
          RTOSInit();
          while(1);
}

void Cpu1()
{
volatile int i;
        
         while(1)
           {
             GPIOD->ODR|=0x1000;
             for(i=0;i<0x000100;i++);
             GPIOD->ODR&=~0x1000;
             for(i=0;i<0x000100;i++);
           } 
}

void Cpu2()
{
volatile int i;
         while(1)
           {
             GPIOD->ODR|=0x2000;
             for(i=0;i<0x000100;i++);
             GPIOD->ODR&=~0x2000;
             for(i=0;i<0x000100;i++);
           } 
}

void Cpu3()
{
volatile int i;
         while(1)
           {
             GPIOD->ODR|=0x4000;
             for(i=0;i<0x000100;i++);
             GPIOD->ODR&=~0x4000;
             for(i=0;i<0x000100;i++);
           } 
}

void Cpu4()
{
volatile int i;
         while(1)
           {
             GPIOD->ODR|=0x8000;
             for(i=0;i<0x000100;i++);
             GPIOD->ODR&=~0x8000;
             for(i=0;i<0x000100;i++);
           } 
}




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

ErsinErce


Erol YILMAZ

#23
Süper bir başlangıç,
Bundan sonrasını geliştirmek çok daha mümkünatlı ! :)

yalnız Cpu yerine Task desek daha isabetli olabilir.....

z

#24


Açıkcası cpu mu demem lazım task mı demem lazım bilmiyorum. Baby RTOS'un yaptığı iş yukarıdakine benziyor.

4 Adet PICi'ın Xtal inp bacağına sırayla harici clk veriyorsunuz. Herhangi bir anda sadece 1 PIC16F84 çalışıyor.

Anahtarın dönme hızı örnekte 1ms.

Yukarıdaki bloktan yola çıktığım için görevlere task değil de CPU dedim.  Arada fark varmı? Varsa fark nedir?

Yukarıdaki blok şemaya göre CPU ların öncelikleri hakkında konuşursak;

Her işlemci çalışmak için sırasını beklemek zorunda. (Ben hala öncelik kısmında takıldım.)

Herhangi bir anda int gelirse, int muhtemelen (test etmedim) cevaplanacaktır. Çünkü aslında bir 5. işlemci daha var bu 5. işlemci (ARM'ın kendisi oluyor) intların yönetimiyle ilgileniyor.

Birisi bu RTOS'u bir anlatsa.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

#25
Bunalmış hocam,

Bir task'a sen illa ki 1 ms zaman geçireceksin demek yerine,

sen max 1 ms zaman harcayabilirsin demek daha iyi görünüyor....

Çünkü !
O TASK fonksiyonu o andaki görevini çok hızlı bir şekilde icra edebilir. (genellikle de öyle olur)
Ve schedular o TASK'tan sonra gelen TASK'ı çalışması için tetiklemeli...

yani TASK fonksiyonunda Delay komutu kullanıldığı anda, (bazı başka özel olaylarda da)
gerekli olan ayarlamalar yapılıp schedular'a geçmeli ve oradan da yeni TASK'a...


Bence şu çok önemli bir konu,
Bir TASK fonksiyonu işlemleri genellikle çok hızlı bir şekilde bitirilip
- delay,
- olay bekleme ve
- uzun bir string gönderme gibi işlemlerde bekliyor.
Bu noktalarda schedular TASK ları gözden geçirip başka birisini çalıştırmalı.

Erol YILMAZ

Ayrıca şu ana kadar anladığım kadarı ile görev değişimleri,

TASK içindeki değişim noktaları ile sağlanıyorsa buna Cooperative Rtos,
TASK içindeki değişim noktaları ve Timer Int ile sağlanıyorsa buna da Preemptive Rtos deniyor.

z

Cooperative Rtos yapılırsa bazı taskların hiç bir zaman çalışmama durumu olamazmı?

1-2-3 iki çalışsın- 2-3  bir çalışsın 1-2-3 bidaha ben 3 ....  4'e hiç sıra gelmeyebilir.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

Erol YILMAZ

Schedular için çok fazla sayıda yöntem var.

Cooperative Schedular yine TASK ları 1.2.3.4.5.6... diye işaret eder ama
işaret edilen TASK ın çalışma şartı gerçekleşmeyince
(delay bitmemiş, olay gerçekleşmemiş vs ise) kod yine Schedular a dönecektir.

Gerçi bu durumda SuperLoop tan ne farkı kalıyor ?

z

#29
A,B,C,D,.... şeklinde tasklardan oluşan bir programımız var. B,C,D den bahsetmeyeceğim fakat A Taskının görevi aşağıda.

Klavyeden basılan tuş ASCI A tuşuysa, bu andan itibaren 10 ms içinde de  seri porttan da ASCI B verisi gelirse LED1'i yak 100ms sonra LED'i söndür.

Tasklara max 1ms zaman ayrılan bir sistemde bu programı nasıl yazarsınız? Gerekiyorsa A,B,C,D ye ilave yeni tasklar oluşturabilirsiniz.

Bu programı X bir ROS için yazabilirmisiniz?



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