Embedded System Tutorial FreeRTOS
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.
Contents
FreeRTOS "Hello World" Task
A task just needs memory for its stack and an 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.
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;
}
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)
 
 -   Note down the observations by doing the following:
- Print a message before and after sending the orientation to the queue
 - Print a message after the second task receives an item from the queue
 - Use the same priority for both tasks, and note down the order of the print-outs
 - Use higher priority for the receiving task, and note down the order of the print-outs.
 
 -   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.
 
 
// 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());
    }
}