FreeRtos C++ Wrapper

Başlatan yamak, 20 Eylül 2016, 16:27:51

yamak

FreeRtos'u C++ ile birlikte kullanmak için bir wrapper yazdım.Rtos ile ilgilenen arkadaşlarında işine yarayacağını düşündüğüm için paylaşıyorum.
Kullanımı şöyle:
FreeRtos taskı olmasını istediğiniz bir fonksiyonu yazacağınız bir class içinde
static void run(void* pvParameters){
}

şeklinde protected olarak tanımlıyorsunuz.Fonksiyonu isminin run olması ve aldığı parametrelerin yukarıdaki gibi olması gerekiyor.Fonksiyonu public olarak da tanımlayabilirsiniz ama protected olsa daha şık olur.
Örneğin LedTask adında bir class içinde.

Daha sonra template class olan Taskable class ından aşağıdaki gibi bir instance oluşturuyorsunuz:

Taskable<LedTask,128> ledTask1;

Buradaki 128 byte cinsinden task'ın stack boyutu.İhtiyacınıza göre artırıp azaltabilirsiniz.

Sonra da aşağıdaki gibi task ı çalıştırıyoruz:
ledTask1.start("LED TASK1",4);

buradaki 4 de task'ın priority'si.

Aşağıda stm32f4 discovery için yazdığım örnek projeyi inceleyip deneyebilirsiniz.Keil ve IAR proje dosyaları mevcut.Herhangi birinde çalıştırabilirsiniz.

https://gitlab.com/yamak/RtosWrapper/blob/master/Application/main.cpp

yamak

Estagfurullah Hocam.
Yukarida yazdigim, c++ da policies leri incelerken aklima gelmisti ordan esinlerek yazdim ben de. Bi de hocam stack size i o sekilde yapmamin nedeni de tasklari static olarak create ediyorum o yuzden template class in parametresi olarak belirledim. Compile time da stack size i belli olsun diye.

Sizin soylediginiz gibi extend etsek guzel olur gercekten. Soylediginiz gibi extend etmeye ugrasayim biraz hocam.

yamak

#2
Hocam bahsettiğiniz yöntemi aşağıdaki başlıkta yaklaşık 2 yıl önce konuşmuştuk sizinle. :)
https://www.picproje.org/index.php/topic,51614.0.html
Bu zamana kadar sizin yönteminizi kullanıyodum.Hatta bu yazdığımda da sizin yöntemden esinlendim.Fakat dediğim gibi Andrei Alexandrescu'nun Modern C++ kitabını okurken kullandığı yöntemlerden de  esinlenerek bu şekilde bir wrapper yazdım.
Bir de Rtos kullanırken taskları static olarak create ettiği için ve düzenlilik açısından her taskın stacki kendi class'ında tanımlı olsun ve boyutu da compile time da belirlenebilsin diye abstract class kullandım.
Hocam dediğim gibi bu yaptığım tamamen C++ policies ın bi uygulamasıydı.

DEno_12

Alıntı yapılan: gerbay - 20 Eylül 2016, 22:39:49
yaşlılık işte hocam..

@z hocam tüketti beni asm diye diye..

:D çok iyi... Maşallahınız var yinede.

X-Fi

@gerbay hocam freertos u C dilinde ve static task create ederek kullanıyorum. Bu haliyle bile stack sorunlarıyla boğuşuyorum. Örneğin semaphore bekleyen bir buzzer task'ının semaphore fail olma durumu yüzünden trace analizi logları dallandıkça dallanıyor ve stack derinliği artıyor. Basit bir task için net 300,400 byte stack derinliği oluşabiliyor. Keza intterrupt içinde semaphore kullanılıyorsa durum aynı.  Bu istenmeyen stack kirliliğinden kurtulmak için taskları birleştirip mesajlarla haberleşmeye çalışıyorum. Sizin virtual tasarımlarınız bu durumları da göz önünde bulundurmalı diye düşünüyorum yoksa dinamik yapı yanlış kullanılırsa stack çökmelerine müsait olacaktır. Yazılımcının kontrolünü kolaylaştıracak hertürlü yeniliğin takipçisiyim.

Saygılarımla.
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)

yamak

@X-Fi hocam tracelyzer i kastetti galiba. Sizin dediginiz gibi konsole imkani freeRtos ta yok galiba. Micrium da vardi boyle bisey ama freertos icin var mi emin olamadim.
Bir de @X-Fi virtual function lar icin bahsettiginiz ozel durumu tam olarak anlayamadim. Duzgun bi tasarimla C ile yazilanla ayni performansta olabilecegini dusunuyorum.

X-Fi

@gerbay hocam Freertos şu yöntemle; http://www.freertos.org/rtos-run-time-stats.html tasklar hakkında bilgi almak ve free heap size öğrenmek mümkün ayrıca bir stack taşması olduğunda hangi fonksiyonda olduğunuda bize söylüyor.

Aslında benim öğrenmek istediğim bu stack alanlarını minimum seviyede nasıl tutabiliriz olacaktı.

