diff --git a/ch02.md b/ch02.md
index 8190d41..1cdb729 100644
--- a/ch02.md
+++ b/ch02.md
@@ -122,7 +122,7 @@ FreeRTOS-Plus
│
└─Demo Contains demo projects for other FreeRTOS and ecosystem libraries
```
-*Figure 2.1 Top level directories within the FreeRTOS distribution*
+***Figure 2.1*** *Top level directories within the FreeRTOS distribution*
* * *
The distribution only contains one copy of the FreeRTOS kernel source
@@ -188,7 +188,7 @@ FreeRTOS
├─stream_buffer.c FreeRTOS source file - optional
└─croutine.c FreeRTOS source file – optional and no longer maintained
```
-*Figure 2.2 Core FreeRTOS source files within the FreeRTOS directory tree*
+***Figure 2.2*** *Core FreeRTOS source files within the FreeRTOS directory tree*
* * *
It is recognized that the file names used in the zip file distribution
@@ -248,7 +248,7 @@ FreeRTOS
├─[architecture 2] Contains files for the compiler 2 architecture 2 port
└─[etc.]
```
-*Figure 2.3 Port specific source files within the FreeRTOS directory tree*
+***Figure 2.3*** *Port specific source files within the FreeRTOS directory tree*
* * *
### 2.2.8 Include Paths
@@ -374,7 +374,7 @@ FreeRTOS source files, but does not define any functionality.
-* * *
+
```c
int main( void )
{
@@ -392,8 +392,8 @@ int main( void )
return 0;
}
```
-*Listing 2.1 The template for a new main() function*
-* * *
+***Listing 2.1*** *The template for a new main() function*
+
### 2.4.2 Creating a New Project from Scratch
@@ -442,7 +442,7 @@ procedure to create a new project:
| All C and assembler files | FreeRTOS/Source/portable/\[compiler\]/\[architecture\] |
| heap\_n.c | FreeRTOS/Source/portable/MemMang, where n is either 1, 2, 3, 4 or 5 |
-*Table 1 FreeRTOS source files to include in the project*
+***Table 1*** *FreeRTOS source files to include in the project*
* * *
**Note on heap memory:**
@@ -498,7 +498,7 @@ typedef used and the actual type:
| TICK\_TYPE\_WIDTH\_32_BITS | uint32\_t | uint32\_t | uint32\_t | N/A |
| TICK\_TYPE\_WIDTH\_64_BITS | N/A | N/A | uint64\_t | uint64\_t |
- *Table 2. TickType_t data type and the configTICK_TYPE_WIDTH_IN_BITS configuration*
+ ***Table 2*** *TickType_t data type and the configTICK_TYPE_WIDTH_IN_BITS configuration*
* * *
- `BaseType_t`
@@ -562,7 +562,7 @@ list of prefixes.
| config (for example, `configUSE_PREEMPTION`) | `FreeRTOSConfig.h` |
| err (for example, `errQUEUE_FULL`) | `projdefs.h` |
-*Table 3 Macro prefixes*
+***Table 3*** *Macro prefixes*
* * *
Note that the semaphore API is written almost entirely as a set of
@@ -581,7 +581,7 @@ The macros defined in Table 4 are used throughout the FreeRTOS source code.
| `pdPASS` | 1 |
| `pdFAIL` | 0 |
-*Table 4 Common macro definitions*
+***Table 4*** *Common macro definitions*
* * *
diff --git a/ch03.md b/ch03.md
index b4262e6..39f904e 100644
--- a/ch03.md
+++ b/ch03.md
@@ -145,7 +145,7 @@ Referring to Figure 3.1:
* * *
![](media/image05.png)
-*Figure 3.1 RAM being allocated from the heap\_1 array each time a task is created*
+***Figure 3.1*** *RAM being allocated from the heap\_1 array each time a task is created*
* * *
@@ -189,7 +189,7 @@ subsequently freed blocks are always the same size.
* * *
![](media/image06.png)
-*Figure 3.2 RAM being allocated and freed from the heap\_2 array as tasks are created and deleted*
+***Figure 3.2*** *RAM being allocated and freed from the heap\_2 array as tasks are created and deleted*
* * *
Figure 3.2 demonstrates how the best-fit algorithm works when a task is
@@ -276,7 +276,7 @@ RAM.
* * *
![](media/image07.png)
-*Figure 3.3 RAM being allocated and freed from the heap\_4 array*
+***Figure 3.3*** *RAM being allocated and freed from the heap\_4 array*
* * *
Figure 3.3 demonstrates how the heap\_4 first-fit algorithm with memory
@@ -350,12 +350,12 @@ the call to `vPortDefineHeapRegions()`.
-* * *
+
```c
void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions );
```
-*Listing 3.1 The vPortDefineHeapRegions() API function prototype*
-* * *
+***Listing 3.1*** *The vPortDefineHeapRegions() API function prototype*
+
`vPortDefineHeapRegions()` takes an array of `HeapRegion_t` structures as
its only parameter. Each structure defines the start address and size of
@@ -365,7 +365,7 @@ structures defines the entire heap space.
-* * *
+
```c
typedef struct HeapRegion
{
@@ -377,8 +377,8 @@ typedef struct HeapRegion
} HeapRegion_t;
```
-*Listing 3.2 The HeapRegion\_t structure*
-* * *
+***Listing 3.2*** *The HeapRegion\_t structure*
+
**Parameters:**
@@ -407,7 +407,7 @@ which is not shown.
* * *
![](media/image08.png)
-*Figure 3.4 Memory Map*
+***Figure 3.4*** *Memory Map*
* * *
Listing 3.3 shows an array of `HeapRegion_t` structures that together
@@ -416,7 +416,7 @@ describe the three blocks of RAM in their entirety.
-* * *
+
```c
/* Define the start address and size of the three RAM regions. */
#define RAM1_START_ADDRESS ( ( uint8_t * ) 0x00010000 )
@@ -449,8 +449,8 @@ int main( void )
/* Add application code here. */
}
```
-*Listing 3.3 An array of HeapRegion\_t structures that together describe the 3 regions of RAM in their entirety*
-* * *
+***Listing 3.3*** *An array of HeapRegion\_t structures that together describe the 3 regions of RAM in their entirety*
+
Although Listing 3.3 correctly describes the RAM, it does not demonstrate a
usable example because it allocates all the RAM to the heap, leaving no
@@ -494,7 +494,6 @@ linker consumes all of RAM1, as shown in Figure 3.4 **C**.
-* * *
```c
/* Define the start address and size of the two RAM regions not used by
the linker. */
@@ -524,8 +523,8 @@ const HeapRegion_t xHeapRegions[] =
{ NULL, 0 } /* Marks the end of the array. */
};
```
-*Listing 3.4 An array of HeapRegion\_t structures that describe all of RAM2, all of RAM3, but only part of RAM1*
-* * *
+***Listing 3.4*** *An array of HeapRegion\_t structures that describe all of RAM2, all of RAM3, but only part of RAM1*
+
The advantages of the technique demonstrated in Listing 3.4 include:
@@ -575,22 +574,22 @@ documentation. Examples for two compilers follow:
-* * *
+
```c
uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] __attribute__ ( ( section( ".my_heap" ) ) );
```
-*Listing 3.5 Using GCC syntax to declare the array that will be used by heap\_4, and place the array in a memory section named .my\_heap*
-* * *
+***Listing 3.5*** *Using GCC syntax to declare the array that will be used by heap\_4, and place the array in a memory section named .my\_heap*
+
-* * *
+
```c
uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] @ 0x20000000;
```
-*Listing 3.6 Using IAR syntax to declare the array that will be used by heap\_4, and place the array at the absolute address 0x20000000*
-* * *
+***Listing 3.6*** *Using IAR syntax to declare the array that will be used by heap\_4, and place the array at the absolute address 0x20000000*
+
### 3.3.2 The xPortGetFreeHeapSize() API Function
@@ -604,12 +603,12 @@ information on heap fragmentation.
-* * *
+
```c
size_t xPortGetFreeHeapSize( void );
```
-*Listing 3.7 The xPortGetFreeHeapSize() API function prototype*
-* * *
+***Listing 3.7*** *The xPortGetFreeHeapSize() API function prototype*
+
**Return value:**
@@ -639,12 +638,12 @@ after executing the code that you know has the highest heap usage,
-* * *
+
```c
size_t xPortGetMinimumEverFreeHeapSize( void );
```
-*Listing 3.8 The xPortGetMinimumEverFreeHeapSize() API function prototype*
-* * *
+***Listing 3.8*** *The xPortGetMinimumEverFreeHeapSize() API function prototype*
+
**Return value:**
@@ -663,17 +662,17 @@ shows the `HeapStats_t` structure members.
-* * *
+
```c
void vPortGetHeapStats( HeapStats_t *xHeapStats );
```
-*Listing 3.9 The vPortGetHeapStatus() API function prototype*
-* * *
+***Listing 3.9*** *The vPortGetHeapStatus() API function prototype*
+
-* * *
+
```c
/* Prototype of the vPortGetHeapStats() function. */
void vPortGetHeapStats( HeapStats_t *xHeapStats );
@@ -710,8 +709,8 @@ typedef struct xHeapStats
size_t xNumberOfSuccessfulFrees;
} HeapStats_t;
```
-*Listing 3.10 The HeapStatus\_t() structure*
-* * *
+***Listing 3.10*** *The HeapStatus\_t() structure*
+
### 3.3.5 Collecting Per-task Heap Usage Statistics
@@ -751,12 +750,12 @@ which should gracefully recover from allocation failures.
-* * *
+
```c
void vApplicationMallocFailedHook( void );
```
-*Listing 3.11 The malloc failed hook function name and prototype*
-* * *
+***Listing 3.11*** *The malloc failed hook function name and prototype*
+
### 3.3.7 Placing Task Stacks in Fast Memory
@@ -774,7 +773,7 @@ macros to call application-provided functions as shown in Listing 3.12.
-* * *
+
```c
/* Functions provided by the application writer than allocate and free
memory from a fast area of RAM. */
@@ -790,8 +789,8 @@ void vPortFreeFastMemory( void *pvBlockToFree );
#define vPortFreeStack( x ) vPortFreeFastMemory( x )
```
-*Listing 3.12 Mapping the pvPortMallocStack() and vPortFreeStack() macros to an application defined memory allcator*
-* * *
+***Listing 3.12*** *Mapping the pvPortMallocStack() and vPortFreeStack() macros to an application defined memory allcator*
+
## 3.4 Using Static Memory Allocation
@@ -850,7 +849,7 @@ also return the size of the timer task stack. A suggested implementation of the
-* * *
+
```c
void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
@@ -874,8 +873,8 @@ void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer,
*pulTimerTaskStackSize = sizeof(uxTimerTaskStack) / sizeof(*uxTimerTaskStack);
}
```
-*Listing 3.13 Typical implementation of vApplicationGetTimerTaskMemory*
-* * *
+***Listing 3.13*** *Typical implementation of vApplicationGetTimerTaskMemory*
+
Since there is only a single timer task in any system including SMP, a valid solution to the timer task memory problem
is to allocate static buffers in the `vApplicationGetTimeTaskMemory()` function and return the buffer pointers to the kernel.
@@ -894,7 +893,6 @@ variables to create the needed buffers.
-* * *
```c
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
@@ -908,5 +906,5 @@ void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
```
-*Listing 3.14 Typical implementation of vApplicationGetIdleTaskMemory*
-* * *
+***Listing 3.14*** *Typical implementation of vApplicationGetIdleTaskMemory*
+
diff --git a/ch04.md b/ch04.md
index 1e5d4ff..cce2e64 100644
--- a/ch04.md
+++ b/ch04.md
@@ -34,14 +34,12 @@ void.
-***
-
```c
void vATaskFunction( void * pvParameters );
```
-*Listing 4.1 The task function prototype*
-***
+***Listing 4.1*** *The task function prototype*
+
Each task is a small program in its own right. It has an entry point,
will normally run forever in an infinite loop, and does not exit.
@@ -61,7 +59,6 @@ within the task itself.
-***
```c
void vATaskFunction( void * pvParameters )
@@ -96,8 +93,7 @@ void vATaskFunction( void * pvParameters )
}
```
-*Listing 4.2 The structure of a typical task function*
-***
+***Listing 4.2*** *The structure of a typical task function*
## 4.3 Top Level Task States
@@ -120,7 +116,7 @@ it does so from the instruction it was about to execute before it left the
***
![](media/figure_4.1_top_level_task_states.png)
-*Figure 4.1 Top level task states and transitions*
+***Figure 4.1*** *Top level task states and transitions*
***
A task transitioned from the *Not Running* state to the *Running* state is
@@ -169,7 +165,6 @@ describes the data types and naming conventions used.
-***
```c
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
@@ -180,8 +175,7 @@ BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
TaskHandle_t * pxCreatedTask );
```
-*Listing 4.3 The xTaskCreate() API function prototype*
-***
+***Listing 4.3*** *The xTaskCreate() API function prototype*
**xTaskCreate() Parameters and return value:**
@@ -262,8 +256,10 @@ BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
+---
+***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
@@ -273,10 +269,8 @@ string they print out—see Listing 4.4 and Listing 4.5 for their respective
implementations. See chapter 8 for warnings about using `printf()` in
tasks.
-
-***
```c
void vTask1( void * pvParameters )
@@ -302,13 +296,11 @@ void vTask1( void * pvParameters )
}
```
-*Listing 4.4 Implementation of the first task used in Example 4.1*
-***
+***Listing 4.4*** *Implementation of the first task used in Example 4.1*
-***
```c
void vTask2( void * pvParameters )
@@ -335,8 +327,7 @@ void vTask2( void * pvParameters )
}
```
-*Listing 4.5 Implementation of the second task used in Example 4.1*
-***
+***Listing 4.5*** *Implementation of the second task used in Example 4.1*
The main() function creates the tasks before starting the scheduler—see
Listing 4.6 for its implementation.
@@ -344,7 +335,6 @@ Listing 4.6 for its implementation.
-***
```c
int main( void )
@@ -384,8 +374,7 @@ int main( void )
}
```
-*Listing 4.6 Starting the Example 4.1 tasks*
-***
+***Listing 4.6*** *Starting the Example 4.1 tasks*
Executing the example produces the output shown in Figure 4.2.
@@ -412,8 +401,8 @@ Task 1 is running
Task 2 is running
```
-***
-*Figure 4.2 The output produced when executing Example 4.1[^4]*
+***Figure 4.2*** *The output produced when executing Example 4.1[^4]*
+
***
[^4]: The screen shot shows each task printing out its message exactly
@@ -446,7 +435,7 @@ enters the *Not Running* state (the task is switched out).
***
![](media/figure_4.3_example_4.1_execution_pattern.png)
-*Figure 4.3 The actual execution pattern of the two Example 4.1 tasks*
+***Figure 4.3*** *The actual execution pattern of the two Example 4.1 tasks*
***
Example 4.1 created both tasks from within `main()`, prior to starting the
@@ -457,7 +446,6 @@ shown by Listing 4.7.
-***
```c
void vTask1( void * pvParameters )
@@ -489,12 +477,13 @@ void vTask1( void * pvParameters )
}
```
-*Listing 4.7 Creating a task from within another task after the scheduler has started*
-***
+***Listing 4.7*** *Creating a task from within another task after the scheduler has started*
+---
+***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
@@ -510,8 +499,6 @@ the task should print out.
-***
-
```c
void vTaskFunction( void * pvParameters )
{
@@ -544,8 +531,7 @@ void vTaskFunction( void * pvParameters )
}
```
-*Listing 4.8 The single task function used to create two tasks in Example 4.2*
-***
+***Listing 4.8*** *The single task function used to create two tasks in Example 4.2*
Listing 4.9 creates two instances of the task implemented by
`vTaskFunction()`, using the task's parameter to pass a different string
@@ -556,7 +542,6 @@ the `pcTaskName` and `ul` variables.
-***
```c
/*
@@ -617,8 +602,8 @@ int main( void )
}
```
-*Listing 4.9 The main() function for Example 2*
-***
+***Listing 4.9*** *The main() function for Example 2*
+
The output from Example 4.2 is exactly as per that shown for example 1 in Figure
4.2.
@@ -712,7 +697,7 @@ although a value of 100 is typical.
***
![](media/figure_4.4_expanded_execution_sequence_with_tick_interrupt.png)
-*Figure 4.4 The execution sequence expanded to show the tick interrupt executing*
+***Figure 4.4*** *The execution sequence expanded to show the tick interrupt executing*
***
FreeRTOS API calls specify time in multiples of tick periods, often
@@ -727,8 +712,6 @@ equivalent time specified in ticks.
-***
-
```c
/*
* pdMS_TO_TICKS() takes a time in milliseconds as its only parameter,
@@ -739,9 +722,8 @@ equivalent time specified in ticks.
TickType_t xTimeInTicks = pdMS_TO_TICKS( 200 );
```
-*Listing 4.10 Using the pdMS\_TO\_TICKS() macro to convert 200 milliseconds
+***Listing 4.10*** *Using the pdMS\_TO\_TICKS() macro to convert 200 milliseconds
into an equivalent time in tick periods*
-***
Using `pdMS_TO_TICKS()` to specify times in milliseconds, rather than
directly as ticks, ensures times specified within the application do not
@@ -758,8 +740,10 @@ describes configuration constants which affect when the scheduler will
select a new task to run and when a tick interrupt will execute.
+---
+***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
@@ -773,7 +757,6 @@ periodically prints a string, using a null loop to create a delay.
-***
```c
/*
@@ -810,8 +793,7 @@ int main( void )
}
```
-*Listing 4.11. Creating two tasks at different priorities*
-***
+***Listing 4.11*** *Creating two tasks at different priorities*
Figure 4.5 shows the output produced by Example 4.3.
@@ -844,7 +826,7 @@ Task 2 is running
Task 2 is running
```
-*Figure 4.5 Running both tasks at different priorities*
+***Figure 4.5*** *Running both tasks at different priorities*
***
Task 2 can always run because it never has to wait for anything—it is
@@ -855,9 +837,8 @@ either cycling around a null loop or printing to the terminal.
***
![](media/figure_4.6_execution_pattern_higher_priority_task.png)
-*Figure 4.6 The execution pattern when one task has a higher priority than the
+***Figure 4.6*** *The execution pattern when one task has a higher priority than the
other from Example 4.3*
-***
## 4.7 Expanding the *Not Running* State
@@ -934,12 +915,14 @@ Figure 4.7 expands on the simplified state diagram to include all of the
***
![](media/figure_4.7_full_task_state_machine.png)
-*Figure 4.7 Full task state machine*
+***Figure 4.7*** *Full task state machine*
***
+---
+***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,
@@ -967,14 +950,12 @@ when there is actually work to be done.
-***
```c
void vTaskDelay( TickType_t xTicksToDelay );
```
-*Listing 4.12 The vTaskDelay() API function prototype*
-***
+***Listing 4.12*** *The vTaskDelay() API function prototype*
**vTaskDelay parameters:**
@@ -996,7 +977,6 @@ void vTaskDelay( TickType_t xTicksToDelay );
-***
```c
void vTaskFunction( void * pvParameters )
@@ -1029,9 +1009,8 @@ void vTaskFunction( void * pvParameters )
}
```
-*Listing 4.13 The source code for the example task after replacing the null loop
+***Listing 4.13*** *The source code for the example task after replacing the null loop
delay with a call to vTaskDelay()*
-***
Even though the two tasks are still being created at different
priorities, both will now run. The output of Example 4.4, which is shown
@@ -1062,7 +1041,7 @@ Task 2 is running
Task 1 is running
```
-*Figure 4.8 The output produced when Example 4.4 is executed*
+***Figure 4.8*** *The output produced when Example 4.4 is executed*
***
The execution sequence shown in Figure 4.9 explains why both tasks run,
@@ -1079,7 +1058,7 @@ describes the Idle task in more detail.
***
![](media/figure_4.9_vTaskDelay_execution_sequence.png)
-*Figure 4.9 The execution sequence when the tasks use vTaskDelay() in place of
+***Figure 4.9*** *The execution sequence when the tasks use vTaskDelay() in place of
the null loop*
***
@@ -1117,7 +1096,7 @@ before being returned to the *Ready* state.
***
![](media/figure_4.10_example_4.4_state_machine.png)
-*Figure 4.10 Bold lines indicate the state transitions performed by the tasks
+***Figure 4.10*** *Bold lines indicate the state transitions performed by the tasks
in Example 4.4*
***
@@ -1143,15 +1122,12 @@ function was called (as is the case with `vTaskDelay()`).
-***
-
```c
void vTaskDelayUntil( TickType_t * pxPreviousWakeTime,
TickType_t xTimeIncrement );
```
-*Listing 4.14 vTaskDelayUntil() API function prototype*
-***
+***Listing 4.14*** *vTaskDelayUntil() API function prototype*
**vTaskDelayUntil() parameters**
@@ -1182,8 +1158,10 @@ void vTaskDelayUntil( TickType_t * pxPreviousWakeTime,
specified in ticks.
+---
+***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
@@ -1194,7 +1172,6 @@ relative to when they call `vTaskDelay()`. Converting the tasks to use
-***
```c
void vTaskFunction( void * pvParameters )
@@ -1234,15 +1211,16 @@ void vTaskFunction( void * pvParameters )
}
```
-*Listing 4.15 The implementation of the example task using vTaskDelayUntil()*
-***
+***Listing 4.15*** *The implementation of the example task using vTaskDelayUntil()*
The output produced by Example 4.5 is exactly as per that shown for Example 4.4
in Figure 4.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
@@ -1268,7 +1246,6 @@ Listing 4.17 shows the source code of the periodic task.
-***
```c
void vContinuousProcessingTask( void * pvParameters )
@@ -1293,13 +1270,11 @@ void vContinuousProcessingTask( void * pvParameters )
}
```
-*Listing 4.16 The continuous processing task used in Example 4.6*
-***
+***Listing 4.16*** *The continuous processing task used in Example 4.6*
-***
```c
void vPeriodicTask( void * pvParameters )
@@ -1331,8 +1306,7 @@ void vPeriodicTask( void * pvParameters )
}
```
-*Listing 4.17 The periodic task used in Example 4.6*
-***
+***Listing 4.17*** *The periodic task used in Example 4.6*
Figure 4.11 shows the output produced by Example 4.6, with an explanation of the
observed behavior given by the execution sequence shown in Figure 4.12.
@@ -1369,7 +1343,7 @@ Continuous task 2 running
Continuous task 2 running
```
-*Figure 4.11 The output produced when Example 4.6 is executed*
+***Figure 4.11*** *The output produced when Example 4.6 is executed*
***
@@ -1377,7 +1351,7 @@ Continuous task 2 running
***
![](media/figure_4.11_example_4.6_execution_pattern.png)
-*Figure 4.12 The execution pattern of Example 4.6*
+***Figure 4.12*** *The execution pattern of Example 4.6*
***
## 4.8 The Idle Task and the Idle Task Hook
@@ -1465,18 +1439,17 @@ Idle task hook functions must have the name and prototype shown in Listing 4.18.
-***
-
```c
void vApplicationIdleHook( void );
```
-*Listing 4.18 The idle task hook function name and prototype*
-***
+***Listing 4.18*** *The idle task hook function name and prototype*
+---
+***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
@@ -1487,8 +1460,6 @@ shown in Listing 4.19.
-***
-
```c
/* Declare a variable that will be incremented by the hook function. */
volatile unsigned long ulIdleCycleCount = 0UL;
@@ -1504,8 +1475,8 @@ void vApplicationIdleHook( void )
}
```
-*Listing 4.19 A very simple Idle hook function*
-***
+***Listing 4.19*** *A very simple Idle hook function*
+
`configUSE_IDLE_HOOK` must be set to 1 in FreeRTOSConfig.h for the idle hook function
to get called.
@@ -1516,7 +1487,6 @@ print out the `ulIdleCycleCount` value, as shown in Listing 4.20.
-***
```c
void vTaskFunction( void * pvParameters )
@@ -1545,9 +1515,8 @@ void vTaskFunction( void * pvParameters )
}
```
-*Listing 4.20 The source code for the example task now prints out the
+***Listing 4.20*** *The source code for the example task now prints out the
ulIdleCycleCount value*
-***
Figure 4.13 shows the output produced by Example 4.7. It can be seen that
the idle task hook function executes approximately 4 million times
@@ -1584,7 +1553,7 @@ ulIdleCycleCount = 17838406
Task 2 is running
```
-*Figure 4.13 The output produced when Example 4.7 is executed*
+***Figure 4.13*** *The output produced when Example 4.7 is executed*
***
@@ -1600,15 +1569,12 @@ FreeRTOSConfig.h.
-***
-
```c
void vTaskPrioritySet( TaskHandle_t xTask,
UBaseType_t uxNewPriority );
```
-*Listing 4.21 The vTaskPrioritySet() API function prototype*
-***
+***Listing 4.21*** *The vTaskPrioritySet() API function prototype*
**vTaskPrioritySet() parameters**
@@ -1639,14 +1605,11 @@ The `uxTaskPriorityGet()` API function returns the priority of a task. The
-***
-
```c
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
```
-*Listing 4.22 The uxTaskPriorityGet() API function prototype*
-***
+***Listing 4.22*** *The uxTaskPriorityGet() API function prototype*
**uxTaskPriorityGet() parameters and return value**
@@ -1665,8 +1628,10 @@ UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
+---
+***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
@@ -1701,8 +1666,6 @@ Example 4.8 behaves as follows:
-***
-
```c
void vTask1( void * pvParameters )
{
@@ -1745,13 +1708,11 @@ void vTask1( void * pvParameters )
}
```
-*Listing 4.23 The implementation of Task 1 in Example 4.8*
-***
+***Listing 4.23*** *The implementation of Task 1 in Example 4.8*
-***
```c
void vTask2( void * pvParameters )
@@ -1790,8 +1751,7 @@ void vTask2( void * pvParameters )
}
```
-*Listing 4.24 The implementation of Task 2 in Example 4.8*
-***
+***Listing 4.24*** *The implementation of Task 2 in Example 4.8*
Each task can both query and set its own priority by using NULL in place
of a valid task handle. A task handle is only required when a task
@@ -1803,8 +1763,6 @@ the comments in Listing 4.25.
-***
-
```c
/* Declare a variable that is used to hold the handle of Task 2. */
TaskHandle_t xTask2Handle = NULL;
@@ -1844,8 +1802,7 @@ int main( void )
}
```
-*Listing 4.25 The implementation of main() for Example 4.8*
-***
+***Listing 4.25*** *The implementation of main() for Example 4.8*
Figure 4.14 demonstrates the sequence in which the tasks in Example 4.8
execute, and the resultant output is shown in Figure 4.15.
@@ -1855,7 +1812,7 @@ execute, and the resultant output is shown in Figure 4.15.
***
![](media/figure_4.14_example_4.8_execution_sequence.png)
-*Figure 4.14 The sequence of task execution when running Example 4.8*
+***Figure 4.14*** *The sequence of task execution when running Example 4.8*
***
@@ -1879,7 +1836,7 @@ About to lower the Task2 priority
Task1 is running
```
-*Figure 4.15 The output produced when Example 4.8 is executed*
+***Figure 4.15*** *The output produced when Example 4.8 is executed*
***
## 4.10 Deleting a Task
@@ -1910,14 +1867,12 @@ time when this is the case.
-***
```c
void vTaskDelete( TaskHandle_t xTaskToDelete );
```
-*Listing 4.26 The vTaskDelete() API function prototype*
-***
+***Listing 4.26*** *The vTaskDelete() API function prototype*
**vTaskDelete() parameters**
@@ -1933,8 +1888,10 @@ void vTaskDelete( TaskHandle_t xTaskToDelete );
+---
+***Example 4.9*** *Deleting tasks*
-Example 4.9 Deleting tasks
+---
This is a very simple example that behaves as follows.
@@ -1962,8 +1919,6 @@ This is a very simple example that behaves as follows.
-***
-
```c
int main( void )
{
@@ -1980,14 +1935,12 @@ int main( void )
}
```
-*Listing 4.27 The implementation of main() for Example 4.9*
+***Listing 4.27*** *The implementation of main() for Example 4.9*
***
-***
-
```c
TaskHandle_t xTask2Handle = NULL;
@@ -2016,13 +1969,11 @@ void vTask1( void * pvParameters )
}
```
-*Listing 4.28 The implementation of Task 1 for Example 4.9*
-***
+***Listing 4.28*** *The implementation of Task 1 for Example 4.9*
-***
```c
void vTask2( void * pvParameters )
@@ -2038,8 +1989,7 @@ void vTask2( void * pvParameters )
}
```
-*Listing 4.29 The implementation of Task 2 for Example 4.9*
-***
+***Listing 4.29*** *The implementation of Task 2 for Example 4.9*
@@ -2066,7 +2016,7 @@ Task1 is running
Task2 is running and about to delete itself
```
-*Figure 4.16 The output produced when Example 4.9 is executed*
+***Figure 4.16*** *The output produced when Example 4.9 is executed*
***
@@ -2074,7 +2024,7 @@ Task2 is running and about to delete itself
***
![](media/figure_4.17_example_4.9_execution_sequence.png)
-*Figure 4.17 The execution sequence for Example 4.9*
+***Figure 4.17*** *The execution sequence for Example 4.9*
***
@@ -2143,8 +2093,6 @@ value of each thread local storage pointer at runtime.
-***
-
```c
void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
BaseType_t xIndex )
@@ -2154,8 +2102,7 @@ void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
void * pvValue );
```
-*Listing 4.30 Function prototypes of the Thread Local Storage Pointer API functions*
-***
+***Listing 4.30*** *Function prototypes of the Thread Local Storage Pointer API functions*
## 4.12 Scheduling Algorithms
@@ -2266,7 +2213,7 @@ priority.
***
![](media/figure_4.18_preemption_execution_pattern.png)
-*Figure 4.18 Execution pattern highlighting task prioritization and preemption
+***Figure 4.18*** *Execution pattern highlighting task prioritization and preemption
in a hypothetical application in which each task has been assigned a unique
priority*
***
@@ -2323,7 +2270,7 @@ Referring to Figure 4.18:
***
![](media/figure_4.19_time_slicing_execution_pattern.png)
-*Figure 4.19 Execution pattern highlighting task prioritization and time slicing
+***Figure 4.19*** *Execution pattern highlighting task prioritization and time slicing
in a hypothetical application in which two tasks run at the same priority*
***
@@ -2382,7 +2329,7 @@ Figure 4.20 is what would be observed in the same scenario when
***
![](media/figure_4.20_time_slicing_with_yield_execution_pattern.png)
-*Figure 4.20 The execution pattern for the same scenario as shown in Figure 4.19,
+***Figure 4.20*** *The execution pattern for the same scenario as shown in Figure 4.19,
but this time with `configIDLE_SHOULD_YIELD` set to 1*
***
@@ -2426,7 +2373,7 @@ experienced users.
***
![](media/figure_4.21_equal_priority_without_time_slicing_execution_pattern.png)
-*Figure 4.21 Execution pattern that demonstrates how tasks of equal priority can
+***Figure 4.21*** *Execution pattern that demonstrates how tasks of equal priority can
receive hugely different amounts of processing time when time slicing is not used*
***
@@ -2491,7 +2438,7 @@ state.
***
![](media/figure_4.22_cooperative_scheduler_execution_pattern.png)
-*Figure 4.22 Execution pattern demonstrating the behavior of the cooperative scheduler*
+***Figure 4.22*** *Execution pattern demonstrating the behavior of the cooperative scheduler*
***
Referring to Figure 4.22:
diff --git a/ch05.md b/ch05.md
index 7f303c9..8a27000 100644
--- a/ch05.md
+++ b/ch05.md
@@ -48,7 +48,7 @@ at the front of a queue.
* * *
![](media/image31.png)
-*Figure 5.1 An example sequence of writes to, and reads from a queue*
+***Figure 5.1*** *An example sequence of writes to, and reads from a queue*
* * *
There are two ways in which queue behaviour can be implemented:
@@ -174,12 +174,10 @@ area, respectively.
-* * *
```c
QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, UBaseType_t uxItemSize );
```
-*Listing 5.1 The xQueueCreate() API function prototype*
-* * *
+***Listing 5.1*** *The xQueueCreate() API function prototype*
**xQueueCreate() parameters and return value:**
@@ -224,25 +222,24 @@ queue.
-* * *
+
```c
BaseType_t xQueueSendToFront( QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait );
```
-*Listing 5.2 The xQueueSendToFront() API function prototype*
-* * *
+***Listing 5.2*** *The xQueueSendToFront() API function prototype*
+
-* * *
+
```c
BaseType_t xQueueSendToBack( QueueHandle_t xQueue,
const void * pvItemToQueue,
TickType_t xTicksToWait );
```
-*Listing 5.3 The xQueueSendToBack() API function prototype*
-* * *
+***Listing 5.3*** *The xQueueSendToBack() API function prototype*
**xQueueSendToFront() and xQueueSendToBack() function parameters and return value**
@@ -315,14 +312,12 @@ is removed from the queue.
-* * *
```c
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
```
-*Listing 5.4 The xQueueReceive() API function prototype*
-* * *
+***Listing 5.4*** *The xQueueReceive() API function prototype*
**xQueueReceive() function parameters and return values**
@@ -393,12 +388,10 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
-* * *
```c
UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );
```
-*Listing 5.5 The uxQueueMessagesWaiting() API function prototype*
-* * *
+***Listing 5.5*** *The uxQueueMessagesWaiting() API function prototype*
**uxQueueMessagesWaiting() function parameters and return value**
@@ -416,8 +409,10 @@ UBaseType_t uxQueueMessagesWaiting( QueueHandle_t xQueue );
+---
+***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
@@ -439,7 +434,6 @@ is used to pass these values into each task instance.
-* * *
```c
static void vSenderTask( void *pvParameters )
{
@@ -484,8 +478,7 @@ static void vSenderTask( void *pvParameters )
}
}
```
-*Listing 5.6 Implementation of the sending task used in Example 5.1*
-* * *
+***Listing 5.6*** *Implementation of the sending task used in Example 5.1*
Listing 5.7 shows the implementation of the task that receives data from
@@ -498,7 +491,6 @@ so the 100 milliseconds timeout never expires.
-* * *
```c
static void vReceiverTask( void *pvParameters )
{
@@ -549,8 +541,7 @@ static void vReceiverTask( void *pvParameters )
}
}
```
-*Listing 5.7 Implementation of the receiver task for Example 5.1*
-* * *
+***Listing 5.7*** *Implementation of the receiver task for Example 5.1*
Listing 5.8 contains the definition of the `main()` function. This simply
@@ -561,7 +552,6 @@ one item at a time.
-* * *
```c
/* Declare a variable of type QueueHandle_t. This is used to store the
handle to the queue that is accessed by all three tasks. */
@@ -603,9 +593,7 @@ int main( void )
for( ;; );
}
```
-*Listing 5.8 The implementation of main() in Example 5.1*
-* * *
-
+***Listing 5.8*** *The implementation of main() in Example 5.1*
Figure 5.2 shows the output produced by Example 5.1.
@@ -613,7 +601,7 @@ Figure 5.2 shows the output produced by Example 5.1.
* * *
![](media/image32.jpg)
-*Figure 5.2 The output produced when Example 5.1 is executed*
+***Figure 5.2*** *The output produced when Example 5.1 is executed*
* * *
@@ -623,7 +611,7 @@ Figure 5.3 demonstrates the sequence of execution.
* * *
![](media/image33.png)
-*Figure 5.3 The sequence of execution produced by Example 5.1*
+***Figure 5.3*** *The sequence of execution produced by Example 5.1*
* * *
@@ -639,7 +627,7 @@ data value and data source, as demonstrated in Figure 5.4.
* * *
![](media/image34.png)
-*Figure 5.4 An example scenario where structures are sent on a queue*
+***Figure 5.4*** *An example scenario where structures are sent on a queue*
* * *
Referring to Figure 5.4:
@@ -676,8 +664,10 @@ the controller task can reply directly to the task that queued a structure.
+---
+***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,
@@ -687,7 +677,6 @@ Listing 5.9 shows the definition of the structure used by Example 5.2.
-* * *
```c
/* Define an enumerated type used to identify the source of the data. */
typedef enum
@@ -710,9 +699,7 @@ static const Data_t xStructsToSend[ 2 ] =
{ 200, eSender2 } /* Used by Sender2. */
};
```
-*Listing 5.9 The definition of the structure that is to be passed on a queue, plus the declaration of two variables for use by the example*
-* * *
-
+***Listing 5.9*** *The definition of the structure that is to be passed on a queue, plus the declaration of two variables for use by the example*
In Example 5.1, the receiving task has the highest priority, so the queue
never contains more than one item. This happens because the receiving task
@@ -734,7 +721,6 @@ in the queue, so the 100 milliseconds timeout never expires.
-* * *
```c
static void vSenderTask( void *pvParameters )
{
@@ -770,8 +756,7 @@ static void vSenderTask( void *pvParameters )
}
}
```
-*Listing 5.10 The implementation of the sending task for Example 5.2*
-* * *
+***Listing 5.10*** *The implementation of the sending task for Example 5.2*
The receiving task has the lowest priority so it only runs only when both
@@ -784,7 +769,6 @@ Listing 5.11 shows the implementation of the receiving task.
-* * *
```c
static void vReceiverTask( void *pvParameters )
{
@@ -843,9 +827,7 @@ static void vReceiverTask( void *pvParameters )
}
}
```
-*Listing 5.11 The definition of the receiving task for Example 5.2*
-* * *
-
+***Listing 5.11*** *The definition of the receiving task for Example 5.2*
`main()` changes only slightly from the previous example. The queue is
created to hold three `Data_t` structures, and the priorities of the
@@ -854,7 +836,6 @@ implementation of `main()`.
-* * *
```c
int main( void )
{
@@ -894,9 +875,7 @@ int main( void )
for( ;; );
}
```
-*Listing 5.12 The implementation of main() for Example 5.2*
-* * *
-
+***Listing 5.12*** *The implementation of main() for Example 5.2*
Figure 5.5 shows the output produced by Example 5.2.
@@ -904,7 +883,7 @@ Figure 5.5 shows the output produced by Example 5.2.
* * *
![](media/image35.jpg)
-*Figure 5.5 The output produced by Example 5.2*
+***Figure 5.5*** *The output produced by Example 5.2*
* * *
Figure 5.6 demonstrates the sequence of execution that results from
@@ -916,7 +895,7 @@ description on why the first four messages originate from the same task.
* * *
![](media/image36.png)
-*Figure 5.6 The sequence of execution produced by Example 5.2*
+***Figure 5.6*** *The sequence of execution produced by Example 5.2*
* * *
**Key to Figure 5.6**
@@ -1019,7 +998,6 @@ to use a queue to send a pointer to a buffer from one task to another:
-* * *
```c
/* Declare a variable of type QueueHandle_t to hold the handle of the
queue being created. */
@@ -1029,12 +1007,10 @@ QueueHandle_t xPointerQueue;
character pointers. */
xPointerQueue = xQueueCreate( 5, sizeof( char * ) );
```
-*Listing 5.13 Creating a queue that holds pointers*
-* * *
+***Listing 5.13*** *Creating a queue that holds pointers*
-* * *
```c
/* A task that obtains a buffer, writes a string to the buffer, then
sends the address of the buffer to the queue created in Listing 5.13. */
@@ -1070,12 +1046,10 @@ void vStringSendingTask( void *pvParameters )
}
}
```
-*Listing 5.14 Using a queue to send a pointer to a buffer*
-* * *
+***Listing 5.14*** *Using a queue to send a pointer to a buffer*
-* * *
```c
/* A task that receives the address of a buffer from the queue created
in Listing 5.13, and written to in Listing 5.14. The buffer contains a
@@ -1102,9 +1076,7 @@ void vStringReceivingTask( void *pvParameters )
}
}
```
-*Listing 5.15 Using a queue to receive a pointer to a buffer*
-* * *
-
+***Listing 5.15*** *Using a queue to receive a pointer to a buffer*
### 5.5.2 Using a Queue to Send Different Types and Lengths of Data[^9]
@@ -1128,7 +1100,6 @@ be used to hold a value directly, or point to a buffer.
-* * *
```c
/* A subset of the enumerated types used in the TCP/IP stack to
identify events. */
@@ -1157,8 +1128,7 @@ typedef struct IP_TASK_COMMANDS
} IPStackEvent_t;
```
-*Listing 5.16 The structure used to send events to the TCP/IP stack task in FreeRTOS+TCP*
-* * *
+***Listing 5.16*** *The structure used to send events to the TCP/IP stack task in FreeRTOS+TCP*
Example TCP/IP events, and their associated data, include:
@@ -1172,7 +1142,6 @@ Example TCP/IP events, and their associated data, include:
- * * *
```c
void vSendRxDataToTheTCPTask( NetworkBufferDescriptor_t *pxRxedData )
{
@@ -1187,8 +1156,7 @@ Example TCP/IP events, and their associated data, include:
xSendEventStructToIPTask( &xEventStruct );
}
```
- *Listing 5.17 Pseudo code showing how an IPStackEvent_t structure is used to send data received from the network to the TCP/IP task*
- * * *
+ ***Listing 5.17*** *Pseudo code showing how an IPStackEvent_t structure is used to send data received from the network to the TCP/IP task*
- `eTCPAcceptEvent`: A socket is to accept, or wait for, a connection
from a client.
@@ -1201,7 +1169,6 @@ Example TCP/IP events, and their associated data, include:
- * * *
```c
void vSendAcceptRequestToTheTCPTask( Socket_t xSocket )
{
@@ -1215,8 +1182,7 @@ Example TCP/IP events, and their associated data, include:
xSendEventStructToIPTask( &xEventStruct );
}
```
- *Listing 5.18 Pseudo code showing how an IPStackEvent_t structure is used to send the handle of a socket that is accepting a connection to the TCP/IP task*
- * * *
+ ***Listing 5.18*** *Pseudo code showing how an IPStackEvent_t structure is used to send the handle of a socket that is accepting a connection to the TCP/IP task*
- `eNetworkDownEvent`: The network needs connecting, or re-connecting.
@@ -1228,7 +1194,6 @@ Example TCP/IP events, and their associated data, include:
- * * *
```c
void vSendNetworkDownEventToTheTCPTask( Socket_t xSocket )
{
@@ -1244,8 +1209,7 @@ Example TCP/IP events, and their associated data, include:
xSendEventStructToIPTask( &xEventStruct );
}
```
- *Listing 5.19 Pseudo code showing how an IPStackEvent_t structure is used to send a network down event to the TCP/IP task*
- * * *
+ ***Listing 5.19*** *Pseudo code showing how an IPStackEvent_t structure is used to send a network down event to the TCP/IP task*
Listing 5.20 shows the code that receives and processes these events
within the TCP/IP task. It can be seen that the `eEventType` member of the
@@ -1254,7 +1218,6 @@ Example TCP/IP events, and their associated data, include:
- * * *
```c
IPStackEvent_t xReceivedEvent;
@@ -1295,9 +1258,7 @@ Example TCP/IP events, and their associated data, include:
}
```
- *Listing 5.20 Pseudo code showing how an IPStackEvent_t structure is received and processed*
- * * *
-
+ ***Listing 5.20*** *Pseudo code showing how an IPStackEvent_t structure is received and processed*
## 5.6 Receiving From Multiple Queues
@@ -1363,12 +1324,10 @@ and returns a `QueueSetHandle_t` that references the created queue set.
-* * *
```c
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength);
```
-*Listing 5.21 The xQueueCreateSet() API function prototype*
-* * *
+***Listing 5.21*** *The xQueueCreateSet() API function prototype*
**xQueueCreateSet() parameters and return value**
@@ -1422,14 +1381,11 @@ are described later in this book.
-* * *
```c
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet );
```
-*Listing 5.22 The xQueueAddToSet() API function prototype*
-* * *
-
+***Listing 5.22*** *The xQueueAddToSet() API function prototype*
**xQueueAddToSet() parameters and return value**
@@ -1479,14 +1435,11 @@ calling task must then read from the queue or semaphore directly.
-* * *
```c
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
const TickType_t xTicksToWait );
```
-*Listing 5.23 The xQueueSelectFromSet() API function prototype*
-* * *
-
+***Listing 5.23*** *The xQueueSelectFromSet() API function prototype*
**xQueueSelectFromSet() parameters and return value**
@@ -1534,8 +1487,10 @@ QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
+---
+***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,
@@ -1548,7 +1503,6 @@ Listing 5.24 for its implementation.
-* * *
```c
/* Declare two variables of type QueueHandle_t. Both queues are added
to the same queue set. */
@@ -1594,9 +1548,7 @@ int main( void )
return 0;
}
```
-*Listing 5.24 Implementation of main() for Example 5.3*
-* * *
-
+***Listing 5.24*** *Implementation of main() for Example 5.3*
The first sending task uses `xQueue1` to send a character pointer to the
receiving task every 100 milliseconds. The second sending task uses
@@ -1606,7 +1558,6 @@ the sending task. Listing 5.25 shows the implementation of both tasks.
-* * *
```c
void vSenderTask1( void *pvParameters )
{
@@ -1656,8 +1607,7 @@ void vSenderTask2( void *pvParameters )
}
}
```
-*Listing 5.25 The sending tasks used in Example 5.3*
-* * *
+***Listing 5.25*** *The sending tasks used in Example 5.3*
The queues written to by the sending tasks are members of the same queue
@@ -1683,7 +1633,6 @@ Listing 5.26 shows the implementation of the receive task.
-* * *
```c
void vReceiverTask( void *pvParameters )
{
@@ -1714,9 +1663,7 @@ void vReceiverTask( void *pvParameters )
}
}
```
-*Listing 5.26 The receive task used in Example 5.3*
-* * *
-
+***Listing 5.26*** *The receive task used in Example 5.3*
Figure 5.7 shows the output produced by Example 5.3. It can be seen that
the receiving task receives strings from both sending tasks. The block
@@ -1728,7 +1675,7 @@ twice as often as those sent by `vSenderTask2()`.
* * *
![](media/image37.jpg)
-*Figure 5.7 The output produced when Example 5.3 is executed*
+***Figure 5.7*** *The output produced when Example 5.3 is executed*
* * *
@@ -1752,7 +1699,6 @@ and added to the queue set.
-* * *
```c
/* The handle of the queue from which character pointers are received. */
QueueHandle_t xCharPointerQueue;
@@ -1822,8 +1768,7 @@ void vAMoreRealisticReceiverTask( void *pvParameters )
}
}
```
-*Listing 5.27 Using a queue set that contains queues and semaphores*
-* * *
+***Listing 5.27*** *Using a queue set that contains queues and semaphores*
## 5.7 Using a Queue to Create a Mailbox
@@ -1854,7 +1799,6 @@ Listing 5.28 shows how a queue is created for use as a mailbox.
-* * *
```c
/* A mailbox can hold a fixed size data item. The size of the data item is set
when the mailbox (queue) is created. In this example the mailbox is created
@@ -1881,8 +1825,7 @@ void vAFunction( void )
xMailbox = xQueueCreate( 1, sizeof( Example_t ) );
}
```
-*Listing 5.28 A queue being created for use as a mailbox*
-* * *
+***Listing 5.28*** *A queue being created for use as a mailbox*
### 5.7.1 The xQueueOverwrite() API Function
@@ -1904,13 +1847,10 @@ has a length > 1.
-* * *
```c
BaseType_t xQueueOverwrite( QueueHandle_t xQueue, const void * pvItemToQueue );
```
-*Listing 5.29 The xQueueOverwrite() API function prototype*
-* * *
-
+***Listing 5.29*** *The xQueueOverwrite() API function prototype*
**xQueueOverwrite() parameters and return value**
@@ -1938,7 +1878,6 @@ Listing 5.30 shows how `xQueueOverwrite()` is used to write to the mailbox
-* * *
```c
void vUpdateMailbox( uint32_t ulNewValue )
{
@@ -1957,8 +1896,7 @@ void vUpdateMailbox( uint32_t ulNewValue )
xQueueOverwrite( xMailbox, &xData );
}
```
-*Listing 5.30 Using the xQueueOverwrite() API function*
-* * *
+***Listing 5.30*** *Using the xQueueOverwrite() API function*
### 5.7.2 The xQueuePeek() API Function
@@ -1976,14 +1914,12 @@ which data is stored in the queue.
-* * *
```c
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait );
```
-*Listing 5.31 The xQueuePeek() API function prototype*
-* * *
+***Listing 5.31*** *The xQueuePeek() API function prototype*
Listing 5.32 shows `xQueuePeek()` being used to receive the item posted to
@@ -1991,7 +1927,6 @@ the mailbox (queue) in Listing 5.30.
-* * *
```c
BaseType_t vReadMailbox( Example_t *pxData )
{
@@ -2030,5 +1965,4 @@ BaseType_t vReadMailbox( Example_t *pxData )
return xDataUpdated;
}
```
-*Listing 5.32 Using the xQueuePeek() API function*
-* * *
+***Listing 5.32*** *Using the xQueuePeek() API function*
diff --git a/ch06.md b/ch06.md
index 6ef072a..c0d0fb2 100644
--- a/ch06.md
+++ b/ch06.md
@@ -63,13 +63,10 @@ callback function prototype is demonstrated by Listing 6.1.
-* * *
```c
void ATimerCallback( TimerHandle_t xTimer );
```
-*Listing 6.1 The software timer callback function prototype*
-* * *
-
+***Listing 6.1*** *The software timer callback function prototype*
Software timer callback functions execute from start to finish, and exit
in the normal way. They should be kept short, and must not enter the
@@ -117,7 +114,7 @@ a tick interrupt occurs.
* * *
![](media/image38.png)
-*Figure 6.1 The difference in behavior between one-shot and auto-reload software timers*
+***Figure 6.1*** *The difference in behavior between one-shot and auto-reload software timers*
* * *
Referring to Figure 6.1:
@@ -164,10 +161,10 @@ executes its callback function then enters the Dormant state.
* * *
![](media/image39.png)
-*Figure 6.2 Auto-reload software timer states and transitions*
+***Figure 6.2*** *Auto-reload software timer states and transitions*
![](media/image40.png)
-*Figure 6.3 One-shot software timer states and transitions*
+***Figure 6.3*** *One-shot software timer states and transitions*
* * *
The `xTimerDelete()` API function deletes a timer. A timer can be deleted
@@ -176,12 +173,10 @@ at any time. The function prototype is demonstrated by Listing 6.2.
-* * *
```c
BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );
```
-*Listing 6.2 The xTimerDelete() API function prototype*
-* * *
+***Listing 6.2*** *The xTimerDelete() API function prototype*
**xTimerDelete() parameters and return value**
@@ -253,7 +248,7 @@ configuration constant in FreeRTOSConfig.h.
* * *
![](media/image41.png)
-*Figure 6.4 The timer command queue being used by a software timer API function to communicate with the RTOS daemon task*
+***Figure 6.4*** *The timer command queue being used by a software timer API function to communicate with the RTOS daemon task*
* * *
@@ -274,7 +269,7 @@ function.
* * *
![](media/image42.png)
-*Figure 6.5 The execution pattern when the priority of a task calling xTimerStart() is above the priority of the daemon task*
+***Figure 6.5*** *The execution pattern when the priority of a task calling xTimerStart() is above the priority of the daemon task*
* * *
Referring to Figure 6.5, in which the priority of Task 1 is higher than
@@ -345,7 +340,7 @@ that calls `xTimerStart()`.
* * *
![](media/image43.png)
-*Figure 6.6 The execution pattern when the priority of a task calling xTimerStart() is below the priority of the daemon task*
+***Figure 6.6*** *The execution pattern when the priority of a task calling xTimerStart() is below the priority of the daemon task*
* * *
Referring to Figure 6.6, in which the priority of the daemon task is
@@ -431,7 +426,6 @@ a task after the scheduler has been started.
-* * *
```c
TimerHandle_t xTimerCreate( const char * const pcTimerName,
const TickType_t xTimerPeriodInTicks,
@@ -439,8 +433,7 @@ TimerHandle_t xTimerCreate( const char * const pcTimerName,
void * const pvTimerID,
TimerCallbackFunction_t pxCallbackFunction );
```
-*Listing 6.3 The xTimerCreate() API function prototype*
-* * *
+***Listing 6.3*** *The xTimerCreate() API function prototype*
**xTimerCreate() parameters and return value**
@@ -513,12 +506,10 @@ at which the scheduler starts.
-* * *
```c
BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
```
-*Listing 6.4 The xTimerStart() API function prototype*
-* * *
+***Listing 6.4*** *The xTimerStart() API function prototype*
**xTimerStart() parameters and return value**
@@ -588,8 +579,10 @@ BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );
+---
+***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.
@@ -597,7 +590,6 @@ timer—as shown in Listing 6.5.
-* * *
```c
/* The periods assigned to the one-shot and auto-reload timers are 3.333
second and half a second respectively. */
@@ -663,8 +655,7 @@ int main( void )
for( ;; );
}
```
-*Listing 6.5 Creating and starting the timers used in Example 6.1*
-* * *
+***Listing 6.5*** *Creating and starting the timers used in Example 6.1*
The timers' callback functions just print a message each time they are
@@ -675,7 +666,6 @@ callback function is shown in Listing 6.7.
-* * *
```c
static void prvOneShotTimerCallback( TimerHandle_t xTimer )
{
@@ -691,13 +681,11 @@ static void prvOneShotTimerCallback( TimerHandle_t xTimer )
ulCallCount++;
}
```
-*Listing 6.6 The callback function used by the one-shot timer in Example 6.1*
-* * *
+***Listing 6.6*** *The callback function used by the one-shot timer in Example 6.1*
-* * *
```c
static void prvAutoReloadTimerCallback( TimerHandle_t xTimer )
{
@@ -712,9 +700,7 @@ static void prvAutoReloadTimerCallback( TimerHandle_t xTimer )
ulCallCount++;
}
```
-*Listing 6.7 The callback function used by the auto-reload timer in Example 6.1*
-* * *
-
+***Listing 6.7*** *The callback function used by the auto-reload timer in Example 6.1*
Executing this example produces the output shown in Figure 6.7. Figure 6.7
shows the auto-reload timer's callback function executing with a fixed
@@ -728,7 +714,7 @@ once, when the tick count is 3333 (`mainONE_SHOT_TIMER_PERIOD` is set to
* * *
![](media/image44.jpg)
-*Figure 6.7 The output produced when Example 6.1 is executed*
+***Figure 6.7*** *The output produced when Example 6.1 is executed*
* * *
@@ -753,12 +739,10 @@ a command to the timer command queue.
-* * *
```c
void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID );
```
-*Listing 6.8 The vTimerSetTimerID() API function prototype*
-* * *
+***Listing 6.8*** *The vTimerSetTimerID() API function prototype*
**vTimerSetTimerID() parameters**
@@ -779,12 +763,10 @@ void vTimerSetTimerID( const TimerHandle_t xTimer, void *pvNewID );
-* * *
```c
void *pvTimerGetTimerID( const TimerHandle_t xTimer );
```
-*Listing 6.9 The pvTimerGetTimerID() API function prototype*
-* * *
+***Listing 6.9*** *The pvTimerGetTimerID() API function prototype*
**pvTimerGetTimerID() parameters and return value**
@@ -801,8 +783,10 @@ void *pvTimerGetTimerID( const TimerHandle_t xTimer );
+---
+***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
@@ -822,7 +806,6 @@ timers are created. This difference is shown in Listing 6.10, where
-* * *
```c
/* Create the one shot timer software timer, storing the handle in
xOneShotTimer. */
@@ -844,8 +827,7 @@ xAutoReloadTimer = xTimerCreate( "AutoReload",
/* prvTimerCallback() is used by both timers. */
prvTimerCallback );
```
-*Listing 6.10 Creating the timers used in Example 6.2*
-* * *
+***Listing 6.10*** *Creating the timers used in Example 6.2*
`prvTimerCallback()` will execute when either timer expires. The
implementation of `prvTimerCallback()` uses the function's parameter to
@@ -862,7 +844,6 @@ The implementation of `prvTimerCallback()` is shown in Listing 6.9.
-* * *
```c
static void prvTimerCallback( TimerHandle_t xTimer )
{
@@ -906,8 +887,7 @@ static void prvTimerCallback( TimerHandle_t xTimer )
}
}
```
-*Listing 6.11 The timer callback function used in Example 6.2*
-* * *
+***Listing 6.11*** *The timer callback function used in Example 6.2*
The output produced by Example 6.2 is shown in Figure 6.8. It can be seen
@@ -918,7 +898,7 @@ that the auto-reload timer only executes five times.
* * *
![](media/image45.jpg)
-*Figure 6.8 The output produced when Example 6.2 is executed*
+***Figure 6.8*** *The output produced when Example 6.2 is executed*
* * *
@@ -959,14 +939,12 @@ will start running).
-* * *
```c
BaseType_t xTimerChangePeriod( TimerHandle_t xTimer,
TickType_t xNewPeriod,
TickType_t xTicksToWait );
```
-*Listing 6.12 The xTimerChangePeriod() API function prototype*
-* * *
+***Listing 6.12*** *The xTimerChangePeriod() API function prototype*
**xTimerChangePeriod() parameters and return value**
@@ -1041,7 +1019,6 @@ referred to as the 'check timer'.
-* * *
```c
/* The check timer is created with a period of 3000 milliseconds, resulting
in the LED toggling every 3 seconds. If the self-checking functionality
@@ -1088,9 +1065,7 @@ static void prvCheckTimerCallbackFunction( TimerHandle_t xTimer )
ToggleLED();
}
```
-*Listing 6.13 Using xTimerChangePeriod()*
-* * *
-
+***Listing 6.13*** *Using xTimerChangePeriod()*
## 6.8 Resetting a Software Timer
@@ -1106,7 +1081,7 @@ function.
* * *
![](media/image46.png)
-*Figure 6.9 Starting and resetting a software timer that has a period of 6 ticks*
+***Figure 6.9*** *Starting and resetting a software timer that has a period of 6 ticks*
* * *
Referring to Figure 6.9:
@@ -1142,12 +1117,10 @@ A timer is reset using the `xTimerReset()` API function.
-* * *
```c
BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
```
-*Listing 6.14 The xTimerReset() API function prototype*
-* * *
+***Listing 6.14*** *The xTimerReset() API function prototype*
**xTimerReset() parameters and return value**
@@ -1201,8 +1174,10 @@ BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );
+---
+***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:
@@ -1234,7 +1209,6 @@ The software timer callback function is shown in Listing 6.15.
-* * *
```c
static void prvBacklightTimerCallback( TimerHandle_t xTimer )
{
@@ -1248,8 +1222,7 @@ static void prvBacklightTimerCallback( TimerHandle_t xTimer )
"Timer expired, turning backlight OFF at time\t\t", xTimeNow );
}
```
-*Listing 6.15 The callback function for the one-shot timer used in Example 6.3*
-* * *
+***Listing 6.15*** *The callback function for the one-shot timer used in Example 6.3*
Example 6.3 creates a task to poll the keyboard[^11]. The task is shown
@@ -1275,7 +1248,6 @@ routine, then `xTimerResetFromISR()` would be used in place of
-* * *
```c
static void vKeyHitTask( void *pvParameters )
{
@@ -1331,8 +1303,7 @@ static void vKeyHitTask( void *pvParameters )
}
}
```
-*Listing 6.16 The task used to reset the software timer in Example 6.3*
-* * *
+***Listing 6.16*** *The task used to reset the software timer in Example 6.3*
The output produced when Example 6.3 is executed is shown in Figure 6.10.
With reference to Figure 6.10:
@@ -1353,7 +1324,7 @@ With reference to Figure 6.10:
* * *
![](media/image47.jpg)
-*Figure 6.10 The output produced when Example 6.3 is executed*
+***Figure 6.10*** *The output produced when Example 6.3 is executed*
* * *
It can be seen in Figure 6.10 that the timer had a period of 5000 ticks;
diff --git a/ch07.md b/ch07.md
index 4128284..98c8ebf 100644
--- a/ch07.md
+++ b/ch07.md
@@ -266,22 +266,18 @@ ports that allowed the entire interrupt handler to be written in C.
-* * *
```c
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
```
-*Listing 7.1 The portEND_SWITCHING\_ISR() macros*
-* * *
+***Listing 7.1*** *The portEND_SWITCHING\_ISR() macros*
-* * *
```c
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
```
-*Listing 7.2 The portYIELD\_FROM\_ISR() macros*
-* * *
+***Listing 7.2*** *The portYIELD\_FROM\_ISR() macros*
The `xHigherPriorityTaskWoken` parameter passed out of an interrupt safe
@@ -348,7 +344,7 @@ processing is deferred.
* * *
![](media/image48.png)
-*Figure 7.1 Completing interrupt processing in a high priority task*
+***Figure 7.1*** *Completing interrupt processing in a high priority task*
* * *
In Figure 7.1, interrupt processing starts at time t2, and effectively
@@ -412,7 +408,7 @@ task can be controlled using a semaphore.
* * *
![](media/image49.png)
-*Figure 7.2 Using a binary semaphore to implement deferred interrupt processing*
+***Figure 7.2*** *Using a binary semaphore to implement deferred interrupt processing*
* * *
The deferred processing task uses a blocking 'take' call to a semaphore
@@ -451,7 +447,7 @@ back—such as the scenarios described in Chapter 8, Resource Management.
* * *
![](media/image50.png)
-*Figure 7.3 Using a binary semaphore to synchronize a task with an interrupt*
+***Figure 7.3*** *Using a binary semaphore to synchronize a task with an interrupt*
* * *
@@ -473,13 +469,10 @@ this book.
-* * *
```c
SemaphoreHandle_t xSemaphoreCreateBinary( void );
```
-*Listing 7.3 The xSemaphoreCreateBinary() API function prototype*
-* * *
-
+***Listing 7.3*** *The xSemaphoreCreateBinary() API function prototype*
**xSemaphoreCreateBinary() Return Value**
@@ -507,12 +500,10 @@ can be 'taken' using the `xSemaphoreTake()` function.
-* * *
```c
BaseType_t xSemaphoreTake( SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait );
```
-*Listing 7.4 The xSemaphoreTake() API function prototype*
-* * *
+***Listing 7.4*** *The xSemaphoreTake() API function prototype*
**xSemaphoreTake() parameters and return value**
@@ -578,14 +569,11 @@ was described at the start of this chapter.
-* * *
```c
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 7.5 The xSemaphoreGiveFromISR() API function prototype*
-* * *
-
+***Listing 7.5*** *The xSemaphoreGiveFromISR() API function prototype*
**xSemaphoreGiveFromISR() parameters and return value**
@@ -629,8 +617,10 @@ BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,
+---
+***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.
@@ -646,7 +636,6 @@ observed in the output produced when the example is executed.
-* * *
```c
/* The number of the software interrupt used in this example. The code
shown is from the Windows project, where numbers 0 to 2 are used by the
@@ -678,8 +667,7 @@ static void vPeriodicTask( void *pvParameters )
}
}
```
-*Listing 7.6 Implementation of the task that periodically generates a software interrupt in Example 7.1*
-* * *
+***Listing 7.6*** *Implementation of the task that periodically generates a software interrupt in Example 7.1*
Listing 7.7 shows the implementation of the task to which the interrupt
@@ -699,7 +687,6 @@ generated interrupts.
-* * *
```c
static void vHandlerTask( void *pvParameters )
{
@@ -720,8 +707,7 @@ static void vHandlerTask( void *pvParameters )
}
}
```
-*Listing 7.7 The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 7.1*
-* * *
+***Listing 7.7*** *The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 7.1*
Listing 7.8 shows the ISR. This does very little other than 'give' the
@@ -749,7 +735,6 @@ explicitly.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
{
@@ -775,8 +760,7 @@ static uint32_t ulExampleInterruptHandler( void )
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
```
-*Listing 7.8 The ISR for the software interrupt used in Example 7.1*
-* * *
+***Listing 7.8*** *The ISR for the software interrupt used in Example 7.1*
The `main()` function creates the binary semaphore, creates the tasks,
installs the interrupt handler, and starts the scheduler. The
@@ -791,7 +775,6 @@ download, to find the syntax required for the port you are using.
-* * *
```c
int main( void )
{
@@ -830,8 +813,7 @@ int main( void )
for( ;; );
}
```
-*Listing 7.9 The implementation of main() for Example 7.1*
-* * *
+***Listing 7.9*** *The implementation of main() for Example 7.1*
Example 7.1 produces the output shown in Figure 7.4. As expected,
@@ -845,10 +827,10 @@ periodic task. Further explanation is provided in Figure 7.5.
* * *
![](media/image51.jpg)
-*Figure 7.4 The output produced when Example 7.1 is executed*
+***Figure 7.4*** *The output produced when Example 7.1 is executed*
![](media/image52.png)
-*Figure 7.5 The sequence of execution when Example 7.1 is executed*
+***Figure 7.5*** *The sequence of execution when Example 7.1 is executed*
* * *
@@ -890,10 +872,10 @@ interrupt:
* * *
![](media/image53.png)
-*Figure 7.6 The scenario when one interrupt occurs before the task has finished processing the first event*
+***Figure 7.6*** *The scenario when one interrupt occurs before the task has finished processing the first event*
![](media/image54.png)
-*Figure 7.7 The scenario when two interrupts occur before the task has finished processing the first event*
+***Figure 7.7*** *The scenario when two interrupts occur before the task has finished processing the first event*
* * *
The deferred interrupt handling task used in Example 7.1, and shown in
@@ -942,7 +924,6 @@ preventing the interrupt from being generated:
-* * *
```c
static void vUARTReceiveHandlerTask( void *pvParameters )
{
@@ -987,8 +968,7 @@ static void vUARTReceiveHandlerTask( void *pvParameters )
}
}
```
-*Listing 7.10 The recommended structure of a deferred interrupt processing task, using a UART receive handler as an example*
-* * *
+***Listing 7.10*** *The recommended structure of a deferred interrupt processing task, using a UART receive handler as an example*
## 7.5 Counting Semaphores
@@ -1041,7 +1021,7 @@ Counting semaphores are typically used for two things:
* * *
![](media/image55.png)
-*Figure 7.8 Using a counting semaphore to 'count' events*
+***Figure 7.8*** *Using a counting semaphore to 'count' events*
* * *
### 7.5.1 The xSemaphoreCreateCounting() API Function
@@ -1057,13 +1037,11 @@ semaphore, use the `xSemaphoreCreateCounting()` API function.
-* * *
```c
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,
UBaseType_t uxInitialCount );
```
-*Listing 7.11 The xSemaphoreCreateCounting() API function prototype*
-* * *
+***Listing 7.11*** *The xSemaphoreCreateCounting() API function prototype*
**xSemaphoreCreateCounting() parameters and return value**
@@ -1106,8 +1084,10 @@ SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount,
+---
+***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
@@ -1117,15 +1097,13 @@ a call to `xSemaphoreCreateCounting()` in place of the call to
-* * *
```c
/* Before a semaphore is used it must be explicitly created. In this example a
counting semaphore is created. The semaphore is created to have a maximum
count value of 10, and an initial count value of 0. */
xCountingSemaphore = xSemaphoreCreateCounting( 10, 0 );
```
-*Listing 7.12 The call to xSemaphoreCreateCounting() used to create the counting semaphore in Example 7.2*
-* * *
+***Listing 7.12*** *The call to xSemaphoreCreateCounting() used to create the counting semaphore in Example 7.2*
To simulate multiple events occurring at high frequency, the interrupt
@@ -1136,7 +1114,6 @@ modified interrupt service routine is shown in Listing 7.13.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
{
@@ -1168,8 +1145,7 @@ static uint32_t ulExampleInterruptHandler( void )
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
```
-*Listing 7.13 The implementation of the interrupt service routine used by Example 7.2*
-* * *
+***Listing 7.13*** *The implementation of the interrupt service routine used by Example 7.2*
All the other functions remain unmodified from those used in Example 7.1.
@@ -1184,7 +1160,7 @@ allowing the task to process them in turn.
* * *
![](media/image56.jpg)
-*Figure 7.9 The output produced when Example 7.2 is executed*
+***Figure 7.9*** *The output produced when Example 7.2 is executed*
* * *
@@ -1262,7 +1238,6 @@ tasks in the application.
-* * *
```c
BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t
xFunctionToPend,
@@ -1270,18 +1245,15 @@ BaseType_t xTimerPendFunctionCallFromISR( PendedFunction_t
uint32_t ulParameter2,
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 7.14 The xTimerPendFunctionCallFromISR() API function prototype*
-* * *
+***Listing 7.14*** *The xTimerPendFunctionCallFromISR() API function prototype*
-* * *
```c
void vPendableFunction( void *pvParameter1, uint32_t ulParameter2 );
```
-*Listing 7.15 The prototype to which a function passed in the xFunctionToPend parameter of xTimerPendFunctionCallFromISR() must conform*
-* * *
+***Listing 7.15*** *The prototype to which a function passed in the xFunctionToPend parameter of xTimerPendFunctionCallFromISR() must conform*
**xTimerPendFunctionCallFromISR() parameters and return value**
@@ -1339,8 +1311,10 @@ void vPendableFunction( void *pvParameter1, uint32_t ulParameter2 );
+---
+***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
@@ -1364,7 +1338,6 @@ used in this example.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
{
@@ -1398,8 +1371,7 @@ static uint32_t ulExampleInterruptHandler( void )
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
```
-*Listing 7.16 The software interrupt handler used in Example 7.3*
-* * *
+***Listing 7.16*** *The software interrupt handler used in Example 7.3*
The implementation of `vDeferredHandlingFunction()` is shown in Listing
@@ -1413,7 +1385,6 @@ actually used.
-* * *
```c
static void vDeferredHandlingFunction( void *pvParameter1, uint32_t ulParameter2 )
{
@@ -1422,8 +1393,7 @@ static void vDeferredHandlingFunction( void *pvParameter1, uint32_t ulParameter2
vPrintStringAndNumber( "Handler function - Processing event ", ulParameter2 );
}
```
-*Listing 7.17 The function that performs the processing necessitated by the interrupt in Example 7.3*
-* * *
+***Listing 7.17*** *The function that performs the processing necessitated by the interrupt in Example 7.3*
The `main()` function used by Example 7.3 is shown in Listing 7.18. It is
@@ -1439,7 +1409,6 @@ daemon task leaves the Blocked state.
-* * *
```c
int main( void )
{
@@ -1466,8 +1435,7 @@ int main( void )
for( ;; );
}
```
-*Listing 7.18 The implementation of main() for Example 7.3*
-* * *
+***Listing 7.18*** *The implementation of main() for Example 7.3*
Example 7.3 produces the output shown in Figure 7.10. The priority of the
@@ -1485,10 +1453,10 @@ task. Further explanation is provided in Figure 7.11.
* * *
![](media/image57.jpg)
-*Figure 7.10 The output produced when Example 7.3 is executed*
+***Figure 7.10*** *The output produced when Example 7.3 is executed*
![](media/image58.png)
-*Figure 7.11 The sequence of execution when Example 7.3 is executed*
+***Figure 7.11*** *The sequence of execution when Example 7.3 is executed*
* * *
@@ -1509,26 +1477,22 @@ service routine, and `xQueueReceiveFromISR()` is the version of
-* * *
```c
BaseType_t xQueueSendToFrontFromISR( QueueHandle_t xQueue,
const void *pvItemToQueue
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 7.19 The xQueueSendToFrontFromISR() API function prototype*
-* * *
+***Listing 7.19*** *The xQueueSendToFrontFromISR() API function prototype*
-* * *
```c
BaseType_t xQueueSendToBackFromISR( QueueHandle_t xQueue,
const void *pvItemToQueue
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 7.20 The xQueueSendToBackFromISR() API function prototype*
-* * *
+***Listing 7.20*** *The xQueueSendToBackFromISR() API function prototype*
`xQueueSendFromISR()` and `xQueueSendToBackFromISR()` are functionally equivalent.
@@ -1620,8 +1584,10 @@ that are suitable for production code, include:
Figure 5.4.
+---
+***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,
@@ -1634,7 +1600,6 @@ values have been sent. The task implementation is shown in Listing 7.21.
-* * *
```c
static void vIntegerGenerator( void *pvParameters )
{
@@ -1673,8 +1638,7 @@ static void vIntegerGenerator( void *pvParameters )
}
}
```
-*Listing 7.21 The implementation of the task that writes to the queue in Example 7.4*
-* * *
+***Listing 7.21*** *The implementation of the task that writes to the queue in Example 7.4*
The interrupt service routine calls `xQueueReceiveFromISR()` repeatedly
@@ -1688,7 +1652,6 @@ of the interrupt service routine is shown in Listing 7.22.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
{
@@ -1753,8 +1716,7 @@ static uint32_t ulExampleInterruptHandler( void )
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
```
-*Listing 7.22 The implementation of the interrupt service routine used by Example 7.4*
-* * *
+***Listing 7.22*** *The implementation of the interrupt service routine used by Example 7.4*
The task that receives the character pointers from the interrupt service
@@ -1764,7 +1726,6 @@ string as it is received. Its implementation is shown in Listing 7.23.
-* * *
```c
static void vStringPrinter( void *pvParameters )
{
@@ -1780,9 +1741,7 @@ static void vStringPrinter( void *pvParameters )
}
}
```
-*Listing 7.23 The task that prints out the strings received from the interrupt service routine in Example 7.4*
-* * *
-
+***Listing 7.23*** *The task that prints out the strings received from the interrupt service routine in Example 7.4*
As normal, `main()` creates the required queues and tasks before starting
the scheduler. Its implementation is shown in Listing 7.24.
@@ -1790,7 +1749,6 @@ the scheduler. Its implementation is shown in Listing 7.24.
-* * *
```c
int main( void )
{
@@ -1828,9 +1786,7 @@ int main( void )
for( ;; );
}
```
-*Listing 7.24 The main() function for Example 7.4*
-* * *
-
+***Listing 7.24*** *The main() function for Example 7.4*
The output produced when Example 7.4 is executed is shown in Figure 7.12.
As can be seen, the interrupt receives all five integers, and produces
@@ -1842,10 +1798,10 @@ five strings in response. More explanation is given in Figure 7.13.
* * *
![](media/image59.jpg)
-*Figure 7.12 The output produced when Example 7.4 is executed*
+***Figure 7.12*** *The output produced when Example 7.4 is executed*
![](media/image60.png)
-*Figure 7.13 The sequence of execution produced by Example 7.4*
+***Figure 7.13*** *The sequence of execution produced by Example 7.4*
* * *
@@ -1930,7 +1886,7 @@ Figure 7.14, which shows a scenario where:
* * *
![](media/image61.png)
-*Figure 7.14 Constants affecting interrupt nesting behavior*
+***Figure 7.14*** *Constants affecting interrupt nesting behavior*
* * *
Referring to Figure 7.14:
@@ -1988,7 +1944,7 @@ Cortex-M microcontroller that implements four priority bits.
* * *
![](media/image62.png)
-*Figure 7.15 How a priority of binary 101 is stored by a Cortex-M microcontroller that implements four priority bits*
+***Figure 7.15*** *How a priority of binary 101 is stored by a Cortex-M microcontroller that implements four priority bits*
* * *
In Figure 7.15 the binary value 101 has been shifted into the most
diff --git a/ch08.md b/ch08.md
index 9f61c3d..e79a996 100644
--- a/ch08.md
+++ b/ch08.md
@@ -19,13 +19,13 @@ Following are some examples:
1. Task A executes and starts to write the string "Hello world" to the
LCD.
- 1. Task A is pre-empted by Task B after outputting just the beginning
+ 2. Task A is pre-empted by Task B after outputting just the beginning
of the string—"Hello w".
- 1. Task B writes "Abort, Retry, Fail?" to the LCD before entering the
+ 3. Task B writes "Abort, Retry, Fail?" to the LCD before entering the
Blocked state.
- 1. Task A continues from the point at which it was pre-empted, and
+ 4. Task A continues from the point at which it was pre-empted, and
completes outputting the remaining characters of its string—"orld".
The LCD now displays the corrupted string "Hello wAbort, Retry, Fail?orld".
@@ -41,7 +41,6 @@ Following are some examples:
- * * *
```c
/* The C code being compiled. */
PORTA |= 0x01;
@@ -52,8 +51,7 @@ Following are some examples:
OR R1,R2 ; Bitwise OR R1 (PORTA) with R2 (constant 1)
STORE R1,[#PORTA] ; Store the new value back to PORTA
```
- *Listing 8.1 An example read, modify, write sequence*
- * * *
+ ***Listing 8.1*** *An example read, modify, write sequence*
This is a 'non-atomic' operation because it takes more than one
instruction to complete, and can be interrupted. Consider the following
@@ -63,12 +61,12 @@ Following are some examples:
1. Task A loads the value of PORTA into a register—the read portion of
the operation.
- 1. Task A is pre-empted by Task B before it completes the modify and
+ 2. Task A is pre-empted by Task B before it completes the modify and
write portions of the same operation.
- 1. Task B updates the value of PORTA, then enters the Blocked state.
+ 3. Task B updates the value of PORTA, then enters the Blocked state.
- 1. Task A continues from the point at which it was pre-empted. It
+ 4. Task A continues from the point at which it was pre-empted. It
modifies the copy of the PORTA value that it already holds in a
register, before writing the updated value back to PORTA.
@@ -122,7 +120,8 @@ Following are some examples:
- `configDEINIT_TLS_BLOCK` - Free the TLS block.
- \n * * *
+
+
```c
/* A parameter is passed into the function. This will either be passed on the
stack, or in a processor register. Either way is safe as each task or
@@ -140,13 +139,11 @@ Following are some examples:
return lVar2;
}
```
- *Listing 8.2 An example of a reentrant function*
- * * *
+ ***Listing 8.2*** *An example of a reentrant function*
- * * *
```c
/* In this case lVar1 is a global variable, so every task that calls
lNonsenseFunction will access the same single copy of the variable. */
@@ -171,8 +168,7 @@ Following are some examples:
}
}
```
- *Listing 8.3 An example of a function that is not reentrant*
- * * *
+ ***Listing 8.3*** *An example of a function that is not reentrant*
### 8.1.1 Mutual Exclusion
@@ -224,7 +220,6 @@ as if it were a function.
-* * *
```c
/* Ensure access to the PORTA register cannot be interrupted by placing
it within a critical section. Enter the critical section. */
@@ -241,8 +236,7 @@ PORTA |= 0x01;
/* Access to PORTA has finished, so it is safe to exit the critical section. */
taskEXIT_CRITICAL();
```
-*Listing 8.4 Using a critical section to guard access to a register*
-* * *
+***Listing 8.4*** *Using a critical section to guard access to a register*
The example projects that accompany this book use a function called
@@ -255,7 +249,6 @@ Listing 8.5.
-* * *
```c
void vPrintString( const char *pcString )
{
@@ -269,8 +262,7 @@ void vPrintString( const char *pcString )
taskEXIT_CRITICAL();
}
```
-*Listing 8.5 A possible implementation of vPrintString()*
-* * *
+***Listing 8.5*** *A possible implementation of vPrintString()*
Critical sections implemented in this way are a very crude method of
@@ -317,7 +309,6 @@ in Listing 8.6.
-* * *
```c
void vAnInterruptServiceRoutine( void )
{
@@ -347,8 +338,7 @@ void vAnInterruptServiceRoutine( void )
interrupt. */
}
```
-*Listing 8.6 Using a critical section in an interrupt service routine*
-* * *
+***Listing 8.6*** *Using a critical section in an interrupt service routine*
It is wasteful to use more processing time executing the code that
@@ -383,12 +373,10 @@ use in each case.
-* * *
```c
void vTaskSuspendAll( void );
```
-*Listing 8.7 The vTaskSuspendAll() API function prototype*
-* * *
+***Listing 8.7*** *The vTaskSuspendAll() API function prototype*
The scheduler is suspended by calling `vTaskSuspendAll()`. Suspending the
@@ -405,12 +393,10 @@ FreeRTOS API functions must not be called while the scheduler is suspended.
-* * *
```c
BaseType_t xTaskResumeAll( void );
```
-*Listing 8.8 The xTaskResumeAll() API function prototype*
-* * *
+***Listing 8.8*** *The xTaskResumeAll() API function prototype*
The scheduler is resumed (un-suspended) by calling `xTaskResumeAll()`.
@@ -435,7 +421,6 @@ suspends the scheduler to protect access to the terminal output.
-* * *
```c
void vPrintString( const char *pcString )
{
@@ -449,8 +434,7 @@ void vPrintString( const char *pcString )
xTaskResumeScheduler();
}
```
-*Listing 8.9 The implementation of vPrintString()*
-* * *
+***Listing 8.9*** *The implementation of vPrintString()*
## 8.3 Mutexes (and Binary Semaphores)
@@ -486,7 +470,7 @@ what happens to the semaphore after it has been obtained:
* * *
![](media/image63.png)
-*Figure 8.1 Mutual exclusion implemented using a mutex*
+***Figure 8.1*** *Mutual exclusion implemented using a mutex*
* * *
The mechanism works purely through the discipline of the application
@@ -509,12 +493,10 @@ semaphore, use the `xSemaphoreCreateMutex()` API function.
-* * *
```c
SemaphoreHandle_t xSemaphoreCreateMutex( void );
```
-*Listing 8.10 The xSemaphoreCreateMutex() API function prototype*
-* * *
+***Listing 8.10*** *The xSemaphoreCreateMutex() API function prototype*
**xSemaphoreCreateMutex() return value**
@@ -532,8 +514,10 @@ SemaphoreHandle_t xSemaphoreCreateMutex( void );
+---
+***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.
@@ -545,7 +529,6 @@ Listing 8.11.
-* * *
```c
static void prvNewPrintString( const char *pcString )
{
@@ -573,8 +556,7 @@ static void prvNewPrintString( const char *pcString )
xSemaphoreGive( xMutex );
}
```
-*Listing 8.11 The implementation of prvNewPrintString()*
-* * *
+***Listing 8.11*** *The implementation of prvNewPrintString()*
`prvNewPrintString()` is called repeatedly by two instances of a task
@@ -586,7 +568,6 @@ Listing 8.12.
-* * *
```c
static void prvPrintTask( void *pvParameters )
{
@@ -612,8 +593,7 @@ static void prvPrintTask( void *pvParameters )
}
}
```
-*Listing 8.12 The implementation of prvPrintTask() for Example 8.1*
-* * *
+***Listing 8.12*** *The implementation of prvPrintTask() for Example 8.1*
As normal, `main()` simply creates the mutex, creates the tasks, then
@@ -640,7 +620,6 @@ Notes specific to using Example 8.1 with the FreeRTOS Windows port:
-* * *
```c
int main( void )
{
@@ -676,8 +655,7 @@ int main( void )
for( ;; );
}
```
-*Listing 8.13 The implementation of main() for Example 8.1*
-* * *
+***Listing 8.13*** *The implementation of main() for Example 8.1*
The output produced when Example 8.1 is executed is shown in Figure 8.2. A
@@ -687,7 +665,7 @@ possible execution sequence is described in Figure 8.3.
* * *
![](media/image64.jpg)
-*Figure 8.2 The output produced when Example 8.1 is executed*
+***Figure 8.2*** *The output produced when Example 8.1 is executed*
* * *
Figure 8.2 shows that, as expected, there is no corruption in the strings
@@ -699,7 +677,7 @@ the random delay periods used by the tasks.
* * *
![](media/image65.png)
-*Figure 8.3 A possible sequence of execution for Example 8.1*
+***Figure 8.3*** *A possible sequence of execution for Example 8.1*
* * *
@@ -721,7 +699,7 @@ This worst case scenario is shown in Figure 8.4.
* * *
![](media/image66.png)
-*Figure 8.4 A worst case priority inversion scenario*
+***Figure 8.4*** *A worst case priority inversion scenario*
* * *
Priority inversion can be a significant problem, but in small embedded
@@ -752,7 +730,7 @@ reset automatically to its original value when it gives the mutex back.
* * *
![](media/image67.png)
-*Figure 8.5 Priority inheritance minimizing the effect of priority inversion*
+***Figure 8.5*** *Priority inheritance minimizing the effect of priority inversion*
* * *
As just seen, priority inheritance functionality effects the priority of
@@ -773,14 +751,14 @@ mutex Y in order to perform an action:
1. Task A executes and successfully takes mutex X.
-1. Task A is pre-empted by Task B.
+2. Task A is pre-empted by Task B.
-1. Task B successfully takes mutex Y before attempting to also take
+3. Task B successfully takes mutex Y before attempting to also take
mutex X—but mutex X is held by Task A so is not available to Task B.
Task B opts to enter the Blocked state to wait for mutex X to be
released.
-1. Task A continues executing. It attempts to take mutex Y—but mutex Y
+4. Task A continues executing. It attempts to take mutex Y—but mutex Y
is held by Task B, so is not available to Task A. Task A opts to
enter the Blocked state to wait for mutex Y to be released.
@@ -811,9 +789,9 @@ returning the mutex. Consider the following scenario:
1. A task successfully obtains a mutex.
-1. While holding the mutex, the task calls a library function.
+2. While holding the mutex, the task calls a library function.
-1. The implementation of the library function attempts to take the same
+3. The implementation of the library function attempts to take the same
mutex, and enters the Blocked state to wait for the mutex to become
available.
@@ -849,7 +827,6 @@ Listing 8.14 demonstrates how to create and use a recursive mutex.
-* * *
```c
/* Recursive mutexes are variables of type SemaphoreHandle_t. */
SemaphoreHandle_t xRecursiveMutex;
@@ -910,8 +887,7 @@ void vTaskFunction( void *pvParameters )
}
}
```
-*Listing 8.14 Creating and using a recursive mutex*
-* * *
+***Listing 8.14*** *Creating and using a recursive mutex*
### 8.3.6 Mutexes and Task Scheduling
@@ -941,7 +917,7 @@ occurs.
* * *
![](media/image68.png)
-*Figure 8.6 A possible sequence of execution when tasks that have the same priority use the same mutex*
+***Figure 8.6*** *A possible sequence of execution when tasks that have the same priority use the same mutex*
* * *
In the scenario shown in Figure 8.6, the FreeRTOS scheduler does *not*
@@ -970,7 +946,6 @@ execution that could occur if two instances of the task shown by Listing
-* * *
```c
/* The implementation of a task that uses a mutex in a tight loop. The task
creates a text string in a local buffer, then writes the string to a display.
@@ -997,8 +972,7 @@ void vATask( void *pvParameter )
}
}
```
-*Listing 8.15 A task that uses a mutex in a tight loop*
-* * *
+***Listing 8.15*** *A task that uses a mutex in a tight loop*
The comments in Listing 8.15 note that creating the string is a fast
@@ -1014,7 +988,7 @@ interrupt occurs.
* * *
![](media/image69.png)
-*Figure 8.7 A sequence of execution that could occur if two instances of the task shown by Listing 8.15 are created at the same priority*
+***Figure 8.7*** *A sequence of execution that could occur if two instances of the task shown by Listing 8.15 are created at the same priority*
* * *
Step 7 in Figure 8.7 shows Task 1 re-entering the Blocked state—that
@@ -1032,7 +1006,6 @@ the task held the mutex.
-* * *
```c
void vFunction( void *pvParameter )
{
@@ -1069,8 +1042,7 @@ void vFunction( void *pvParameter )
}
}
```
-*Listing 8.16 Ensuring tasks that use a mutex in a loop receive a more equal amount of processing time, while also ensuring processing time is not wasted by switching between tasks too rapidly*
-* * *
+***Listing 8.16*** *Ensuring tasks that use a mutex in a loop receive a more equal amount of processing time, while also ensuring processing time is not wasted by switching between tasks too rapidly*
## 8.4 Gatekeeper Tasks
@@ -1113,18 +1085,16 @@ kernel during each tick interrupt. To use a tick hook function:
1. Set `configUSE_TICK_HOOK` to 1 in FreeRTOSConfig.h.
-1. Provide the implementation of the hook function, using the exact
+2. Provide the implementation of the hook function, using the exact
function name and prototype shown in Listing 8.17.
-* * *
```c
void vApplicationTickHook( void );
```
-*Listing 8.17 The name and prototype for a tick hook function*
-* * *
+***Listing 8.17*** *The name and prototype for a tick hook function*
Tick hook functions execute within the context of the tick interrupt,
@@ -1140,7 +1110,6 @@ that parameter can be set to NULL.
-* * *
```c
static void prvStdioGatekeeperTask( void *pvParameters )
{
@@ -1167,18 +1136,22 @@ static void prvStdioGatekeeperTask( void *pvParameters )
}
}
```
-*Listing 8.18 The gatekeeper task*
-* * *
+***Listing 8.18*** *The gatekeeper task*
+
+
+---
+***Example 8.2*** *The alternative implementation for print task*
+
+---
The task that writes to the queue is shown in Listing 8.19. As before,
two separate instances of the task are created, and the string the task
writes to the queue is passed into the task using the task parameter.
+
-
-* * *
```c
static void prvPrintTask( void *pvParameters )
{
@@ -1208,8 +1181,8 @@ static void prvPrintTask( void *pvParameters )
}
}
```
-*Listing 8.19 The print task implementation for Example 8.2*
-* * *
+
+***Listing 8.19*** *The print task implementation for Example 8.2*
The tick hook function counts the number of times it is called, sending
@@ -1221,7 +1194,6 @@ implementation is shown in Listing 8.20.
-* * *
```c
void vApplicationTickHook( void )
{
@@ -1246,18 +1218,13 @@ void vApplicationTickHook( void )
}
}
```
-*Listing 8.20 The tick hook implementation*
-* * *
+***Listing 8.20*** *The tick hook implementation*
As normal, `main()` creates the queues and tasks necessary to run the
example, then starts the scheduler. The implementation of `main()` is
shown in Listing 8.21.
-
-
-
-* * *
```c
/* Define the strings that the tasks and interrupt will print out via the
gatekeeper. */
@@ -1309,8 +1276,9 @@ int main( void )
for( ;; );
}
```
-*Listing 8.21 The implementation of main() for Example 8.2*
-* * *
+
+
+***Listing 8.21*** *The implementation of main() for Example 8.2*
The output produced when Example 8.2 is executed is shown in Figure 8.8.
@@ -1323,7 +1291,7 @@ corruption.
* * *
![](media/image70.jpg)
-*Figure 8.8 The output produced when Example 8.2 is executed*
+***Figure 8.8*** *The output produced when Example 8.2 is executed*
* * *
The gatekeeper task is assigned a lower priority than the print tasks—so
diff --git a/ch09.md b/ch09.md
index 982bfb0..9f00719 100644
--- a/ch09.md
+++ b/ch09.md
@@ -77,7 +77,7 @@ in a variable of type `EventBits_t`.
* * *
![](media/image71.png)
-*Figure 9.1 Event flag to bit number mapping in a variable of type EventBits\_t*
+***Figure 9.1*** *Event flag to bit number mapping in a variable of type EventBits\_t*
* * *
As an example, if the value of an event group is 0x92 (binary 1001 0010)
@@ -91,7 +91,7 @@ bits clear, giving the event group a value of 0x92.
* * *
![](media/image72.png)
-*Figure 9.2 An event group in which only bits 1, 4 and 7 are set, and all the other event flags are clear, making the event group's value 0x92*
+***Figure 9.2*** *An event group in which only bits 1, 4 and 7 are set, and all the other event flags are clear, making the event group's value 0x92*
* * *
It is up to the application writer to assign a meaning to individual
@@ -182,12 +182,10 @@ creates.
-* * *
```c
EventGroupHandle_t xEventGroupCreate( void );
```
-*Listing 9.1 The xEventGroupCreate() API function prototype*
-* * *
+***Listing 9.1*** *The xEventGroupCreate() API function prototype*
**xEventGroupCreate() return value**
@@ -217,14 +215,12 @@ represented by the bit, or bits, being set has occurred.
-* * *
```c
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet );
```
-*Listing 9.2. The xEventGroupSetBits() API function prototype*
-* * *
+***Listing 9.2*** *The xEventGroupSetBits() API function prototype*
**xEventGroupSetBits() parameters and return value**
@@ -276,14 +272,12 @@ daemon task.
-* * *
```c
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 9.3 The xEventGroupSetBitsFromISR() API function prototype*
-* * *
+***Listing 9.3*** *The xEventGroupSetBitsFromISR() API function prototype*
**xEventGroupSetBitsFromISR() parameters and return value**
@@ -346,7 +340,6 @@ not already set.
-* * *
```c
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
@@ -354,8 +347,7 @@ EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait );
```
-*Listing 9.4 The xEventGroupWaitBits() API function prototype*
-* * *
+***Listing 9.4*** *The xEventGroupWaitBits() API function prototype*
The condition used by the scheduler to determine if a task will enter
the Blocked state, and when a task will leave the Blocked state, is
@@ -388,7 +380,7 @@ assumed to be zero.
| 0100 | 0110 | pdFALSE | The calling task will not enter the Blocked state because xWaitForAllBits is pdFALSE, and one of the two bits specified by uxBitsToWaitFor is already set in the event group. |
| 0100 | 0110 | pdTRUE | The calling task will enter the Blocked state because xWaitForAllBits is pdTRUE, and only one of the two bits specified by uxBitsToWaitFor is already set in the event group. The task will leave the Blocked state when both bit 1 and bit 2 are set in the event group. |
-*Table 5 The Effect of the uxBitsToWaitFor and xWaitForAllBits Parameters*
+***Table 5*** *The Effect of the uxBitsToWaitFor and xWaitForAllBits Parameters*
* * *
The calling task specifies bits to test using the `uxBitsToWaitFor`
@@ -500,14 +492,12 @@ routine.
-* * *
```c
BaseType_t xEventGroupGetStaticBuffer( EventGroupHandle_t xEventGroup,
StaticEventGroup_t ** ppxEventGroupBuffer );
```
-*Listing 9.5 The xEventGroupGetStaticBuffer() API function prototype*
-* * *
+***Listing 9.5*** *The xEventGroupGetStaticBuffer() API function prototype*
**xEventGroupGetStaticBuffer() parameters and return value**
@@ -531,8 +521,10 @@ StaticEventGroup_t ** ppxEventGroupBuffer );
- `pdFALSE` will be returned if the buffer was not successfully retrieved.
+---
+***Example 9.1*** *Experimenting with event groups*
-Example 9.1 Experimenting with event groups
+---
This example demonstrates how to:
@@ -553,15 +545,13 @@ names using the \#define statements shown in Listing 9.6.
-* * *
```c
/* Definitions for the event bits in the event group. */
#define mainFIRST_TASK_BIT ( 1UL << 0UL ) /* Event bit 0, set by a task */
#define mainSECOND_TASK_BIT ( 1UL << 1UL ) /* Event bit 1, set by a task */
#define mainISR_BIT ( 1UL << 2UL ) /* Event bit 2, set by an ISR */
```
-*Listing 9.6 Event bit definitions used in Example 9.1*
-* * *
+***Listing 9.6*** *Event bit definitions used in Example 9.1*
Listing 9.7 shows the implementation of the task that sets event bit 0
@@ -573,7 +563,6 @@ allow the sequence of execution to be seen in the console.
-* * *
```c
static void vEventBitSettingTask( void *pvParameters )
{
@@ -599,8 +588,7 @@ static void vEventBitSettingTask( void *pvParameters )
}
}
```
-*Listing 9.7 The task that sets two bits in the event group in Example 9.1*
-* * *
+***Listing 9.7*** *The task that sets two bits in the event group in Example 9.1*
Listing 9.8 shows the implementation of the interrupt service routine
@@ -618,7 +606,6 @@ the interrupt is generated every 500 milliseconds.
-* * *
```c
static uint32_t ulEventBitSettingISR( void )
{
@@ -665,8 +652,7 @@ static uint32_t ulEventBitSettingISR( void )
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
```
-*Listing 9.8 The ISR that sets bit 2 in the event group in Example 9.1*
-* * *
+***Listing 9.8*** *The ISR that sets bit 2 in the event group in Example 9.1*
Listing 9.9 shows the implementation of the task that calls
@@ -681,7 +667,6 @@ returns.
-* * *
```c
static void vEventBitReadingTask( void *pvParameters )
{
@@ -730,8 +715,7 @@ static void vEventBitReadingTask( void *pvParameters )
}
}
```
-*Listing 9.9 The task that blocks to wait for event bits to become set in Example 9.1*
-* * *
+***Listing 9.9*** *The task that blocks to wait for event bits to become set in Example 9.1*
The `main()` function creates the event group, and the tasks, before
@@ -744,7 +728,6 @@ unblock condition is met.
-* * *
```c
int main( void )
{
@@ -776,8 +759,7 @@ int main( void )
return 0;
}
```
-*Listing 9.10 Creating the event group and tasks in Example 9.1*
-* * *
+***Listing 9.10*** *Creating the event group and tasks in Example 9.1*
The output produced when Example 9.1 is executed with the
@@ -792,7 +774,7 @@ state and executes immediately every time any of the event bits are set.
* * *
![](media/image73.jpg)
-*Figure 9.3 The output produced when Example 9.1 is executed with xWaitForAllBits set to pdFALSE*
+***Figure 9.3*** *The output produced when Example 9.1 is executed with xWaitForAllBits set to pdFALSE*
* * *
The output produced when Example 9.1 is executed with the
@@ -807,7 +789,7 @@ event bits are set.
* * *
![](media/image74.jpg)
-*Figure 9.4 The output produced when Example 9.1 is executed with xWaitForAllBits set to pdTRUE*
+***Figure 9.4*** *The output produced when Example 9.1 is executed with xWaitForAllBits set to pdTRUE*
* * *
@@ -849,7 +831,6 @@ that was dependent on the socket being open.
-* * *
```c
void SocketTxTask( void *pvParameters )
{
@@ -923,8 +904,7 @@ void SocketRxTask( void *pvParameters )
}
}
```
-*Listing 9.11 Pseudo code for two tasks that synchronize with each other to ensure a shared TCP socket is no longer in use by either task before the socket is closed*
-* * *
+***Listing 9.11*** *Pseudo code for two tasks that synchronize with each other to ensure a shared TCP socket is no longer in use by either task before the socket is closed*
An event group can be used to create a synchronization point:
@@ -952,12 +932,12 @@ event group:
their event bits are set in the event group, and they are in the
Blocked state to wait for task C's event bit to also become set.
-1. Task C reaches the synchronization point, and uses
+2. Task C reaches the synchronization point, and uses
`xEventGroupSetBits()` to set its bit in the event group. As soon as
Task C's bit is set, Task A and Task B leave the Blocked state, and
clear all three event bits.
-1. Task C then calls `xEventGroupWaitBits()` to wait for all three event
+3. Task C then calls `xEventGroupWaitBits()` to wait for all three event
bits to become set, but by that time, all three event bits have
already been cleared, Task A and Task B have left their respective
synchronization points, and so the synchronization has failed.
@@ -984,15 +964,13 @@ will be cleared back to zero before `xEventGroupSync()` returns, if
-* * *
```c
EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet,
const EventBits_t uxBitsToWaitFor,
TickType_t xTicksToWait );
```
-*Listing 9.12 The xEventGroupSync() API function prototype*
-* * *
+***Listing 9.12*** *The xEventGroupSync() API function prototype*
**xEventGroupSync() parameters and return value**
@@ -1057,8 +1035,10 @@ EventBits_t xEventGroupSync( EventGroupHandle_t xEventGroup,
+---
+***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
@@ -1076,7 +1056,6 @@ See Listing 9.12 for the task's implementation.
-* * *
```c
static void vSyncingTask( void *pvParameters )
{
@@ -1133,8 +1112,7 @@ static void vSyncingTask( void *pvParameters )
}
}
```
-*Listing 9.13 The implementation of the task used in Example 9.2*
-* * *
+***Listing 9.13*** *The implementation of the task used in Example 9.2*
The `main()` function creates the event group, creates all three tasks,
and then starts the scheduler. See Listing 9.14 for its implementation.
@@ -1142,7 +1120,6 @@ and then starts the scheduler. See Listing 9.14 for its implementation.
-* * *
```c
/* Definitions for the event bits in the event group. */
@@ -1174,8 +1151,7 @@ int main( void )
return 0;
}
```
-*Listing 9.14 The main() function used in Example 9.2*
-* * *
+***Listing 9.14*** *The main() function used in Example 9.2*
The output produced when Example 9.2 is executed is shown in Figure 9.5.
It can be seen that, even though each task reaches the synchronization
@@ -1193,6 +1169,6 @@ therefore show some timing variation.
* * *
![](media/image75.jpg)
-*Figure 9.5 The output produced when Example 9.2 is executed*
+***Figure 9.5*** *The output produced when Example 9.2 is executed*
* * *
diff --git a/ch10.md b/ch10.md
index 515cb34..2514691 100644
--- a/ch10.md
+++ b/ch10.md
@@ -23,7 +23,7 @@ or ISR that sent the event or data. This is depicted in Figure 10.1.
* * *
![](media/image76.png)
-*Figure 10.1 A communication object being used to send an event from one task to another*
+***Figure 10.1*** *A communication object being used to send an event from one task to another*
* * *
### 10.1.2 Task Notifications—Direct to Task Communication
@@ -38,7 +38,7 @@ directly to the receiving task. This is depicted in Figure 10.2.
* * *
![](media/image77.png)
-*Figure 10.2 A task notification used to send an event directly from one task to another*
+***Figure 10.2*** *A task notification used to send an event directly from one task to another*
* * *
Task notification functionality is optional. To include task
@@ -220,15 +220,13 @@ binary or counting semaphore.
-* * *
```c
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
```
-*Listing 10.1 The xTaskNotifyGive() API function prototype*
-* * *
+***Listing 10.1*** *The xTaskNotifyGive() API function prototype*
**xTaskNotifyGive()/xTaskNotifyGiveIndexed() parameters and return value**
@@ -257,16 +255,13 @@ used in an interrupt service routine.
-* * *
```c
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
BaseType_t *pxHigherPriorityTaskWoken );
```
-* * *
-*Listing 10.2 The vTaskNotifyGiveFromISR() API function prototype*
-* * *
+***Listing 10.2*** *The vTaskNotifyGiveFromISR() API function prototype*
**vTaskNotifyGiveFromISR() parameters and return value**
@@ -310,16 +305,13 @@ binary or counting semaphore.
-* * *
```c
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t
xTicksToWait );
```
-* * *
-*Listing 10.3 The ulTaskNotifyTake() API function prototype*
-* * *
+***Listing 10.3*** *The ulTaskNotifyTake() API function prototype*
**ulTaskNotifyTake() parameters and return value**
@@ -368,8 +360,10 @@ xTicksToWait );
+---
+***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
@@ -397,7 +391,6 @@ has notifications pending.
-* * *
```c
/* The rate at which the periodic task generates software interrupts. */
@@ -438,8 +431,7 @@ static void vHandlerTask( void *pvParameters )
}
```
-*Listing 10.4 The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 10.1*
-* * *
+***Listing 10.4*** *The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 10.1*
The periodic task used to generate software interrupts prints a message
before the interrupt is generated, and again after the interrupt has
@@ -453,7 +445,6 @@ handling is deferred.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
@@ -487,8 +478,7 @@ static uint32_t ulExampleInterruptHandler( void )
}
```
-*Listing 10.5 The implementation of the interrupt service routine used in Example 10.1*
-* * *
+***Listing 10.5*** *The implementation of the interrupt service routine used in Example 10.1*
The output produced when Example 10.1 is executed is shown in Figure 10.3.
As expected, it is identical to that produced when Example 7.1 is
@@ -502,15 +492,17 @@ produced by the periodic task. Further explanation is provided in Figure 10.4.
* * *
![](media/image78.png)
-*Figure 10.3 The output produced when Example 7.1 is executed*
+***Figure 10.3*** *The output produced when Example 7.1 is executed*
![](media/image79.png)
-*Figure 10.4 The sequence of execution when Example 10.1 is executed*
+***Figure 10.4*** *The sequence of execution when Example 10.1 is executed*
* * *
+---
+***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
@@ -537,7 +529,6 @@ Listing 10.6.
-* * *
```c
static void vHandlerTask( void *pvParameters )
@@ -570,8 +561,7 @@ static void vHandlerTask( void *pvParameters )
}
```
-*Listing 10.6 The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 102*
-* * *
+***Listing 10.6*** *The implementation of the task to which the interrupt processing is deferred (the task that synchronizes with the interrupt) in Example 102*
For demonstration purposes, the interrupt service routine has also been
modified to send more than one task notification per interrupt, and in
@@ -582,7 +572,6 @@ shown in Listing 10.7.
-* * *
```c
static uint32_t ulExampleInterruptHandler( void )
@@ -603,9 +592,7 @@ static uint32_t ulExampleInterruptHandler( void )
}
```
-* * *
-*Listing 10.7 The implementation of the interrupt service routine used in Example 10.2*
-* * *
+***Listing 10.7*** *The implementation of the interrupt service routine used in Example 10.2*
The output produced when Example 10.2 is executed is shown in Figure 10.5.
As can be seen, `vHandlerTask()` processes all three events each time an
@@ -616,7 +603,7 @@ interrupt is generated.
* * *
![](media/image80.jpg)
-*Figure 10.5 The output produced when Example 10.2 is executed*
+***Figure 10.5*** *The output produced when Example 10.2 is executed*
* * *
### 10.3.5 The xTaskNotify() and xTaskNotifyFromISR() API Functions
@@ -659,7 +646,6 @@ state to pending, if it was not already pending.
-* * *
```c
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify,
@@ -672,8 +658,7 @@ BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify,
BaseType_t *pxHigherPriorityTaskWoken );
```
-*Listing 10.8 Prototypes for the xTaskNotify() and xTaskNotifyFromISR() API functions*
-* * *
+***Listing 10.8*** *Prototypes for the xTaskNotify() and xTaskNotifyFromISR() API functions*
**xTaskNotify() parameters and return value**
@@ -757,7 +742,6 @@ from the function.
-* * *
```c
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
@@ -766,8 +750,7 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
TickType_t xTicksToWait );
```
-*Listing 10.9 The xTaskNotifyWait() API function prototype*
-* * *
+***Listing 10.9*** *The xTaskNotifyWait() API function prototype*
**xTaskNotifyWait() parameters and return value**
@@ -908,7 +891,6 @@ port. In Listing 10.10:
-* * *
```c
/* Driver library function to send data to a UART. */
@@ -958,8 +940,7 @@ void xUART_TransmitEndISR( xUART *pxUARTInstance )
}
```
-*Listing 10.10 Pseudo code demonstrating how a binary semaphore can be used in a driver library transmit function*
-* * *
+***Listing 10.10*** *Pseudo code demonstrating how a binary semaphore can be used in a driver library transmit function*
The technique demonstrated in Listing 10.10 is perfectly workable, and
indeed common practice, but it has some drawbacks:
@@ -1030,7 +1011,6 @@ pointer, so `sizeof( TaskHandle_t )` always equals `sizeof( void * )`.
-* * *
```c
/* Driver library function to send data to a UART. */
@@ -1097,8 +1077,7 @@ void xUART_TransmitEndISR( xUART *pxUARTInstance )
}
```
-*Listing 10.11 Pseudo code demonstrating how a task notification can be used in a driver library transmit function*
-* * *
+***Listing 10.11*** *Pseudo code demonstrating how a task notification can be used in a driver library transmit function*
Task notifications can also replace semaphores in receive functions, as
demonstrated in pseudo code Listing 10.12, which provides the outline of
@@ -1134,7 +1113,6 @@ Referring to Listing 10.12:
-* * *
```c
/* Driver library function to receive data from a UART. */
@@ -1215,8 +1193,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*
-* * *
+***Listing 10.12*** *Pseudo code demonstrating how a task notification can be used in a driver library receive function*
### 10.3.8 Task Notifications Used in Peripheral Device Drivers: ADC Example
@@ -1253,7 +1230,6 @@ for an Analog to Digital Converter (ADC). In Listing 10.13:
-* * *
```c
/* A task that uses an ADC. */
@@ -1326,8 +1302,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*
-* * *
+***Listing 10.13*** *Pseudo code demonstrating how a task notification can be used to pass a value to a task*
### 10.3.9 Task Notifications Used Directly Within an Application
@@ -1374,13 +1349,12 @@ The structure sent to the server task by the `CloudRead()` and
* * *
![](media/image81.png)
-*Figure 10.6 The communication paths from the application tasks to the cloud server, and back again*
+***Figure 10.6*** *The communication paths from the application tasks to the cloud server, and back again*
* * *
-* * *
```c
typedef enum CloudOperations
@@ -1398,8 +1372,7 @@ typedef struct CloudCommand
} CloudCommand_t;
```
-*Listing 10.14 The structure and data type sent on a queue to the server task*
-* * *
+***Listing 10.14*** *The structure and data type sent on a queue to the server task*
Pseudo code for `CloudRead()` is shown in Listing 10.15. The function sends
its request to the server task, then calls `xTaskNotifyWait()` to wait in
@@ -1418,7 +1391,6 @@ does not have to wait to obtain a value from the cloud server.
-* * *
```c
/* ulDataID identifies the data to read. pulValue holds the address of the
@@ -1458,13 +1430,11 @@ BaseType_t CloudRead( uint32_t ulDataID, uint32_t *pulValue )
}
```
-*Listing 10.15 The Implementation of the Cloud Read API Function*
-* * *
+***Listing 10.15*** *The Implementation of the Cloud Read API Function*
-* * *
```c
void ServerTask( void *pvParameters )
@@ -1501,8 +1471,7 @@ void ServerTask( void *pvParameters )
}
```
-*Listing 10.16 The Server Task Processing a Read Request*
-* * *
+***Listing 10.16*** *The Server Task Processing a Read Request*
Pseudo code for `CloudWrite()` is shown in Listing 10.17. For the purpose of
demonstration, `CloudWrite()` returns a bitwise status code, where each
@@ -1516,7 +1485,6 @@ status notification.
-* * *
```c
/* Status bits used by the cloud write operation. */
@@ -1572,8 +1540,7 @@ pdMS_TO_TICKS( 250 ) ); /* Wait a maximum of 250ms. */
return ( ulNotificationValue & CLOUD_WRITE_STATUS_BIT_MASK );
```
-*Listing 10.17 The Implementation of the Cloud Write API Function*
-* * *
+***Listing 10.17*** *The Implementation of the Cloud Write API Function*
Pseudo code demonstrating how the server task manages a write request is
shown in Listing 10.18. When the data has been sent to the cloud server,
@@ -1591,7 +1558,6 @@ server.
-* * *
```c
void ServerTask( void *pvParameters )
@@ -1634,5 +1600,4 @@ void ServerTask( void *pvParameters )
}
```
-*Listing 10.18 The Server Task Processing a Send Request*
-* * *
+***Listing 10.18*** *The Server Task Processing a Send Request*
diff --git a/ch11.md b/ch11.md
index 26cc92a..e21ca39 100644
--- a/ch11.md
+++ b/ch11.md
@@ -58,12 +58,10 @@ macro when the following two conditions are satisfied:
-* * *
```c
portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime )
```
-*Listing 11.1 The prototype for the portSUPPRESS\_TICKS\_AND\_SLEEP macro*
-* * *
+***Listing 11.1*** *The prototype for the portSUPPRESS\_TICKS\_AND\_SLEEP macro*
The value of the `xExpectedIdleTime` parameter in `portSUPPRESS_TICKS_AND_SLEEP()` equals the total number
of tick periods before a task is due to be moved into the Ready state. The parameter value is therefore the
@@ -78,12 +76,10 @@ by the application writer.
-* * *
```c
void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime );
```
-*Listing 11.2 The vPortSuppressTicksAndSleep API function prototype*
-* * *
+***Listing 11.2*** *The vPortSuppressTicksAndSleep API function prototype*
### 11.3.3 The eTaskConfirmSleepModeStatus Function
@@ -94,12 +90,10 @@ is set to 1.
-* * *
```c
eSleepModeStatus eTaskConfirmSleepModeStatus( void );
```
-*Listing 11.3 The eTaskConfirmSleepModeStatus API function prototype*
-* * *
+***Listing 11.3*** *The eTaskConfirmSleepModeStatus API function prototype*
If `eTaskConfirmSleepModeStatus()` returns `eNoTasksWaitingTimeout` when it is called from
@@ -131,12 +125,10 @@ power state, respectively.
-* * *
```c
configPRE_SLEEP_PROCESSING( xExpectedIdleTime )
```
-*Listing 11.4 The prototype for the configPRE\_SLEEP\_PROCESSING macro*
-* * *
+***Listing 11.4*** *The prototype for the configPRE\_SLEEP\_PROCESSING macro*
Before the user can make the MCU enter the low-power mode, `configPRE_SLEEP_PROCESSING()` must be called to
@@ -148,12 +140,10 @@ clocks, reducing the system frequency.
-* * *
```c
configPOST_SLEEP_PROCESSING( xExpectedIdleTime )
```
-*Listing 11.5 The prototype for the configPOST\_SLEEP\_PROCESSING macro*
-* * *
+***Listing 11.5*** *The prototype for the configPOST\_SLEEP\_PROCESSING macro*
After exiting the low-power mode, the user should call the `configPOST_SLEEP_PROCESSING()` function
@@ -177,7 +167,6 @@ application writer.
-* * *
```c
/* First define the portSUPPRESS_TICKS_AND_SLEEP() macro. The parameter is the
time, in ticks, until the kernel next needs to execute. */
@@ -257,8 +246,7 @@ void vApplicationSleep( TickType_t xExpectedIdleTime )
}
}
```
-*Listing 11.6 An example of a user defined implementation of portSUPPRESS\_TICKS\_AND\_SLEEP()*
-* * *
+***Listing 11.6*** *An example of a user defined implementation of portSUPPRESS\_TICKS\_AND\_SLEEP()*
## 11.5 Idle Task Hook Function
@@ -272,12 +260,10 @@ to 1 within FreeRTOSConfig.h.
-* * *
```c
void vApplicationIdleHook( void );
```
-*Listing 11.7 The vApplicationIdleHook API function prototype*
-* * *
+***Listing 11.7*** *The vApplicationIdleHook API function prototype*
The idle hook is called repeatedly as long as the idle task is running. It is paramount that the idle
diff --git a/ch12.md b/ch12.md
index f70d3d6..e9d5913 100644
--- a/ch12.md
+++ b/ch12.md
@@ -21,13 +21,11 @@ assertion that the pointer `pxMyPointer` is not NULL.
-* * *
```c
/* Test the assertion that pxMyPointer is not NULL */
assert( pxMyPointer != NULL );
```
-*Listing 12.1 Using the standard C assert() macro to check pxMyPointer is not NULL*
-* * *
+***Listing 12.1*** *Using the standard C assert() macro to check pxMyPointer is not NULL*
The application writer specifies the action to take if an assertion
fails by providing an implementation of the `assert()` macro.
@@ -64,7 +62,6 @@ debug session is paused.
-* * *
```c
/* Disable interrupts so the tick interrupt stops executing, then sit
in a loop so execution does not move past the line that failed the
@@ -73,8 +70,7 @@ debug session is paused.
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for(;;); }
```
-*Listing 12.2 A simple configASSERT() definition useful when executing under the control of a debugger*
-* * *
+***Listing 12.2*** *A simple configASSERT() definition useful when executing under the control of a debugger*
The definition of `configASSERT()` shown in Listing 12.3 is useful when an
application is not being executed under the control of a debugger. It
@@ -87,7 +83,6 @@ source file.
-* * *
```c
/* This function must be defined in a C source file, not the FreeRTOSConfig.h
header file. */
@@ -111,8 +106,7 @@ void vAssertCalled( const char *pcFile, uint32_t ulLine )
extern void vAssertCalled( const char *pcFile, unsigned long ulLine );
#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ )
```
-*Listing 12.3 A configASSERT() definition that records the source code line that failed an assertion*
-* * *
+***Listing 12.3*** *A configASSERT() definition that records the source code line that failed an assertion*
## 12.3 Tracealyzer for FreeRTOS
@@ -141,22 +135,22 @@ perspective.
* * *
![](media/image82.png)
-*Figure 12.1 FreeRTOS+Trace includes more than 20 interconnected views*
+***Figure 12.1*** *FreeRTOS+Trace includes more than 20 interconnected views*
![](media/image83.png)
-*Figure 12.2 FreeRTOS+Trace main trace view - one of more than 20 interconnected trace views*
+***Figure 12.2*** *FreeRTOS+Trace main trace view - one of more than 20 interconnected trace views*
![](media/image84.png)
-*Figure 12.3 FreeRTOS+Trace CPU load view - one of more than 20 interconnected trace views*
+***Figure 12.3*** *FreeRTOS+Trace CPU load view - one of more than 20 interconnected trace views*
![](media/image85.png)
-*Figure 12.4 FreeRTOS+Trace response time view - one of more than 20 interconnected trace views*
+***Figure 12.4*** *FreeRTOS+Trace response time view - one of more than 20 interconnected trace views*
![](media/image86.png)
-*Figure 12.5 FreeRTOS+Trace user event plot view - one of more than 20 interconnected trace views*
+***Figure 12.5*** *FreeRTOS+Trace user event plot view - one of more than 20 interconnected trace views*
![](media/image87.png)
-*Figure 12.6 FreeRTOS+Trace kernel object history view - one of more than 20 interconnected trace views*
+***Figure 12.6*** *FreeRTOS+Trace kernel object history view - one of more than 20 interconnected trace views*
* * *
@@ -283,17 +277,15 @@ below.
-* * *
```c
UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
const UBaseType_t uxArraySize,
configRUN_TIME_COUNTER_TYPE * const pulTotalRunTime );
```
-*Listing 12.4 The uxTaskGetSystemState() API function prototype*
+***Listing 12.4*** *The uxTaskGetSystemState() API function prototype*
> Note: `configRUN_TIME_COUNTER_TYPE` defaults to `uint32_t` for backward compatibility, but can be
> overridden in FreeRTOSConfig.h if `uint32_t` is too restrictive.
-* * *
**uxTaskGetSystemState() parameters and return value**
@@ -338,7 +330,6 @@ UBaseType_t uxTaskGetSystemState( TaskStatus_t * const pxTaskStatusArray,
-* * *
```c
typedef struct xTASK_STATUS
{
@@ -360,8 +351,7 @@ typedef struct xTASK_STATUS
#endif
} TaskStatus_t;
```
-*Listing 12.5 The TaskStatus\_t structure*
-* * *
+***Listing 12.5*** *The TaskStatus\_t structure*
**TaskStatus_t structure members**
@@ -479,12 +469,10 @@ FreeRTOSConfig.h.
-* * *
```c
void vTaskListTasks( char * pcWriteBuffer, size_t uxBufferLength );
```
-*Listing 12.6 The vTaskListTasks() API function prototype*
-* * *
+***Listing 12.6*** *The vTaskListTasks() API function prototype*
**vTaskListTasks() parameters**
@@ -527,7 +515,7 @@ In the output:
* * *
![](media/image88.png)
-*Figure 12.7 Example output generated by vTaskListTasks()*
+***Figure 12.7*** *Example output generated by vTaskListTasks()*
* * *
> Note:
@@ -539,12 +527,10 @@ In the output:
-* * *
```c
void vTaskList( signed char *pcWriteBuffer );
```
-*Listing 12.7 The vTaskList() API function prototype*
-* * *
+***Listing 12.7*** *The vTaskList() API function prototype*
**vTaskList() parameters**
@@ -571,12 +557,10 @@ production real-time system.
-* * *
```c
void vTaskGetRunTimeStatistics( char * pcWriteBuffer, size_t uxBufferLength );
```
-*Listing 12.8 The vTaskGetRunTimeStatistics() API function prototype*
-* * *
+***Listing 12.8*** *The vTaskGetRunTimeStatistics() API function prototype*
**vTaskGetRunTimeStatistics() parameters**
@@ -613,7 +597,7 @@ Figure 12.8. In the output:
* * *
![](media/image89.png)
-*Figure 12.8 Example output generated by vTaskGetRunTimeStatistics()*
+***Figure 12.8*** *Example output generated by vTaskGetRunTimeStatistics()*
* * *
> Note:
@@ -626,12 +610,10 @@ Figure 12.8. In the output:
- * * *
```c
void vTaskGetRunTimeStats( signed char *pcWriteBuffer );
```
- *Listing 12.9 The vTaskGetRunTimeStats() API function prototype*
- * * *
+ ***Listing 12.9*** *The vTaskGetRunTimeStats() API function prototype*
**vTaskGetRunTimeStats() parameters**
@@ -658,7 +640,6 @@ value. Pseudo code for the interrupt service routine is shown in Listing
-* * *
```c
void TimerOverflowInterruptHandler( void )
{
@@ -669,8 +650,7 @@ void TimerOverflowInterruptHandler( void )
ClearTimerInterrupt();
}
```
-*Listing 12.10 16-bit timer overflow interrupt handler used to count timer overflows*
-* * *
+***Listing 12.10*** *16-bit timer overflow interrupt handler used to count timer overflows*
Listing 12.11 shows the lines added to FreeRTOSConfig.h to enable the
collection of run-time statistics.
@@ -678,7 +658,6 @@ collection of run-time statistics.
-* * *
```c
/* Set configGENERATE_RUN_TIME_STATS to 1 to enable collection of run-time
statistics. When this is done, both portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
@@ -717,15 +696,13 @@ void vSetupTimerForRunTimeStats( void );
ResumeTimer(); \
}
```
-*Listing 12.11 Macros added to FreeRTOSConfig.h to enable the collection of run-time statistics*
-* * *
+***Listing 12.11*** *Macros added to FreeRTOSConfig.h to enable the collection of run-time statistics*
The task shown in Listing 12.12 prints out the collected run-time statistics every 5 seconds.
-* * *
```c
#define RUN_TIME_STATS_STRING_BUFFER_LENGTH 512
@@ -770,8 +747,7 @@ static void prvStatsTask( void *pvParameters )
}
}
```
-*Listing 12.12 The task that prints out the collected run-time statistics*
-* * *
+***Listing 12.12*** *The task that prints out the collected run-time statistics*
## 12.6 Trace Hook Macros
diff --git a/ch13.md b/ch13.md
index 20d5091..5d5cbd1 100644
--- a/ch13.md
+++ b/ch13.md
@@ -92,12 +92,10 @@ it. This value is called the stack 'high water mark'.
-* * *
```c
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
```
-*Listing 13.1 The uxTaskGetStackHighWaterMark() API function prototype*
-* * *
+***Listing 13.1*** *The uxTaskGetStackHighWaterMark() API function prototype*
**uxTaskGetStackHighWaterMark() parameters and return value**
@@ -127,12 +125,10 @@ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
-* * *
```c
configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask );
```
-*Listing 13.2 The uxTaskGetStackHighWaterMark2() API function prototype*
-* * *
+***Listing 13.2*** *The uxTaskGetStackHighWaterMark2() API function prototype*
Using `configSTACK_DEPTH_TYPE` allows the application writer to control the type
used for stack depth.
@@ -157,12 +153,10 @@ overflow hook function:
-* * *
```c
void vApplicationStackOverflowHook( TaskHandle_t *pxTask, signed char *pcTaskName );
```
-*Listing 13.3 The stack overflow hook function prototype*
-* * *
+***Listing 13.3*** *The stack overflow hook function prototype*
The stack overflow hook is provided to make trapping and debugging stack
errors easier, but there is no real way to recover from a stack overflow
diff --git a/toc.md b/toc.md
index 0887b96..59898c5 100644
--- a/toc.md
+++ b/toc.md
@@ -286,6 +286,33 @@
+ [13.5.7 Symptom: Calling API functions while the scheduler is suspended, or from inside a critical section, causes the application to crash](ch13.md#1357-symptom-calling-api-functions-while-the-scheduler-is-suspended-or-from-inside-a-critical-section-causes-the-application-to-crash)
+ [13.6 Additional Debugging Steps](ch13.md#136-additional-debugging-steps)
+
+## 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 8.2 The alternative implementation for print task](ch08.md#example8.2)
++ [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)
+
## Figures:
+ [Figure 2.1 Top level directories within the FreeRTOS distribution](ch02.md#fig2.1)
+ [Figure 2.2 Core FreeRTOS source files within the FreeRTOS directory tree](ch02.md#fig2.2)
@@ -571,36 +598,6 @@
+ [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)