FreeRTOS was created using C. C++ offers something more than C, which are object oriented and inheritance. This is shown by the usage of class. By using class, users can create their task by simply creating the object of the class.
To implement the class, I need to understand the definition of class and its properties.
Class is like data structure, except that it can contain functions. So, each object created from a class will not only has the same variables, but also the same functions. Back to FreeRTOS, each task has a task name, a stack size, a priority, a void parameter and a task handle. All of this will become a member of the class Task. To create a task, users will have to use FreeRTOS built-in function xTaskCreate(). Since this function is valid for every task, this function also becomes a function member of the task.
Another strong feature of class is inheritance. Inheritance is when the child class which is derived from another class (parent class) will inherit all the members of the parent class. The parent class do not take anything from the child class. This means that the child class(es) can have similar members of the parent class but still has some different properties compared to the parent class. This feature can help simplify the users as they can create child classes which has FreeRTOS requirements already inherited from the parent class Task but they can write their task inside the child class.
I create the class Task by adding the required members one by one. To not confuse myself writing the child classes as a dummy user, I only let the task name be a user-defined variable while the others set beforehand. Dr Shawn advised me to structure the class like an Arduino program (a setup body and loop body). Therefore, I added both void functions as virtual function in the parent class. These two function will be defined in the child classes. I also created a member function initiate which will initiate the loop() function with an infinite loop.
I thought that this was enough and it was time to create child classes by sending the member functions into xTaskCreate. However, this was not the case as I encountered a compilation error. The error was that xTaskCreate only accepts global function pointer while member function pointer are different from them. This means that I cannot create task by using the virtual member functions or even the non-virtual members. One possible way was to use static member function as the task function. Static member pointers act the same way as global function pointers so they can be used in xTaskCreate. In this case, the virtual members that the user write their task needs to be converted to static members which is not desired.
The other way was to use an immediate class object which the users have to declared themselves. Below is the coding for this solution.
class TASK
{
TaskHandle_t *pvCreatedTask;
public:
const char* const Task_Name;
virtual void setup()
{ }
virtual void loop()
{ }
void initiate() //wrap the loop() function with infinite loop
{
while(1)
loop();
}
void start(void intermediate(void *pvParameters)) //creates the task
{
xTaskCreate( intermediate,
Task_Name,
1000,
NULL,
1,
pvCreatedTask
);
}
TASK( const char* const TaskName ):Task_Name(TaskName){}
~TASK(){}
};
On the users side, the users will have to create their task in the following format.
class TASK1: public TASK //their task
{
public:
TASK1():TASK("T0"){}
void setup()
{}
void loop() //their task statements
{
}
~TASK1(){}
};
TASK1 Task1_obj; //Child class object of their task
void task1(void *pvParameters) //Global function which calls the member function of child, uses name of class in small letters
{
Task1_obj.initiate();
}
As you can see the users need to declare a global function which will link to their object class.
Finally, in the main() function the users will have to start their task with the following code.
Task1_obj.start(task1);
There are 2 more extra steps and this still needs to be further improved.
0 Comments