@yamak hocam performans olarak karşılaştırmıyorum. Bir task hangi metotlarla oluşturulursa oluşturulsun tabiki aynı işi yapar ancak C de static stack alanlarını hesaplamak çetrefilli ve zor iken virtual mekanizmalarda taskların heap size içerisinde güvenli çalışma alanları bulup bulamayacağından emin olabilecek miyiz. Benim paranoyam burada başlıyor.

iyi çalışmalar.
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)

yamak

#7
Alıntı yapılan: X-Fi - 21 Eylül 2016, 08:22:24
@gerbay hocam Freertos şu yöntemle; http://www.freertos.org/rtos-run-time-stats.html tasklar hakkında bilgi almak ve free heap size öğrenmek mümkün ayrıca bir stack taşması olduğunda hangi fonksiyonda olduğunuda bize söylüyor.

Aslında benim öğrenmek istediğim bu stack alanlarını minimum seviyede nasıl tutabiliriz olacaktı.

@yamak hocam performans olarak karşılaştırmıyorum. Bir task hangi metotlarla oluşturulursa oluşturulsun tabiki aynı işi yapar ancak C de static stack alanlarını hesaplamak çetrefilli ve zor iken virtual mekanizmalarda taskların heap size içerisinde güvenli çalışma alanları bulup bulamayacağından emin olabilecek miyiz. Benim paranoyam burada başlıyor.

iyi çalışmalar.

Hocam static olması konusunda haklısınız.Zaten freertos a 9 versiyonundan önce kıl oluyodum,tasklar static olarak create edilemiyor diye.Aslında @gerbay hocamın yöntemi biraz değiştererek taskları static olarak create edebilecek hale getirmiştim.

RtosTask.h:
#ifndef RTOS_TASK_H
#define RTOS_TASK_H

#include "FreeRTOS.h"
#include "task.h"

class RtosTask {
  
public:
  void start(const char* name, unsigned int priority, StackType_t* const stackPtr, unsigned int stackDepth);
  
  void stop() {_terminated=true;}
  
  bool isTerminated(){return _terminated;}
  
  void suspend(){vTaskSuspend(_handle);}
  
  void resume(){vTaskResume(_handle);}
  
private:
  bool _terminated;
  TaskHandle_t _handle;
  StaticTask_t _tcb;
  
protected:
  virtual void run() = 0;
  
private:
  static void bridge(void* pThis);
};
#endif


RtosTask.c
#include "RtosTask.h"

void RtosTask::start(const char* name, unsigned int priority, StackType_t* const stackPtr, unsigned int stackDepth) {
  
  xTaskCreateStatic(bridge,name,stackDepth,this,priority,stackPtr,&(this->_tcb));
  
}
void RtosTask::bridge(void* pThis) {
  
  RtosTask* pTask=(RtosTask*)pThis;
  pTask->run();
  pTask->_terminated=true;
  pTask->_handle=0;
  
}

Kullanımı da şöyle:
LedTask1 ledTask1;
LedTask2 ledTask2;
StackType_t LedTask1Stack[256];
StackType_t LedTask2Stack[256];
int main()
{
  ledTask1.start("LED_TASK1",5,LedTask1Stack,256);
  ledTask2.start("LED_TASK2",4,LedTask2Stack,256);
  vTaskStartScheduler();
  return 0;
}

engineer

@yamak hocam sizin RTOS yazı dizisinin devamı gelmedi, şimdi biz bu wrapper'a fransız kaldık :) devam etsenizde öğrensek ne güzel olurdu.

yamak

Alıntı yapılan: engineer - 21 Eylül 2016, 09:24:45
@yamak hocam sizin RTOS yazı dizisinin devamı gelmedi, şimdi biz bu wrapper'a fransız kaldık :) devam etsenizde öğrensek ne güzel olurdu.
Haklısınız hocam bi ara bi heyecanla başlangıç yaptım ama sonradan araya bi şeyler girdi devamını getiremedim.Devamını getirecem İnşallah :)

engineer

inşallah @yamak hocam, emeğinize sağlık. dört gözle bekliyorum :)

leblebitozu

C örneğinde new yerine malloc kullanılmalı sanırım..

X-Fi

#12
@gerbay hocam CPP örneğiniz bilgilerimizi tazelememiz açısından çok faydalı oldu. Benim size bahsettiğim C ve C++ farkından oluşacak stack yükü değildi zaten okadar küçük RAM kapasitesi olan işlemciler artık tarih oldu. Class içerisinde task üreten fonksiyonlarınıza StackCheck yapacak bir mekanizma ile yetersiz durumlarda işlemi askıda tutarsanız o zaman hiç stack şüphem kalmaz. Çokta güzel olur. Freertos yeteri kadar stack alanı kalmamış ise task oluştururken hata dönerdi diye hatırlıyorum.

iyi çalışmalar.
http://www.coskunergan.dev/    (Yürümekle varılmaz, lakin varanlar yürüyenlerdir.)