2. Software Platform Overview

This section gives an overview of the overall platform including the software architecture that supports the DA1453x/DA1458x SoC Platform. Figure 9 shows a diagram of the overall software architecture and provides a visual overview of the various layers of software that are involved. The following paragraphs of this document provide a high level description of the functionality of each layer and the APIs that each layer exposes to the application programmer.

../_images/image11.png

Figure 9 Software Architecture

2.1. System Software and Main Loop

At system start up the main function initializes the system and gets into the main loop. The key concept is simple: check if the BLE is active, and if it is, provide CPU time to the kernel scheduler to process all pending messages and events. Next, inquire if the user application has non-message related tasks to do. If both kernel and user application have nothing more to do, then quickly transition into low power mode and wait for an interrupt to start again. The main loop is not intended to be altered by the user application.

A set of callbacks are provided that notify the application about the state of the main loop. We often use the term asynchronous execution for these callbacks to distinguish them from other events and callbacks that are generated from within the kernel scheduler, which is referred to as synchronous execution. The application can partially control the main loop with the return value of the callbacks or by setting the sleep settings accordingly. It is important to understand here, that the Kernel scheduler is called from within the main loop when the BLE is active. If we do not grant control back to the main loop or if the BLE is inactive, the processing of the kernel messages is delayed.

2.2. Peripheral and Radio Drivers

The system software incorporates a number of drivers for the peripheral devices, the radio and some hardware specific blocks of the BLE. Application programmers are able to use the peripheral drivers, however the rest of the drivers are to be used only by the kernel and BLE controller software.

2.3. Real-Time Kernel

The DA1453x/DA1458x software platform utilizes a small and efficient Real-Time Kernel licensed from Riviera Waves. Almost the complete BLE Stack and most of the application makes use of the services offered by the Real-Time Kernel. The kernel offers task, message, events and dynamic memory capabilities. The tasks communicate with messages, which are pushed in a queue whenever a task is trying to send a message to another task. Timers and other hardware events also push events in a queue. Whenever the kernel scheduler is called from the main loop it pops messages and events out of the queues according to their priority and invokes the relevant handler, to trigger the execution of the different tasks. The execution continues until the queues are empty.

2.3.1. Overview

The DA1453x/DA1458x software platform utilizes a small and efficient Real-Time Kernel licensed from Riviera Waves. The kernel offers the following features:

  • Task creation and state transition

  • Message exchange between tasks

  • Timer management

  • Dynamic memory allocation

  • BLE events scheduling and handling

2.3.2. Scheduler

The core of the kernel is a scheduler that runs in the main loop of the application. The scheduler checks if an event is set and calls the corresponding handler to service the pending events. The event may be a BLE or a timer event, or a message between two tasks.

The scheduler obtains any of the timing information from the BLE core hardware. The main loop code ensures that the kernel scheduler is not executed while the hardware module of the BLE core is not in sleep mode.

The implementation of the kernel resides in the ROM memory area. Because of that the source code files are not included in the SDK distribution. The definitions of the API types and the prototypes of API functions can be found in the following header files.

  • ke_task.h - Kernel task management and creation API

  • ke_msg.h - Message handling API

  • ke_mem.h - Dynamic memory allocation API

  • ke_timer.h - Timer creation and deletion API

2.3.3. Tasks

Each standalone software module, i.e. BLE stack layers/GATT profiles/Host application et cetera, of the DA1453x/DA1458x SDK is instantiated as a task of the kernel. The task is usually created at system initialization. The maximum supported number of tasks in a single BLE application is 23.

A task is defined by the task ID number, which is a unique identifier per task and a task descriptor structure. The type of the structure is struct ke_task_desc and is defined in ke_task.h. The members of the task descriptor determine the message handlers for each state of the application, the default message handlers, the placeholder of the current task state, the highest valid state of the task and the maximum number of task instances.

The task is created by calling the ke_task_create() function. The task ID and descriptor are passed into the function parameters.

The state of the task is changed by calling ke_task_set() function. The current state of the task is returned by ke_state_get() function.

All the API functions and types of kernel task creation and management are declared in the ke_task.h header file.

  • Types:

    • ke_msg_handler – Message handler structure

    • ke_state_handler – List of message handlers for a specific or default state

    • ke_task_desc - Task descriptor

  • Functions:

    • ke_task_create() – Creates a new task

    • ke_state_set() – Sets the state of the task

    • ke_state_get() – Returns the current state of the task

2.3.4. Dynamic Memory Allocation

The kernel provides an API to the application code for dynamic memory allocation in the heap memories of the kernel. There are four heap memory areas defined in DA1453x/DA1458x kernel:

  • KE_MEM_ENV – Used for environmental variables memory allocation

  • KE_MEM_ATT_DB – Used for ATT protocol databases, i.e. services, characteristics, attributes

  • KE_MEM_KE_MSG – Used for kernel messages memory allocation

  • KE_MEM_NON_RETENTION – General purpose heap memory. If the allocated memory space in this heap is non zero, when the system decides to enter sleep (extended sleep with or without OTP copy), then the RAM memory blocks, which are touched by the non retention heap, must be retained.

The size of the heap memories is determined either by the user via the per target configuration file da1458x_config_advanced.h:

  • da14585_config_advanced.h for DA14585/586

  • da14531_config_advanced.h for DA14531-0x

  • da14535_config_advanced.h for DA14535, or

automatically by the SDK file da1458x_scatter_config.h.

Dynamic memory allocation in any of these heaps is done by calling the ke_malloc() function. The size and the selection of the heap memory are passed in the parameters of the function. If the memory space in the selected heap memory is insufficient, then the kernel memory management code will try to allocate the requested memory space in another heap. If memory allocation fails in all heap memories of the kernel, then a system software reset is issued.

The API functions provided by the kernel are:

  • ke_malloc() – Allocate the requested memory space

  • ke_msg_free() – Free the allocated memory space at the requested memory address

Note

