diff --git a/ch04.md b/ch04.md index c4411ba..1e5d4ff 100644 --- a/ch04.md +++ b/ch04.md @@ -231,7 +231,7 @@ BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, - `uxPriority` Defines the task's priority. 0 is the lowest priority and - `(configMAX_PRIORITIES – 1)` is the highest priority. [Section 4.6](#46-task-priorities) + `(configMAX_PRIORITIES – 1)` is the highest priority. [Section 4.5](#45-task-priorities) describes the user defined `configMAX_PRIORITIES` constant. If a `uxPriority` greater than `(configMAX_PRIORITIES – 1)` is defined, it will @@ -260,7 +260,10 @@ BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, the task. [Chapter 3](ch03.md#3-heap-memory-management) provides more information on heap memory management. -### 4.5.1 Example 4.1. Creating tasks + + + +

Example 4.1 Creating tasks

The following example demonstrates the steps needed to create two simple tasks and then start the newly created tasks. The tasks simply print out a string @@ -489,7 +492,9 @@ void vTask1( void * pvParameters ) *Listing 4.7 Creating a task from within another task after the scheduler has started* *** -### 4.5.2 Example 4.2. Using the task parameter + + +

Example 4.2 Using the task parameter

The two tasks created in Example 4.1 are almost identical, the only difference between them is the text string they print out. If you create @@ -618,7 +623,7 @@ int main( void ) The output from Example 4.2 is exactly as per that shown for example 1 in Figure 4.2. -## 4.6 Task Priorities +## 4.5 Task Priorities The FreeRTOS scheduler always ensures the highest priority task that can run is the task selected to enter the *Running* state. Tasks of equal @@ -639,14 +644,14 @@ The FreeRTOS scheduler has two implementations of the algorithm used to select the *Running* state task and the maximum allowable value for `configMAX_PRIORITIES` depends on the implementation used: -### Generic Scheduler +### 4.5.1 Generic Scheduler The generic scheduler is written in C and can be used with all FreeRTOS architecture ports. It does not impose an upper limit on `configMAX_PRIORITEIS`. In general, it is advisable to minimize `configMAX_PRIORITIES` because more values require more RAM and will result in a longer worst-case execution time. -### Architecture-Optimized Scheduler +### 4.5.2 Architecture-Optimized Scheduler Architecture optimized implementations are written in architecture-specific assembly code and are more performant than the generic c implementation, and the @@ -666,9 +671,9 @@ implementation. Those that do default Those that do not, default `configUSE_PORT_optimized_TASK_SELECTION` to 0 if it is left undefined. -## 4.7 Time Measurement and the Tick Interrupt +## 4.6 Time Measurement and the Tick Interrupt -[Section 4.13, Scheduling Algorithms](#413-scheduling-algorithms), describes an +[Section 4.12, Scheduling Algorithms](#412-scheduling-algorithms), describes an optional feature called 'time slicing'. Time slicing was used in the examples presented so far, and is the behavior observed in the output they produced. In the examples, both tasks were created at the same priority, and both @@ -748,11 +753,13 @@ overflowed. User applications do not have to consider overflows when specifying delay periods, as FreeRTOS manages time consistency internally. -[Section 4.13: Scheduling Algorithms](#413-scheduling-algorithms) +[Section 4.12: Scheduling Algorithms](#412-scheduling-algorithms) describes configuration constants which affect when the scheduler will select a new task to run and when a tick interrupt will execute. -### 4.7.1 Example 4.3. Experimenting with priorities + + +

Example 4.3 Experimenting with priorities

The scheduler will always ensure the highest priority task that can run is the task selected to enter the *Running* state. The examples so far @@ -852,7 +859,7 @@ either cycling around a null loop or printing to the terminal. other from Example 4.3* *** -## 4.8 Expanding the *Not Running* State +## 4.7 Expanding the *Not Running* State So far, the created tasks have always had processing to perform and have never had to wait for anything—and since they never had to wait for anything, @@ -871,7 +878,7 @@ can run. Therefore, writing event-driven tasks means tasks can be created at different priorities without the highest priority tasks starving all the lower priority tasks of processing time. -### 4.8.1 The *Blocked* State +### 4.7.1 The *Blocked* State A task waiting for an event is said to be in the 'Blocked' state, a sub-state of the *Not Running* state. @@ -899,7 +906,7 @@ choose to wait for a maximum of 10 milliseconds for data to arrive on a queue. The task will leave the *Blocked* state if data arrives within 10 milliseconds or if 10 milliseconds pass without data arriving. -### 4.8.2 The *Suspended* State +### 4.7.2 The *Suspended* State *Suspended* is also a sub-state of *Not Running*. Tasks in the Suspended state are not available to the scheduler. The only way to enter the @@ -908,13 +915,13 @@ and the only way out is through a call to the `vTaskResume()` or `xTaskResumeFromISR()` API functions. Most applications do not use the Suspended state. -### 4.8.3 The Ready State +### 4.7.3 The Ready State Tasks that are in the *Not Running* state and are not *Blocked* or *Suspended* are said to be in the *Ready* state. They can run, and are therefore 'ready' to run, but are not currently in the *Running* state. -### 4.8.4 Completing the State Transition Diagram +### 4.7.4 Completing the State Transition Diagram Figure 4.7 expands on the simplified state diagram to include all of the *Not Running* sub-states described in this section. The tasks created in the @@ -930,7 +937,9 @@ Figure 4.7 expands on the simplified state diagram to include all of the *Figure 4.7 Full task state machine* *** -### 4.8.5 Example 4.4. Using the *Blocked* state to create a delay + + +

Example 4.4 Using the *Blocked* state to create a delay

