Difference between revisions of "Embedded System Tutorial FreeRTOS"

From Embedded Systems Learning Academy
Jump to: navigation, search
(C++ based FreeRTOS task)
Line 25: Line 25:
 
== C++ based FreeRTOS task ==
 
== C++ based FreeRTOS task ==
 
As a project gets more complex, it becomes difficult to manage initialization and share queue or semaphore handles.  This was the motivation to create a C++ based FreeRTOS task.
 
As a project gets more complex, it becomes difficult to manage initialization and share queue or semaphore handles.  This was the motivation to create a C++ based FreeRTOS task.
 +
 +
=== Share "Objects" ===
 +
A task can "share" its pointers, handles, or "objects" with another task by name. This way, we don't have to worry about declaring handles into a common header file, hence we do not plague the global namespace :)  See the next examples on how a task can share a handle with another task by an intuitive string name.
  
 
=== C++ Task ===
 
=== C++ Task ===
TODO
+
<syntaxhighlight lang="cpp">
 +
class orient_compute : public scheduler_task
 +
{
 +
    public:
 +
        orient_compute(uint8_t priority) : scheduler_task("compute", 512, priority)
 +
        {
 +
            xQueueHandle my_queue = xQueueCreate(1, sizeof(int));
 +
            addSharedObject("queue_id", my_queue);
 +
        }
 +
 
 +
        bool run(void *p)
 +
        {
 +
            /* Compute orientation here, and send it to the queue once a second */
 +
            int orientation = 0;
 +
            xQueueSend(getSharedObject("queue_id"), &orientation, 999999);
 +
            vTaskDelay(1000);
 +
            return true;
 +
        }
 +
};
  
 +
class orient_process : public scheduler_task
 +
{
 +
    public:
 +
        orient_process (uint8_t priority) : scheduler_task("process", 512, priority)
 +
        {
 +
            /* Nothing to init */
 +
        }
 +
 +
        bool run(void *p)
 +
        {
 +
            /* Compute orientation here, and send it to the queue once a second */
 +
            int orientation = 0;
 +
            if (xQueueReceive(getSharedObject("queue_id"), &orientation, 999999))
 +
            {
 +
            }
 +
            return true;
 +
        }
 +
};
 +
</syntaxhighlight>
 +
 +
<BR/>
 
=== Add the task in main() ===
 
=== Add the task in main() ===
TODO
+
<syntaxhighlight lang="c">
 
+
int main()
=== Share "Objects" ===
+
{
A task can "share" its pointers, handles, or "objects" with another task by name. This way, we don't have to worry about declaring handles into a common header file, hence we do not plague the global namespace :)
+
    scheduler_add_task(new orient_compute(PRIORITY_LOW));
 +
    scheduler_add_task(new orient_process(PRIORITY_LOW));
 +
    scheduler_start();
 +
    return 0;
 +
}
  
 +
<BR/>
 
== Assignment ==
 
== Assignment ==
 
This assignment is based on SJ-One board, but you can alter the requirement to fit your own hardware.
 
This assignment is based on SJ-One board, but you can alter the requirement to fit your own hardware.

Revision as of 18:13, 6 February 2014

The objective of this assignment is to show you how to create a FreeRTOS task a few different ways. The FreeRTOS Tutorial is definitely a must read before going through this lesson.

FreeRTOS "Hello World" Task

A task just needs memory for its stack and and infinite loop. To prevent "hogging" the CPU, you should use a delay such that the CPU can be allocated to other tasks. Here is the simplest FreeRTOS task:

void hello_world_task(void* p)
{
    while(1) {
        puts("Hello World!");
        vTaskDelay(1000);
    }
}

int main()
{
    xTaskCreate(hello_world_task, (signed char*)"task_name", STACK_BYTES(2048), 0, 1, 0);
    vTaskStartScheduler();

    return -1;
}


C++ based FreeRTOS task

As a project gets more complex, it becomes difficult to manage initialization and share queue or semaphore handles. This was the motivation to create a C++ based FreeRTOS task.

Share "Objects"

A task can "share" its pointers, handles, or "objects" with another task by name. This way, we don't have to worry about declaring handles into a common header file, hence we do not plague the global namespace :) See the next examples on how a task can share a handle with another task by an intuitive string name.

C++ Task

class orient_compute : public scheduler_task
{
    public:
        orient_compute(uint8_t priority) : scheduler_task("compute", 512, priority)
        {
            xQueueHandle my_queue = xQueueCreate(1, sizeof(int));
            addSharedObject("queue_id", my_queue);
        }

        bool run(void *p)
        {
            /* Compute orientation here, and send it to the queue once a second */
            int orientation = 0;
            xQueueSend(getSharedObject("queue_id"), &orientation, 999999);
            vTaskDelay(1000);
            return true;
        }
};

class orient_process : public scheduler_task
{
    public:
        orient_process (uint8_t priority) : scheduler_task("process", 512, priority)
        {
            /* Nothing to init */
        }

        bool run(void *p)
        {
            /* Compute orientation here, and send it to the queue once a second */
            int orientation = 0;
            if (xQueueReceive(getSharedObject("queue_id"), &orientation, 999999))
            {
            }
            return true;
        }
};


Add the task in main()

int main()
{
    scheduler_add_task(new orient_compute(PRIORITY_LOW));
    scheduler_add_task(new orient_process(PRIORITY_LOW));
    scheduler_start();
    return 0;
}

<BR/>
== Assignment ==
This assignment is based on SJ-One board, but you can alter the requirement to fit your own hardware.
#  Create a task (task1) that computes the orientation of the board.
#:   Send the orientation enumeration, such as "up", "down", "left", "right" to a queue
#  Create another task (task2) that waits on the queued item
#:   If the orientation is left or right, light up the LEDs (otherwise turn them off)
#  Create a terminal task with a command "orientation on" and "orientation off"
#:   If orientation is commanded on, resume the task1, otherwise suspend it
#:   See code below on hints of how this command can get control of another task.

<syntaxhighlight lang="c">
// At the terminal tasks taskEntry() function :
bool terminalTask::taskEntry()
{
    // Add the command, but pass the "this" pointer when the command is invoked
    cp.addHandler(orientationCmd,  "orientation", "Two options: 'orientation on' or 'orientation off'", this);
}

// Somewhere else:
CMD_HANDLER_FUNC(orientationCmd)
{
    // Our parameter was the terminal task's "this" pointer:
    scheduler_task *terminalTask = (scheduler_task*) pDataParam;

    // Use this to get the pointer of the "other task"
    scheduler_task *orientTask = terminalTask->getTaskPtrByName("orientTask");

    // We've got the handle now, so use FreeRTOS API to suspend or resume
    if (cmdParams == "on") {
        vTaskResume(orientTask->getTaskHandle());
    }
    else {
        vTaskSuspend(orientTask->getTaskHandle());
    }
}