To enable the logging of heap memory usage, which is a feature that can be used in development/debug mode, an application must be executed in the Keil debugger environment.

  • For SDK-6.0.18 and previous versions the default library (<target>.lib file) must be replaced with the target specific library file that supports the heap logging mechanism. For example, in case of DA1458x, this is the library file da14585_586_with_heap_logging.lib.

  • For SDK-6.0.22 and forth the developer must build the application with the macro CFG_USE_HEAP_LOG defined in system_library.h header file.

Then, the developer must stop the program execution in debug mode and type in the Keil debug command line box the disp_heaplog keyword. This will show the heap memory statistics.

2.3.5. Messages

The kernel provides a mechanism to exchange messages between tasks. The messages exchanged by the kernel have a specific format. The format is determined by the struct ke_msg type defined in ke_msg.h. The ke_msg structure includes the following members:

  • id: A 16-bit unsigned integer that contains the message identification. The ten least significant bits form a sequential number that is unique among the messages of the task. In the six most significant bits is the ID of the task, to ensure the uniqueness of the message identification in the system. The macro KE_BUILD_ID can be used to build message IDs compliant to this convention.

  • dest_id: Task ID of the destination task of the message.

  • src_id: Task ID of the source task of the message.

  • param_len: Size of the message data contained in param.

  • param: The placeholder of the message data. The type of the structure member is a one position table of a 32-bit unsigned integer. However the size of the allocated memory space is determined by the heap memory, which is allocated by the message memory allocation function and is equal to param_len.

The transmission of a message is done in three steps:

  1. Allocation of a message structure by the sender task. One of the following macros is called for message allocation:

    • KE_MSG_ALLOC: Allocates space in KE_MEM_KE_MSG heap memory for the message. Message ID, source and destination task IDs, and the type of message data are passed in the parameters of the function. A function calculates the memory space to allocate based on the type of data. Returns a pointer to the start of the data of the allocated message.

    • KE_MSG_ALLOC_DYN: Similar to KE_MSG_ALLOC. Additional memory size to the size of data type is passed in an additional parameter.

  2. Fills in the message parameters. The code of the source task should fill in the data of the message.

  3. Pushes the message structure in the kernel.

Function ke_msg_send() is called to send the message to the destination task. The pointer returned by KE_MSG_ALLOC or KE_MSG_ALLOC_DYN must be passed in the parameter of the function. If the message is allocated but not sent, ke_msg_free() must be called to free the allocated memory space.

The reception of a message sent to a task is implemented by defining a message handler function (structure ke_msg_handler) in the task descriptor of the message (ke_task_desc). A state handler should return KE_MSG_CONSUMED when the message is consumed by the destination task and return KE_MSG_NO_FREE when the message is forwarded to another task. Function ke_msg_forward() must be used for this operation.

2.3.6. Timer

The DA1453x/DA1458x kernel provides timer services to create and delete a timer event. The time reference of the kernel timers is the BLE_GROSS_TIMER of the BLE HW core. The precision of the BLE_GROSS_TIMER timer is 10 ms. The task that requested the timer event will be notified with a message about the expiration of the timer. The message ID is equal to the timer ID used for timer creation. Therefore, the timer ID must be a valid message ID. A timer handler function must also be defined in the list of task handlers. Kernel timers are one-shot timers.

  • API functions:

    • app_timer_set() – This is a wrapper of ke_timer_set(). Timer ID, task ID and timeout in units of 10 ms. The maximum valid timeout is 4194300, which corresponds to a period of 699 minutes.

    • ke_timer_delete() – Deletes an active kernel timer.

2.4. Bluetooth Low Energy Software

The BLE software implements the Bluetooth® Low Energy protocol as specified in Version 5.0 (DA14585/586), 5.1 (DA14531-0x) and 5.3 (DA14535) of the Bluetooth® standard and complies with these standards. It is a single-mode BLE implementation. Therefore there is no support for the Basic Rate / Enhanced Data Rate protocol (BR/EDR).

The basic parts of the BLE software consists of the Host and Controller related software.

Each layer (ATT, GATT, GAP, etc.) of the stack is instantiated as multiple different tasks. The radio events are captured by the drivers and fed to the low level software of the BLE controller. The event handlers spawn messages that trigger the protocol layers. If user action or user notification is required, this sequence of messages will dispatch messages to the application or profile task. In the reverse direction, if the user application wants to do a specific operation, it dispatches messages to the lower layers, beginning a sequence of messages that may reach, depending to the operation, the BLE controller and the radio.

On top of the Host, a library of ready to use profiles and some profile utilities are provided to simplify application development. Programmers should interface with the profile, GATT and GAP modules to do all of the functionality required by a BLE application.

In this section the Bluetooth Low Energy layers of the software architecture are described.

2.4.1. Overview

Figure 10 presents a diagram of the Bluetooth Low Energy software architecture.

../_images/image41.png

Figure 10 Bluetooth Low Energy Software

Most of the BLE controller for the DA1453x/DA1458x is implemented in hardware. On top of the controller, the Host is implemented with all the required layers. The L2CAP and SMP are internal layers within the stack and are not intended for direct access from the application, although this is possible. Most of the ATT layer should not be accessed from the application directly, since its functionality is provided through GATT. The attribute database API may be used to implement profile related functionality.

The GAP and GATT layers are built on top of the ATT and SMP. Those two layers form the borderline of the Host with the application. The majority of the operations can be done with the use of those two APIs. To further assist the development, the DA1453x/DA1458x SDK provides a library of ready-to-use profile implementations. Those profiles make use of the GATT and ATT APIs and a set of helper functions gathered within the prf_utils.c. The profiles expose a message API and a set of function calls to the application.

The code of the Host is pre-compiled and burned into ROM while the profile implementation and the prf_utils.c are provided in source code, compiled with the application and run in RAM. The symbols of the ROM are included into file:

  • da14585_symbols.txt for the DA14585/586 ROM.

  • da14531_symbols.txt and da14531_01_symbols for the DA14531-0x ROM.

  • da14535_symbols.txt for the DA14535 ROM.

and linked with the user application during the build process.

The arrows in Figure 10 designate the APIs that a user application can use. Moreover, these are also listed in Table 2 as a reference.

