.. _the_application:

Introduction
============

This section describes the application portion of the
basic\_ble project, which includes the following:

-  :ref:`start-up-in-main`

-  :ref:`icall`

-  :ref:`intertask_messages`

-  :ref:`can_driver_usage_with_cc27xx`

..
  -  :ref:`basic_framework_overview_page`

.. _start-up-in-main:

Main initialization
===================

The ``main`` function is contained in source file ``main_freertos.c`` located in the
IDE Start-up or root folder. This function is the starting point at run time.
The purpose of main is to bring up the target with interrupts disabled,
drivers initialized, power management on, FreeRTOS tasks created, and start 
the FreeRTOS kernel scheduler with interrupts enabled.
The ``main`` function does not return. Because the main_freertos.c file exists in the 
application project, main_freertos.c will be allocated within 
the flash memory reserved for the application.

  .. code-block:: c
    :caption: A basic main function.
    :linenos:

    int main()
    {
      /* Register Application callback to trap asserts raised in the Stack */
      halAssertCback = AssertHandler;
      RegisterAssertCback(AssertHandler);

      Board_init();

      /* Update User Configuration of the stack */
      user0Cfg.appServiceInfo->timerTickPeriod = ICall_getTickPeriod();
      user0Cfg.appServiceInfo->timerMaxMillisecond  = ICall_getMaxMSecs();

      /* Initialize all applications tasks */
      appMain();

      /* Start the FreeRTOS scheduler */
      vTaskStartScheduler();

      return 0;
    }


See :ref:`sec-freertos-overview` for how the application is
constructed through FreeRTOS.

.. note::
    The ICall module must be initialized by :ble_api:`ICall_init` and the
    stack task is created via :ble_api:`ICall_createRemoteTasks`.

.. _icall:

ICall
=====

Introduction
------------

Indirect Call Framework (ICall) is a module that provides a
mechanism for the application to interface with the Bluetooth low
energy protocol stack services (that is, |STACK| APIs) as well as certain
primitive services provided by FreeRTOS (for example, thread synchronization).
ICall allows the application and protocol stack to operate efficiently,
communicate, and share resources in a unified FreeRTOS environment.

The central component of the ICall architecture is the API translation,
which facilitates the application program interface between the
application and the |STACK|. Although most ICall interactions are abstracted
within the |STACK| APIs (for example, GAP, HCI, and so forth), the application
developer must understand the underlying architecture for the |STACK|
to operate properly in the multithreaded RTOS environment.

The ICall module source code is provided in the ICall and ICall
BLE IDE folders in the application project. The figure below shows an example
of the application calling the stack API ``GATT_Notification``.

.. ditaa::
    :--no-separation:

    /------------------------------\  +-----------------------+
    | GATT_Notification(...)       |  |       Application     |
    \------------------------------/  |        c0BC           |
                                      +-----------------------+
                                      |       ICall           |
                                      |        cEEE           |
                                      +---+-------------------+
    /------------------------------\      |              ^
    | icall_directAPI(...)         |      |              |
    |   o ICall_sendServiceMsg(...)|      |              |
    |   o ICall_waitMatch(...)     |      |              |
    |   o mq_receive(...)          |      |              |
    \------------------------------/      |     App      |
                                      ----+--------------+-----
                                          |    Stack     |      /---------------+---------------\
                                          |              |      | ble_dispatch_liteProcess(...) |
                                          |              |      |   o osal_msg_receive(...)     |
                                          |              |      |   o icall_liteTranslation(...)|
                                          |              |      |   o sendLiteCmdStatus(...)    |
                                          |              |      \-------------------------------/
                                          V              |
                                      +------------------+----+
                                      |    API Translation    |
                                      |      cEEE             |
                                      +-----------------------+
                                      |       Stack  c900     |
                                      |                       |
                                      +-----------------------+

ICall |STACK| Protocol Service
---------------------------------

As the figure above shows, the ICall core use case involves messaging
between a server entity (that is, the |STACK|
task) and a client entity (for example, the application task).

