System Architecture

The Micro BLE Stack consists of the Micro Link Layer (Micro LL or uLL) and Micro Generic Access Profile (Micro GAP or uGAP).

The uLL is mainly responsible for maintaining the device state and scheduling radio commands to perform advertising operations. The pre- and post-processing for each radio command execution are also done by the uLL. The uLL directly interfaces with the RF Driver.

The uGAP sits between the uLL and the application and is mainly responsible for controlling the uLL to set up and run a profile role. The application can indirectly configure the uLL through uGAP and be notified of events from uLL through uGAP callbacks. uGAP needs TI-RTOS because the clock/timer service is used.

The Micro BLE Stack is not designed to run as a separate TI-RTOS task, in order to save memory that would otherwise be required to maintain an additional task. Instead, it is integrated in the application, from TI-RTOS context’s point of view, so that all the application callbacks that are originated from RF and Clock SWIs in the Micro BLE Stack and might have lengthy operations such as command completion post processing and error handling are called in the application task context. How the Micro BLE Stack is integrated context-wise in the application is illustrated in Figure 75. Note that only the subcomponents directly relevant to the Micro BLE Stack in the application and the RF driver are depicted.

alternate text

Figure 75. System Context Diagram

For that integration a message queue associated with the events is managed by the Micro BLE Stack internally. The message and loop code will look like the following:

 void uBLEStack_eventProxy()
 {
   MicroEddystoneBeacon_enqueueMsg(UEB_EVT_MICROBLESTACK, 0);
 }

 static void MicroEddystoneBeacon_taskFxn(UArg a0, UArg a1)
 {
   // Initialize application
   MicroEddystoneBeacon_init();

   for (;;)
   {
     uint32 events;

     // Waits for an event to be posted associated with the calling thread.
     // Note that an event associated with a thread is posted when a
     // message is queued to the message receive queue of the thread
 #ifdef USE_ICALL
     events = Event_pend(syncEvent, Event_Id_NONE, UEB_ALL_EVENTS,
                        ICALL_TIMEOUT_FOREVER);
 #else /* !USE_ICALL */
     events = Event_pend(syncEvent, Event_Id_NONE, UEB_ALL_EVENTS,
                        BIOS_WAIT_FOREVER);
 #endif /* USE_ICALL */

     if (events | UEB_QUEUE_EVT)
     {
       // If RTOS queue is not empty, process app message.
       while (!Queue_empty(appMsgQueue))
       {
         uebEvt_t *pMsg = (uebEvt_t *) Util_dequeueMsg(appMsgQueue);
         if (pMsg)
         {
           // Process message.
           MicroEddystoneBeacon_processAppMsg(pMsg);

           // Free the space from the message.
 #ifdef USE_ICALL
           ICall_free(pMsg);
 #else /* USE_ICALL */
           free(pMsg);
 #endif /* USE_ICALL */
         }
       }
     }
   }
 }