Difference between revisions of "Embedded System Tutorial FreeRTOS"
(→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 === | ||
− | + | <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() === | ||
− | + | <syntaxhighlight lang="c"> | |
− | + | int main() | |
− | + | { | |
− | + | 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.
Contents
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.
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());
}
}