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.
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 APIke_msg.h
- Message handling APIke_mem.h
- Dynamic memory allocation APIke_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 structureke_state_handler
– List of message handlers for a specific or default stateke_task_desc
- Task descriptor
Functions:
ke_task_create()
– Creates a new taskke_state_set()
– Sets the state of the taskke_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 allocationKE_MEM_ATT_DB
– Used for ATT protocol databases, i.e. services, characteristics, attributesKE_MEM_KE_MSG
– Used for kernel messages memory allocationKE_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/586da14531_config_advanced.h
for DA14531-0xda14535_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 spaceke_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 fileda14585_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 insystem_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 macroKE_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 inparam
.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 toparam_len
.
The transmission of a message is done in three steps:
Allocation of a message structure by the sender task. One of the following macros is called for message allocation:
KE_MSG_ALLOC
: Allocates space inKE_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 toKE_MSG_ALLOC
. Additional memory size to the size of data type is passed in an additional parameter.
Fills in the message parameters. The code of the source task should fill in the data of the message.
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 ofke_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.
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
andda14531_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.
API |
API Files |
---|---|
ATT Database |
|
GAP Manager |
|
GAP Controller |
|
GATT Manager |
|
GATT Controller |
|
Profile Utilities |
|
<Profile> |
|
Custom Profile |
|
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.
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.
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.
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
andda14585_config_advanced.h
for DA1458x.Use
da14531_config_basic.h
andda14531_config_advanced.h
for DA14531-0x.Use
da14535_config_basic.h
andda14535_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.
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.
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.
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.
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.