All the tasks created in the examples presented so far have been 'periodic'—they have delayed for a period and then printed out their string, @@ -1062,7 +1071,7 @@ the scheduler itself is omitted for simplicity. The idle task is created automatically when the scheduler is started, to ensure there is always at least one task that can run (at least one task -in the *Ready* state). [Section 4.9: The Idle Task and the Idle Task Hook](#49-the-idle-task-and-the-idle-task-hook) +in the *Ready* state). [Section 4.8: The Idle Task and the Idle Task Hook](#48-the-idle-task-and-the-idle-task-hook) describes the Idle task in more detail. @@ -1113,7 +1122,7 @@ in Example 4.4* *** -### 4.8.6 The vTaskDelayUntil() API Function +### 4.7.5 The vTaskDelayUntil() API Function `vTaskDelayUntil()` is similar to `vTaskDelay()`. As just demonstrated, the `vTaskDelay()` parameter specifies the number of tick interrupts that @@ -1172,8 +1181,9 @@ void vTaskDelayUntil( TickType_t * pxPreviousWakeTime, be used to convert a time specified in milliseconds into a time specified in ticks. + -### 4.8.7 Example 4.5. Converting the example tasks to use vTaskDelayUntil() +

Example 4.5 Converting the example tasks to use vTaskDelayUntil()

The two tasks created in Example 4.4 are periodic tasks, but using `vTaskDelay()` does not guarantee that the frequency at which they run is @@ -1230,8 +1240,9 @@ void vTaskFunction( void * pvParameters ) The output produced by Example 4.5 is exactly as per that shown for Example 4.4 in Figure 4.8. + -### 4.8.8 Example 4.6. Combining blocking and non-blocking tasks +

Example 4.6 Combining blocking and non-blocking tasks

The previous examples examined the behavior of both polling and blocking tasks in isolation. This example re-enforces what we have already said regarding @@ -1369,7 +1380,7 @@ Continuous task 2 running *Figure 4.12 The execution pattern of Example 4.6* *** -## 4.9 The Idle Task and the Idle Task Hook +## 4.8 The Idle Task and the Idle Task Hook The tasks created in Example 4.4 spend most of their time in the Blocked state. While in this state, they are not able to run, so they cannot be @@ -1394,7 +1405,7 @@ task priority, if desired. The `configIDLE_SHOULD_YIELD` compile time configuration constant in `FreeRTOSConfig.h` can be used to prevent the Idle task from consuming processing time that would be more productively allocated to applications tasks that also have a priority of 0. Section -4.13, Scheduling Algorithms, describes `configIDLE_SHOULD_YIELD`. +4.12, Scheduling Algorithms, describes `configIDLE_SHOULD_YIELD`. Running at the lowest priority ensures the Idle task is transitioned out of the *Running* state as soon as a higher priority task enters the Ready @@ -1409,7 +1420,7 @@ task being preempted. > This is because the Idle task is responsible for cleaning up kernel > resources used by tasks that deleted themselves.* -### 4.9.1 Idle Task Hook Functions +### 4.8.1 Idle Task Hook Functions It is possible to add application specific functionality directly into the idle task through the use of an idle hook (or idle callback) @@ -1433,7 +1444,7 @@ Common uses for the Idle task hook include: processing to be performed (although the achievable power saving is less than that achieved by tick-less idle mode). -### 4.9.2 Limitations on the Implementation of Idle Task Hook Functions +### 4.8.2 Limitations on the Implementation of Idle Task Hook Functions Idle task hook functions must adhere to the following rules. @@ -1463,8 +1474,9 @@ void vApplicationIdleHook( void ); *Listing 4.18 The idle task hook function name and prototype* *** + -### 4.9.3 Example 4.7. Defining an idle task hook function +

Example 4.7 Defining an idle task hook function

The use of blocking `vTaskDelay()` API calls in Example 4.4 created a lot of idle time, that is, time when the Idle task executes because both application @@ -1576,9 +1588,9 @@ Task 2 is running *** -## 4.10 Changing the Priority of a Task +## 4.9 Changing the Priority of a Task -### 4.10.1 The vTaskPrioritySet() API Function +### 4.9.1 The vTaskPrioritySet() API Function The `vTaskPrioritySet()` API function changes the priority of a task after the scheduler has been started. The `vTaskPrioritySet()` API function is @@ -1618,7 +1630,7 @@ void vTaskPrioritySet( TaskHandle_t xTask, FreeRTOSConfig.h header file. -### 4.10.2 The uxTaskPriorityGet() API Function +### 4.9.2 The uxTaskPriorityGet() API Function The `uxTaskPriorityGet()` API function returns the priority of a task. The `uxTaskPriorityGet()` API function is only available when @@ -1651,7 +1663,10 @@ UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask ); The priority currently assigned to the task being queried. -### 4.10.3 Example 4.8. Changing task priorities + + + +

Example 4.8 Changing task priorities

The scheduler always selects the highest *Ready* state task as the task to enter the *Running* state. Example 4.8 demonstrates this by using the @@ -1867,9 +1882,9 @@ Task1 is running *Figure 4.15 The output produced when Example 4.8 is executed* *** -## 4.11 Deleting a Task +## 4.10 Deleting a Task -### 4.11.1 The vTaskDelete() API Function +### 4.10.1 The vTaskDelete() API Function The `vTaskDelete()` API function deletes a task. The `vTaskDelete()` API function is only available when `INCLUDE_vTaskDelete` is set to 1 in @@ -1916,7 +1931,10 @@ void vTaskDelete( TaskHandle_t xTaskToDelete ); A task can delete itself by passing NULL in place of a valid task handle. -### 4.11.2 Example 4.9. Deleting tasks + + + +

Example 4.9 Deleting tasks

This is a very simple example that behaves as follows. @@ -2060,7 +2078,7 @@ Task2 is running and about to delete itself *** -## 4.12 Thread Local Storage and Reentrancy +## 4.11 Thread Local Storage and Reentrancy Thread Local Storage allows an application developer to store arbitrary data in the Task Control Block of each task. This feature is most commonly used to store @@ -2078,7 +2096,7 @@ in the ISO C standard used by the C standard library and POSIX systems. The ```errno``` global is used to provide an extended result or error code for common standard library functions such as strtof and strtol. -### 4.12.1 C Runtime Thread Local Storage Implementations +### 4.11.1 C Runtime Thread Local Storage Implementations Most embedded libc implementations provide APIs to ensure that non-reentrant functions can work correctly in a multi-threaded environment. FreeRTOS includes @@ -2092,7 +2110,7 @@ file. - ```configUSE_NEWLIB_REENTRANT``` for [newlib](https://sourceware.org/newlib/) - ```configUSE_PICOLIBC_TLS``` for [picolibc](https://github.com/picolibc/picolibc) -### 4.12.2 Custom C Runtime Thread Local Storage +### 4.11.2 Custom C Runtime Thread Local Storage Application developers may implement thread local storage by defining the following macros in their FreeRTOSConfig.h file: @@ -2112,7 +2130,7 @@ in a new task - Define ```configDEINIT_TLS_BLOCK``` to the c code which should be run when de-initializing the C Runtime Thread Local Storage block. -### 4.12.3 Application Thread Local Storage +### 4.11.3 Application Thread Local Storage In addition to C Runtime Thread Local Storage, application developers may also define a set of application specific pointers to be included in the task control @@ -2140,9 +2158,9 @@ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, *** -## 4.13 Scheduling Algorithms +## 4.12 Scheduling Algorithms -### 4.13.1 A Recap of Task States and Events +### 4.12.1 A Recap of Task States and Events The task that is actually running (using processing time) is in the *Running* state. On a single core processor there can only be one task in @@ -2168,7 +2186,7 @@ generally used to signal asynchronous activity, such as data arriving at a peripheral. -### 4.13.2 Selecting the Scheduling Algorithm +### 4.12.2 Selecting the Scheduling Algorithm The scheduling algorithm is the software routine that decides which *Ready* state task to transition into the *Running* state. @@ -2200,7 +2218,7 @@ enter the *Running* state in turn. | Preemptive Without Time Slicing | Yes | 1 | 0 | | Co-Operative | No | 0 | Any | -### 4.13.3 Prioritized Preemptive Scheduling with Time Slicing +### 4.12.3 Prioritized Preemptive Scheduling with Time Slicing The configuration shown in the table below sets the FreeRTOS scheduler to use a scheduling algorithm called 'Fixed Priority Preemptive Scheduling with @@ -2373,7 +2391,7 @@ task selected to enter the *Running* state after the Idle task does not execute for an entire time slice, but instead executes for whatever remains of the time slice during which the Idle task yielded. -### 4.13.4 Prioritized Preemptive Scheduling without Time Slicing +### 4.12.4 Prioritized Preemptive Scheduling without Time Slicing Prioritized Preemptive Scheduling without time slicing maintains the same task selection and preemption algorithms as described in the @@ -2451,7 +2469,7 @@ Referring to Figure 4.21, which assumes `configIDLE_SHOULD_YIELD` is set to 0: At time t10 the Idle task re-enters the *Running* state, despite having already received more than four times more processing time than Task 2. -### 4.13.5 Cooperative Scheduling +### 4.12.5 Cooperative Scheduling This book focuses on preemptive scheduling, but FreeRTOS can also use cooperative scheduling. The table below shows the FreeRTOSConfig.h settings diff --git a/ch05.md b/ch05.md index 62af52f..7f303c9 100644 --- a/ch05.md +++ b/ch05.md @@ -146,7 +146,7 @@ waiting the longest. Queues can be grouped into sets, allowing a task to enter the Blocked state to wait for data to become available on any of the queues in the -set. Section 4.6, Receiving From Multiple Queues, demonstrates queue +set. Section 5.6, Receiving From Multiple Queues, demonstrates queue sets. @@ -415,7 +415,9 @@ UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue ); then the queue is empty. -### 5.3.5 Example 5.1. Blocking when receiving from a queue + + +

Example 5.1 Blocking when receiving from a queue

This example demonstrates creating a queue, sending data to the queue from multiple tasks, and receiving data from the queue. The queue is @@ -673,7 +675,9 @@ Chapter (RB-TBD) shows how to extend this design pattern such that the controller task can reply directly to the task that queued a structure. -### 5.4.1 Example 5.2: Blocking when sending to a queue, and sending structures on a queue + + +

Example 5.2 Blocking when sending to a queue, and sending structures on a queue

Example 5.2 is similar to Example 5.1, but with reversed task priorities, so the receiving task has a lower priority than the sending tasks. Also, @@ -1529,7 +1533,9 @@ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet, in the set, but the block time expired before that happened. -### 5.6.5 Example 5.3. Using a Queue Set + + +

Example 5.3 Using a Queue Set

This example creates two sending tasks and one receiving task. The sending tasks send data to the receiving task on two separate queues, @@ -1726,7 +1732,7 @@ twice as often as those sent by `vSenderTask2()`. * * * -### 5.6.6 More Realistic Queue Set Use Cases +### 5.6.5 More Realistic Queue Set Use Cases Example 5.3 demonstrated a very simplistic case; the queue set only contained queues, and the two queues it contained were both used to send diff --git a/ch06.md b/ch06.md index 099f6b4..6ef072a 100644 --- a/ch06.md +++ b/ch06.md @@ -426,7 +426,7 @@ timers are created in the Dormant state. Software timers can be created before the scheduler is running, or from a task after the scheduler has been started. -Section 0 describes the data types and naming conventions used. +[Section 2.5: Data Types and Coding Style Guide](ch02.md#25-data-types-and-coding-style-guide) describes the data types and naming conventions used. @@ -587,7 +587,9 @@ BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait ); specified block time expired before that happened. -### 6.5.3 Example 6.1. Creating one-shot and auto-reload timers + + +

Example 6.1 Creating one-shot and auto-reload timers

This example creates and starts a one-shot timer and an auto-reload timer—as shown in Listing 6.5. @@ -798,7 +800,9 @@ void *pvTimerGetTimerID( const TimerHandle_t xTimer ); The ID of the software timer being queried. -### 6.6.3 Example 6.2. Using the callback function parameter and the software timer ID + + +

Example 6.2 Using the callback function parameter and the software timer ID

The same callback function can be assigned to more than one software timer. When that is done, the callback function parameter is used to @@ -1196,7 +1200,9 @@ BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait ); expired before that happened. -### 6.8.2 Example 6.3. Resetting a software timer + + +