.. note::
    The ICall framework is not the GATT server and client
    architecture, as defined by the Bluetooth Low Energy protocol.

The reasoning for this architecture is as follows:

-  To enable independent updating of the application and Bluetooth Low
   Energy protocol stack

-  To maintain API consistency as software is ported from legacy
   platforms (that is, OSAL for the CC254x) to FreeRTOS of the |DEVICE|.

The ICall |STACK| service serves as the application interface to |STACK| APIs.
When a |STACK| API is called by the application internally, the ICall module
dispatches the command to the |STACK| and routes
messages from the |STACK| to the application when appropriate.

Because the ICall module is part of the application project, the
application task can access ICall with direct function calls.
Because the |STACK| executes at the highest priority, the application task
blocks until the response is received. Certain protocol stack APIs may
respond immediately, but the application thread blocks as the API is
dispatched to the |STACK| through ICall. Other |STACK| APIs may also
respond asynchronously to the application through ICall
(for example, event updates) with the response sent to the event handler of
the application task.

ICall Primitive Service
-----------------------

ICall includes a primitive service that abstracts various operating
system-related functions. Due to shared resources and to maintain
interprocess communication, the application must use the following
ICall primitive service functions:

-  Messaging and Thread Synchronization

-  Heap Allocation and Management

Some of these are abstracted to Util functions (such as ``Util_enqueueMsg``
and ``Util_dequeueMsg``). The ICall primitive service is
implemented as part of ``icall_POSIX.c``.

Messaging and Thread Synchronization
------------------------------------

The Messaging and Thread Synchronization functions provided by ICall
enable an application to communicate with the |STACK| in the
multithreaded FreeRTOS environment.

In ICall, messaging between two tasks occurs by sending a 
message from one thread to the other through a message queue. The
sender allocates a memory block, writes the content of the message
into the memory block, and then sends (that is, enqueues) the memory
block to the recipient. Notification of message delivery occurs
using an event flag. The receiver wakes up on the event flag post,
copies the message memory block (or blocks), processes the message,
and returns (frees) the memory block to the heap.

The stack uses ICall for notifying and sending messages to the
application. ICall delivers these service messages, the application
task receives them, and the messages are processed in the context
of the application.

Heap Allocation and Management
------------------------------

ICall provides the application with global heap APIs for dynamic
memory allocation. ICall uses this heap for all protocol stack messaging
and to obtain memory for other ICall services. TI recommends that the
application uses these ICall APIs to allocate dynamic memory.

.. _the-application-icall-initialization-and-registration:

ICall Initialization and Registration
-------------------------------------

To instantiate and initialize the ICall service, the application
must call the functions shown in the snippet below before starting the
FreeRTOS scheduler:

  .. code-block:: c
    :caption: Required code to utilize ICall.
    :linenos:

    /* Initialize ICall module */
    ICall_init();

    /* Start tasks of external images - Priority 5 */
    ICall_createRemoteTasks();

Calling :ble_api:`ICall_init` initializes the ICall primitive service (for
example, heap manager) and framework. Calling
:ble_api:`ICall_createRemoteTasks` creates but does not start the |STACK|
task. Before using ICall protocol
services, the server and client must enroll and register with ICall.
The server enrolls a service, which is defined at build time.
Service function handler registration uses a globally defined unique
identifier for each service. For example, Bluetooth Low Energy uses
:c:type:`ICALL_SERVICE_CLASS_BLE` for receiving |STACK| task messages through
ICall.

To enroll the |STACK| service (server) with ICall in osal\_icall\_ble.c,
see the snippet below:

  .. code-block:: c
    :caption: ICall Enrollment
    :linenos:

    /* Enroll the service that this stack represents */
    ICall_enrollService(ICALL_SERVICE_CLASS_BLE, NULL, &entity, &syncHandle);

The registration mechanism is used by the client to send and/or
receive messages through the ICall dispatcher.

