Difference between revisions of "Embedded System Tutorial FreeRTOS"
From Embedded Systems Learning Academy
(→Assignment) |
|||
(14 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 | + | 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", | + | orient_compute(uint8_t priority) : scheduler_task("compute", 2048, priority) |
{ | { | ||
− | + | /* We save the queue handle by using addSharedObject() */ | |
− | addSharedObject( | + | 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 */ | ||
− | + | orientation_t orientation = invalid; | |
− | xQueueSend(getSharedObject( | + | 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", | + | 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) | ||
{ | { | ||
− | /* | + | /* We first get the queue handle the other task added using addSharedObject() */ |
− | + | orientation_t orientation = invalid; | |
− | if (xQueueReceive( | + | 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) | ||
Line 94: | Line 125: | ||
#: Use the same priority for both tasks, and note down the order of the print-outs | #: 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. | #: Use higher priority for the receiving task, and note down the order of the print-outs. | ||
− | # Create a terminal | + | # 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 102: | Line 136: | ||
bool terminalTask::taskEntry() | bool terminalTask::taskEntry() | ||
{ | { | ||
− | + | cp.addHandler(orientationCmd, "orientation", "Two options: 'orientation on' or 'orientation off'"); | |
− | cp.addHandler(orientationCmd, "orientation", "Two options: 'orientation on' or 'orientation off'" | ||
} | } | ||
Line 109: | Line 142: | ||
CMD_HANDLER_FUNC(orientationCmd) | CMD_HANDLER_FUNC(orientationCmd) | ||
{ | { | ||
− | // Our parameter was the | + | // Our parameter was the orientation tasks' pointer, but you may want to check for NULL pointer first. |
− | + | scheduler_task *compute = scheduler_task::getTaskPtrByName("compute"); | |
− | |||
− | |||
− | scheduler_task * | ||
− | // | + | // You can use FreeRTOS API or the wrapper resume() or suspend() methods |
if (cmdParams == "on") { | if (cmdParams == "on") { | ||
− | vTaskResume( | + | vTaskResume(compute->getTaskHandle()); // Can also use: compute->resume(); |
} | } | ||
else { | else { | ||
− | vTaskSuspend( | + | 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