Example 6.3 Resetting a software timer

This example simulates the behavior of the backlight on a cell phone. The backlight: diff --git a/ch07.md b/ch07.md index d9763d6..4128284 100644 --- a/ch07.md +++ b/ch07.md @@ -628,7 +628,9 @@ BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore, `xSemaphoreGiveFromISR()` will return `pdFAIL`. -### 7.4.4 Example 7.1. Using a binary semaphore to synchronize a task with an interrupt + + +

Example 7.1 Using a binary semaphore to synchronize a task with an interrupt

This example uses a binary semaphore to unblock a task from an interrupt service routine, effectively synchronizing the task with the interrupt. @@ -850,7 +852,7 @@ periodic task. Further explanation is provided in Figure 7.5. * * * -### 7.4.5 Improving the Implementation of the Task Used in Example 7.1 +### 7.4.4 Improving the Implementation of the Task Used in Example 7.1 Example 7.1 used a binary semaphore to synchronize a task with an interrupt. The execution sequence was as follows: @@ -1103,7 +1105,9 @@ SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, to the created semaphore. -### 7.5.2 Example 7.2. Using a counting semaphore to synchronize a task with an interrupt + + +

Example 7.2 Using a counting semaphore to synchronize a task with an interrupt

Example 7.2 improves on the Example 7.1 implementation by using a counting semaphore in place of the binary semaphore. `main()` is changed to include @@ -1334,7 +1338,9 @@ void vPendableFunction( void *pvParameter1, uint32_t ulParameter2 ); command queue. -### 7.6.2 Example 7.3. Centralized deferred interrupt processing + + +

Example 7.3 Centralized deferred interrupt processing

Example 7.3 provides similar functionality to Example 7.1, but without using a semaphore, and without creating a task specifically to perform @@ -1613,8 +1619,9 @@ that are suitable for production code, include: than the raw data) to a task. This was previously demonstrated by Figure 5.4. + -### 7.7.3 Example 7.4. Sending and receiving on a queue from within an interrupt +

Example 7.4 Sending and receiving on a queue from within an interrupt

This example demonstrates `xQueueSendToBackFromISR()` and `xQueueReceiveFromISR()` being used within the same interrupt. As before, diff --git a/ch08.md b/ch08.md index 548f103..9f61c3d 100644 --- a/ch08.md +++ b/ch08.md @@ -531,7 +531,9 @@ SemaphoreHandle_t xSemaphoreCreateMutex( void ); created mutex. -### 8.3.2 Example 8.1. Rewriting vPrintString() to use a semaphore + + +

Example 8.1 Rewriting vPrintString() to use a semaphore

This example creates a new version of `vPrintString()` called `prvNewPrintString()`, then calls the new function from multiple tasks. @@ -701,7 +703,7 @@ the random delay periods used by the tasks. * * * -### 8.3.3 Priority Inversion +### 8.3.2 Priority Inversion Figure 8.3 demonstrates one of the potential pitfalls of using a mutex to provide mutual exclusion. The sequence of execution depicted shows the @@ -727,7 +729,7 @@ systems it can often be avoided at system design time by considering how resources are accessed. -### 8.3.4 Priority Inheritance +### 8.3.3 Priority Inheritance FreeRTOS mutexes and binary semaphores are very similar—the difference being that mutexes include a basic 'priority inheritance' mechanism, @@ -758,7 +760,7 @@ tasks that are using the mutex. For that reason, mutexes must not be used from interrupt service routines. -### 8.3.5 Deadlock (or Deadly Embrace) +### 8.3.4 Deadlock (or Deadly Embrace) 'Deadlock' is another potential pitfall of using mutexes for mutual exclusion. Deadlock is sometimes also known by the more dramatic name @@ -801,7 +803,7 @@ application, and so can identify and remove the areas where it could occur. -### 8.3.6 Recursive Mutexes +### 8.3.5 Recursive Mutexes It is also possible for a task to deadlock with itself. This will happen if a task attempts to take the same mutex more than once, without first @@ -912,7 +914,7 @@ void vTaskFunction( void *pvParameters ) * * * -### 8.3.7 Mutexes and Task Scheduling +### 8.3.6 Mutexes and Task Scheduling If two tasks of different priority use the same mutex, then the FreeRTOS scheduling policy makes the order in which the tasks will execute clear; diff --git a/ch09.md b/ch09.md index 9f2f8d3..982bfb0 100644 --- a/ch09.md +++ b/ch09.md @@ -530,8 +530,9 @@ StaticEventGroup_t ** ppxEventGroupBuffer ); - `pdFALSE` will be returned if the buffer was not successfully retrieved. + -### 9.3.6 Example 9.1. Experimenting with event groups +

Example 9.1 Experimenting with event groups

This example demonstrates how to: @@ -1055,7 +1056,9 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup, condition. -### 9.4.2 Example 9.2. Synchronizing tasks + + +

Example 9.2 Synchronizing tasks

Example 9.2 uses `xEventGroupSync()` to synchronize three instances of a single task implementation. The task parameter is used to pass into each diff --git a/ch10.md b/ch10.md index cef82b8..515cb34 100644 --- a/ch10.md +++ b/ch10.md @@ -366,7 +366,10 @@ xTicksToWait ); state to wait for its notification value to be greater than zero, but the specified block time expired before that happened. -### 10.3.5 Example 10.1. Using a task notification in place of a semaphore, method 1 + + + +

Example 10.1 Using a task notification in place of a semaphore, method 1

Example 7.1 used a binary semaphore to unblock a task from within an interrupt service routine—effectively synchronizing the task with the @@ -505,7 +508,9 @@ produced by the periodic task. Further explanation is provided in Figure 10.4. *Figure 10.4 The sequence of execution when Example 10.1 is executed* * * * -### 10.3.6 Example 10.2. Using a task notification in place of a semaphore, method 2 + + +

Example 10.2 Using a task notification in place of a semaphore, method 2