Table 2 Bluetooth Low Energy Software API

API

API Files

ATT Database

attm_db.h

GAP Manager

gapm.h

gapm_task.h

gapm_util.h

GAP Controller

gapc.h

gapc_task.h

GATT Manager

gattm.h

gattm_task.h

GATT Controller

gattc.h

gattc_task.h

Profile Utilities

prf_utils.h

prf_utils_128.h

prf_types.h

<Profile>

<profile>.h

<profile>_task.h

Custom Profile

custs1_task.h

custs1.h

custs2_task.h

custs2.h

The following sections describe the role and usage of the various APIs. For more information please see the documents that describe each layer.

2.4.2. GAP

The RW-BLE Generic Access Profile (GAP) defines the basic procedures related to the discovery and link management of Bluetooth devices. Furthermore, it defines procedures related to the use of different LE security modes and levels.

The RW-BLE GAP provides complete and substantial support for the LE GAP:

  • Four Roles: central, peripheral, broadcaster and scanner

  • Broadcast and Scan

  • Modes: Discovery, Connectivity, Bonding

  • Security with Authentication, Encryption and Signing

  • Link Establishment and Detachment

  • Random and Static Addresses

  • Privacy Features

  • Pairing and Key Generation

The RW-BLE GAP is divided into two parts: the GAP Manager (GAPM) and the GAP Controller (GAPC). The GAP Manager manages all application requests that are not related to an established link. The GAP Controller (called GAPC) on the other hand is created upon a connection to a peer device and deleted when the connection is terminated.

The GAP Manager initialization takes place in the system_init() function. When the GAP entity has been initialized and ready to provide services to the upper layers, the GAP entity dispatches the GAPM_DEVICE_READY_IND message. This message is handled internally in the GAP application module. In response, the GAP module configures the GAP Manager to a specific role, to send a GAPM_SET_DEV_CONFIG message. After the GAP Manager configuration is complete, the device is ready to initialize the databases, and then according to the selected role, do operations such as scanning and advertising to establish connections with other peers.

For example, in order to start advertising, the GAPM_START_ADVERTISE_CMD message is compiled and sent to the GAPM. A message is allocated with the the KE_MSG_ALLOC macro. For example:

struct gapm_start_advertise_cmd cmd = KE_MSG_ALLOC(GAPM_START_ADVERTISE_CMD,
                                                   TASK_GAPM,
                                                   TASK_APP,
                                                   gapm_start_advertise_cmd);

The message is filled with the necessary data:

cmd->op.code        = GAPM_ADV_UNDIRECT;
cmd->op.addr_src    = GAPM_PUBLIC_ADDR;
cmd->intv_min       = APP_ADV_INT_MIN;
cmd->intv_max       = APP_ADV_INT_MAX;
cmd->channel_map    = APP_ADV_CHMAP;
cmd->info.host.mode = GAP_GEN_DISCOVERABLE;

and is then sent to the GAPM task. The result is to start an undirected advertising operation.

When a remote peer tries to connect to the device, the GAP Controller will report the peer’s request with the GAPC_CONNECTION_REQ_IND to the application. Since the stack is now referring to a specific connection, the messages will now be delivered from/to the related GAP Controller. The application GAP handler will respond to this request with the desired security requirements and will try to establish a secure or non-secure connection with the peer according to the requirements. The security management protocol messages arrive at the application through the GAP Controller. After a secure connection is established, the device is connected and can start to use the available profile services. Each service may have its own security requirement and establishing a connection with adequate security will expose the services to the peer.

2.4.3. BLE Data Services

After an connection with the peer device is established, the GAP related operations only manage certain aspects of the connection such as change connection parameters, security level or to drop the connection. The data services of a BLE connection are provided through the database. The BLE stack provides numerous APIs to the application to manage and exchange data with local and remote databases. Those are the GATT Manager API and GATT Controller API. Alternatively, the programmer can also make use of the Attribute database API (ATTDB) directly instead of going through GATT to add and manage services and characteristics in the database. The reason behind this is to produce smaller and efficient code. The user can use either approach, through GATT or directly to ATTDB.

2.4.3.1. GATT

Similar to GAP, GATT consists of two modules: the GATT Manager and the GATT Controller. The GATT Manager is not related to a specific connection and is instantiated once to provide a message API that is used to manage the internal attribute database. The GATT Manager is put between either the profile or the application and the ATT Manager, and conveys messages between them. It provides service and attribute operations such as adding services and characteristics to the database, setting and getting permission level, and setting and getting values to attributes.

The GATT controller is related to a specific BLE connection instance. The interface is used in both client and server roles. In a client role the interface is used to discover, read and write attributes of peer devices and to receive notifications or indications. In a server role, this interface is notified when modification of the database is requested by the peer device, and to send indications or notifications.

2.4.3.2. ATTDB

Instead of using the GATT Manager API, the user can directly access the native attribute database API. The ATTDB API provides functions to add elements to the database (services and attributes), choose the position of the element in the database, hide/show attributes as well as manage the permissions and their value. For a detailed description of the ATTDB supported functions, please see the files attm_db.h, attm_db_128.h and attm_util.h.

2.4.4. BLE Profiles

The SDK provides implementations of various profiles each with its own profile specific API exposed to the application. Please check the Dialog support website for an updated list of the supported profiles from the SDK. There are two distinct roles: the server role and the client role. The server exposes a profile database on the local device. A client reads, writes and manages the database of a remote device.

Every profile server implements generic and profile-specific functionality. The generic part includes:

  • The profile database description, with all the services and attributes

  • The profile initialization function to create the profile task

  • The database creation handler that creates the database when the application task issues the relevant message

  • The profile enable handler that enables the database when the application task issues the relevant message

  • The profile disconnect handler that takes care of profile housekeeping operations when the connection drops

Depending on the profile, the profile specific part may include update of specific attributes with or without notification and handling and verification of write attempts from peer devices.

