You can basically choose between two option when creating a FreeRTOS project:
The steps to create a microcontroller application using FreeRTOS are:
When you have created the native FreeRTOS project, you can configure the real-time operating system using the FreeRTOSConfig.h file. Please refer to the FreeRTOS documentation for more information on the specific settings.
FreeRTOS implements critical sections using the BASEPRI register (available in Armv7-M and Armv8-M architecture based devices) which masks only a subset of interrupts. This is configured via the configMAX_SYSCALL_INTERRUPT_PRIORITY
setting. Therefore, it is needed to properly configure this setting. It is also needed to set appropriate interrupt priorities for interrupt service routines (ISR) that use RTOS functions. This can especially impact drivers which typically use peripheral interrupts. Normally, these use the RTOS directly or indirectly through registered callbacks.
Arm Cortex-M cores store interrupt priority values in the most significant bits of the interrupt priority registers which can have a maximum of eight bits. Many implementations offer only three priority bits. These three bits are shifted up to be bits five, six and seven respectively. configMAX_SYSCALL_INTERRUPT_PRIORITY
must not be 0 and can be xxx00000. This results in the following table:
configMAX_SYSCALL_INTERRUPT_PRIORITY | Upper three bits | Priority |
---|---|---|
32 | 001 | 1 (Highest) |
64 | 010 | 2 |
96 | 011 | 3 |
128 | 100 | 4 |
160 | 101 | 5 |
196 | 110 | 6 |
224 | 111 | 7 (Lowest) |
Example
If you set configMAX_SYSCALL_INTERRUPT_PRIORITY
to 32, then the priority of an interrupt service routine that uses RTOS functions must then be higher or equal to 1. This ensures that this interrupt will be masked during critical a section.
A WiFi driver using the SPI interface registers a callback to SPI which is executed in an interrupt context. The callback function in the WiFi driver uses RTOS functions. Therefore, the SPI interrupt priority must be set to a value equal or higher to the FreeRTOS preempt priority, for example 1.
main()
).Once the target application generates event information, it can be viewed in the µVision debugger using the Event Recorder.
The steps to create a microcontroller application using CMSIS-FreeRTOS are:
When you have created the CMSIS-FreeRTOS project, you can configure the real-time operating system using the FreeRTOSConfig.h file. It can be opened using the Configuration Wizard view:
The following main settings are available:
Name | #define | Description |
---|---|---|
Minimal stack size [words] | configMINIMAL_STACK_SIZE | Stack for idle task and default task stack in words. |
Total heap size [bytes] | configTOTAL_HEAP_SIZE | Heap memory size in bytes. |
Kernel tick frequency [Hz] | configTICK_RATE_HZ | Kernel tick rate in Hz. |
Timer task stack depth [words] | configTIMER_TASK_STACK_DEPTH | Stack for timer task in words. |
Timer task priority | configTIMER_TASK_PRIORITY | Timer task priority. |
Timer queue length | configTIMER_QUEUE_LENGTH | Timer command queue length. |
Preemption interrupt priority | configMAX_SYSCALL_INTERRUPT_PRIORITY | Maximum priority of interrupts that are safe to call FreeRTOS API. |
Use time slicing | configUSE_TIME_SLICING | Enable setting to use time slicing. |
Use tickless idle | configUSE_TICKLESS_IDLE | Enable low power tickless mode that stops tick interrupt when idle. |
Idle should yield | configIDLE_SHOULD_YIELD | Control Yield behavior of the idle task. |
Check for stack overflow | configCHECK_FOR_STACK_OVERFLOW | Enable or disable stack overflow checking. |
Use idle hook | configUSE_IDLE_HOOK | Enable callback function call on each idle task iteration. |
Use tick hook | configUSE_TICK_HOOK | Enable callback function call during each tick interrupt. |
Use daemon task startup hook | configUSE_DAEMON_TASK_STARTUP_HOOK | Enable callback function call when timer service starts. |
Use malloc failed hook | configUSE_MALLOC_FAILED_HOOK | Enable callback function call when out of dynamic memory. |
Queue registry size | configQUEUE_REGISTRY_SIZE | Define maximum number of queue objects registered for debug purposes. |
configMAX_SYSCALL_INTERRUPT_PRIORITY
.Event Recorder Configuration
The following settings are available (see Configure Event Recorder for details):
Name | #define | Description |
---|---|---|
Initialize Event Recorder | configEVR_INITIALIZE | Initialize Event Recorder before FreeRTOS kernel start. |
Setup recording level filter | configEVR_SETUP_LEVEL | Enable configuration of FreeRTOS events recording level. |
Task functions | configEVR_LEVEL_TASKS | Define event recording level bitmask for events generated from Tasks functions. |
Queue functions | configEVR_LEVEL_QUEUE | Define event recording level bitmask for events generated from Queue functions. |
Timer functions | configEVR_LEVEL_TIMERS | Define event recording level bitmask for events generated from Timer functions. |
Event Groups functions | configEVR_LEVEL_EVENTGROUPS | Define event recording level bitmask for events generated from Event Groups functions. |
Heap functions | configEVR_LEVEL_HEAP | Define event recording level bitmask for events generated from Heap functions. |
Stream Buffer functions | configEVR_LEVEL_STREAMBUFFER | Define event recording level bitmask for events generated from Stream Buffer functions. |
Memory Allocation Configuration
The following settings are available:
Name | #define | Description |
---|---|---|
Support static memory allocation | configSUPPORT_STATIC_ALLOCATION | Enable or disable support for static memory allocation. |
Support dynamic memory allocation | configSUPPORT_DYNAMIC_ALLOCATION | Enable or disable support for dynamic memory allocation. |
Use kernel provided static memory | configKERNEL_PROVIDED_STATIC_MEMORY | When enabled, FreeRTOS kernel provides static memory for Idle and Timer tasks. |
Use application allocated heap | configAPPLICATION_ALLOCATED_HEAP | When enabled, application must provide heap buffer externally. |
Use separate heap for stack allocation | configSTACK_ALLOCATION_FROM_SEPARATE_HEAP | Enable or disable stack allocation for any task from a separate heap. |
Use heap protector | configENABLE_HEAP_PROTECTOR | Enable or disable bounds checking and obfuscation to heap block pointers. |
Port Specific Configuration
The following settings are available:
Name | #define | Description |
---|---|---|
Use Floating Point Unit | configENABLE_FPU | Enable or disable support for FPU when switching execution context. |
Use M-Profile Vector Extension | configENABLE_MVE | Enable or disable support for MVE when switching execution context. |
Use Memory Protection Unit | configENABLE_MPU | Enable or disable support for MPU on ARMv8-M MPU enabled ports. |
Use TrustZone Secure Side Only | configRUN_FREERTOS_SECURE_ONLY | Enable this setting when FreeRTOS runs on the Secure side only. |
Use TrustZone Security Extension | configENABLE_TRUSTZONE | Enable TrustZone when FreeRTOS runs on the Non-Secure side and calls functions from the Secure side. |
Minimal secure stack size [words] | configMINIMAL_SECURE_STACK_SIZE | Stack for idle task Secure side context in words. |
Interrupt Controller Configuration
The following settings are available:
Name | #define | Description |
---|---|---|
Interrupt controller base address | configINTERRUPT_CONTROLLER_BASE_ADDRESS | Sets the base address of the interrupt controller peripheral. |
Interrupt controller CPU interface offset | configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET | Sets the offset from interrupt controller base address at which the CPU interface starts. |
Interrupt controller unique priorities | configUNIQUE_INTERRUPT_PRIORITIES | Sets the number of unique priorities that can be specified in the interrupt controller peripheral. |
Symmetric Multiprocessing Configuration
The following settings are available:
Name | #define | Description |
---|---|---|
Number of processor cores | configNUMBER_OF_CORES | Sets the number of available processor cores. |
Use processor core affinity | configUSE_CORE_AFFINITY | Enables the control for task to run on specific processor cores. |
Use passive idle hook | configUSE_PASSIVE_IDLE_HOOK | Enable callback function call on each idle task iteration. |
main()
) to setup Event Recorder according to configuration settings.Once the target application generates event information, it can be viewed in the µVision debugger using the Event Recorder.
Using CMSIS-RTOS2 API and native FreeRTOS API simultaneously is possible and some projects do require using the native FreeRTOS API and the CMSIS-RTOS2 API at the same time. Such project should be created as CMSIS-FreeRTOS project.
Depending on the application requirements, FreeRTOS kernel can be started either by using FreeRTOS native API or by using CMSIS-RTOS2 API.
Restrictions
After the kernel is started using CMSIS-RTOS2 API, FreeRTOS native API can be used with the following restrictions:
Restrictions
After the kernel is started using FreeRTOS native API, CMSIS-RTOS2 API can be used without restrictions.
This section describes the configuration settings for the Event Recorder annotations. For more information refer to section Add Event Recorder Visibility to native FreeRTOS project or Add Event Recorder Visibility to CMSIS-FreeRTOS project.
Use below definitions to configure Event Recorder initialization and recording level filter setup.
Value | Description |
---|---|
0 | Disable Event Recorder initialization |
1 | Enable Event Recorder initialization |
Definition configEVR_INITIALIZE enables Event Recorder initialization during execution of function EvrFreeRTOSSetup. Default value is 1.
Value | Description |
---|---|
0 | Disable recording level filter setup |
1 | Enable recording level filter setup |
Definition configEVR_SETUP_LEVEL enables setup of recording level filter for events generated by FreeRTOS. Recording level is configured during execution of function EvrFreeRTOSSetup. Default value is 1.
Value | Description |
---|---|
0x00 | Disable event generation |
0x01 | Enable generation of error events |
0x05 | Enable generation of error and operational events |
0x07 | Enable generation of error, API and operational events |
0x0F | Enable generation of all events |
Definitions configEVR_LEVEL_x set the recording level bitmask for events generated by each function group. They are taken into account only when recording level filter setup is enabled. Default value is 0x05.
Apart from the debug capabilities that Event Recorder offers, Keil MDK also supports thread aware breakpoints, just like for the standard CMSIS-RTOS.
Code Example
Caveats
'tid_phaseA'
would be valid, 'tid_phaseA + 1'
is not but will still capture the most recent registers and store them to the actual thread context each time a thread aware breakpoint is checked.'noinline'
attribute to the function that is used to stop when the current FreeRTOS thread id matches: