Difference between revisions of "Embedded System Tutorial FreeRTOS"

From Embedded Systems Learning Academy
Jump to: navigation, search
 
(15 intermediate revisions by one other user not shown)
Line 1: Line 1:
 +
Socialledge is moving to two portals. 
 +
*  The Wiki will remain here for general references about the SJ-One board, and to document student reports.
 +
*  The bookstack will now be used for SJSU assignments
 +
 +
[http://books.socialledge.com/books/embedded-drivers-real-time-operating-systems/page/freertos-tasks This article has been moved here]
 +
 +
<!--
 +
 
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.
 
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 ==
 
== 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:
+
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:
  
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
Line 23: Line 31:
  
 
<BR/>
 
<BR/>
 +
 
== 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.
Line 31: Line 40:
 
=== C++ Task ===
 
=== C++ Task ===
 
<syntaxhighlight lang="cpp">
 
<syntaxhighlight lang="cpp">
 +
 +
/// IDs used for getSharedObject() and addSharedObject()
 +
typedef enum {
 +
  shared_SensorQueueId,
 +
} sharedHandleId_t;
 +
 +
/// Orientation type enumeration
 +
typedef enum {
 +
    invalid,
 +
    left,
 +
    right,
 +
} orientation_t;
 +
 
class orient_compute : public scheduler_task
 
class orient_compute : public scheduler_task
 
{
 
{
 
     public:
 
     public:
         orient_compute(uint8_t priority) : scheduler_task("compute", 512, priority)
+
         orient_compute(uint8_t priority) : scheduler_task("compute", 2048, priority)
 
         {
 
         {
             xQueueHandle my_queue = xQueueCreate(1, sizeof(int));
+
             /* We save the queue handle by using addSharedObject() */
             addSharedObject("queue_id", my_queue);
+
            QueueHandle_t my_queue = xQueueCreate(1, sizeof(orientation_t));
 +
             addSharedObject(shared_SensorQueueId, my_queue);
 
         }
 
         }
  
Line 43: Line 66:
 
         {
 
         {
 
             /* Compute orientation here, and send it to the queue once a second */
 
             /* Compute orientation here, and send it to the queue once a second */
             int orientation = 0;
+
             orientation_t orientation = invalid;
             xQueueSend(getSharedObject("queue_id"), &orientation, 999999);
+
             xQueueSend(getSharedObject(shared_SensorQueueId), &orientation, portMAX_DELAY);
 +
 
 
             vTaskDelay(1000);
 
             vTaskDelay(1000);
 
             return true;
 
             return true;
Line 53: Line 77:
 
{
 
{
 
     public:
 
     public:
         orient_process (uint8_t priority) : scheduler_task("process", 512, priority)
+
         orient_process (uint8_t priority) : scheduler_task("process", 2048, priority)
 
         {
 
         {
 
             /* Nothing to init */
 
             /* Nothing to init */
Line 60: Line 84:
 
         bool run(void *p)
 
         bool run(void *p)
 
         {
 
         {
             /* Compute orientation here, and send it to the queue once a second */
+
             /* We first get the queue handle the other task added using addSharedObject() */
             int orientation = 0;
+
             orientation_t orientation = invalid;
             if (xQueueReceive(getSharedObject("queue_id"), &orientation, 999999))
+
            QueueHandle_t qid = getSharedObject(shared_SensorQueueId);
 +
 
 +
            /* Sleep the task forever until an item is available in the queue */
 +
             if (xQueueReceive(qid, &orientation, portMAX_DELAY))
 
             {
 
             {
 
             }
 
             }
 +
 
             return true;
 
             return true;
 
         }
 
         }
Line 70: Line 98:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 +
Note that a better design is to minimize the use of <b><code>getSharedObject()</code></b>.  So it is recommended that the creator of the handle add the shared object in its <b><code>init()</code></b>, and other tasks can store the handle in their <b><code>taskEntry()</code></b> function.
 
<BR/>
 
<BR/>
 +
 
=== Add the task in main() ===
 
=== Add the task in main() ===
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
Line 86: Line 116:
 
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.
 
#  Create a task (task1) that computes the orientation of the board.
 
#  Create a task (task1) that computes the orientation of the board.
#:  Send the orientation enumeration, such as "up", "down", "left", "right" to a queue
+
#:  You can use the acceleration sensor to figure out the orientation of the board
 +
#:  Send the orientation enumeration, such as "up", "down", "left", "right" to a queue every 1 second
 
#  Create another task (task2) that waits on the queued item
 
#  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)
 
#:  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"
+
#  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 command: "orientation on" and "orientation off"
 
#:  If orientation is commanded on, resume the task1, otherwise suspend it
 
#:  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.
 
#:  See code below on hints of how this command can get control of another task.
 +
#  Answer the following questions:
 +
#:  What if you use ZERO block time while sending an item to the queue, will that make any difference?
 +
#:  What is the purpose of the block time during xQueueReceive() ?
  
 
<syntaxhighlight lang="c">
 
<syntaxhighlight lang="c">
Line 97: Line 136:
 
bool terminalTask::taskEntry()
 
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'");
     cp.addHandler(orientationCmd,  "orientation", "Two options: 'orientation on' or 'orientation off'", this);
 
 
}
 
}
  
Line 104: Line 142:
 
CMD_HANDLER_FUNC(orientationCmd)
 
CMD_HANDLER_FUNC(orientationCmd)
 
{
 
{
     // Our parameter was the terminal task's "this" pointer:
+
     // Our parameter was the orientation tasks' pointer, but you may want to check for NULL pointer first.
    scheduler_task *terminalTask = (scheduler_task*) pDataParam;
+
     scheduler_task *compute = scheduler_task::getTaskPtrByName("compute");
 
 
    // 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
+
     // You can use FreeRTOS API or the wrapper resume() or suspend() methods
 
     if (cmdParams == "on") {
 
     if (cmdParams == "on") {
         vTaskResume(orientTask->getTaskHandle());
+
         vTaskResume(compute->getTaskHandle());  // Can also use: compute->resume();
 
     }
 
     }
 
     else {
 
     else {
         vTaskSuspend(orientTask->getTaskHandle());
+
         vTaskSuspend(compute->getTaskHandle()); // Can also use: compute->suspend();
 
     }
 
     }
 +
   
 +
    return true;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
 +
-->

Latest revision as of 20:11, 25 January 2019

Socialledge is moving to two portals.

  • The Wiki will remain here for general references about the SJ-One board, and to document student reports.
  • The bookstack will now be used for SJSU assignments

This article has been moved here