For a client (for example, application task) to use the |STACK| APIs,
the client must first register its task with
ICall. This registration usually occurs in the task initialization
function of the application. The snippet below is an example
on how to register the current thread with ICall.

  .. code-block:: c
    :caption: ICall Registration
    :linenos:

    // Register the current thread as an ICall dispatcher application
    // so that the application can send and receive messages.
    ICall_registerApp(&selfEntity, &syncEvent);

The application supplies the selfEntity and syncEvent inputs. These inputs
are initialized for the task of the client (for example,
application) when the :ble_api:`ICall_registerApp` is called.
These objects are subsequently used by ICall to facilitate messaging
between the client (e.g. the application) and server (e.g. the BLE stack) 
tasks. The syncEvent argument represents the POSIX message queue descriptor 
for signaling and the selfEntity represents the destination identifier of the
client task. Each task registering with ICall has unique syncEvent and 
selfEntity identifiers.

.. note::
    |STACK| APIs defined in ``icall_ble_api.h`` and other ICall primitive
    services are not available before ICall registration.

.. _sec-the-application-icall-thread-sync:

ICall Thread Synchronization
----------------------------

The ICall module uses POSIX message queues (MQ) for thread synchronization.

To allow a client or a server thread to block until it receives a message,
ICall provides the POSIX mq_receive API function to block until a message 
from the sender FreeRTOS thread is enqueued.

.. _icall_blocking:

  .. code-block:: c
    :caption: ICall Blocking/Pending Calls
    :linenos:

    ssize_t mq_receive(mqd_t mqdes, 
                       char *msg_ptr, 
                       size_t msg_len,
                       unsigned int *msg_prio);

``mqdes`` is the message queue descriptor. If the function is successful,
the selected message will be removed from the queue and copied into the buffer
pointed to by ``msg_ptr``. ``msg_len`` is the length of the buffer pointed by
``msg_ptr``. If ``msg_prio`` is not NULL (i.e a valid RAM address), the message 
priority of the selected message will be stored in the location referenced by 
``msg_prio``.

``mq_receive`` blocks the current task until a message is enqueued, allowing an
client or a server thread to block and yield the processor resource to 
other lower priority threads or conserve energy by shutting down power and
clock domains when possible.

A message is delivered to another thread through the message queue when 
``mq_send`` is called. This will unblock a thread that is waiting with 
``mq_receive``. 

.. _icall_signal:

  .. code-block:: c
    :caption: ICall Signaling/Posting Call
    :linenos:

    int mq_send(mqd_t mqdes, 
                const char *msg_ptr,
                size_t msg_len,
                unsigned int msg_prio);

``mqdes`` is the message queue descriptor. ``msg_ptr`` points to the data 
buffer (i.e. the message) that will be added by the message queue. ``msg_len``
defines the lenght of the message, in bytes. ``msg_prio`` defines the 
message priority; that is, where in the queue the message will be inserted:
before other messages with lower ``msg_prio`` and after other messages with the
same or higher ``msg_prio``.

The message queue descriptor associated with the thread is obtained through
either :ble_api:`ICall_enrollService` call or :ble_api:`ICall_registerApp` call.

.. warning::
    Do not call an ICall function from a stack callback. This
    action can cause ICall to abort (with :ble_api:`ICall_abort`) and break the
    system.


For more information on POSIX, see the TI-POSIX Users Guide included in your
SDK and the 
`official specification <https://pubs.opengroup.org/onlinepubs/9699919799/>`_.

Example ICall Usage
-------------------

:numref:`icall_messaging_example` shows an example command being sent from the
application to the |STACK| through the ICall framework with a corresponding
return value passed back to the application.

:ble_api:`ICall_init` initializes the ICall module instance and
:ble_api:`ICall_createRemoteTasks` creates a task per external image with an
entry function at a known address.

After initializing ICall, the application task registers with ICall
through :ble_api:`ICall_registerApp`.

After the FreeRTOS scheduler starts and the application task runs,
the application sends a protocol command defined in ``ble_dispatch_JT.c``
such as :ble_api:`GAP_GetParamValue`.

.. warning::
    Although the protocol command is declared in ``gap.h`` and defined
    on the |STACK| side via ``ble_dispatch_JT.c``, the declaration
    **MUST** be overridden by ``icall_api.h``.