Similar principles apply for the client profile as well. The client will include a description of the services to expect, functions and message handlers to initialize, enable the client, housekeep the discovery results and handlers for errors and disconnections. Depending on the specific profile special handlers for read and write operation, and reception of notifications may exist, tied to specific attributes. For detailed information please see the available documents for every profile located in the support site, or browse through the <profile>.h and <profile>_task.h header files.

The SDK provides a useful set of helper functions to access the GATT and ATTDB services. They are located in the prf_utils.h and are used frequently in the existing profile code. For detailed information, please see prf_utils.h.

  • The source codes for the different BLE profiles can be found in the folder: <SDK_root>sdk\ble_stack\profiles of the SDK.

2.4.5. LE Data Packet Length Extension

For Bluetooth Core versions 4.0 and 4.1 the maximum Data Physical Channel PDU size was 27 octets. Bluetooth Core version 4.2 introduced an important enhancement, namely LE Data Packet Length Extension, which allows for the Data Physical Channel PDU size to be anywhere between 27 and 251 octets. This means that, for example, the L2CAP layer can now fill up to 244 data octets of higher layer data packets in every L2CAP PDU compared to 20 octets with previous Bluetooth Core versions. This increase is more than 10 times higher. Therefore, the increase in amount of useful user data sent per packet allows devices to transfer data up to 2.5 times faster compared with previous versions. This will be of great benefit to applications that might require the transfer of large amounts of data. For example, Over-the-Air (OTA) firmware updates or the download of large data logs from sensors.

For the default Data Physical Channel PDU size to be extended on an established connection, the Data Length Update procedure must be done. According to this control procedure, the LL_LENGTH_REQ and LL_LENGTH_RSP LL control PDUs must be exchanged by the connected devices so that each is notified of the peer device’s capabilities. After this exchange is done, the two controllers select the minimum exchanged values on their Rx and Tx data paths.

All the DA1453x/DA1458x devices support the LE Data Length Extension feature. Its usefulness can be assessed by the SDK examples which can transfer big chunks of data when an OTA firmware update is taking place.

Note

Not all the BLE peer devices will be capable of utilizing DLE. Please check the version installed in the peer devices. If the peer device does not support DLE, the default Data Physical Channel PDU size will be 27 octets on both sides.

2.5. Application Software

Although the provided message API is powerful and complete, there are some restrictions on how fast and how easy one can build an application. To address this issue in the Software Development Kit (SDK), a new layer is introduced that is depicted as SDK Application, which collects part of the common functionality required to build an application in a library and exposes a number of APIs and helper functions. Care has been taken to hide the task management and message management as much as possible from the user and provide a function/callback-like API.

2.5.1. Overview

Messages are generated from different layers of the BLE stack and the profile code, to signal events to the application task. The application on the other hand generates messages and sends the messages to the stack to begin numerous operations.

There are two distinct directions for the messages.

  • Messages from the stack and the profiles to the application task

  • Messages from the application task to the stack and the profiles

Although the provided message API is powerful and complete, there are some restrictions on how fast an application can be built. And the minimum amount of knowledge about the system required to build even a simple application. To address this issue in the SDK, part of the common functionality required to build an application has been collected in a library, which exposes a number of APIs and helper functions. Care has been taken to hide the task management and message management as much as possible from the user and to provide a function/callback like API.

In addition, most of the parameters required to do operations have been turned into constants that are defined in the user space. A set of working constants are predefined for the user in the template project.

2.5.2. API

Figure 11 shows a detailed diagram of the application architecture that consists of two parts:

  • SDK Application: This part is defined in the SDK and implements the library functionality.

  • User Application: This part contains configuration constants and callback definitions and is provided from the template. It configures the operation of the SDK application library. The source code of the actual user application resides here.

../_images/image51.png

Figure 11 Application Architecture

As mentioned earlier, there are two message directions. The API description starts with the possible ways the User Application can send messages toward the stack and the profiles. Next the available ways the User Application can get messages from other tasks and profiles are described.

2.5.3. Message API

The standard and most versatile way to execute operations in the stack and profiles is when the message API is used. This includes the standard message allocation and message send functions of the kernel together with the message list supported from every task. The message list and the data structure of each message are usually defined in file <destination_task>_task.h. Please see the relevant documents of each task (gapm, gapc, gatt, etc.) for further details.

Whenever a function is not provided from the app_mid.h and app_easy.h APIs, described later in this document, the user can use the message API.

2.5.3.1. Mid Layer API

The Mid Layer API is a light stateless set of macros to describe how the most common operations for the gap and security are done. It describes the generation of a specific message, how to fill the message with data and the dispatch of the message to the required task. The idea behind it is to provide a function API rather than a message API. The following pattern is used:

  • <message pointer*> app_<message_name>_msg_create(): Allocates a message and fills in the correct destination task.

  • void app_<message_name>_msg_send(<message pointer*>): Sends the message.

  • void <operation>_op(parameters): Does the complete operation. The <operation>_op function usually creates a message, fills the message with the required data as provided from the caller through the parameters, and dispatches the message.

The complete Mid Layer API is described in the app_mid.h file in <sdk_root>/sdk/app_modules/api folder.

2.5.3.2. Easy API

The Easy API concept tries to reduce the burden of the application programmer for message handling, task handling and special sequences that are required to correctly do some actions in the stack or kernel.

The Easy API also addresses the fact that the majority of the data used in the messages are constants at compile time. Asking the programmer to provide all of the constants when a function call is done, is cumbersome and produces larger code. Moreover, there are a lot of these constants that need to be defined even for the simplest of applications. This makes it challenging for a novice programmer to quickly bring his program into an operational state.

For this reason most, if not all, of the constants are predefined in the user application space from the template and accessed from the Easy API at compile time. The programmer can quickly bring up his application and then alter the default behavior. Usually behavior alteration only requires the programmer to change the proper constant parameters and to recompile the code. As a plus, the small number of parameters used in the function calls of the Easy API provides better readable code and better visibility to the programmer.

The design pattern used for the Easy API is shown in Figure 12.

../_images/image61.png

Figure 12 Easy API Design Pattern

