RTOS Öğrenmek İçin Bahane

Başlatan muhittin_kaplan, 25 Temmuz 2013, 02:28:21

muhittin_kaplan

MPU 6050 ile belli bir seviyede iletişim kurdum. Raw bilgileri i2c üzerinden okuyabiliyorum. Bunu Yapmamda http://harinadha.wordpress.com/2012/07/ bu arkadaşın katkısı çok oldu.
Ayrıca Bunu Usart tan BT aracılığıyla PC ye gönderiyorum.

Şimdi diyeceksiniz ki "Arkadaş ne gerek var buna zaten yapmışsın" ama amacım RTOS denilen nirvana ya ulaşmak. Bunu CoOS (http://www.coocox.com/CoOS.htm) ile yapmayı planlıyorum.
(Bu arada Ramazan Ve Ben Haftaya İzine ayrılıyorum. Sabaha Kadar Ne Yapacagız?)


muhittin_kaplan

Şu an Raund Robin (Benim İçin Raundlar şeklinde Geçiyor :) )Çalışmayı deniyorum. Basit ve zor değil anladığım kadarıyla, Çünki CoOS nin nasıl yazıldığını değil Nasıl Kullanacağımı Öğrenmeye Çalışıyorum.
Sorum Şu Herhangi bir Taskın Süresini belirleyebiliyor muyum ?
Örneğin TaskA 10ms
TaskB 3ms gibi
Yoksa Hepsi 10Ms oluyor ama işlemi bittiğinde sıradaki task a mı atlıyor ?

muhittin_kaplan

#2
Aşağıda 3 task olan bir örneği çalıştırdım. ama anlamadığım konu şu oldu

CoTimeDelay(0,0,1,0); // Delay 1 second

ile 1 saniye bekle diyorum.  bu esnada sıradaki task a gidiyor mu gitmiyormu ? gidiyor gibi geldi bana.
Böyle bir durumda her taskın kesin zamanını nereden bileceğim ?
Saat ta 5:44 olmuş

/*---------------------------- Include ---------------------------------------*/
#include <CoOS.h>			              /*!< CoOS header file	         */
#include "stm32f4xx.h"
GPIO_InitTypeDef GPIO_InitStructure;


/*---------------------------- Symbol Define -------------------------------*/
#define STACK_SIZE_TASKA 128              /*!< Define "taskA" task size */
#define STACK_SIZE_TASKB 128              /*!< Define "taskA" task size */
#define STACK_SIZE_TASKC 128              /*!< Define "taskA" task size */


/*---------------------------- Variable Define -------------------------------*/
OS_STK     taskA_stk[STACK_SIZE_TASKA];	  /*!< Define "taskA" task stack */
OS_STK     taskB_stk[STACK_SIZE_TASKB];	  /*!< Define "taskB" task stack */
OS_STK     taskC_stk[STACK_SIZE_TASKC];	  /*!< Define "taskB" task stack */




void initGPIO()
{

	{

	      /* GPIOD Periph clock enable */
	      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


	      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
	      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	      GPIO_Init(GPIOD, &GPIO_InitStructure);


	      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);


	      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
	      	GPIO_Init(GPIOA, &GPIO_InitStructure);



	}


}


void taskA (void* pdata) {


  for (;;){

	  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

	  //CoTickDelay(1);
	  CoTimeDelay(0,0,1,0); // Delay 1 second

  }
}


void taskB (void* pdata){

  for (;;){
	  int i;
	  i = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
          GPIO_WriteBit(GPIOD,GPIO_Pin_13,i);
          CoTickDelay(10);//Delay 10 SystemTick
  	  }
  }

void taskC (void* pdata){

  for (;;){
	  	  GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
	 	  CoTimeDelay(0,0,0,300); // Delay 300 milisecond

  }
}


int main(void)
{
	SystemInit();
	initGPIO();
	CoInitOS ();				 /*!< Initial CooCox CoOS          */

	/*!< Create three tasks	*/
	CoCreateTask (taskA,0,0,&taskA_stk[STACK_SIZE_TASKA-1],STACK_SIZE_TASKA);
	CoCreateTask (taskB,0,1,&taskB_stk[STACK_SIZE_TASKB-1],STACK_SIZE_TASKB);
	CoCreateTask (taskC,0,1,&taskC_stk[STACK_SIZE_TASKC-1],STACK_SIZE_TASKC);
	CoStartOS ();			    /*!< Start multitask	           */

    while(1)
    {

    }
}


