Adding BLE Enabled RTOS Task

From Texas Instruments Wiki
Jump to: navigation, search

Bluetooth Low Energy Main Page

Introduction

Note: this wiki applies to CC2640/CC2650 devices only.

The objective of this wiki page is to familiarize the programmer with the process of adding an RTOS task that can communicate with the BLE stack via ICall. In this example, we will create a simple task that sends a notification when the select button is pressed on the SmartRF06 board. This task will be added to the SimpleBLEPeripheral project. It is important to note that RTOS tasks should be created only when absolutely necessary, they consume extra memory and change the timing of the system. Simple tasks such as sending a notification do not need a separate task and should be done within the context of SimpleBLEPeripheral. However, if the need is justified, this example will provide a task foundation that the programmer can modify to their needs.

Definitions

Name(Acronym) Definition
TI Real Time Operating System(TI RTOS) TI's real time preemptive operating system which BLE stacks v2.0 and higher are based on
Indirect Call Framework (ICALL) A client/server communication protocol by which the BLE application can talk to the BLE stack across the dual image boundary and vice versa
Task/thread Refers to one of the processes that the RTOS may schedule to run, each Task has its own context maintained by the RTOS, and a priority that assists in scheduling
SYS/BIOS Legacy name for the kernel within the TI RTOS
Priority Refers to a system of setting up a task hierarchy that establishes each task's importance relative to other tasks. In the case of TI RTOS the higher the priority number, the more important the task is

Note: To avoid confusion in this wiki, the software that controls the BLE radio will always be referred to as the BLE stack, where as the region of memory used for storing local data and call info is referred to as the stack.


Prerequisites

It is assumed the user has:

  • Installed the latest version of the BLE stack (v2.1 at the time of this writing), found here
  • Downloaded the notification task files from TI git (here) or github(coming soon)
  • Installed a supported version of IAR (7.40) or CCS (6.1)
  • Read the Software Developer's Guide, especially the sections listed below:
    • 3 RTOS
    • 4.2 ICall

Anatomy of an RTOS Task

Each RTOS task that can communicate with the BLE stack has at minimum:
1. An init function that allocates the stack space and sets priority

  Task_Params_init(&taskParams);
  taskParams.stack = notifyTaskStack;
  taskParams.stackSize = NOTIFY_TASK_STACK_SIZE;
  taskParams.priority = NOTIFY_TASK_PRIORITY;

  Task_construct(&notifyTask, NotificationTask_taskFxn, &taskParams, NULL);
  • As per section 3.11.6 of the Software Developer's Guide, whenever possible you should use _contruct() instead of _create() for RTOS objects to save RTOS heap space.

2. A main processing loop where events are processed

// Application main loop
	for (;;)
	{
	    // Waits for a signal to the semaphore associated with the calling thread.
	    // Note that the semaphore associated with a thread is signaled when a
	    // message is queued to the message receive queue of the thread or when
	    // ICall_signal() function is called onto the semaphore.
	    ICall_Errno errno = ICall_wait(ICALL_TIMEOUT_FOREVER);


	    if (events & NOTIFY_TASK_SELECT_EVT)
	    {
	    	//Set up notificaiton data
	    	uint16 len = sizeof(UInt32);
		attHandleValueNoti_t noti;
		bStatus_t status;
		noti.handle = 0x1E;
		noti.len = len;


		//attempt to allocate payload
		noti.pValue = (uint8 *)GATT_bm_alloc( 0, ATT_HANDLE_VALUE_NOTI, GATT_MAX_MTU, &len );

		if ( noti.pValue != NULL ) //if allocated
		{
		    //place index
		    noti.pValue[0] = (dataToNotify >> 24) & 0xFF;
	            noti.pValue[1] = (dataToNotify >> 16) & 0xFF;
	            noti.pValue[2] = (dataToNotify >> 8) & 0xFF;
	            noti.pValue[3] = dataToNotify & 0xFF;
		    status = GATT_Notification( 0, &noti, 0 );    //attempt to send
		    if ( status != SUCCESS ) //if noti not sent
	            {
		        GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
		    }
		}
		else
		{
		    //bleNoResources
	            asm(" NOP");
		}
	        //Clear the event
	    	events &= ~NOTIFY_TASK_SELECT_EVT;
	    }

	}


  • This is the thread's main processing loop, notice the thread sleeps until an ICall message is posted to its queue or its semaphore is posted

3. Interrupts and other real time event processing functions

    static void NotificationTask_selectPINHwiFxn(PIN_Handle hPin, PIN_Id pinId)
    {
        if (sem != NULL)
	{
		//Set the event and wake up the tas
		events |= NOTIFY_TASK_SELECT_EVT;
		Semaphore_post(sem);
	}
    }


  • Note that the hardware ISR function is simple and quick. Since Hwi's can preempt the BLE stack task, they must be kept short so as to not violate the BLE stack's real time requirements.
  • It is convention to trigger one of the app's event flags in the ISR and post the semaphore. This allows the BLE stack to do any pending processing, and allows the app to process the event later.


Project File Modifications

1. In order to increase the number of tasks in the current project, you must override a few preprocessor defines.
Preprocessor defines can be modified as shown below:
IAR

  • Right click on project name, options > C/C++ Compiler > Preprocessor

CCS

  • Right click on project name, properties > Build > ARM Compiler > Advanced Options > Predefined Symbols

Add the following defines to your app and stack projects respectively
Stack

  • OSAL_MAX_NUM_PROXY_TASKS=3:
    • This define controls the number of tasks that are allowed to communicate with the BLE protocol stack through ICall
    • In the SimpleBLEPeripheral, we need to set this to 3 because there are now 3 tasks that need to access the stack: SimpleBLEPerpheral Task, GAPRole task, and NPI Task

Application

  • ICALL_MAX_NUM_TASKS=4
    • This defines how many tasks will be registered with ICall, in the case of the SimpleBLEPeripheral we have the stack task, the SimpleBLEPeripheralTask, the NPI task, and the GAPRole task
  • ICALL_MAX_NUM_ENTITIES=7
    • This Maximum number of entities that use ICall, including service entities and application entities. Since we are adding another task that also registers a service with ICall, this number must be increased

2. Copy required files into your project folder, in the case of SimpleBLEPeripheral: BLE_STACK_INSTALL\Projects\ble\SimpleBLEPeripheral\CC26xx\Source\Application

  • notificationTask.c
  • notificationTask.h

3. Add the files to the IAR or CCS project by dragging them into the application folder

4. Modify the Main.c file to create and add your task.

#include "notificationTask.h"

Create the task in the main function. The notification tasks runs at the same priority as the SimpleBLEPeripheral task.

    /* Kick off your task */
    NotificationTask_createTask();


Demoing the Task

  • After performing the above modifications the SimpleBLEPeripheral project should behave as expected
  • Try connecting to the modified SimpleBLEPeripheral project using BTool (included in TI BLE Stack)
  • When pressing the select key on the SmartRF06 board, notice that the project is sending out notifications from the newly created task
  • Modify the provided task to fit your needs