It is crucial to note that the protocol command is not executed in the thread
of the application but is encapsulated in an ICall message and routed to the
|STACK| task via the ICall framework. This command is sent to the ICall 
dispatcher where it is dispatched and executed in the |STACK| context. 
The application thread meanwhile blocks until the corresponding command status
message is received.
The |STACK| finishes executing the command, then sends a command status message
response through ICall back to the application thread. An sequence diagram of 
this exchange can be seen below in :numref:`icall_messaging_example`

.. _icall_messaging_example:
.. uml::
    :caption: ICall Messaging Example
    :align: center

    @startuml
    participant App
    participant "ICall"
    participant "BLE Stack"
      App -> "ICall" : ICall_Init
      App -> "ICall" : ICall_createRemoteTasks
      App -> "ICall" : ICall_registerApp
      App -> "ICall" : GAP_GetParamValue
      ICall -> ICall : icall_directAPI(...)

      ICall -> "BLE Stack" : ICall_sendServiceMsg\n(BLE Primitive Service)

    rnote over "BLE Stack"
        Stack Executes
        GAP_GetParamValue
    end note

    activate App

    rnote over App
       App Task Blocks
    end note

      "BLE Stack" -> "ICall" : osal_service_complete(sendGapCmdStatus)

    deactivate "App"

      ICall -> App : return

    @enduml


    ICall Messaging Example

.. _sec-the-application-icall-lite:

ICall Translation and Include
-----------------------------

Effectively, ``icall_ble_api.h`` defines all the ICall/Stack API
while keeping their original function prototypes. This redefinition is done to
utilize a different message format for the dispatcher to handle.

In order for the redefinition to take effect correctly,
``icall_ble_api.h`` **MUST** be the last file to be included in
the source file. This ensures that the redefinition correctly occurs.
If ``icall_ble_api.h`` is not the last file to be included, it's possible
that original definitions could be used due to ``gapbondmgr.h``,
``gapgattserver.h``, or any other ICall/Stack API being included in
another header file.

.. warning::
    For any source file utilizing ICall/Stack API, ``#include "icall_ble_api.h"``
    must be the last include statement. Erratic runtime behavior or
    link time errors may result.

The ICall translation layer is where the stack parses API calls from the app,
defined in ``icall_lite_translation.c`` in the |STACK| project.
All messages will be processed with ``icall_liteTranslation`` in the
BLE-Stack context.

.. warning::
    Only Tasks/Threads registered with ICall via
    :ble_api:`ICall_registerApp` should use ICall/Stack API.

    Application will abort if an unknown task uses ICall/Stack API.

**APIs that are not in ``icall_ble_api.h`` should not be called by the
application. This file should be treated as the high level stack header
definition**


.. _intertask_messages:

Intertask Messages
==================

These messages are passed from another task (such as the |STACK| Service)
through ICall to the application task.

Some possible examples are as follows:

- A confirmation sent from the protocol stack in acknowledgment of a
  successful over-the-air indication

- An event corresponding to an HCI command (see :ref:`ble_api_reference` for
  HCI command documentation and corresponding events)

- A response to a GATT client operation (see :ref:`using_the_gatt_layer_directly`)

Using FreeRTOS Events Module
----------------------------

All |STACKVER| projects use the FreeRTOS Event module acquire ICall stack
message event. Usage is described in
:ref:`sec-the-application-icall-thread-sync` and more documentation on thread
synchronization can be found in the |FreeRTOS HOME|.

Processing Queued Messages in BLEAppUtil framework
--------------------------------------------------

Messages enqueued using the :ble_api:`BLEAppUtil_enqueueMsg` function are
dequeued for processing in the order in which they occurred. The BLEAppUtil framework
dequeues and frees messages when new events are posted.