mesaj birleştirme:: 28 Temmuz 2013, 06:03:30

1 saniyede bir bu işi yap gibi bir şey sanırım .

ayhan_eee

Hocam ben daha önceden CMSIS RTX RTOS çalıştırdım. Orada taskların sonuna eklenen osDelay() fonksiyonu ile her taska kaç saniye(milisaniye) gelineceği belirtiliyordu. Yani task sonunda yazan süre kadar sonra tekrar geri geliniyor.

Mucit23

Coos ile Keilin kendi Rtos u arasında terimsel olarak pek fark olmasa gerek. Muhittin hocam bende bu işin takipçisiyim. Şuanda git gide Rtos un kendi yapısına sürükleniyorum.

Bazı Sormak istediklerim var.

1-) Bir Task En fazla nekadar sıklıkla çağrılabilir? Örneğin Ben timer kullanarak 800uS aralıklarla kesme oluşturabiliyorum. Mesela Kesme yerine Herhangi bir Rtos Taskını bu işe yönlendirebilirmiyim. Buradaki sınır nedir?

2-) Rtos Kullanıldığı zamanlar Timer kesmeleri çalışırmı, Yani Rtos Tasklarının dışında yine Timer kesmesi veya başka herhangi bir kesme kullanabilirmiyim?

3-) Örneğin Ben bir task ın max işlem süresini 3ms yaptım. Program bu taskın içerisindebir yere takılıp 3ms den fazla kalması gerekirse başka bir task çalıştırabilirmiyim. Yani taskda bir bekleme olursa başka bir taskı devreye sokup önlem alayım.

4-) En fazla kaç adet task oluşturabilirim?

Daha soracağım çok Soru var fakat şimdilik aklıma bunlar geldi. En Fazla merak ettiklerim bunlar

ayhan_eee

Soru bana gelmese de deneyimlerime dayanarak bildiklerim(ya da bildiğimi zannettiklerimi yanlışlarım varsa düzeltelim) dahilinde açıklamaya çalışayım.

1-Öncelikle RTOS ile bir bakıma yazılımsal olarak kesme oluşturmuş gibi oluyoruz.Yani timer kesmesi ile yapmak istediğiniz herşeyi uygun delay koyarak yaptırabiliriz.
2-Timer kesmeleri de çalışır.Ben denemedim.Ama ben CAN kesmesi çalıştırdım.Dikkat edilmesi gereken nokta kesmenin threadler arası geçişini bozmamak için kesme içinde fazla takılmadan bayrağını temizleyip, kendi kesme threadimi yazdım. Kesmeden bir signal yollayarak kesme threadini aktif ettim.Kesme den sonra threa yine pasif yaptım.Çalıştırdım CAN Kesmesini.
3-Eğer bir task yapılırken başka bir taskın süresi dolar ise izinler ve öncelikler dahilinde diğerine gider işini yapar ve geri dönüp kaldığı yerden devam eder.
4-Ben RTX ile 7 thread çalıştırdım.Daha da olabilir.

muhittin_kaplan

Mucit Diğerlerine Vakıf değilim ayhan cevaplamış.
CoOS de DelayTick vermiş ve herbir tick i 10ms ye ayarlamış görünüyor.
CoOS da verilen örneği incelediğimde 3 Task yapmış ama ben koplaya yapıştır 4 task yaptım. Sonrasında CoOSConfig dosyasında MaxUserTAsk Adında bir değişkenin 5 olarak tanımlandığını gördüm. [deneyip bakacağım kaça kadar gidiyor. (Murada Muhtemelen yapılan Task_stack boyutu önemli)]

muhittin_kaplan

Aklıma Takılan Bir Konuyu Sorayım.

taskA()
   .....
   .....
   Falanfilan
   Delay (10) // her 10ms de buraya gel (Eğer değilse lütfen uyarınız.)
EndTAskA

taskB()
   .....
   .....
   Falanfilan
   Delay (10) // her 10ms de buraya gel (Eğer değilse lütfen uyarınız.)
EndTaskB

taskC()
   .....
   .....
   Falanfilan
   Delay (10) // her 10ms de buraya gel (Eğer değilse lütfen uyarınız.)
EndTaskC


gibi üç adet Görevim olsun.

Öncelik Sırası A,B,C.
birinci görevi bitirdi 3ms de, erken bitti. Bekliyormu ? yoksa doğrudan B ye mi gidiyor. Eğer B ye gidiyorsa "Zamanlamanın Kesinliğinden" Nasıl emin oluyoruz.
Aynısı Tersi içinde geçerli, Task için biçilen süre  (Burayıda anlamadım) Geçer ama task bitmez ise (buton durumunu beklemek gibi yada ADC çevriminin bitmemesi) işlemi yarıda bırakıp sıradaki Göreve gidiyor. (Muhtemelen Tanımladığımız Stack, birdahaki çevrimde ki kullanılacak bilgileri tutuyor.) Taskların Sürelerini Nasıl Ayarlıyoruz.
Usartla Bilgi Gönderirken Kesilme Olmasını İstemem , Yada olurmu.

(Oruçtan Sanırım :D )

muhittin_kaplan

Sabah 5 oldu ve ben beceremedim.
2 taskım var, bunlar ADC oku ve Usart tan gönder. Adc Okuyorum Ama Usart tan Gönderemiyorum. Normal Yolla Yapıyorum.
Hatta Herhangi bir değeri de gönderemiyorum.
yatayım

muhittin_kaplan

#9
Yok Gerbay anlamıyorum,
Anladığımı Anlatayım.


int AdcDeger
taskADC
...
...
Flag=1
endTask

taskUsart
waitFlag
.....
.....
endtask


burada benim yapmadığım bayrağı beklemekti. global bir değişkeni kullanmıştım.

mesaj birleştirme:: 30 Temmuz 2013, 14:25:57

Hocam Şurada Bir örnek buldum. Adam Doğrudan Yapmış

http://www.mikrocontroller.net/attachment/161617/STM32F4_Discovery_CoOS_V0202.zip

mesaj birleştirme:: 30 Temmuz 2013, 14:52:21

birde DEBUG yaparken sıradan gitmesi gerekirken ileri geri olmadı 3 geri sonradan sıradan işletiyor komutları. garip.

mesaj birleştirme:: 30 Temmuz 2013, 14:56:55

Yukarda bahsettiğim DEBUG problemi code optimazate den kaynaklanıyormuş. none yaptım şu an düzgün debug yapıyorum.

muhittin_kaplan

Sonuç Olarak Okuma Yapmadan Usarttan Birşey Gönderemem, Gönderdiğimde Hatalı Olur. Bunun İçin Flag i Bekliyorum.

muhittin_kaplan


u32 flagID;
.
.
void taskA (void* pdata) {


  for (;;){

	  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

	  CoTickDelay(10);
	  //CoTimeDelay(0,0,10,0); 

  }
}


void taskB (void* pdata){

  for (;;){

	  int i;
	  i = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
          GPIO_WriteBit(GPIOD,GPIO_Pin_13,i);
          CoTickDelay(1);//Delay 1 SystemTick
          if (i==1) {
        	  CoSetFlag(flagID);
		}

  	  }
  }

void taskC (void* pdata){

  for (;;){
	  flagID = CoCreateFlag(0,0);      // Reset manually, the original state is not-ready
	   CoWaitForSingleFlag(flagID,0);

	  	  GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
	 	  CoTimeDelay(0,0,1,0); // Delay 1 second

  }
}


Hocam Şu şekilde Flag ile çalıştım.
Buradan Anlamam Gereken Şu mudur ?

flagId ye bak eğer set değilse sıradaki Task a atla. Bunun bize sağladığı avantaj ise,  eğer  herhangi bir görevin sonuç değeri başka bir görevi etkiliyorsa ve görev tamamlanmadığından dolayı sonucun hatalı olma olasılığı karşısında önlem almış alıyoruz.

muhittin_kaplan

#12
hocam benimde aklıma yatmadı ama
http://www.coocox.org/CoOSGuide/CoOS_Semaphores.htm
verdiği örnekte nedense taskın içerisine koymuş.