Every app_easy_<operation> exposed to the user has a static app_easy_<operation>_msg_create() function and a pointer (msg_pointer). When the user calls the app_easy_<operation>() function, the relevant msg_create() function is called. The message create function will check if the msg_pointer points to a message that has already been created for this operation or not. If a message is already there, the existing message is returned to the app_easy_<operation>() function. If no message exists it will create a new message, fill the message with constant data provided from the user configuration data files and assign the message to the msg_pointer. The app_easy_<operation>() will send the message and clear the msg_pointer.

This means that every time the app_easy_<operation>() either creates a new message or sends and automatically consumes an existing message. To support dynamic configuration of the messages the app_easy_<operation>_get_active() function is provided. This function will call the message create function and return the pointer to the active message. This way the user application can alter the message dynamically.

To save memory space, there are operations that may share the msg_pointer, for example the different app_easy_<type>_advertise() operations.

2.5.4. app_<profile> API

For some of the profiles provided with the SDK an additional application layer exists, which exposes the create database, initialization and profile specific operation functions. Please see the relevant header file for the list of functions supported for each profile.

2.5.5. App Entry Point API

In the SDK there is a piece of software that handles the messages that arrive in the application task. This module is called app_entry_point.c. The messages that arrive at the app_entry_point_handler() will be delivered to all the included application modules of the SDK until a module acknowledges that the message is handled, in which case the application entry point returns the state of the message, as it has been reported, to the kernel scheduler.

In case a message has not been handled by any module, the message will be delivered to the application through the app_process_catch_rest_cb() function pointer where the user can hook his message handler. The messages that arrive at the user space are always considered consumed and cannot be saved or forwarded.

Together with the app_entry_point_handler() and the app_process_catch_rest_cb() function pointer, the app_entry_point.c module also exposes a set of EXCLUDE_DLG_<MODULE> options defined in user_modules_config.h. These options can be used to disable specific message handlers of the SDK to receive the messages in the user application space via the app_process_catch_rest_cb(). This allows the user to override or extend the functionality of the existing SDK modules without the need to touch any SDK files.

2.5.6. User Callback API

The SDK provides numerous modules that are hooked on the entry point to handle messages sent to the application task. The primary function of the modules is to transform the received messages into events, which are exposed to the user application space as function pointers with meaningful names and parameters. There are also modules that implement a lot of application functionality, such as the app_suotar_task.c. The modules that follow this pattern are the gap, security, and all the existing app_<profile>_task.c modules.

The library looks for the value of the pointers in user_callback_config.h. There the user can assign a new function of his application to be called upon a specific event. The GAP and Security related function pointers are grouped in the user_app_callbacks structure, while the profile related pointers (for profiles with an app_<profile>_task.c) are grouped in the user_profile_callbacks structure. For example, this structure may be initialized as follows:

static const struct app_callbacks user_app_callbacks = {
    .app_on_connection                  = default_app_on_connection,
    .app_on_disconnect                  = user_app_on_disconnect,
    .app_on_update_params_rejected      = NULL,
    .app_on_update_params_complete      = NULL,
    .app_on_set_dev_config_complete     = default_app_on_set_dev_config_complete,
    .app_on_adv_nonconn_complete        = NULL,
    .app_on_adv_undirect_complete       = app_advertise_complete,
    .app_on_adv_direct_complete         = NULL,
    .app_on_db_init_complete            = default_app_on_db_init_complete,
    .app_on_scanning_completed          = NULL,
    .app_on_adv_report_ind              = NULL,
    .app_on_get_dev_name                = default_app_on_get_dev_name,
    .app_on_get_dev_appearance          = default_app_on_get_dev_appearance,
    .app_on_get_dev_slv_pref_params     = default_app_on_get_dev_slv_pref_params,
    .app_on_set_dev_info                = default_app_on_set_dev_info,
    .app_on_data_length_change          = NULL,
    .app_on_update_params_request       = default_app_update_params_request,
    .app_on_generate_static_random_addr = default_app_generate_static_random_addr,
    .app_on_svc_changed_cfg_ind         = NULL,
    .app_on_get_peer_features           = NULL,
#if (BLE_APP_SEC)
    .app_on_pairing_request             = default_app_on_pairing_request,
    .app_on_tk_exch                     = default_app_on_tk_exch,
    .app_on_irk_exch                    = NULL,
    .app_on_csrk_exch                   = NULL,
    .app_on_ltk_exch                    = default_app_on_ltk_exch,
    .app_on_pairing_succeeded           = NULL,
    .app_on_encrypt_ind                 = NULL,
    .app_on_encrypt_req_ind             = NULL,
    .app_on_security_req_ind            = NULL,
    .app_on_addr_solved_ind             = NULL,
    .app_on_addr_resolve_failed         = NULL,
    .app_on_ral_cmp_evt                 = NULL,
    .app_on_ral_size_ind                = NULL,
    .app_on_ral_addr_ind                = NULL,
#endif // (BLE_APP_SEC)
};

2.5.7. Default Handlers

Simple BLE peripheral applications to a large extent share common functionality. They should advertise and respond to specific requests from the central device to establish a connection. To minimize the amount of code that is required from an application programmer to start an application, a library of Default Handler functions is created. These functions are already hooked from the template project in the user callbacks, giving a working peripheral device without writing a single line of code. The programmer can then alter the functionality, and override the default functionality.

The default handlers have their own configuration options and function hooks as well. The user can configure the advertise operation scenario or the security request scenario of the peripheral as implemented by the default handlers, in the app_default_handlers.c file. The user can also override the advertise operation entirely in the user_default_app_operations structure.

2.5.8. User Configuration Description

The user_config folder for each project, contains all the necessary user configuration files to develop a BLE application.

Folder user_config is located in: <sdk_root>\projects\target_apps\ble_examples\<ble-project>\src\config

The user_config folder structure is shown in Figure 13.

../_images/image71.png

Figure 13 user_config Folder Structure in Keil Projects

2.5.8.1. Files da1458x_config_basic.h and da1458x_config_advanced.h