The code snippet below shows how BLEAppUtil framework processes events & messages.

  .. code-block:: c
      :caption: Queued messages are processed in the order they occurred.
      :linenos:

      // wait until receive queue message
      if (mq_receive(BLEAppUtil_theardEntity.queueHandle, (char*)&pAppEvt, sizeof(pAppEvt), NULL) > 0)
      {
          BLEAppUtil_msgHdr_t *pMsgData = (BLEAppUtil_msgHdr_t *)pAppEvt.pData;
          bool freeMsg = FALSE;
          
          switch (pAppEvt.event){
              if (pMsg)
              {
                case BLEAPPUTIL_EVT_STACK_CALLBACK:
                {
                  // ..
                }
                case BLEAPPUTIL_EVT_ADV_CB_EVENT:
                {
                    BLEAppUtil_processAdvEventMsg(pMsgData);
                    if (((BLEAppUtil_AdvEventData_t *)pMsgData)->event != BLEAPPUTIL_ADV_INSUFFICIENT_MEMORY &&
                        ((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf)
                    {
                        BLEAppUtil_free(((BLEAppUtil_AdvEventData_t *)pMsgData)->pBuf);
                    }
                    break;
                }
          }
      }

.. warning::

    Messages originating from the message queue should be free'd
    using ``ICall_free()`` (``BLEAppUtil_free()`` is a wrapper function
    for ``ICall_free()``).


Processing Stack Events from the ICall Message Queue
----------------------------------------------------

The stack will often asynchronously signal the application by placing a
message the application's ICall message queue. This includes event types
defined in ``bcomdef.h`` under "BLE OSAL GAP GLOBAL Events". Any
incoming stack messages are caught by the ``BLEAPPUTIL_EVT_STACK_CALLBACK``
case in the switch-case block.

The BLEAppUtil framework receives these messages as below:

  .. code-block:: c
      :caption: BLEAppUtil receives event from ICall message queue.
      :linenos:

      void *BLEAppUtil_Task(void *arg)
      {
        // Register to the stack and create queue and event
        BLEAppUtil_stackRegister();

        // Init the ble stack
        BLEAppUtil_stackInit();

        // Application main loop
        for (;;)
        {
            BLEAppUtil_appEvt_t pAppEvt;

            // wait until receive queue message
            if (mq_receive(BLEAppUtil_theardEntity.queueHandle, (char*)&pAppEvt, sizeof(pAppEvt), NULL) > 0)
            {
                BLEAppUtil_msgHdr_t *pMsgData = (BLEAppUtil_msgHdr_t *)pAppEvt.pData;
                bool freeMsg = FALSE;

                switch (pAppEvt.event)
                {
                  case BLEAPPUTIL_EVT_STACK_CALLBACK:
                  {
                      // Set the flag to true to indicate that BLEAppUtil_freeMsg
                      // should be used to free the msg
                      freeMsg = TRUE;

                      switch (pMsgData->event)
                      {
                          case GAP_MSG_EVENT:
                              BLEAppUtil_processGAPEvents(pMsgData);
                              break;

                          case GATT_MSG_EVENT:
                              BLEAppUtil_processGATTEvents(pMsgData);
                              break;

                          case L2CAP_DATA_EVENT:
                              BLEAppUtil_processL2CAPDataMsg(pMsgData);
                              break;

                          case L2CAP_SIGNAL_EVENT:
                              BLEAppUtil_processL2CAPSignalEvents(pMsgData);
                              break;

                          case HCI_GAP_EVENT_EVENT:
                              BLEAppUtil_processHCIGAPEvents(pMsgData);
                              break;

                          case HCI_DATA_EVENT:
                              BLEAppUtil_processHCIDataEvents(pMsgData);
                              break;

                          case HCI_SMP_EVENT_EVENT:
                              BLEAppUtil_processHCISMPEvents(pMsgData);
                              break;

                          case HCI_SMP_META_EVENT_EVENT:
                              BLEAppUtil_processHCISMPMetaEvents(pMsgData);
                              break;
                      // ..
                      }
                    }
                  }
                }
              }
            }
          }
        }


Messages **that originate from the ICall Message Queue** should be free'd
using ``ICall_freeMsg()``. Messages coming from the ICall message queue
are received using ``ICall_fetchServiceMsg``.

.. warning::

    Using ``ICall_freeMsg()`` on messages that are not from the ICall message
    queue can cause memory corruption. Only use ``ICall_freeMsg()`` on
    messages that have be fetched using ``ICall_fetchServiceMsg``.

Callbacks
---------

The application code also includes various callbacks to protocol
stack layers, profiles, and FreeRTOS modules. To ensure thread safety,
processing must be minimized in the actual callback and the bulk of
the processing should occur in the application context. Two
functions are defined per callback. One is the callback itself, which
is called upon by another module or task. The second is the function
to handle the event generated by the callback in the application context.
Consider the characteristic change callback, which is called when a
characteristic change occurs.

.. warning::
    No blocking FreeRTOS function calls or protocol stack APIs
    should be performed in a callback function. Such function calls may
    result in an abort or undefined behavior. Always perform protocol
    stack and FreeRTOS blocking calls from the application task context.

.. Note::
    All callbacks are called in the context of the calling task or module
    (for example, the stack task). To minimize processing in the calling
    context, this function should enqueue an event that the application pends on.

  .. code-block:: c
    :caption: BLEAppUtil framework connection event callback
    :linenos:

    void BLEAppUtil_connEventCB(Gap_ConnEventRpt_t *pReport)
    {
        // Enqueue the event msg
        if ( BLEAppUtil_enqueueMsg(BLEAPPUTIL_EVT_CONN_EVENT_CB, pReport) != SUCCESS)
        {
            BLEAppUtil_free(pReport);
        }
    }

The callback simply places a message in the queue to signal the application to wake 
up. Once the callback's context returns and its parent task goes to sleep, the 
application wakes up due to the enqueue from the callback. The code snippet below 
is called when the event is popped from the application queue and processed.

  .. code-block:: c
    :caption: BLEAppUtil Framework connection event processor.
    :linenos:

    void BLEAppUtil_processConnEventMsg(BLEAppUtil_msgHdr_t *pMsg)
    {
      //...
    }

.. _can_driver_usage_with_cc27xx:

CAN Driver Usage with |DEVICEHIGH|
----------------------------------

The CAN driver is available for selected |DEVICEHIGH| devices that support the 
CAN peripheral. The driver allows for packets to be sent within the CAN protocol, 
with the addition of a CAN transceiver. 

To utilize the CAN driver, the following guidelines must be followed: 

* Do **NOT** call CAN functions from within a critical section. 
* Ensure CAN event processing is implemented within its own task. 
* Ensure the stack size for the CAN task is large enough to handle all CAN operations.
   * To ensure the stack size of the applications CAN task is appropriate, monitor the 
     values of both the StackPeak and StackLimit in the ROV Task Detail view. For details, 
     please refer to the ROV (Runtime Objects) section :ref:`sec-rov`
* Data received from CAN must be processed within a separate task or thread. 
   * CAN data processing must **NOT** be done within the ISR context (CAN event callback). 

.. Note:: 
    The default priority for the CAN task is 2 and the default priority for the 
    BLE task is 1. Do not set the CAN task priority higher than the BLE task priority. 

.. _i2s_driver_usage_with_cc27xx:

I2S Driver Usage with |DEVICEHIGH|
----------------------------------

The I2S driver is available for |DEVICEHIGH| devices. The driver 
allows for data to be sent and received using the I2S protocol, which
is primarily used for audio applications. 

To utilize the I2S driver, the following guidelines must be followed:

* Do **NOT** call I2S functions from within a critical section.
* Ensure I2S event processing is implemented within its own task.
* Ensure the stack size for the I2S task is large enough to handle all I2S operations.
   * To ensure the stack size of the applications I2S task is appropriate, monitor the 
     values of both the StackPeak and StackLimit in the ROV Task Detail view. 
     For details, please refer to the ROV (Runtime Objects) section :ref:`sec-rov`
* Data received from I2S must be processed within a separate task or thread.

.. Note:: 
    The default priority for the I2S task is 2 and the default priority for the 
    BLE task is 1. Do not set the I2S task priority higher than the BLE task priority. 