10. Using the Operating System DA1468x Software Platform Reference (UM-B-044)
10.1. FreeRTOS
The SmartSnippets™ DA1468x SDK contains the FreeRTOS v8.2.0 kernel, updated with a few back-ported bug fixes from v8.2.1 and v8.2.3. The FreeRTOS API documentation is available online at http://www.freertos.org/modules.html#API_reference.
The SmartSnippets™ DA1468x SDK contains several FreeRTOS-based example applications. The corresponding Eclipse projects use (as a convention) the folder <sdk_root_directory>/sdk/bsp/free_rtos
to include the FreeRTOS kernel source files.
10.1.1. FreeRTOS Source Files
The FreeRTOS kernel source files are in the following directory tree:
<sdk_root_directory>/sdk/bsp/free_rtos/
├── include
└── portable
├── GCC
│ └── ARM_CM0
└── MemMang
The kernel source files are in <sdk_root_directory>/sdk/bsp/free_rtos/
:
Source Files | Description |
---|---|
croutine.c | Not used in the SmartSnippets™ DA1468x SDK |
event_groups.c | Implementation of the Event Groups API |
list.c | List data structure implementation, used internally by FreeRTOS |
queue.c | Implementation of the Queue and QueueSet API |
tasks.c | Implementation of the Tasks API |
timers.c | Implementation of the Timers API |
The FreeRTOS header files are in <sdk_root_directory>/sdk/bsp/free_rtos/include/
:
Some FreeRTOS code is specific for the compiler and the platform processor. The corresponding files are located under <sdk_root_directory>/sdk/bsp/free_rtos/portable/
:
├── GCC
│ └── ARM_CM0
│ ├── port.c (DA1468x-specific customizations for timers and interrupts)
│ └── portmacro.h (DA1468x-specific customizations for constants and sections)
└── MemMang
└── heap_4.c (heap memory manager)
The FreeRTOS kernel provides different heap memory algorithms (see http://www.freertos.org/a00111.html for descriptions). The SmartSnippets™ DA1468x SDK employs the heap_4
algorithm, which consolidates adjacent free blocks to avoid fragmentation. The memory area allocated for the heap is assumed to be contiguous (i.e. there are no “holes”).
Note
the SmartSnippets™ DA1468x SDK has only been tested with heap_4
algorithm.
10.1.2. FreeRTOS Configuration
Several FreeRTOS configuration options (see http://www.freertos.org/a00110.html for description) for SmartSnippets™ SDK are specified in <sdk_root_directory>/sdk/bsp/free_rtos/include/FreeRTOSConfig.h
using macro definitions which are described below. For the rest of the configuration options, the defaults are used.
Name | Default Definitions | Default Value |
---|---|---|
configUSE_PREEMPTION | Use the preemptive scheduler. | 1 |
configUSE_IDLE_HOOK | Do not use an idle hook (callback). | 0 |
configUSE_TICK_HOOK | Do not use a system-tick hook (callback). | 0 |
configIDLE_SHOULD_YIELD | The idle task immediately yields if there are any tasks that can be scheduled. | 1 |
configUSE_MUTEXES | The mMutex functionality is enabled. | 1 |
configCHECK_FOR_STACK_OVERFLOW | The extended stack overflow detection is enabled. | 2 |
configUSE_RECURSIVE_MUTEXES | The recursive mutex functionality is enabled. | 1 |
configUSE_MALLOC_FAILED_HOOK | Trigger hook (callback) on memory allocation failure. | 1 |
configUSE_COUNTING_SEMAPHORES | The counting semaphore functionality is enabled. | 1 |
configGENERATE_RUN_TIME_STATS | No run-time statistics are generated. | 0 |
configUSE_QUEUE_SETS | The QueueSet functionality is enabled. | 1 |
configUSE_TICKLESS_IDLE | The periodic tick interrupt is disabled during idle intervals, to save energy. | 2 |
The hardware timer “Timer1” is dedicated to FreeRTOS and runs as the system timer. Due to the width of the Timer1 period and the available pre-scaling options, the maximum time that a DA1468x-based system can stay in sleep mode is 8 seconds.
Finally, the macro config_ASSERT()
is defined in:
<sdk_root_directory>/sdk/bsp/free_rtos/include/FreeRTOSConfig.h
as:
/* Normal assert() semantics without relying on the provision of an assert.h header file. */ #if (dg_configIMAGE_SETUP == DEVELOPMENT_MODE) #define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); hw_watchdog_freeze(); do {} while(1); } #else #define configASSERT( x ) do { } while (0) #endif
Therefore, in development builds it generates a breakpoint, while in production builds it has no effect.
10.1.3. Platform-specific Definitions
As mentioned in Section 10.1.1 the portmacro.h file in:
<sdk_root_directory>/sdk/bsp/free_rtos/portable/GCC/ARM_CM0/
path customizes certain definitions (attributes) for DA1468x.
FreeRTOS uses the concept of “privileged” code and data which is meaningless for DA1468x as an ARM Cortex-M0 does not provide different execution levels (e.g. supervisor and user).
Therefore, on DA1468x the concept of privileged code/data is redefined to denote code/data that should be placed in retained RAM (i.e. RAM areas that stay active even during sleep periods).
The pertinent definitions are:
/* Code and Data Retention specific constants. */ #if ((dg_configCODE_LOCATION == NON_VOLATILE_IS_FLASH) && (dg_configEXEC_MODE == MODE_IS_CACHED)) #define PRIVILEGED_APP_FUNCTION __attribute__((section("text_retained"))) #else #define PRIVILEGED_APP_FUNCTION #endif // RetRAM0 #define PRIVILEGED_DATA __attribute__((section("privileged_data_zi"))) #define INITIALISED_PRIVILEGED_DATA __attribute__((section("privileged_data_init"))) // RetRAM1 #define PRIVILEGED_DATA_1 __attribute__((section("privileged_data_1_zi")))
Symbols (i.e. functions and variables) that are defined with one of the above attributes will be placed in special sections by the linker and will be moved in their appropriate RAM locations at run-time.
10.1.4. FreeRTOS Task Priorities
Warning
Please do not modify priorities or corresponding settings, as there is a high risk of affecting the stability of time-critical parts of your application.
The priority (FreeRTOS: uxPriority
) parameter of the OS_TASK_CREATE
(FreeRTOS: xTaskCreate()
) API function initially assigns a priority to every newly created task. It is possible to change this priority later, after the scheduler has been started, with the use of the vTaskPrioritySet()
API function.
The priority that a task can be assigned to is in the range of 0 to (configMAX_PRIORITIES
– 1). The configMAX_PRIORITIES
constant is defined in the FreeRTOSconfig.h file which is in the <sdk_root_directory>/sdk/FreeRTOS/include
folder of the project. For example, Code 3 shows the currently configured value for configMAX_PRIORITIES
for the pxp_reporter demo application.
#define configMAX_PRIORITIES ( 7 )
The only restriction in the maximum value that configMAX_PRIORITIES
constant can take is when the port in use implements a port optimized task selection mechanism that uses a ‘count leading zeros’ type instruction (for task selection in a single instruction) and configUSE_PORT_OPTIMISED_TASK_SELECTION
is set to 1 in FreeRTOSconfig.h file. In this case configMAX_PRIORITIES
cannot be higher than 32. Otherwise there is no restriction in the maximum value that this constant can take but is advisable to set its value to minimum necessary for RAM efficiency reasons.
The lowest priority that a task can have is zero. The priority of the idle task, which is defined by the tskIDLE_PRIORITY
constant, is zero. In SmartSnippets™ DA1468x SDK the priority of the idle task is defined in task.h file located in the <sdk_root_directory>/sdk/FreeRTOS/include
folder as shown in Code 4. A priority assigned to a task is not unique and can be shared among many tasks.
/* * Defines the priority used by the idle task. This must not be modified. * * \ingroup TaskUtils */ #define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U )
As described in the FreeRTOS documentation (http://www.freertos.org/) the states in which a task can exist are:
- Running
- Ready
- Blocked
- Suspended
The task that is in the Running state, is the task with the highest priority among the tasks that are placed in the Ready state. The FreeRTOS scheduler ensures that tasks in the Ready or Running state will get CPU time in comparison with tasks that are also placed in the Ready state but have lower priorities.
Tasks that are in the Ready state and share the same priority will be sharing the available processing time, using a time sliced round robin schedule, unless configUSE_TIME_SLICING
is defined or configUSE_TIME_SLICING
is set to 0.
Code 5 below shows the task priorities as defined in the osal.h file which is in the folder``<sdk_root_directory>/sdk/FreeRTOS/osal`` of the pxp_reporter demo application. Table 6 provides information about the wrappers of the Operating System Abstraction Layer (section 10.2).
#define OS_TASK_PRIORITY_LOWEST tskIDLE_PRIORITY #define OS_TASK_PRIORITY_NORMAL tskIDLE_PRIORITY + 1 #define OS_TASK_PRIORITY_HIGHEST configMAX_PRIORITIES - 1
Table 4 below shows the tasks of the pxp_reporter demo application, starting with the lowest priority task. The same information is illustrated in a different way in Figure 6
Task | Priority | File | Description |
---|---|---|---|
prvIdleTask | tskIDLE_PRIORITY | tasks.c | The idle task. |
rcx_calibration_task | tskIDLE_PRIORITY | sys_clock_mgr.c | The RCX calibration task. |
pxp_reporter_task | mainPXP_REPORTER_TASK_PRIORITY (OS_TASK_PRIORITY_NORMAL) | main.c | The PXP reporter application task. |
ble_mgr_task | mainBLE_MGR_PRIORITY (OS_TASK_PRIORITY_HIGHEST - 4) | ble_mgr.c | The ble manager task. |
ad_ble_task | mainBLE_TASK_PRIORITY (OS_TASK_PRIORITY_HIGHEST - 3) | ad_ble.c | The ble adapter task. |
usb_charger_task | OS_TASK_PRIORITY_HIGHEST – 2 | sys_charger.c | The USB Charger task. |
usb_charger_fsm_task | OS_TASK_PRIORITY_HIGHEST - 2 | sys_charger.c | The USB Charger FSM task. |
prvTimerTask | configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1) | timers.c | The timer task. |
system_init | OS_TASK_PRIORITY_HIGHEST | main.c | The System Initialization task. |
10.1.5. Delaying the execution of a FreeRTOS Task
The following two functions can be used to delay a FreeRTOS task. They are intended for different lengths of delays:
hw_cpm_delay_usec()
can be used to add a delay of a specific number of microseconds in the code execution by executing a loop in assembly code. The function is as accurate as possible (the error is less than or equal to 1usec for clocks higher than or equal to 16MHz) and it will never generate a delay less than requested. It operates correctly with all possible clock setups. As long as the delay is of a few microseconds it is possible to call this function with the interrupts disabled as it will not impact the real time behavior of any other tasks. It does not call the RTOS scheduler as it just creates the delay in the current task.OS_DELAY_MS()
can be used to add a delay in the range of milliseconds in the execution of a task. It will block the task and so the RTOS can schedule other lower priority tasks in the delay period. The delay time requested is converted to system ticks, so its accuracy depends on the tick period which is by default ~2msec. So, a call likeOS_DELAY_MS(5)
would be rounded down to a 2 tick delay which is ~4ms, leading to an error of ~1msec. The bigger the delay setting, the less important is the “tick error” to the actual delay. In addition, this function will block a task for a specific number of OS ticks. Even though it will be unblocked on time, this does not guarantee that it will be executed immediately as this depends on its priority. If a higher priority task is running then the task will be left in the “ready-to-run” state, waiting for the OS scheduler to allow it to run. Finally, since calling this function results in the blocking of the running task, it does not make any sense to call it with the interrupts disabled.
10.2. Operating System Abstraction Layer
10.2.1. Scope
The SmartSnippets™ DA1468x offers an Operating System Abstraction Layer (OSAL), which:
The OSAL source files are located under <sdk_root_directory>/sdk/bsp/osal/
:
Source files | Description |
---|---|
msg_queues.c | Message queues implementation. |
msg_queues.h | Message queues API. |
osal.h | RTOS-agnostic API wrappers. |
resmgmt.c | Resource management implementation. |
resmgmt.h | Resource management API. |
10.2.2. RTOS-agnostic API
OSAL provides wrappers of the FreeRTOS API for the following RTOS primitives, presented in Table 6.
Description | API |
---|---|
Tasks/Threads | OS_TASK_* |
Mutexes | OS_MUTEX_* |
Events/Notifications | OS_EVENT_* |
Thread-safe queues | OS_QUEUE_* |
Memory allocation | OS_MALLOC_* |
Memory de-allocation | OS_FREE_* |
Timers | OS_TIMER_* |
Note
The OSAL API does not yet completely cover the FreeRTOS API being used in the SmartSnippets™ DA1468x SDK.
10.2.3. Resource Management API
The OSAL resource management API is:
Function | Description |
---|---|
resource_init() | Initialize resource management structures. |
resource_acquire(mask, timeout) | Attempt to acquire exclusive access to a set of resources. |
resource_release(mask) | Release exclusive access to a set of resources. |
resource_add() | Add new resources at run-time (compile-time configurable). |
The OSAL resource management capability is used by the adapters to provide exclusive access from hardware resources. The low-level drivers layer are bare-metal drivers, so they do not have the notions of resource locking, synchronization etc. The adapter layer is RTOS-aware, and can provide such capabilities.
10.2.4. Message Queues API
OSAL message queues can be used to exchange messages between tasks. Although they build on top of the queue primitive, they add the capability to define the message allocation/de-allocation functions per message queue or even per message.
The available APIs are:
Functions |
---|
msg_queue_create(queue, size, allocator) |
msg_queue_delete(queue) |
msg_queue_put(queue, msg, timeout) |
msg_queue_get(queue, msg, timeout) |
msg_init(msg, id, type, buf, size, free_cb) |
msg_release(msg) |
msg_queue_init_msg(queue, msg, id, type, size) |
msg_queue_send(queue, id, type, buf, size, timeout) |
msq_queue_send_zero_copy(queue, id, type, buf, size, timeout, free_cb) |
The exact prototypes of these functions with types of arguments and returned values can be found in the source code or in Doxygen.
Usage of message queues is demonstrated in the peripherals_demo/uart
demo.
ncG1vNJzZmirY2OytnnWnqqtZWJjrq6t2ailmq%2BjY7CwuY6lp5ybo2KxsK%2FSZ5uimZyktG6%2FxKagnKeemcKkwM6rZZynnWTCrnnBZmdtbF2ZrnKAlXGvmKufm8G4rdGelqmkkamzsL7MmKmenpWnsq%2BvxGhnbZeFqLavs76tn56Xf6Wys63ToqWgl4OuwLWxzGiMrKGenKy1tMSYhqmdopbBqrrGmIqyq6Saum%2B006aj