These header files contain only macros definitions for the target device configuration based on the application needs. From SDK-6.0.22 and forth these configuration header file (basic and advanced) are distinguished per target device:

  • Use da14585_config_basic.h and da14585_config_advanced.h for DA1458x.

  • Use da14531_config_basic.h and da14531_config_advanced.h for DA14531-0x.

  • Use da14535_config_basic.h and da14535_config_advanced.h for DA14535.

Note

For any details regarding on the macros usage refer to the respective configuration header files, per SDK example and per target device. The configuration header files contain detailed information.

2.5.8.2. File user_callback_config.h

This header file holds callback functions that handle various events or operations.

Several events can occur during the lifetime of the BLE application and these events need to be handled in a specific manner. Also, operations need to be served depending on the application scenario. It depends on the application itself to define which events and operations are handled and how. The SDK is flexible enough to either call a default handler or call the user-defined event or operation handler.

The SDK mechanism that takes care of the above requirements, is the registration of callback functions for every event or operation. The C header file user_callback_config.h, which resides in the user space, contains the registration of the callback functions.

Note: For reference, the user_callback_config.h file of the prox_reporter BLE demo project is presented in the following sections.

The prox_reporter BLE demo project registers the following callback functions:

2.5.8.2.1. Callbacks for General BLE Events
static const struct app_callbacks user_app_callbacks = {
    .app_on_connection                  = default_app_on_connection,
    .app_on_disconnect                  = user_app_on_disconnect,
    .app_on_update_params_rejected      = NULL,
    .app_on_update_params_complete      = NULL,
    .app_on_set_dev_config_complete     = default_app_on_set_dev_config_complete,
    .app_on_adv_nonconn_complete        = NULL,
    .app_on_adv_undirect_complete       = app_advertise_complete,
    .app_on_adv_direct_complete         = NULL,
    .app_on_db_init_complete            = default_app_on_db_init_complete,
    .app_on_scanning_completed          = NULL,
    .app_on_adv_report_ind              = NULL,
    .app_on_get_dev_name                = default_app_on_get_dev_name,
    .app_on_get_dev_appearance          = default_app_on_get_dev_appearance,
    .app_on_get_dev_slv_pref_params     = default_app_on_get_dev_slv_pref_params,
    .app_on_set_dev_info                = default_app_on_set_dev_info,
    .app_on_data_length_change          = NULL,
    .app_on_update_params_request       = default_app_update_params_request,
    .app_on_generate_static_random_addr = default_app_generate_static_random_addr,
    .app_on_svc_changed_cfg_ind         = NULL,
    .app_on_get_peer_features           = NULL,
#if (BLE_APP_SEC)
    .app_on_pairing_request             = default_app_on_pairing_request,
    .app_on_tk_exch                     = default_app_on_tk_exch,
    .app_on_irk_exch                    = NULL,
    .app_on_csrk_exch                   = NULL,
    .app_on_ltk_exch                    = default_app_on_ltk_exch,
    .app_on_pairing_succeeded           = NULL,
    .app_on_encrypt_ind                 = NULL,
    .app_on_encrypt_req_ind             = NULL,
    .app_on_security_req_ind            = NULL,
    .app_on_addr_solved_ind             = NULL,
    .app_on_addr_resolve_failed         = NULL,
    .app_on_ral_cmp_evt                 = NULL,
    .app_on_ral_size_ind                = NULL,
    .app_on_ral_addr_ind                = NULL,
#endif // (BLE_APP_SEC)
};

The above structure defines that a certain event is processed by a default handler or by a user-defined handler or it will not be processed at all (NULL entries).

2.5.8.2.2. Callbacks for System Specific Events
#if (BLE_APP_SEC)
static const struct app_bond_db_callbacks user_app_bond_db_callbacks = {
    .app_bdb_init                       = NULL,
    .app_bdb_get_size                   = NULL,
    .app_bdb_add_entry                  = NULL,
    .app_bdb_remove_entry               = NULL,
    .app_bdb_search_entry               = NULL,
    .app_bdb_get_number_of_stored_irks  = NULL,
    .app_bdb_get_stored_irks            = NULL,
    .app_bdb_get_device_info_from_slot  = NULL,
};
#endif // (BLE_APP_SEC)

The above structure defines that a certain event is processed by a default handler or by a user-defined handler, or will not be processed at all (NULL entries). By default, a bond database is implemented in app_bond_db.c. However, a user implementation of the bond database can be hooked to the above callback table.

2.5.8.2.3. Callbacks for BLE Operations
// Default Handler Operations
static const struct default_app_operations user_default_app_operations = {
    .default_operation_adv = default_advertise_operation,
};

The structure above defines that a certain operation is processed by a default handler or by a user-defined handler or will not be processed at all (NULL entries).

2.5.8.2.4. Callbacks for Custom Profile Message Handling
//Put in this structure the app_<profile>_db_create and app_<profile>_enable functions
//for SIG profiles that do not have this function already implemented in the SDK
//or if you want to override the functionality. Check the prf_func array in the SDK
//for your reference of which profiles are supported.
static const struct prf_func_callbacks user_prf_funcs[] =
{
    {TASK_ID_INVALID,    NULL, NULL}   // DO NOT MOVE. Must always be last
};

Put in this structure the app_<profile>_db_create() and app_<profile>_enable() functions for SIG profiles that do not have this function already implemented in the SDK or if you want to override the functionality. Check the prf_func array in the SDK for your reference of which profiles are supported.

2.5.8.3. File user_config.h

This file holds the user-defined parameters for:

  • Security configuration:

    • IO capability:

      • Display Only

      • Display Yes No

      • Keyboard Only

      • No Input No Output

      • Keyboard Display

    • OOB (Out of Band) support (only in Legacy Pairinig)

    • Authentication requirements:

      • No authentication

      • Bonding

      • MITM (Man in the Middle) protection

      • Secure connection

    • Encryption key size configuration

    • Device security requirements:

      • No security (no authentication and encryption)

      • Unauthenticated pairing with encryption

      • Authenticated pairing with encryption

      • Authenticated LE Secure Connections pairing with encryption

      • Unauthenticated pairing with data signing

      • Authentication pairing with data signing

    • Initiator key distribution (any combination of the below):

      • No Keys to distribute

      • LTK (Encryption key) in distribution

      • IRK (ID key)in distribution

      • CSRK (Signature key) in distribution

    • Responder key distribution (any combination of the below):

      • No Keys to distribute

      • LTK (Encryption key) in distribution

      • IRK (ID key)in distribution

      • CSRK (Signature key) in distribution

  • Sleep mode:

    • No sleep

    • Extended sleep without OTP copy on wake-up

    • Extended sleep with OTP copy on wake-up

