RTOS Öğrenmek İçin Bahane

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

mufitsozen

#30
Alıntı yapılan: muhittin_kaplan - 02 Ağustos 2013, 17:38:11
5 kez irdeledim ama
Geybay ın bahsettiği flag ile alakalı olarak,
"eğer flag ile blokladığın task ı atlayıp diğer task a sıradaki task a geçmiyorsa" demiş, (geçmiş konuşmalardan dolayı) bende bunun üzerine flag ile alakalı olmayıp delay koymadığım hiçbir taskı bırakmıyor dedim.

atladığım nokta nedir, hatalı yaptığım mı, zaten hatalı yaptığımdan dolayı düzgün çalışmıyor.

sayin @muhittin_kaplan, tam 10 dakikadir yazip birseyler aciklamaya calismistimki, yanlis bir tusa bastim, hepsi uctu!  :(

yarin vaktim olursa size biraz detayli cevap yazmaya calisacagim

mesaj birleştirme:: 02 Ağustos 2013, 18:28:43

Write Short ISR's:

- Even lowest priority ISR's are handled before the highest priority task code (minimize task code response time)
- ISR's are error prone and hard to debug (due to hardware-dependent software parts)
- Parts ISR code requiring immediate / quick response should be in the core of ISR code; parts needing 'longer' processing and not-so-urgent response should be done a task (signaled by the ISR)

-Recommended Task Structure

-Modeled/Structured as State-Machines –
-Tasks run in an infinite loop
-Tasks wait on RTOS for an event (expected in each task's independent message queue)
-Tasks declare their own private data to use (fully encapsulated)
-Tasks block on in one place (RTOS signal), and not any other semaphore, no data sharing
-Tasks use no microprocessor time when their queues are empty

-Avoid Creating and Destroying Tasks
  -Creating tasks takes more system time
  -Destroying tasks could leave destroy pointers-to-messages, remove semaphore others are waiting on (blocking them forever)
  -Rule-of-thumb: Create all tasks needed at start, and keep them

Bu kisa liste sizin prblemlerinze cevap verecektir.

mesaj birleştirme:: 02 Ağustos 2013, 18:39:27

cok kucuk ve yetersiz bir ornek ama, soyle bir set-top-box tasklari olabilir(mi ki acaba?  :P )

Task 1:
Read Signal
Separate Audio/Video
Send Audio to Task 2
Send Video to Task 3
Repeat

Task 2:
Wait on Task 1
Decode/output Audio
Repeat


Task 3:
Wait on Task 1
Decode/output Video
Repeat


lutfen producer/consumer modeli vb gibi arayarak daha formal bir tasarim aciklamasi bakiniz.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan

hocam zahmet veriyorum farkındayım, hakkınızı helal edin, kusruma bakmayın artık. belkide aptalca bir yerde takılıyor önümdekini görmüyorum. yada kafa bu kadar basmıyor.


http://www.bilgisayarkavramlari.com/2012/03/05/producer-consumer-problem-uretici-tuketici-problemi/
Hocam Olayı Anladım, Burada bir problem yok,

Taskın birindeki bir değişim diğerini etkiliyorsa, değişim olana kadar beklemeli.

ama benim uğraştığım problem task switching yapmaması, birbirini etkileyen durumlar yokken.

Aşağıdaki Kodlarda taslar arası geçiş sağlanırken

/*---------------------------- Include ---------------------------------------*/
#include <CoOS.h>			              /*!< CoOS header file	         */
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
/*---------------------------- 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 "led" task stack   */


void initGPIO()
{

	GPIO_InitTypeDef GPIO_InitStructure;

	      /* 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);
}



/**
 *******************************************************************************
 * @brief       "taskA" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to crate mutex and flags,print message "taskA running".
 *             Indicate "taskA" had been executed.
 *******************************************************************************
 */
void taskA (void* pdata) {

  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
	CoTickDelay (50);
  }
}


/**
 *******************************************************************************
 * @brief       "taskB" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to print message "taskB running". Indicate "taskB"
 *             had been executed.
 *******************************************************************************
 */
void taskB (void* pdata){
  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
	CoTickDelay (50);
  }
}


/**
 *******************************************************************************
 * @brief       "taskB" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to print message "taskB running". Indicate "taskB"
 *             had been executed.
 *******************************************************************************
 */
void taskC (void* pdata){
  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
	CoTickDelay (50);
  }
}

int main(void)
{
	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,2,&taskC_stk[STACK_SIZE_TASKC-1],STACK_SIZE_TASKC);
	CoStartOS ();			    /*!< Start multitask	           */

    while(1)
    {
    }
}


Bu Kodlarla Yapmıyor.

/*---------------------------- Include ---------------------------------------*/
#include <CoOS.h>			              /*!< CoOS header file	         */
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
/*---------------------------- 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 "led" task stack   */