mesaj birleştirme:: 31 Temmuz 2013, 16:00:58

hocam ayrıca global alanda yapıyorum bu flag oluşturmayı nedense derlemiyor.

muhittin_kaplan

#13
tamam şimdi oldu. nedense ben Task ı sonsuz döngü ile birlikte kabul etmişim. meslek icabı fazla sorgulamıyoruz zannımca. deneyelim.

mesaj birleştirme:: 31 Temmuz 2013, 16:34:06

/*---------------------------- Include ---------------------------------------*/
#include <CoOS.h>			              /*!< CoOS header file	         */
#include "stm32f4xx.h"
GPIO_InitTypeDef GPIO_InitStructure;


/*---------------------------- Symbol Define -------------------------------*/
#define STACK_SIZE_TASKA 128              /*!< Define "taskA" task size */
#define STACK_SIZE_TASKB 128              /*!< Define "taskA" task size */
#define STACK_SIZE_TASKC 128              /*!< Define "taskA" task size */


/*---------------------------- Variable Define -------------------------------*/
OS_STK     taskA_stk[STACK_SIZE_TASKA];	  /*!< Define "taskA" task stack */
OS_STK     taskB_stk[STACK_SIZE_TASKB];	  /*!< Define "taskB" task stack */
OS_STK     taskC_stk[STACK_SIZE_TASKC];	  /*!< Define "taskB" task stack */


u32 flagID;

void initGPIO()
{

	{

	      /* GPIOD Periph clock enable */
	      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);


	      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
	      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	      GPIO_Init(GPIOD, &GPIO_InitStructure);


	      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);


	      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
	      	GPIO_Init(GPIOA, &GPIO_InitStructure);



	}


}


void taskA (void* pdata) {


  for (;;){

	  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

	  CoTickDelay(10);
	  //CoTimeDelay(0,0,10,0); // Delay 1 second

  }
}


void taskB (void* pdata){

  for (;;){

	  int i;
	  i = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
          GPIO_WriteBit(GPIOD,GPIO_Pin_13,i);
          CoTickDelay(1);//Delay 10 SystemTick

          if (i==1) {
        	  CoSetFlag(flagID);
		}

  	  }
  }

void taskC (void* pdata){

  for (;;){

	   CoWaitForSingleFlag(flagID,0);

	  	  GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
	 	  CoTimeDelay(0,0,1,0); // Delay 1 second

  }
}


int main(void)
{
	SystemInit();//168mhz
	initGPIO();
	CoInitOS ();				 /*!< Initial CooCox CoOS          */

	 flagID = CoCreateFlag(0,0);      // Reset manually, the original state is not-ready*******************************************
	/*!< Create three tasks	*/

	CoCreateTask (taskA,0,0,&taskA_stk[STACK_SIZE_TASKA-1],STACK_SIZE_TASKA);
	CoCreateTask (taskB,0,1,&taskB_stk[STACK_SIZE_TASKB-1],STACK_SIZE_TASKB);
	CoCreateTask (taskC,0,1,&taskC_stk[STACK_SIZE_TASKC-1],STACK_SIZE_TASKC);
	CoStartOS ();			    /*!< Start multitask	           */

    while(1)
    {

    }
}


mesaj birleştirme:: 31 Temmuz 2013, 16:35:00

amacım butonu kontrol ederek diğer taskı sıraya almak. herhalde bu doğru oldu..

şimdi Usart ile bilgi göndereyim.

mesaj birleştirme:: 31 Temmuz 2013, 16:52:26

Hocam Yukarda Verdiğim Kodda ise şöyle bir durum gerçekleşti. Birkez bayrağı set ettiğimde ve task sıraya girdiğinde devamlı çalışıyor. 

mesaj birleştirme:: 31 Temmuz 2013, 16:55:58

flagID = CoCreateFlag(Bool AutoReset,Bool initial state);
de parametre olarak veriliyormuş buna bağlı olarak
flagID = CoCreateFlag(1,0); yapınca her task bitiminde bayrağı sıfırlıyor sanırım.

muhittin_kaplan

Gerbay Hocam Sizi yakaladığım iyi oldu,
Flag i anladım. Peki Mutex nedir ? Neden Kullanırız ?