Note

The above sleep modes may be reconfigured during the DA1453x/DA1458x runtime, if the user calls the respective API function.

Note

DA1453x/DA1458x will enter the configured extended sleep mode if and only if specific requirements are met during the runtime, e.g. there is enough sleep time until the next programmed BLE event, etc.

Note

DA1453x/DA1458x can enter the deep sleep mode, if the user explicitly calls the respective API function.

Note

DA1453x can enter the hibernation mode, if the user explicitly calls the respective API function.

  • Advertising configuration:

    • min-max advertising interval

    • advertising channel map (channels 37, 38, 39)

    • advertising mode:

      • Non discoverable mode

      • General discoverable mode

      • Limited discoverable mode

      • Broadcaster mode

    • advertising filter policy

    • address of peer device for connectable directed advertising (ADV_DIRECT_IND)

    • address type (public or random) for connectable directed advertising (ADV_DIRECT_IND)

  • advertising data

  • device name (appended to advertising or scan response data if there is space left)

  • device configuration:

    • GAP role:

      • central

      • peripheral

      • observer

      • broadcaster

    • MTU size

    • address type:

      • public address

      • static random address

      • private random resolvable address

      • private random non-resolvable address

    • Renewal duration for private random address

    • static ranodm address (can be configured automatically as well)

    • IRK used for private random addrress generation

  • parameter update configuration (for L2CAP):

    • min-max suggested connection interval

    • suggested slave latency

    • suggested supervision timeout

    • suggested min-max connection event duration

  • default handlers configuration:

  • configuration parameters for central role:

    • connection mode:

      • direct connection operation

      • automatic connection operation

      • selective connection operation

      • name request operation (requires to start a direct connection)

    • scan interval

    • scan window

    • min-max connection interval

    • slave latency

    • supervision timeout

    • min-max connection event duration

    • peer device information (address and type)

2.5.8.4. File user_modules_config.h

This header file defines which application modules are included or excluded from the user’s application. For example:

  • #define EXCLUDE_DLG_DISS (0) - the SDK takes care of the DISS application profile message handling. The DISS application profile is included, that is:

    • app_diss_task.c as provided by the SDK

  • #define EXCLUDE_DLG_DISS (1) - the user application has to take care of the DISS application profile message handling

2.5.8.4.1. Configuration Flags

The define statements below enable to include or exclude a module in the user application code. When defined as:

  • (0) - The module is included. The module’s messages are handled by the SDK

  • (1) - The module is excluded. The user must handle the module’s messages

The code snippet below show a user module configuration example.

#define EXCLUDE_DLG_GAP             (0)
#define EXCLUDE_DLG_TIMER           (0)
#define EXCLUDE_DLG_MSG             (1)
#define EXCLUDE_DLG_SEC             (0)
#define EXCLUDE_DLG_DISS            (0)
#define EXCLUDE_DLG_PROXR           (1)
#define EXCLUDE_DLG_BASS            (1)
#define EXCLUDE_DLG_FINDL           (1)
#define EXCLUDE_DLG_FINDT           (1)
#define EXCLUDE_DLG_SUOTAR          (1)
#define EXCLUDE_DLG_CUSTS1          (0)
#define EXCLUDE_DLG_CUSTS2          (1)

2.5.8.5. File user_periph_setup.h

Configuration file for the peripherals that the application uses.

This header file holds the port-pin mapping of the used peripherals per example, such as GPIOs, UART, SPI, I2C, etc. Apart from the port-pin mapping of the used peripherals the header file may contain configuration values for a peripheral itself, such as UART baudrate, SPI clock speed, I2C slave address, etc.

Table 3 describes the functions that are defined in header file user_periph_setup.h.

Table 3 user_periph_setup.h Function Prototypes

Function

Description

periph_init()

Initializes the used peripherals.

set_pad_functions()

Configures the port-pin mapping of the used peripherals.

GPIO_reservations()

Reserves the pins that the peripheral uses.

2.5.8.6. File user_profiles_config.h

Configuration file for the BLE profiles used by the application.

2.5.8.6.1. Configuration Flags

The user_profiles_config.h file defines the required BLE profiles of the application. For example, if the application requires the

DISS, PXPR, SUOTAR and BASS profiles, then the following must be defined in user_profiles_config.h:

/*********************/
/* Used BLE profiles */
/*********************/

#define CFG_PRF_DISS
#define CFG_PRF_PXPR
#define CFG_PRF_SUOTAR
#define CFG_PRF_BASS

Table 4 describes the SDK supported BLE profiles.

Note

The supported profiles are defined in file rwprf_config.h.

Table 4 Supported BLE Profiles

Flag

Profile

Description

CFG_PRF_PXPM

Proximity Reporter

If defined enables the Proximity Profile Monitor role

CFG_PRF_PXPR

Proximity Reporter

If defined enables the Proximity Profile Reporter role

CFG_PRF_FMPL

Find Me Profile

If defined enables the Find Me Profile Locator role

CFG_PRF_FMPT

Find Me Profile

If defined enables the Find Me Profile Target role

CFG_PRF_HTPC

Health Thermometer

If defined enables the Health Thermometer Profile Collector role

CFG_PRF_HTPT

Health Thermometer

If defined enables the Health Thermometer Profile Thermometer role

CFG_PRF_DISC

Device Information Service

If defined enables the Device Information Service Client role

CFG_PRF_DISS

Device Information Service

If defined enables the Device Information Service Server role

