Yet another FreeRTOS C++ wrapper library (I)

This is my first successful C++ attempt for a library to wrap the FreeRTOS kernel. The idea behind any wrapper is to make life easier when using a software. Not only FreeRTOS’ names are awful, but there are state variables that must be kept during the program’s life cycle. Did I say state variables? Weeee! This is an excellent opportunity for abstracting the kernel and the tasks with classes in C++, while hidding and encapsulating such state variables. Let me mention something that I read time ago “If there is no state to hold, then there is no reason for a class to exist”. This is my first successful C++ attempt for a library to wrap the FreeRTOS kernel. The idea behind any wrapper is to make life easier when using a software. Not only FreeRTOS’ names are awful, but there are state variables that must be kept during the program’s life cycle. Did I say state variables? Weeee! This is an excellent opportunity for abstracting the kernel and the tasks with classes in C++, while hidding and encapsulating such state variables. Let me mention something that I read time ago “If there is no state to hold, then there is no reason for a class to exist”.

First of all, with the task’s handler one is able to completely access the task, so this might be the only state variable a class should hold, as shown later. And taking advantage of default parameters and function overload, some methods calls are really easy, for example:

Thread aTask (256); 
Led aLed (256);

Even easier:

Button aButton;

One thing is the kernel itself, and one thing are the tasks. So I wrote two classes. And each class answers this question: Who is responsibly of what? Each task can be an object, or can be a regular task. Stroustrup said “A good software is a mixed of the different programming paradigms.” (or something like that, and I’m pretty sure Java developers must be hating me by now!). When the time comes to abstract the other kernel’s modules, then each one will be a class (semaphores, mutex, queues, etc.).

The code so far is really easy to understand, so there is no need for further explanations. Nonetheless the most important thing IMHO, beyond C++ syntax, is the philosophy I’ve followed: to abstract whenever it’s needed.

Some specs: LPC11U68 microcontroller, MCUXpresso IDE, LPCXpresso LPC11U68 board, Linux Box and FreeRTOSv9.0.0. C++11 as compiler and the NewlibNano library was used to link against.

I’ll be posting in each major advance I make. Keep in mind that this is a work in progress and any suggestion is welcomed.

#include "board.h"

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

namespace oscpp
{

class OS
{
public:
  static void Start ()
  {
    //running = true;
    vTaskStartScheduler ();
  }

  static void End ()
  {
    //running = false;
    vTaskEndScheduler ();
  }


  static bool Task (  TaskHandle_t* handle, TaskFunction_t _code, uint16_t _stackDepth,
            UBaseType_t _priority = tskIDLE_PRIORITY, void* _params = NULL);

  void Sleep (uint32_t _milis);

private:
  bool running;

};

bool OS::Task (TaskHandle_t* handle, TaskFunction_t _code, uint16_t _stackDepth,
        UBaseType_t _priority, void* _params)
{
  return (xTaskCreate (_code, "", _stackDepth, _params, _priority, handle) == pdFALSE) ?
    false :
    true;
}

void OS::Sleep (uint32_t _millis)
{
  vTaskDelay (_millis);
}

OS os;
// global scope

} //namespace oscpp

namespace oscpp
{

class Thread_T
{
public:
  Thread_T (uint16_t _stackDepth = configMINIMAL_STACK_SIZE, UBaseType_t _priority = tskIDLE_PRIORITY, void* _params = NULL)
  {
    this->created = oscpp::os.Task (&this->handler, runner, _stackDepth, _priority, _params);
  }

  virtual void Run () = 0;

protected:
  static void runner (void* _params)
  {
    Thread_T* thread = static_cast<Thread_T*> (_params);
    thread->Run ();
  }

  TaskHandle_t handler;
  bool created;
};

} //namespace oscpp

//----------------------------------------------------------------------
//  Userspace
//----------------------------------------------------------------------


#define ledSTACK_SIZE 256

TaskHandle_t ledHandler;

void led (void* _params)
{
  _params = _params;

  while (1)
  {
    oscpp::os.Sleep (1000);
  }
}



class Thread : public oscpp::Thread_T
{
public:
  Thread (uint16_t _stackDepth, UBaseType_t _priority = tskIDLE_PRIORITY, void* _params = NULL) :
    Thread_T (_stackDepth, _priority, _params) {}

  void Run () override
  {
    while (1);
  }
};

class Led : public oscpp::Thread_T
{
public:
  Led (uint16_t _stackDepth) : Thread_T (_stackDepth) {}

  void Run () override
  {
    while (1);
  }
};

//----------------------------------------------------------------------
//  Driver program
//----------------------------------------------------------------------
int main(void)
{
  SystemCoreClockUpdate();
  Board_Init();
  Board_LED_Set(0, true);

  // three ways to create a task
  oscpp::os.Task (&ledHandler, led, tskIDLE_PRIORITY, ledSTACK_SIZE, NULL);
  Thread aTask (256);
  Led aLed;

  oscpp::os.Start ();

}

Greetings!

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s