In Example 10.1, the `ulTaskNotifyTake()` `xClearOnExit` parameter was set to `pdTRUE`. Example 10.1 modifies Example 10.1 slightly to demonstrate the @@ -614,7 +619,7 @@ interrupt is generated. *Figure 10.5 The output produced when Example 10.2 is executed* * * * -### 10.3.7 The xTaskNotify() and xTaskNotifyFromISR() API Functions +### 10.3.5 The xTaskNotify() and xTaskNotifyFromISR() API Functions `xTaskNotify()` is a more capable version of `xTaskNotifyGive()` that can be used to update the receiving task's notification value in any of the @@ -740,7 +745,7 @@ Effect on the Receiving Task's Notification Value** receiving task had a notification pending before `xTaskNotify()` was called or not. -### 10.3.8 The xTaskNotifyWait() API Function +### 10.3.6 The xTaskNotifyWait() API Function `xTaskNotifyWait()` is a more capable version of `ulTaskNotifyTake()`. It allows a task to wait, with an optional timeout, for the calling task's @@ -844,7 +849,7 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, held in the Blocked state to wait for its notification state to become pending, but the specified block time expired before that happened. -### 10.3.9 Task Notifications Used in Peripheral Device Drivers: UART Example +### 10.3.7 Task Notifications Used in Peripheral Device Drivers: UART Example Peripheral driver libraries provide functions that perform common operations on hardware interfaces. Examples of peripherals for which @@ -1213,7 +1218,7 @@ void xUART_ReceiveISR( xUART *pxUARTInstance ) *Listing 10.12 Pseudo code demonstrating how a task notification can be used in a driver library receive function* * * * -### 10.3.10 Task Notifications Used in Peripheral Device Drivers: ADC Example +### 10.3.8 Task Notifications Used in Peripheral Device Drivers: ADC Example The previous section demonstrated how to use `vTaskNotifyGiveFromISR()` to send a task notification from an interrupt to a task. @@ -1324,7 +1329,7 @@ void ADC_ConversionEndISR( xADC *pxADCInstance ) *Listing 10.13 Pseudo code demonstrating how a task notification can be used to pass a value to a task* * * * -### 10.3.11 Task Notifications Used Directly Within an Application +### 10.3.9 Task Notifications Used Directly Within an Application This section reinforces the power of task notifications by demonstrating their use in a hypothetical application that includes the following diff --git a/toc.md b/toc.md index 42f31a8..0887b96 100644 --- a/toc.md +++ b/toc.md @@ -69,43 +69,34 @@ + [4.3 Top Level Task States](ch04.md#43-top-level-task-states) + [4.4 Task Creation](ch04.md#44-task-creation) + [4.4.1 The xTaskCreate() API Function](ch04.md#441-the-xtaskcreate-api-function) - + [4.5.1 Example 4.1. Creating tasks](ch04.md#451-example-41-creating-tasks) - + [4.5.2 Example 4.2. Using the task parameter](ch04.md#452-example-42-using-the-task-parameter) - + [4.6 Task Priorities](ch04.md#46-task-priorities) - + [Generic Scheduler](ch04.md#generic-scheduler) - + [Architecture-Optimized Scheduler](ch04.md#architecture-optimized-scheduler) - + [4.7 Time Measurement and the Tick Interrupt](ch04.md#47-time-measurement-and-the-tick-interrupt) - + [4.7.1 Example 4.3. Experimenting with priorities](ch04.md#471-example-43-experimenting-with-priorities) - + [4.8 Expanding the *Not Running* State](ch04.md#48-expanding-the-not-running-state) - + [4.8.1 The *Blocked* State](ch04.md#481-the-blocked-state) - + [4.8.2 The *Suspended* State](ch04.md#482-the-suspended-state) - + [4.8.3 The Ready State](ch04.md#483-the-ready-state) - + [4.8.4 Completing the State Transition Diagram](ch04.md#484-completing-the-state-transition-diagram) - + [4.8.5 Example 4.4. Using the *Blocked* state to create a delay](ch04.md#485-example-44-using-the-blocked-state-to-create-a-delay) - + [4.8.6 The vTaskDelayUntil() API Function](ch04.md#486-the-vtaskdelayuntil-api-function) - + [4.8.7 Example 4.5. Converting the example tasks to use vTaskDelayUntil()](ch04.md#487-example-45-converting-the-example-tasks-to-use-vtaskdelayuntil) - + [4.8.8 Example 4.6. Combining blocking and non-blocking tasks](ch04.md#488-example-46-combining-blocking-and-non-blocking-tasks) - + [4.9 The Idle Task and the Idle Task Hook](ch04.md#49-the-idle-task-and-the-idle-task-hook) - + [4.9.1 Idle Task Hook Functions](ch04.md#491-idle-task-hook-functions) - + [4.9.2 Limitations on the Implementation of Idle Task Hook Functions](ch04.md#492-limitations-on-the-implementation-of-idle-task-hook-functions) - + [4.9.3 Example 4.7. Defining an idle task hook function](ch04.md#493-example-47-defining-an-idle-task-hook-function) - + [4.10 Changing the Priority of a Task](ch04.md#410-changing-the-priority-of-a-task) - + [4.10.1 The vTaskPrioritySet() API Function](ch04.md#4101-the-vtaskpriorityset-api-function) - + [4.10.2 The uxTaskPriorityGet() API Function](ch04.md#4102-the-uxtaskpriorityget-api-function) - + [4.10.3 Example 4.8. Changing task priorities](ch04.md#4103-example-48-changing-task-priorities) - + [4.11 Deleting a Task](ch04.md#411-deleting-a-task) - + [4.11.1 The vTaskDelete() API Function](ch04.md#4111-the-vtaskdelete-api-function) - + [4.11.2 Example 4.9. Deleting tasks](ch04.md#4112-example-49-deleting-tasks) - + [4.12 Thread Local Storage and Reentrancy](ch04.md#412-thread-local-storage-and-reentrancy) - + [4.12.1 C Runtime Thread Local Storage Implementations](ch04.md#4121-c-runtime-thread-local-storage-implementations) - + [4.12.2 Custom C Runtime Thread Local Storage](ch04.md#4122-custom-c-runtime-thread-local-storage) - + [4.12.3 Application Thread Local Storage](ch04.md#4123-application-thread-local-storage) - + [4.13 Scheduling Algorithms](ch04.md#413-scheduling-algorithms) - + [4.13.1 A Recap of Task States and Events](ch04.md#4131-a-recap-of-task-states-and-events) - + [4.13.2 Selecting the Scheduling Algorithm](ch04.md#4132-selecting-the-scheduling-algorithm) - + [4.13.3 Prioritized Preemptive Scheduling with Time Slicing](ch04.md#4133-prioritized-preemptive-scheduling-with-time-slicing) - + [4.13.4 Prioritized Preemptive Scheduling without Time Slicing](ch04.md#4134-prioritized-preemptive-scheduling-without-time-slicing) - + [4.13.5 Cooperative Scheduling](ch04.md#4135-cooperative-scheduling) + + [4.5 Task Priorities](ch04.md#45-task-priorities) + + [Generic Scheduler](ch04.md#451-generic-scheduler) + + [Architecture-Optimized Scheduler](ch04.md#452-architecture-optimized-scheduler) + + [4.6 Time Measurement and the Tick Interrupt](ch04.md#46-time-measurement-and-the-tick-interrupt) + + [4.7 Expanding the *Not Running* State](ch04.md#47-expanding-the-not-running-state) + + [4.7.1 The *Blocked* State](ch04.md#471-the-blocked-state) + + [4.7.2 The *Suspended* State](ch04.md#472-the-suspended-state) + + [4.7.3 The Ready State](ch04.md#473-the-ready-state) + + [4.7.4 Completing the State Transition Diagram](ch04.md#474-completing-the-state-transition-diagram) + + [4.7.5 The vTaskDelayUntil() API Function](ch04.md#475-the-vtaskdelayuntil-api-function) + + [4.8 The Idle Task and the Idle Task Hook](ch04.md#48-the-idle-task-and-the-idle-task-hook) + + [4.8.1 Idle Task Hook Functions](ch04.md#481-idle-task-hook-functions) + + [4.8.2 Limitations on the Implementation of Idle Task Hook Functions](ch04.md#482-limitations-on-the-implementation-of-idle-task-hook-functions) + + [4.9 Changing the Priority of a Task](ch04.md#49-changing-the-priority-of-a-task) + + [4.9.1 The vTaskPrioritySet() API Function](ch04.md#491-the-vtaskpriorityset-api-function) + + [4.9.2 The uxTaskPriorityGet() API Function](ch04.md#492-the-uxtaskpriorityget-api-function) + + [4.10 Deleting a Task](ch04.md#410-deleting-a-task) + + [4.10.1 The vTaskDelete() API Function](ch04.md#4101-the-vtaskdelete-api-function) + + [4.11 Thread Local Storage and Reentrancy](ch04.md#411-thread-local-storage-and-reentrancy) + + [4.11.1 C Runtime Thread Local Storage Implementations](ch04.md#4111-c-runtime-thread-local-storage-implementations) + + [4.11.2 Custom C Runtime Thread Local Storage](ch04.md#4112-custom-c-runtime-thread-local-storage) + + [4.11.3 Application Thread Local Storage](ch04.md#4113-application-thread-local-storage) + + [4.12 Scheduling Algorithms](ch04.md#412-scheduling-algorithms) + + [4.12.1 A Recap of Task States and Events](ch04.md#4121-a-recap-of-task-states-and-events) + + [4.12.2 Selecting the Scheduling Algorithm](ch04.md#4122-selecting-the-scheduling-algorithm) + + [4.12.3 Prioritized Preemptive Scheduling with Time Slicing](ch04.md#4123-prioritized-preemptive-scheduling-with-time-slicing) + + [4.12.4 Prioritized Preemptive Scheduling without Time Slicing](ch04.md#4124-prioritized-preemptive-scheduling-without-time-slicing) + + [4.12.5 Cooperative Scheduling](ch04.md#4125-cooperative-scheduling) ## [5 Queue Management](ch05.md#5-queue-management) + [5.1 Introduction](ch05.md#51-introduction) @@ -122,9 +113,7 @@ + [5.3.2 The xQueueSendToBack() and xQueueSendToFront() API Functions](ch05.md#532-the-xqueuesendtoback-and-xqueuesendtofront-api-functions) + [5.3.3 The xQueueReceive() API Function](ch05.md#533-the-xqueuereceive-api-function) + [5.3.4 The uxQueueMessagesWaiting() API Function](ch05.md#534-the-uxqueuemessageswaiting-api-function) - + [5.3.5 Example 5.1. Blocking when receiving from a queue](ch05.md#535-example-51-blocking-when-receiving-from-a-queue) + [5.4 Receiving Data From Multiple Sources](ch05.md#54-receiving-data-from-multiple-sources) - + [5.4.1 Example 5.2: Blocking when sending to a queue, and sending structures on a queue](ch05.md#541-example-52-blocking-when-sending-to-a-queue-and-sending-structures-on-a-queue) + [5.5 Working with Large or Variable Sized Data](ch05.md#55-working-with-large-or-variable-sized-data) + [5.5.1 Queuing Pointers](ch05.md#551-queuing-pointers) + [5.5.2 Using a Queue to Send Different Types and Lengths of Data[^9]](ch05.md#552-using-a-queue-to-send-different-types-and-lengths-of-data9) @@ -133,8 +122,7 @@ + [5.6.2 The xQueueCreateSet() API Function](ch05.md#562-the-xqueuecreateset-api-function) + [5.6.3 The xQueueAddToSet() API Function](ch05.md#563-the-xqueueaddtoset-api-function) + [5.6.4 The xQueueSelectFromSet() API Function](ch05.md#564-the-xqueueselectfromset-api-function) - + [5.6.5 Example 5.3. Using a Queue Set](ch05.md#565-example-53-using-a-queue-set) - + [5.6.6 More Realistic Queue Set Use Cases](ch05.md#566-more-realistic-queue-set-use-cases) + + [5.6.5 More Realistic Queue Set Use Cases](ch05.md#565-more-realistic-queue-set-use-cases) + [5.7 Using a Queue to Create a Mailbox](ch05.md#57-using-a-queue-to-create-a-mailbox) + [5.7.1 The xQueueOverwrite() API Function](ch05.md#571-the-xqueueoverwrite-api-function) + [5.7.2 The xQueuePeek() API Function](ch05.md#572-the-xqueuepeek-api-function) @@ -154,16 +142,13 @@ + [6.5 Creating and Starting a Software Timer](ch06.md#65-creating-and-starting-a-software-timer) + [6.5.1 The xTimerCreate() API Function](ch06.md#651-the-xtimercreate-api-function) + [6.5.2 The xTimerStart() API Function](ch06.md#652-the-xtimerstart-api-function) - + [6.5.3 Example 6.1. Creating one-shot and auto-reload timers](ch06.md#653-example-61-creating-one-shot-and-auto-reload-timers) + [6.6 The Timer ID](ch06.md#66-the-timer-id) + [6.6.1 The vTimerSetTimerID() API Function](ch06.md#661-the-vtimersettimerid-api-function) + [6.6.2 The pvTimerGetTimerID() API Function](ch06.md#662-the-pvtimergettimerid-api-function) - + [6.6.3 Example 6.2. Using the callback function parameter and the software timer ID](ch06.md#663-example-62-using-the-callback-function-parameter-and-the-software-timer-id) + [6.7 Changing the Period of a Timer](ch06.md#67-changing-the-period-of-a-timer) + [6.7.1 The xTimerChangePeriod() API Function](ch06.md#671-the-xtimerchangeperiod-api-function) + [6.8 Resetting a Software Timer](ch06.md#68-resetting-a-software-timer) + [6.8.1 The xTimerReset() API Function](ch06.md#681-the-xtimerreset-api-function) - + [6.8.2 Example 6.3. Resetting a software timer](ch06.md#682-example-63-resetting-a-software-timer) ## [7 Interrupt Management](ch07.md#7-interrupt-management) + [7.1 Introduction](ch07.md#71-introduction) @@ -180,18 +165,14 @@ + [7.4.1 The xSemaphoreCreateBinary() API Function](ch07.md#741-the-xsemaphorecreatebinary-api-function) + [7.4.2 The xSemaphoreTake() API Function](ch07.md#742-the-xsemaphoretake-api-function) + [7.4.3 The xSemaphoreGiveFromISR() API Function](ch07.md#743-the-xsemaphoregivefromisr-api-function) - + [7.4.4 Example 7.1. Using a binary semaphore to synchronize a task with an interrupt](ch07.md#744-example-71-using-a-binary-semaphore-to-synchronize-a-task-with-an-interrupt) - + [7.4.5 Improving the Implementation of the Task Used in Example 7.1](ch07.md#745-improving-the-implementation-of-the-task-used-in-example-71) + + [7.4.4 Improving the Implementation of the Task Used in Example 7.1](ch07.md#744-improving-the-implementation-of-the-task-used-in-example-71) + [7.5 Counting Semaphores](ch07.md#75-counting-semaphores) + [7.5.1 The xSemaphoreCreateCounting() API Function](ch07.md#751-the-xsemaphorecreatecounting-api-function) - + [7.5.2 Example 7.2. Using a counting semaphore to synchronize a task with an interrupt](ch07.md#752-example-72-using-a-counting-semaphore-to-synchronize-a-task-with-an-interrupt) + [7.6 Deferring Work to the RTOS Daemon Task](ch07.md#76-deferring-work-to-the-rtos-daemon-task) + [7.6.1 The xTimerPendFunctionCallFromISR() API Function](ch07.md#761-the-xtimerpendfunctioncallfromisr-api-function) - + [7.6.2 Example 7.3. Centralized deferred interrupt processing](ch07.md#762-example-73-centralized-deferred-interrupt-processing) + [7.7 Using Queues within an Interrupt Service Routine](ch07.md#77-using-queues-within-an-interrupt-service-routine) + [7.7.1 The xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() API Functions](ch07.md#771-the-xqueuesendtofrontfromisr-and-xqueuesendtobackfromisr-api-functions) + [7.7.2 Considerations When Using a Queue From an ISR](ch07.md#772-considerations-when-using-a-queue-from-an-isr) - + [7.7.3 Example 7.4. Sending and receiving on a queue from within an interrupt](ch07.md#773-example-74-sending-and-receiving-on-a-queue-from-within-an-interrupt) + [7.8 Interrupt Nesting](ch07.md#78-interrupt-nesting) + [7.8.1 A Note to ARM Cortex-M[^22] and ARM GIC Users](ch07.md#781-a-note-to-arm-cortex-m22-and-arm-gic-users) @@ -206,12 +187,11 @@ + [8.2.4 The xTaskResumeAll() API Function](ch08.md#824-the-xtaskresumeall-api-function) + [8.3 Mutexes (and Binary Semaphores)](ch08.md#83-mutexes-and-binary-semaphores) + [8.3.1 The xSemaphoreCreateMutex() API Function](ch08.md#831-the-xsemaphorecreatemutex-api-function) - + [8.3.2 Example 8.1. Rewriting vPrintString() to use a semaphore](ch08.md#832-example-81-rewriting-vprintstring-to-use-a-semaphore) - + [8.3.3 Priority Inversion](ch08.md#833-priority-inversion) - + [8.3.4 Priority Inheritance](ch08.md#834-priority-inheritance) - + [8.3.5 Deadlock (or Deadly Embrace)](ch08.md#835-deadlock-or-deadly-embrace) - + [8.3.6 Recursive Mutexes](ch08.md#836-recursive-mutexes) - + [8.3.7 Mutexes and Task Scheduling](ch08.md#837-mutexes-and-task-scheduling) + + [8.3.2 Priority Inversion](ch08.md#832-priority-inversion) + + [8.3.3 Priority Inheritance](ch08.md#833-priority-inheritance) + + [8.3.4 Deadlock (or Deadly Embrace)](ch08.md#834-deadlock-or-deadly-embrace) + + [8.3.5 Recursive Mutexes](ch08.md#835-recursive-mutexes) + + [8.3.6 Mutexes and Task Scheduling](ch08.md#836-mutexes-and-task-scheduling) + [8.4 Gatekeeper Tasks](ch08.md#84-gatekeeper-tasks) + [8.4.1 Re-writing vPrintString() to use a gatekeeper task](ch08.md#841-re-writing-vprintstring-to-use-a-gatekeeper-task) @@ -229,10 +209,8 @@ + [9.3.3 The xEventGroupSetBitsFromISR() API Function](ch09.md#933-the-xeventgroupsetbitsfromisr-api-function) + [9.3.4 The xEventGroupWaitBits() API Function](ch09.md#934-the-xeventgroupwaitbits-api-function) + [9.3.5 The xEventGroupGetStaticBuffer() API Function](ch09.md#935-the-xeventgroupgetstaticbuffer-api-function) - + [9.3.6 Example 9.1. Experimenting with event groups](ch09.md#936-example-91-experimenting-with-event-groups) + [9.4 Task Synchronization Using an Event Group](ch09.md#94-task-synchronization-using-an-event-group) + [9.4.1 The xEventGroupSync() API Function](ch09.md#941-the-xeventgroupsync-api-function) - + [9.4.2 Example 9.2. Synchronizing tasks](ch09.md#942-example-92-synchronizing-tasks) ## [10 Task Notifications](ch10.md#10-task-notifications) + [10.1 Introduction](ch10.md#101-introduction) @@ -249,13 +227,11 @@ + [10.3.2 The xTaskNotifyGive() API Functions](ch10.md#1032-the-xtasknotifygive-api-functions) + [10.3.3 The vTaskNotifyGiveFromISR() API Function](ch10.md#1033-the-vtasknotifygivefromisr-api-function) + [10.3.4 The ulTaskNotifyTake() API Function](ch10.md#1034-the-ultasknotifytake-api-function) - + [10.3.5 Example 10.1. Using a task notification in place of a semaphore, method 1](ch10.md#1035-example-101-using-a-task-notification-in-place-of-a-semaphore-method-1) - + [10.3.6 Example 10.2. Using a task notification in place of a semaphore, method 2](ch10.md#1036-example-102-using-a-task-notification-in-place-of-a-semaphore-method-2) - + [10.3.7 The xTaskNotify() and xTaskNotifyFromISR() API Functions](ch10.md#1037-the-xtasknotify-and-xtasknotifyfromisr-api-functions) - + [10.3.8 The xTaskNotifyWait() API Function](ch10.md#1038-the-xtasknotifywait-api-function) - + [10.3.9 Task Notifications Used in Peripheral Device Drivers: UART Example](ch10.md#1039-task-notifications-used-in-peripheral-device-drivers-uart-example) - + [10.3.10 Task Notifications Used in Peripheral Device Drivers: ADC Example](ch10.md#10310-task-notifications-used-in-peripheral-device-drivers-adc-example) - + [10.3.11 Task Notifications Used Directly Within an Application](ch10.md#10311-task-notifications-used-directly-within-an-application) + + [10.3.5 The xTaskNotify() and xTaskNotifyFromISR() API Functions](ch10.md#1035-the-xtasknotify-and-xtasknotifyfromisr-api-functions) + + [10.3.6 The xTaskNotifyWait() API Function](ch10.md#1036-the-xtasknotifywait-api-function) + + [10.3.7 Task Notifications Used in Peripheral Device Drivers: UART Example](ch10.md#1037-task-notifications-used-in-peripheral-device-drivers-uart-example) + + [10.3.8 Task Notifications Used in Peripheral Device Drivers: ADC Example](ch10.md#1038-task-notifications-used-in-peripheral-device-drivers-adc-example) + + [10.3.9 Task Notifications Used Directly Within an Application](ch10.md#1039-task-notifications-used-directly-within-an-application) ## [11 Low Power Support](ch11.md#11-low-power-support) + [11.1 Power Saving Introduction](ch11.md#111-power-saving-introduction) @@ -595,6 +571,36 @@ + [Listing 13.2 The uxTaskGetStackHighWaterMark2() API function prototype](ch13.md#list13.2) + [Listing 13.3 The stack overflow hook function prototype](ch13.md#list13.3) +## Examples: ++ [Example 4.1 Creating tasks](ch04.md#example4.1) ++ [Example 4.2 Using the task parameter](ch04.md#example4.2) ++ [Example 4.3 Experimenting with priorities](ch04.md#example4.3) ++ [Example 4.4 Using the *Blocked* state to create a delay](ch04.md#example4.4) ++ [Example 4.5 Converting the example tasks to use vTaskDelayUntil()](ch04.md#example4.5) ++ [Example 4.6 Combining blocking and non-blocking tasks](ch04.md#example4.6) ++ [Example 4.7 Defining an idle task hook function](ch04.md#example4.7) ++ [Example 4.8 Deleting tasks](ch04.md#example4.8) ++ [Example 5.1 Blocking when receiving from a queue](ch05.md#example5.1) ++ [Example 5.2 Blocking when sending to a queue, and sending structures on a queue](ch05.md#example5.2) ++ [Example 5.3 Using a Queue Set](ch05.md#example5.3) ++ [Example 6.1 Creating one-shot and auto-reload timers](ch06.md#example6.1) ++ [Example 6.2 Using the callback function parameter and the software timer ID](ch06.md#example6.2) ++ [Example 6.3 Resetting a software timer](ch06.md#example6.3) ++ [Example 7.1 Using a binary semaphore to synchronize a task with an interrupt](ch07.md#example7.1) ++ [Example 7.2 Using a counting semaphore to synchronize a task with an interrupt](ch07.md#example7.2) ++ [Example 7.3 Centralized deferred interrupt processing](ch07.md#example7.3) ++ [Example 7.4 Sending and receiving on a queue from within an interrupt](ch07.md#example7.4) ++ [Example 8.1 Rewriting vPrintString() to use a semaphore](ch08.md#example8.1) ++ [Example 9.1 Experimenting with event groups](ch09.md#example9.1) ++ [Example 9.2 Synchronizing tasks](ch09.md#example9.2) ++ [Example 10.1 Using a task notification in place of a semaphore, method 1](ch10.md#example10.1) ++ [Example 10.2 Using a task notification in place of a semaphore, method 2](ch10.md#example10.2) + + + + + + ## Tables: + [Table 1 FreeRTOS source files to include in the project](ch02.md#tbl1) + [Table 2 TickType\_t data type and the configTICK\_TYPE\_WIDTH\_IN\_BITS configuration](ch02.md#tbl2)