CFG_PRF_BLPC

Blood Pressure

If defined enables the Blood Pressure Profile Collector role

CFG_PRF_BLPS

Blood Pressure

If defined enables the Blood Pressure Profile Sensor role

CFG_PRF_TIPC

Time

If defined enables the Time Profile Client role

CFG_PRF_TIPS

Time

If defined enables the Time Profile Server role

CFG_PRF_HRPC

Heart Rate

If defined enables the Heart Rate Profile Collector role

CFG_PRF_HRPS

Heart Rate

If defined enables the Heart Rate Profile Sensor role

CFG_PRF_SCPPC

Scan Parameter

If defined enables the Scan Parameter Profile Client role

CFG_PRF_SCPPS

Scan Parameter

If defined enables the Scan Parameter Profile Server role

CFG_PRF_BASC

Battery Service

If defined enables the Battery Service Client role

CFG_PRF_BASS

Battery Service

If defined enables the Battery Service Server role

CFG_PRF_HOGPD

HID

If defined enables the HID Device role

CFG_PRF_HOGPBH

HID

If defined enables the HID Boot Host role

CFG_PRF_HOGPRH

HID

If defined enables the HID Report Host role

CFG_PRF_GLPC

Glucose

If defined enables the Glucose Profile Collector role

CFG_PRF_GLPS

Glucose

If defined enables the Glucose Profile Sensor role

CFG_PRF_RSCPC

Running Speed and Cadence

If defined enables the Running Speed and Cadence Profile Collector role

CFG_PRF_RSCPS

Running Speed and Cadence

If defined enables the Running Speed and Cadence Profile Server role

CFG_PRF_CSCPC

Cycling Speed and Cadence

If defined enables the Cycling Speed and Cadence Profile Collector role

CFG_PRF_CSCPS

Cycling Speed and Cadence

If defined enables the Cycling Speed and Cadence Profile Server role

CFG_PRF_CPPC

Cycling Power

If defined enables the Cycling Power Profile Collector role

CFG_PRF_CPPS

Cycling Power

If defined enables the Cycling Power Profile Server role

CFG_PRF_LANC

Location and Navigation

If defined enables the Location and Navigation Profile Collector role

CFG_PRF_LANS

Location and Navigation

If defined enables the Location and Navigation Profile Server role

CFG_PRF_ANPC

Alert Notification Profile

If defined enables the Alert Notification Profile Client role

CFG_PRF_ANPS

Alert Notification Profile

If defined enables the Alert Notification Profile Server role

CFG_PRF_PASPC

Phone Alert Status

If defined enables the Phone Alert Status Profile Client role

CFG_PRF_PASPS

Phone Alert Status

If defined enables the Phone Alert Status Profile Server role

CFG_PRF_BMSC

Bond Management Service

If defined enables the Bond Management Service Client role

CFG_PRF_BMSS

Bond Management Service

If defined enables the Bond Management Service Server role

CFG_PRF_ANCC

Apple Notification Center Service

If defined enables the Apple Notification Center Service Client role

CFG_PRF_BCSC

Body Composition Service

If defined enables the Body Management Service Client role

CFG_PRF_BCSS

Body Composition Service

If defined enables the Body Management Service Server role

CFG_PRF_WSSC

Weight Scale Service

If defined enables the Weight Scale Service Client role

CFG_PRF_WSSS

Weight Scale Service

If defined enables the Weight Scale Service Server role

CFG_PRF_UDSC

User Data Service

If defined enables the User Data Service Client role

CFG_PRF_UDSS

User Data Service

If defined enables the User Data Service Server role

CFG_PRF_GATTC

Generic Attribute Profile Service

If defined enables the Generic Attribute Profile Service Client role

CFG_PRF_SUOTAR

Software Patching Over the Air

If defined enables the Software Patching Over the Air Receiver role

CFG_PRF_CUST1

Custom1 Profile

If defined enables the Custom1 Profile Service Server role

CFG_PRF_CUST2

Custom2 Profile

If defined enables the Custom2 Profile Service Server role

2.6. Supported Hardware Configurations

2.6.1. Integrated Processor

The straightforward approach to develop an application with the DA1453x/DA1458x family is the integrated processor configuration. All SW components, lower layers (controller), higher layers (host), profiles and the complete application run on the DA1453x/DA1458x as a single chip solution. This configuration is well suited for many low to mid complexity applications. Please check the complete list of reference designs provided by Dialog on the Customer Support site to understand the complexity of the applications that can be supported.

../_images/image21.png

Figure 14 Integrated Processor HW Configuration

2.6.2. External Processor

In cases where an external processor is present or in mid and high complexity applications, the DA1453x/DA1458x can be used as a BLE interface controlled from an external processor via a proprietary protocol called Generic Transport Layer (GTL). The DA1453x/DA1458x can accommodate the link layer, the host protocols and the profiles, and the external processor will implement the application functionality. The two components will communicate via GTL over a serial link which can be either UART or SPI.

../_images/image31.png

Figure 15 External Processor HW Configuration

2.7. Software Development Environment

Software development on DA1453x/DA1458x is done with a Software Development Kit (SDK) that is supported by a number of other tools, which aim at assisting the designers and programmers to develop a new application for the DA1453x/DA1458x family of devices. The projects are based on, and supported by, the Arm® Keil® µVision® IDE/Debugger, Arm C/C++ Compiler and essential middleware components, Keil IDE and the Keil build tools. The DA1453x/DA1458x can be interfaced with Arm Segger JTAG cables, which is something that is fully supported by the Keil environment.

To assist with the quick evaluation and programming of the DA1453x/DA1458x chip, Dialog provides a powerful graphical software tool called SmartSnippets Toolbox. SmartSnippets Toolbox provides a connection to the DA1453x/DA1458x devices via UART or JTAG, to program the on-chip OTP or even external Flash/EEPROM. A very powerful tool that is included in the SmartSnippets Toolbox, to use with the standard Dialog development kits is the Power profiler. The user can track power consumption of the board in realtime, and set a software marker and correlate board consumption with events happening during the execution of the software.