CC254x to CC2640

Introduction

TI-RTOS is the new operating environment for Bluetooth low energy projects on CC26xx devices. This software is a multi-threaded environment where the protocol stack, application, and its profiles exist on different threads. TI-RTOS has similar features to OSAL but different mechanisms for accomplishing them. This section covers the main differences between TI-RTOS and OSAL when developing applications on top of the Bluetooth low energy protocol stack. Although the incorporation of TI-RTOS is a major architecture change, Bluetooth low energy APIs and related procedures are similar to CC254x.

This section covers the following topics:

  • OSAL
  • Application and stack separation with ICall
  • Threads, semaphores, and queues
  • Peripheral Drivers
  • Event Processing

Most of these differences are unique to TI-RTOS. This section covers these differences and how they relate to OSAL.

OSAL

A major change in moving to TI-RTOS is the complete removal of the application from the OSAL environment. While the stack code uses OSAL within its own thread, the application thread can only use the APIs of OSAL that are defined in ICallBleAPI.c. Many functions such as osal_memcpy, osal_memcmp, and osal_mem_alloc() are unavailable. These functions have been replaced by TI-RTOS, C runtime, and ICall APIs.

Application and Stack Separation With ICall

In the CC2640 Bluetooth low energy protocol stack, the application is a separate image from the stack image unlike the OSAL method, which consists of only a single image. The benefit for this separation is detailed in the ICall. This structure allows independent upgrading of the application and stack images.

The address of the startup entry for the stack image is known by the application image at build time so the application image knows where the stack image starts. Messages between the application and stack pass through a framework developed called ICall. (Indirect Call Framework) This functionality lets the application call the same APIs used in OSAL but is parsed by the ICall and sent to the stack for processing. Many of these stack functions are defined in ICallBleAPI.c for the application to use transparently while ICall handles the sending and receiving from the stack transparently.

Threads, Semaphores, and Queues

Unlike single-threaded operating systems such as OSAL, TI-RTOS is multi-threaded with custom priorities for each thread. The TI-RTOS handles thread synchronization and APIs are provided for the application threads to use to maintain synchronization between different threads. Semaphores are the prime source of synchronization for applications. The semaphores are used to pass event messages to the event processor of the application.

Profile callbacks that run in the context of the Bluetooth low energy protocol stack thread are made re-entrant by storing event data and posting a semaphore of the application to process in the context of the application. Similarly, key press events and clock events that run in ISR context also post semaphores to pass events to the application. Unique to TI-RTOS, queues are how applications process events in the order the events were called and make callback functions from profiles and the stack re-entrant. The queues also provide a FIFO ordering for event processing. An example project may use a queue to manage internal events from an application profile or a GAP profile role (for example, Peripheral or Central). ICall uses a queue and it is accessed through the ICall API. For a description of the TI-RTOS objects used by the Bluetooth low energy stack SDK, see TI-RTOS Overview.

Peripheral Drivers

Aside from switching to an RTOS-based environment, peripheral drivers represent a significant change from the CC254x architecture. Any drivers used by the CC254x software must be ported to the respective TI-RTOS driver interfaces. For details on adding and using a CC26xx peripheral driver, see Drivers.

Event Processing

Similar to OSAL, each TI-RTOS task has two functions that implement the fundamental tasks for an application: simple_peripheral_init() and simple_peripheral_taskFxn().

simple_peripheral_init() contains ICall registration routines and initialization functions for the application profiles and the GAP and GATT roles. Function calls that are normally in the START_DEVICE_EVT event of the CC254x application are also made in the simple_peripheral_init() function. The initialization includes setting up callbacks that the application should receive from the profile and stack layers. For more details on callbacks, and other messaging systems see Intertask Messages.

simple_peripheral_taskFxn() contains an infinite loop in which events are processed. After entry of the loop and having just finished initialization, the application task calls ICall_wait() to block on its semaphore until an event occurs. For an example on how events are processed in simple_peripheral, see Simple Peripheral Task.

Similar to osal_set_event() in a CC254x application, the application task can post the semaphore of the application with a call to Semaphore_post(sem) after setting an event such as in simple_peripheral_clockHandler(). An alternative way is to enqueue a message using simple_peripheral_enqueueMsg() which preserves the order in which the events are processed. Similar to osal_start_timerEx() in a CC254x application, you can use a clock to set an event after a predetermined amount of time using Util_constructClock().This function can also set a periodic event as shown in the simple_peripheral project.

Events can come from within the same task, the profiles, or the stack. Events from the stack are handled first with a call to ICall_fetchServiceMsg() similar to osal_msg_receive() in a CC254x application. Internal events and messages from profiles or the GAP roles, that are received in callback functions, must be treated as re-entrant and should be handled in the simple_peripheral_taskFxn() function too. In other words, processing should be done within the application context. In many cases such as in GAP role profile callbacks, you must place events in a queue to preserve the order in which messages arrive. For general overview of application architecture see The Application.