void initGPIO()
{

	GPIO_InitTypeDef GPIO_InitStructure;

	      /* 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);
}



/**
 *******************************************************************************
 * @brief       "taskA" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to crate mutex and flags,print message "taskA running".
 *             Indicate "taskA" had been executed.
 *******************************************************************************
 */
void taskA (void* pdata) {

  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_12);

  }
}


/**
 *******************************************************************************
 * @brief       "taskB" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to print message "taskB running". Indicate "taskB"
 *             had been executed.
 *******************************************************************************
 */
void taskB (void* pdata){
  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_13);

  }
}


/**
 *******************************************************************************
 * @brief       "taskB" task code
 * @param[in]   None
 * @param[out]  None
 * @retval      None
 * @par Description
 * @details    This task use to print message "taskB running". Indicate "taskB"
 *             had been executed.
 *******************************************************************************
 */
void taskC (void* pdata){
  unsigned int led_num;

  for (;;) {
	  GPIO_ToggleBits(GPIOD, GPIO_Pin_14);

  }
}

int main(void)
{
	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,2,&taskC_stk[STACK_SIZE_TASKC-1],STACK_SIZE_TASKC);
	CoStartOS ();			    /*!< Start multitask	           */

    while(1)
    {
    }
}


aralarındaki tek fark task sonlarında delay olmaması (delay da değildir ya :p)

mufitsozen

#32
Bu cevabi yazarken ornek verdiginiz prgramlari compile edip denemedim onun icin yaniliyorda olabilirim ama son 30 dakikada kucuk bir inceleme yapinca sanki prbleminizin ne oldugunu buldum.

sayin @muhittin_kaplan delay olmayan programdaki task priorityleri 0,1,2 yerine hepsini ayni yapiniz ki time-tick interrupt gelince siradaki ayni prioritydeki taske gecilsin.

Orneginizin kisitli/kotu olmasindan dolayi kafaniz karisiyor ve size @gerbay yada benim soylediklerimle gozlemleriniz celisiyor gibi geliyor. (su-i misal emsal olmaz yani  :P )

affiniza dayanarak bir kere daha soylemem gerek. RTOS ile ilgili conceptleri bilmeden yapilan deneme yanilma ile ogrenmeniz hem zaman alacak hemde burada goruldugu gibi size yanlis intiba/aliskanliklar verecek. Bahsettiginiz (problem olmayan) problem CoOSun isleyisinden geliyor.

Benim okuduguma ve incelememe gore:

ilk programinizda (delay olan) delay yapinca task ready den cikiyor, siradaki en yuksek oncelikli ready diger task devreye geliyor ve taskler arasinda gecis oluyor

ikinci programinizda 3 task birden ready ve oncelikleri de farkli, dolayisi ile hep en yuksek oncelikli task calisiyor.

CoOS user guide sayfa 18de soyle soyluyor.

2.5 Task Scheduling
CooCox CoOS supports two kinds of scheduling mode, preemptive priority
and round-robin. The former is used among tasks of different priority, while the
latter among tasks of the same priority.

CooCox CoOS will start a task scheduling in the following three situations:

1) A task whose priority is higher than the current running one is
converting to the ready state;

2) The current running task is changing from the running state to the
waiting or dormant state;

3) A task sharing the same priority with the current running task is in the
ready state, and meanwhile the time slice of the current task runs out .

When a system tick interrupt exits or some tasks' states have changed,
CooCox CoOS will call the task scheduling function to determine whether it is
essential to start a task scheduling or not.

For the scheduling of tasks sharing the same priority, the system starts the
rotation scheduling according to the time slice of each task. When the system
has run out the time slice of the current task, it will give the right of control to
the next task with the same priority

isterseniz ozelden mesaj atip mbl telefonunuzu verirseniz size yardimci olmak isterim
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan

hocam bu task önceliğini ben yanlış anlamışım. öncelik derken anladığım bir nevi sıralama idi. ama dediğiniz doğru tasların önceliğini aynı yapınca şuan doğrudan geçiş yapıyor.
Cep telefonundan zor olmaz mı bu ?
Saygıyla

mufitsozen

Alıntı yapılan: muhittin_kaplan - 03 Ağustos 2013, 02:12:07
hocam bu task önceliğini ben yanlış anlamışım. öncelik derken anladığım bir nevi sıralama idi. ama dediğiniz doğru tasların önceliğini aynı yapınca şuan doğrudan geçiş yapıyor.
Cep telefonundan zor olmaz mı bu ?
Saygıyla

Benim her yanlis anladigim konu icin sen otur yarim saat programlari incele/karsilastir, dokuman oku, neyi yanlis anladigimi bul diyorsunuz yani.

Haklisiniz, evet cep telefonundan cok zor olur. Pahalida olur ustelik.

Bol sans. Saygilar.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan

Bana Haksızlık Ediyorsunuz Hocam, Sadece Flag i Kavramak için Defalarca CoOS yi inceledim, Kaldıkı Mesaj Yazdığım Saatlere Bakarsanız Üzerinde Ne Kadar Durduğumu Anlarsınız.
Saygıyla..

mufitsozen

#36
Alıntı yapılan: muhittin_kaplan - 03 Ağustos 2013, 03:33:33
Bana Haksızlık Ediyorsunuz Hocam, Sadece Flag i Kavramak için Defalarca CoOS yi inceledim, Kaldıkı Mesaj Yazdığım Saatlere Bakarsanız Üzerinde Ne Kadar Durduğumu Anlarsınız.
Saygıyla..

Yine cok haklisiniz.

Sizin bu yogun calismalariniz sirasinda caninizi sikmak istememistim.

Ilerlemis zamanin (neredeyse gece 4 olmus) yasli bir zihine oynattigi oyun diyelim.

Ozur dilerim.
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan

#37
Hocam Özre Gerek Yoktur,
Durduğum Yeri Bilen Biriyim, Sizin Nazarında Diğer Hocaların Karşısında Saygılı olmamız gerekir. Eksiklerimiz vardır elbet. Bunları da Sizler affedin.

Mümkün Olduğunca Paylaşırım. Belkide Bu "Hayatımı Bu İşten Kazanmıyor" olmamdan kaynaklıdır.
Saygıyla.

mesaj birleştirme:: 03 Ağustos 2013, 04:07:26

Unutmadan Espri ile karışık, Saat 20 gibi Bana Kızdığınızı Farketmiş diğer konuya Yapıştırmışım (Araştırmadan Soruyor algısı oluştuğunu hissetmiştim.)

https://www.picproje.org/index.php/topic,48120.msg358795.html#msg358795

muhittin_kaplan

#38
Şurada iğrenç bir müzikle bir video verilmiş, bu video da preemptive priority yi anltmış ve bazı chartlar çıkartmış,
www.youtube.com/watch?v=c-DuS9iYkWc

buradaki burst time nedir
diye araştırınca task için gerekli olan süre olduğunu anlıyorum, peki task için gerekli süreyi nasıl bileceğim ?

mesaj birleştirme:: 06 Ağustos 2013, 05:37:08

ROUND ROBIN SCHEDULING ALGORITHM

AsHeS

#39
Muhittin hocam genel konsept için şu kitabın e-kitabını indirin aklınıza takılan birçok soruya cevap olacaktır:
http://www.amazon.com/Embedded-Multitasking-Technology-Keith-Curtis/dp/0750679182

mufitsozen

#40
Alıntı Yap.....task için gerekli olan süre olduğunu anlıyorum, peki task için gerekli süreyi nasıl bileceğim ?

sayin @muhittin_kaplan hocam, siz bilmeyeceksinizde bizmi bilecegiz?  :D

Saka bir yana bu sure sizin gereksinimlerinizin (requirements) size dikte ettirdigi sure.

Ornegin her 5 msde bir ADC okunup bilgisayara gonderilecek. yada saniyede 100 sample islenecek vb

tabii buradaki sureler cok siki (tight) değil. oyle olsaydi hard-real-time bir sistem olurdu, tasarimida daha zor olurdu (radar, savas sistemleri, vb)

Normal olarak ticari sistemlerde gereksinimler x zamanda bir +-%y diye olur.

Ornegin benim tecrubeli oldugum VoIP sistemlerde acceptable round-trip delay 200ms'dir kullanicilar bu deger 250-300msyi gecerse farki algilayabilmeye baslarlar. yani round-trip delay icin gereksinim 200ms +-50 ms olsa kabul edilebilir limitlerde olur.

Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan

Yok Hocam Kastım Taskın Süresi Değil. (1tick 10ms olarak ayalanmış CoOs da-http://coocox.org/CoOSguide/CoOS_System_Ticks.htm-) Onu ben belirliyorum OS un parametreleriyle.

Oluşturduğum bir task ne kadar sürede işlem yapar ? (belkide yanlış sorular soruyorum, bu yüzden doğru cevabı bulamıyorum.)
Dolayısıyla BirTaskın işlemini bitirmesi TaskSüresi+RoundTrip değilmidir.

mesela bir Gyrodan bilgi okumam gereksin (zaman önemli) ve ben RoundRobin kullanayım. taskA nın işlemini bitrme süresini nereden bileceğim.
void taskA (void* pdata) {



  for (;;) {
		s16 AccelGyro[6]={0};
		MPU6050_GetRawAccelGyro(AccelGyro);


		AccX=AccelGyro[0];
		AccY=AccelGyro[1];
		AccZ=AccelGyro[2];

		GyrX=AccelGyro[3];
		GyrY=AccelGyro[4];
		GyrZ=AccelGyro[5];


		sprintf(str,"GX%dGY%dGZ%dAX%dAY%dAZ%dS\r\n",GyrX,GyrY,GyrZ,AccX,AccY,AccZ);
		USART_puts(USART2,str);
		CoSetFlag(flag0);

  }
}

void taskB (void* pdata){


  for (;;) {
    CoTickDelay(10);
  }
}

void taskC (void* pdata){

  for (;;) {
	  CoWaitForSingleFlag(flag0,0);
	  GPIO_ToggleBits(GPIOD,GPIO_Pin_12);
	  //CoTickDelay(1);
	  GPIO_ToggleBits(GPIOD,GPIO_Pin_13);
	  //CoTickDelay(1);
	  GPIO_ToggleBits(GPIOD,GPIO_Pin_14);
	  //CoTickDelay(1);
	  GPIO_ToggleBits(GPIOD,GPIO_Pin_15);
	  CoTickDelay(5);//5*10ms=50ms de bir bu işlemi gerçekleştir mi oluyor ?

  }
}


mufitsozen

#42
Herseyden once belirtmem lazimki, ben CoOS expert'i değilim. onun icin yazdiklarim tam dogru olmiyabilir

Ayrica tam olarak ne yapmak istediginiz sizce belirli ama, bizim bu konuda cok flu bir fikrimiz var

Tam olarak ne yapmak istediginizi soylerseniz ona gore dusunuruz.

ustelik acik bir forumda sadece mesajlasarak kisitli ortamin dezavantajlarindan dolayi yanlis anlasilmalarda cok olacaktir.

simdi kaide olarak taskler bir event vb ile uyanip birsey yapip tekrar beklemeli, vede taskler arasinda mesajlar ile haberlesilmeli dedik.

Ayrica hw ile ilgili konularda ISR yapip, onlarida tasklere IPC teknikleri ile baglamak lazim diye daha once yazmistik.

Simdi sizin gyrodan okumanizin sadece periodik bir timer ile yapildigini (ornegin gereksiniminizin, her 10msde bir gyrodan okuma yapmak ve bunu PCye gondermek oldugunu oldugu varsayalim.

PCye olan iletisim, RS232 olacak ve buda bir ISR ile kontrol edilecek. Bu ISR rs232den gelen ve giden karakterleri bir message queue'sundan alacak.

Gyro icin bir ISR gerekmiyor, dogrudan okuma yapilabilir varsayiyoruz.

o zaman (bence) taskler soyle olur:

taskA:
10 msde bir gyroyu oku, 
  sonuclari taskBye queue et

10msde bir calisma kisminida bir periodik timer yapip, while loop icinde onu bekleyip, sonra gyroyu okuyarak yapabilirsiniz.

yani

taskA:
  /* tanimlari yap */
  /* initializationlar: periodik timer icin kullanacaginiz semaphore'u yaratin  */
  /* periodik 10ms timer baslat: call_back fonksiyonunda bu timer ile ilgili olan ve timerin expire oldugunu gosteren semaphonu set eden fonksiyonu belirtin)
  while (1){
     timer_semaphorunu bekleyin,
    semaphoru reset edin (timeri islediginiz icin)
     gyro_degerlerini okuyun
     degerleri rs232 taskine queue edin
  }

gibi bir yapida yapabilirsiniz

timeriniz periodik oldugu icin, siz bu islemleri yaparken yine 10m sayacaktir.

boylece her 10ms+x milisaniyede (x=minik bir miktar interrupt latency ve semaphore set edilmesi vb icin fix bir zaman degeri ki, bu epsilon gibi birsey olacaktir, microsaniyeler mertebesinde olur.)

yada call_back fonksiyonunda semaphore set filanlaugrasmayip, direk gyro degerlerini okuyup rs232 taskine queue edebilirsiniz.

Benim kisisel tercihim, bu sekilde yapilirsa, call_back fonksiyonlarinin ne zaman cagrildigi ve program execution'i karisik olur hatalara yol acar, bu yuzden call_back fonksiyonlarinida cok kucuk ve kisitli bir fonksiyon yapmak icin kullanmak dahah dogru olur diye dusunuyorum.

birde taskB yapacaksiniz, kendi queue'una gelen karakterleri alip PCye yolliyacak.

(vede belki PCden gelenleride ISR ile alip, baska bir taskC ye yolliyacak, yada rs232 ISR gelen datayi taskCye queue edecek, ne bileyim ben  :))
Aptalca bir soru yoktur ve hiç kimse soru sormayı bırakana kadar aptal olmaz.

muhittin_kaplan