Freertos: Alberto Bosio
Freertos: Alberto Bosio
Alberto Bosio
Université de Montpellier
[email protected]
1 Introduction
2 Task Management
3 Scheduler
4 Queue Management
5 Semaphores
vTaskDelete ( NULL );
}
Prototype
BaseType_t xTaskCreate (
TaskFunction_t pvTaskCode ,
const char * const pcName ,
uint16_t usStackDepth ,
void * pvParameters ,
UBaseType_t uxPriority ,
TaskHandle_t * pxCreatedTask )
for (;;);
}
Prototype
Prototype
void vTaskDelayUnti (
TickType_t * pxPreviousWakeTime ,
TickType_t xTimeIncrement
);
The configuration:
configUSE PREEMPTION set to 1
configUSE TIME SLICING set to 1
sets the FreeRTOS scheduler to use a scheduling algorithm called
‘Fixed Priority Pre-emptive Scheduling with Time Slicing’, which is
the scheduling algorithm used by most small RTOS applications.
92
The configuration:
configUSE PREEMPTION set to 1
configUSE TIME SLICING set to 0
If time slicing is not used, then the scheduler will only select a new
task to enter the Running state when either:
A higher priority task enters the Ready state;
The task in the Running state enters the Blocked or Suspended state;
There are fewer task context switches when time slicing is not used than when time slicing is
used. Therefore, turning time slicing off results in a reduction in the scheduler’s processing
overhead. However, turning time slicing off can also result in tasks of equal priority receiving
greatly different amounts of processing time, a scenario demonstrated by Figure 29. For this
reason, running the scheduler without time slicing is considered an advanced technique that
Example:
should only be used by experienced users.
Figure 29 Execution pattern that demonstrates how tasks of equal priority can
receive hugely different amounts of processing time when time slicing is not
used
The configuration:
configUSE PREEMPTION set to 0
configUSE TIME SLICING set to any value
When the co-operative scheduler is used, a context switch will only
occur when the Running state task enters the Blocked state, or the
Running state task explicitly yields (manually requests a re-schedule)
by calling taskYIELD(). Tasks are never pre-empted, so time slicing
cannot be used.
Figure 30 demonstrates the behavior of the co-operative scheduler. The horizontal dashed
Example:
lines in Figure 30 show when a task is in the Ready state.
1. Task 1
A queue can hold a finite number of fixed size data items. The
maximum number of items a queue can hold is called its ‘length’.
Both the length and the size of each data item are set when the
queue is created;
Queues are normally used as First In First Out (FIFO) buffers, where
data is written to the end (tail) of the queue and removed from the
front (head) of the queue.
161204 Pre-release for FreeRTOS V8.x.x. See http://www.FreeRTOS.org/FreeRTOS-V9.html for information about FreeRTOS
V9.x.x. Use http://www.FreeRTOS.org/contact to provide feedback, corrections, and check for updates.
Task A Task B
Queue
int x; int y;
A queue is created to allow Task A and Task B to communicate. The queue can hold a maximum of 5
integers. When the queue is created it does not contain any values so is empty.
Task A Task B
Queue
int x; 10 int y;
x = 10; Send
Task A writes (sends) the value of a local variable to the back of the queue. As the queue was previously
empty the value written is now the only item in the queue, and is therefore both the value at the back of the
queue and the value at the front of the queue.
Task A Task B
Queue
int x; 20 10 int y;
x = 20; Send
Task A changes the value of its local variable before writing it to the queue again. The queue now
contains copies of both values written to the queue. The first value written remains at the front of the
Albertoqueue,
Bosio the
(UM) FreeRTOS
new value is inserted at the end of the February
queue. The queue has three empty spaces 27, 2017
remaining. 29 / 52
x = 10; Send
Example (cont)
Task A writes (sends) the value of a local variable to the back of the queue. As the queue was previously
empty the value written is now the only item in the queue, and is therefore both the value at the back of the
queue and the value at the front of the queue.
Task A Task B
Queue
int x; 20 10 int y;
x = 20; Send
Task A changes the value of its local variable before writing it to the queue again. The queue now
contains copies of both values written to the queue. The first value written remains at the front of the
queue, the new value is inserted at the end of the queue. The queue has three empty spaces remaining.
Task A Task B
Queue
int x; 20 10 int y;
Receive
x = 20; // y now equals 10
Task B reads (receives) from the queue into a different variable. The value received by Task B is the
value from the head of the queue, which is the first value Task A wrote to the queue (10 in this illustration).
Task A Task B
Queue
int x; 20 int y;
Task B has removed one item, leaving only the second value written by Task A remaining in the queue.
This is the value Task B would receive next if it read from the queue again. The queue now has four
empty spaces remaining.
Figure 31. An example sequence of writes to, and reads from a queue
Alberto Bosio (UM) FreeRTOS February 27, 2017 30 / 52
Access by Multiple Tasks
Queues are objects in their own right that can be accessed by any
task that knows of their existence. Any number of tasks can write to
the same queue, and any number of tasks can read from the same
queue. In practice it is very common for a queue to have multiple
writers, but much less common for a queue to have multiple readers.;
Create
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength,
UBaseType_t uxItemSize );
Prototypes
BaseType_t xQueueSendToFront( QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait );
xQueue: The handle of the queue to which the data is being sent
(written). The queue handle will have been returned from the call to
xQueueCreate() used to create the queue;
pvItemToQueue: A pointer to the data to be copied into the queue;
xTicksToWait: The maximum amount of time the task should
remain in the Blocked state to wait for space to become available on
the queue, should the queue already be full;
Return Value:
pdPASS will be returned only if data was successfully sent to the queue.
errQUEUE FULL will be returned if data could not be written to the
queue because the queue was already full.
Prototype
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
xQueue: The handle of the queue to which the data is being sent
(written). The queue handle will have been returned from the call to
xQueueCreate() used to create the queue;
pvBuffer: A pointer to the memory into which the received data will
be copied;
xTicksToWait: The maximum amount of time the task should
remain in the Blocked state to wait for data to become available on
the queue, should the queue already be empty;
If xTicksToWait is zero, then xQueueReceive() will return immediately
if the queue is already empty.
Return Value:
pdPASS will be returned only if data was successfully read from the
queue.
errQUEUE EMPTY will be returned if data cannot be read from the
queue because the queue is already empty.
for ( ;; ) {
xStatus = xQueueSendToBack (
xQueue , & lValueToSend , 0 );
if ( xStatus != pdPASS ) {
QueueHandle_t xQueue ;
int main ( void )
{
xQueue = xQueueCreate ( 5 , sizeof ( int32_t ) );
if ( xQueue != NULL )
{
vTaskStart Sc h e du l e r ();
}
Alberto Bosio (UM) FreeRTOS February 27, 2017 42 / 52
Binary Semaphore (Mutex)
Prototype
SemaphoreHandle_t xSemaphoreCreateBinary( void );
Return Value:
If NULL is returned, then the semaphore cannot be created because
there is insufficient heap memory available for FreeRTOS to allocate
the semaphore data structures.
A non-NULL value being returned indicates that the semaphore has
been created successfully. The returned value should be stored as the
handle to the created semaphore.
Prototype
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore,
TickType_t xTicksToWait );
Prototype
BaseType_t xSemaphoreGive (
SemaphoreHandle_t xSemaphore );
Prototype
SemaphoreHandle_t xSemaphoreCreateCounting(
UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount );