10. Using the Operating System DA1468x Software Platform Reference (UM-B-044)

Publish date: 2024-05-03

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/:

Table 1 Kernel source files for FreeRTOS
Source FilesDescription
croutine.cNot used in the SmartSnippets™ DA1468x SDK
event_groups.cImplementation of the Event Groups API
list.cList data structure implementation, used internally by FreeRTOS
queue.cImplementation of the Queue and QueueSet API
tasks.cImplementation of the Tasks API
timers.cImplementation 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.

Table 3 Macro Definitions for the FreeRTOSConfig.h
NameDefault DefinitionsDefault Value
configUSE_PREEMPTIONUse the preemptive scheduler.1
configUSE_IDLE_HOOKDo not use an idle hook (callback).0
configUSE_TICK_HOOKDo not use a system-tick hook (callback).0
configIDLE_SHOULD_YIELDThe idle task immediately yields if there are any tasks that can be scheduled.1
configUSE_MUTEXESThe mMutex functionality is enabled.1
configCHECK_FOR_STACK_OVERFLOWThe extended stack overflow detection is enabled.2
configUSE_RECURSIVE_MUTEXESThe recursive mutex functionality is enabled.1
configUSE_MALLOC_FAILED_HOOKTrigger hook (callback) on memory allocation failure.1
configUSE_COUNTING_SEMAPHORESThe counting semaphore functionality is enabled.1
configGENERATE_RUN_TIME_STATSNo run-time statistics are generated.0
configUSE_QUEUE_SETSThe QueueSet functionality is enabled.1
configUSE_TICKLESS_IDLEThe 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:

Code 1 Code defining the config_ASSERT() macro
/* 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 2 Code and Data Retention specific constants
/* 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.

Code 3 currently configured value for the configMAX_PRIORITIES
#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.

Code 4 Idle task’s priority
/* * 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:

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).

Code 5 Task priorities
#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

Table 4 pxp_reporter tasks
TaskPriorityFileDescription
prvIdleTasktskIDLE_PRIORITYtasks.cThe idle task.
rcx_calibration_tasktskIDLE_PRIORITYsys_clock_mgr.cThe RCX calibration task.
pxp_reporter_task

mainPXP_REPORTER_TASK_PRIORITY

(OS_TASK_PRIORITY_NORMAL)

main.cThe PXP reporter application task.
ble_mgr_task

mainBLE_MGR_PRIORITY

(OS_TASK_PRIORITY_HIGHEST - 4)

ble_mgr.cThe ble manager task.
ad_ble_task

mainBLE_TASK_PRIORITY

(OS_TASK_PRIORITY_HIGHEST - 3)

ad_ble.cThe ble adapter task.
usb_charger_taskOS_TASK_PRIORITY_HIGHEST – 2sys_charger.cThe USB Charger task.
usb_charger_fsm_taskOS_TASK_PRIORITY_HIGHEST - 2sys_charger.cThe USB Charger FSM task.
prvTimerTask

configTIMER_TASK_PRIORITY

(configMAX_PRIORITIES - 1)

timers.cThe timer task.
system_initOS_TASK_PRIORITY_HIGHESTmain.cThe System Initialization task.
../_images/image04_01.png

Figure 6 pxp_reporter task priorities

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:

10.2. Operating System Abstraction Layer

10.2.1. Scope

The SmartSnippets™ DA1468x offers an Operating System Abstraction Layer (OSAL), which:

  • Facilitates porting to an RTOS other than FreeRTOS, by providing RTOS-agnostic wrappers around FreeRTOS Application Programming Interface (API).
  • Provides resource management (i.e. exclusive access) capabilities.
  • Provides a message-queue data structure.
  • The OSAL source files are located under <sdk_root_directory>/sdk/bsp/osal/:

    Table 5 Source files for OSAL
    Source filesDescription
    msg_queues.cMessage queues implementation.
    msg_queues.hMessage queues API.
    osal.hRTOS-agnostic API wrappers.
    resmgmt.cResource management implementation.
    resmgmt.hResource management API.

    10.2.2. RTOS-agnostic API

    OSAL provides wrappers of the FreeRTOS API for the following RTOS primitives, presented in Table 6.

    Table 6 OSAL wrappers of the FreeRTOS API
    DescriptionAPI
    Tasks/ThreadsOS_TASK_*
    MutexesOS_MUTEX_*
    Events/NotificationsOS_EVENT_*
    Thread-safe queuesOS_QUEUE_*
    Memory allocationOS_MALLOC_*
    Memory de-allocationOS_FREE_*
    TimersOS_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:

    Table 7 OSAL resource management API
    FunctionDescription
    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:

    Table 8 OSAL message queues functions
    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