Other Parts Discussed in Thread: CC2640, SYSBIOS
Tool/software: Code Composer Studio
I want to use the "sleep()" function to make CC2640 enter standby mode directly . Refer to the pinStandby project in CC2640 SDK , "sleep()" function is added into
"simple_peripheral.c". However , after rebuilding the simple_peripheral project , CCS shows error . Where am I wrong ?
1、My detailed steps of adding "sleep()" function is as followed:
(1)Add the head file "#include <unistd.h>" of "sleep()" function in "simple_peripheral.c" , as shown in picture 1.
picture 1
(2)Add the "sleep()" function in "SimpleBLEPeripheral_taskFxn()" funtion in in "simple_peripheral.c" , as shown in picture 2 . Set "standbyDuration" to 10 seconds .
picture 2
(3)Configure the "include options" of app and stack . The file path of "unistd.h" in my computer is "C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\kernel\tirtos\packages\ti\sysbios\posix". Add
this file path into "include options" of app , as shown in picture 3 .
picture 3
(4)Add the above file path into "include options" of stack , as shown in picture 4.
picture 4
(5)Rebuild the simple_peripheral project .However ,CCS shows errors . The result is shown in picture 5 and 6 .
picture 5
picture 6
Where am I wrong ?
4、Attachments
(1) the location of simple_peripheral_oad_onchip in my computer
C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\blestack\simple_peripheral_oad_onchip
(2) the location of pinStandby project in my computer
C:\ti\simplelink_cc2640r2_sdk_1_40_00_45\examples\rtos\CC2640R2_LAUNCHXL\drivers\pinStandby
(3) simplelink_cc2640r2_sdk_1_40_00_45 can be downloaded here
dev.ti.com/.../
(4) CC2640R2 launchpad can be bought here
www.ti.com/.../launchxl-cc2640r2
(5) my source code can be downloaded here (including:"simple_peripheral.c" )
/******************************************************************************
@file simple_peripheral.c
@brief This file contains the Simple Peripheral sample application for use
with the CC2650 Bluetooth Low Energy Protocol Stack.
Group: CMCU, SCS
Target Device: CC2640R2
******************************************************************************
Copyright (c) 2013-2017, Texas Instruments Incorporated
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Texas Instruments Incorporated nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
******************************************************************************
Release Name: simplelink_cc2640r2_sdk_1_40_00_45
Release Date: 2017-07-20 17:16:59
*****************************************************************************/
/*********************************************************************
* INCLUDES
*/
#include <string.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/knl/Clock.h>
#include <ti/sysbios/knl/Event.h>
#include <ti/sysbios/knl/Queue.h>
#include <ti/display/Display.h>
#include <ti/mw/extflash/ExtFlash.h>
#if defined( USE_FPGA ) || defined( DEBUG_SW_TRACE )
#include <driverlib/ioc.h>
#endif // USE_FPGA | DEBUG_SW_TRACE
#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"
#include "devinfoservice.h"
#include "simple_gatt_profile.h"
#include "ll_common.h"
#include "peripheral.h"
#ifdef USE_RCOSC
#include "rcosc_calibration.h"
#endif //USE_RCOSC
#include "board_key.h"
#include "board.h"
#include "simple_peripheral.h"
//fuheng1 force cc2640 entering standby
#include <unistd.h>
/*********************************************************************
* CONSTANTS
*/
// Advertising interval when device is discoverable (units of 625us, 160=100ms)
#define DEFAULT_ADVERTISING_INTERVAL 160 //100ms
//#define DEFAULT_ADVERTISING_INTERVAL 320 //200ms
//#define DEFAULT_ADVERTISING_INTERVAL 480 //300ms
//#define DEFAULT_ADVERTISING_INTERVAL 640 //400ms
//#define DEFAULT_ADVERTISING_INTERVAL 800 //500ms
//#define DEFAULT_ADVERTISING_INTERVAL 1600 //1000ms
// General discoverable mode: advertise indefinitely
#define DEFAULT_DISCOVERABLE_MODE GAP_ADTYPE_FLAGS_GENERAL
// Minimum connection interval (units of 1.25ms, 80=100ms) for automatic
// parameter update request
#define DEFAULT_DESIRED_MIN_CONN_INTERVAL 80
// Maximum connection interval (units of 1.25ms, 800=1000ms) for automatic
// parameter update request
#define DEFAULT_DESIRED_MAX_CONN_INTERVAL 800
// Slave latency to use for automatic parameter update request
#define DEFAULT_DESIRED_SLAVE_LATENCY 0
// Supervision timeout value (units of 10ms, 1000=10s) for automatic parameter
// update request
#define DEFAULT_DESIRED_CONN_TIMEOUT 1000
// After the connection is formed, the peripheral waits until the central
// device asks for its preferred connection parameters
#define DEFAULT_ENABLE_UPDATE_REQUEST GAPROLE_LINK_PARAM_UPDATE_WAIT_REMOTE_PARAMS
// Connection Pause Peripheral time value (in seconds)
#define DEFAULT_CONN_PAUSE_PERIPHERAL 6
// How often to perform periodic event (in msec)
#define SBP_PERIODIC_EVT_PERIOD 5000
// Application specific event ID for HCI Connection Event End Events
#define SBP_HCI_CONN_EVT_END_EVT 0x0001
// Type of Display to open
#if !defined(Display_DISABLE_ALL)
#if defined(BOARD_DISPLAY_USE_LCD) && (BOARD_DISPLAY_USE_LCD!=0)
#define SBP_DISPLAY_TYPE Display_Type_LCD
#elif defined (BOARD_DISPLAY_USE_UART) && (BOARD_DISPLAY_USE_UART!=0)
#define SBP_DISPLAY_TYPE Display_Type_UART
#else // !BOARD_DISPLAY_USE_LCD && !BOARD_DISPLAY_USE_UART
#define SBP_DISPLAY_TYPE 0 // Option not supported
#endif // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
#else // BOARD_DISPLAY_USE_LCD && BOARD_DISPLAY_USE_UART
#define SBP_DISPLAY_TYPE 0 // No Display
#endif // !Display_DISABLE_ALL
// Task configuration
#define SBP_TASK_PRIORITY 1
#ifndef SBP_TASK_STACK_SIZE
#define SBP_TASK_STACK_SIZE 644
#endif
// Application events
#define SBP_STATE_CHANGE_EVT 0x0001
#define SBP_CHAR_CHANGE_EVT 0x0002
#define SBP_PAIRING_STATE_EVT 0x0004
#define SBP_PASSCODE_NEEDED_EVT 0x0008
// Internal Events for RTOS application
#define SBP_ICALL_EVT ICALL_MSG_EVENT_ID // Event_Id_31
#define SBP_QUEUE_EVT UTIL_QUEUE_EVENT_ID // Event_Id_30
#define SBP_PERIODIC_EVT Event_Id_00
// Bitwise OR of all events to pend on
#define SBP_ALL_EVENTS (SBP_ICALL_EVT | \
SBP_QUEUE_EVT | \
SBP_PERIODIC_EVT)
/*********************************************************************
* TYPEDEFS
*/
// App event passed from profiles.
typedef struct
{
appEvtHdr_t hdr; // event header.
uint8_t *pData; // event data
} sbpEvt_t;
/*********************************************************************
* GLOBAL VARIABLES
*/
// Display Interface
Display_Handle dispHandle = NULL;
/*********************************************************************
* LOCAL VARIABLES
*/
// Entity ID globally used to check for source and/or destination of messages
static ICall_EntityID selfEntity;
// Event globally used to post local events and pend on system and
// local events.
static ICall_SyncHandle syncEvent;
// Clock instances for internal periodic events.
static Clock_Struct periodicClock;
// Queue object used for app messages
static Queue_Struct appMsg;
static Queue_Handle appMsgQueue;
// Task configuration
Task_Struct sbpTask;
Char sbpTaskStack[SBP_TASK_STACK_SIZE];
// Scan response data (max size = 31 bytes)
static uint8_t scanRspData[] =
{
// complete name
0x14, // length of this data
GAP_ADTYPE_LOCAL_NAME_COMPLETE,
'S',
'i',
'm',
'p',
'l',
'e',
'B',
'L',
'E',
'P',
'e',
'r',
'i',
'p',
'h',
'e',
'r',
'a',
'l',
// connection interval range
0x05, // length of this data
GAP_ADTYPE_SLAVE_CONN_INTERVAL_RANGE,
LO_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL), // 100ms
HI_UINT16(DEFAULT_DESIRED_MIN_CONN_INTERVAL),
LO_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL), // 1s
HI_UINT16(DEFAULT_DESIRED_MAX_CONN_INTERVAL),
// Tx power level
0x02, // length of this data
GAP_ADTYPE_POWER_LEVEL,
0 // 0dBm
};
// Advertisement data (max size = 31 bytes, though this is
// best kept short to conserve power while advertising)
static uint8_t advertData[] =
{
// Flags: this field sets the device to use general discoverable
// mode (advertises indefinitely) instead of general
// discoverable mode (advertise for 30 seconds at a time)
0x02, // length of this data
GAP_ADTYPE_FLAGS,
DEFAULT_DISCOVERABLE_MODE | GAP_ADTYPE_FLAGS_BREDR_NOT_SUPPORTED,
// service UUID, to notify central devices what services are included
// in this peripheral
0x03, // length of this data
GAP_ADTYPE_16BIT_MORE, // some of the UUID's, but not all
LO_UINT16(SIMPLEPROFILE_SERV_UUID),
HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};
// GAP GATT Attributes
static uint8_t attDeviceName[GAP_DEVICE_NAME_LEN] = "Simple Peripheral";
// Globals used for ATT Response retransmission
static gattMsgEvent_t *pAttRsp = NULL;
static uint8_t rspTxRetry = 0;
/*********************************************************************
* LOCAL FUNCTIONS
*/
static void SimpleBLEPeripheral_init( void );
static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1);
static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg);
static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg);
static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg);
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState);
static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID);
static void SimpleBLEPeripheral_performPeriodicTask(void);
static void SimpleBLEPeripheral_clockHandler(UArg arg);
static void SimpleBLEPeripheral_sendAttRsp(void);
static void SimpleBLEPeripheral_freeAttRsp(uint8_t status);
static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
uint8_t uiInputs, uint8_t uiOutputs);
static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,
uint8_t status);
static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status);
static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs);
static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState);
static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID);
static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,
uint8_t *pData);
/*********************************************************************
* EXTERN FUNCTIONS
*/
extern void AssertHandler(uint8 assertCause, uint8 assertSubcause);
/*********************************************************************
* PROFILE CALLBACKS
*/
// Peripheral GAPRole Callbacks
static gapRolesCBs_t SimpleBLEPeripheral_gapRoleCBs =
{
SimpleBLEPeripheral_stateChangeCB // GAPRole State Change Callbacks
};
// GAP Bond Manager Callbacks
// These are set to NULL since they are not needed. The application
// is set up to only perform justworks pairing.
static gapBondCBs_t simpleBLEPeripheral_BondMgrCBs =
{
(pfnPasscodeCB_t) SimpleBLEPeripheral_passcodeCB, // Passcode callback
SimpleBLEPeripheral_pairStateCB // Pairing / Bonding state Callback
};
// Simple GATT Profile Callbacks
static simpleProfileCBs_t SimpleBLEPeripheral_simpleProfileCBs =
{
SimpleBLEPeripheral_charValueChangeCB // Simple GATT Characteristic value change callback
};
/*********************************************************************
* PUBLIC FUNCTIONS
*/
/*********************************************************************
* @fn SimpleBLEPeripheral_createTask
*
* @brief Task creation function for the Simple Peripheral.
*
* @param None.
*
* @return None.
*/
void SimpleBLEPeripheral_createTask(void)
{
Task_Params taskParams;
// Configure task
Task_Params_init(&taskParams);
taskParams.stack = sbpTaskStack;
taskParams.stackSize = SBP_TASK_STACK_SIZE;
taskParams.priority = SBP_TASK_PRIORITY;
Task_construct(&sbpTask, SimpleBLEPeripheral_taskFxn, &taskParams, NULL);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_init
*
* @brief Called during initialization and contains application
* specific initialization (ie. hardware initialization/setup,
* table initialization, power up notification, etc), and
* profile initialization/setup.
*
* @param None.
*
* @return None.
*/
static void SimpleBLEPeripheral_init(void)
{
ExtFlash_open();
ExtFlash_close();
// ******************************************************************
// N0 STACK API CALLS CAN OCCUR BEFORE THIS CALL TO ICall_registerApp
// ******************************************************************
// Register the current thread as an ICall dispatcher application
// so that the application can send and receive messages.
ICall_registerApp(&selfEntity, &syncEvent);
#ifdef USE_RCOSC
RCOSC_enableCalibration();
#endif // USE_RCOSC
#if defined( USE_FPGA )
// configure RF Core SMI Data Link
IOCPortConfigureSet(IOID_12, IOC_PORT_RFC_GPO0, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_11, IOC_PORT_RFC_GPI0, IOC_STD_INPUT);
// configure RF Core SMI Command Link
IOCPortConfigureSet(IOID_10, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_OUT, IOC_STD_OUTPUT);
IOCPortConfigureSet(IOID_9, IOC_IOCFG0_PORT_ID_RFC_SMI_CL_IN, IOC_STD_INPUT);
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT);
#else // !USE_FPGA
#if defined( DEBUG_SW_TRACE )
// configure RF Core tracer IO
IOCPortConfigureSet(IOID_8, IOC_PORT_RFC_TRC, IOC_STD_OUTPUT | IOC_CURRENT_4MA | IOC_SLEW_ENABLE);
#endif // DEBUG_SW_TRACE
#endif // USE_FPGA
// Create an RTOS queue for message from profile to be sent to app.
appMsgQueue = Util_constructQueue(&appMsg);
// Create one-shot clocks for internal periodic events.
Util_constructClock(&periodicClock, SimpleBLEPeripheral_clockHandler,
SBP_PERIODIC_EVT_PERIOD, 0, false, SBP_PERIODIC_EVT);
dispHandle = Display_open(SBP_DISPLAY_TYPE, NULL);
// Set GAP Parameters: After a connection was established, delay in seconds
// before sending when GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE,...)
// uses GAPROLE_LINK_PARAM_UPDATE_INITIATE_BOTH_PARAMS or
// GAPROLE_LINK_PARAM_UPDATE_INITIATE_APP_PARAMS
// For current defaults, this has no effect.
GAP_SetParamValue(TGAP_CONN_PAUSE_PERIPHERAL, DEFAULT_CONN_PAUSE_PERIPHERAL);
// Setup the Peripheral GAPRole Profile. For more information see the User's
// Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html/
{
// Device starts advertising upon initialization of GAP
uint8_t initialAdvertEnable = TRUE;
// By setting this to zero, the device will go into the waiting state after
// being discoverable for 30.72 second, and will not being advertising again
// until re-enabled by the application
uint16_t advertOffTime = 0;
uint8_t enableUpdateRequest = DEFAULT_ENABLE_UPDATE_REQUEST;
uint16_t desiredMinInterval = DEFAULT_DESIRED_MIN_CONN_INTERVAL;
uint16_t desiredMaxInterval = DEFAULT_DESIRED_MAX_CONN_INTERVAL;
uint16_t desiredSlaveLatency = DEFAULT_DESIRED_SLAVE_LATENCY;
uint16_t desiredConnTimeout = DEFAULT_DESIRED_CONN_TIMEOUT;
// Set the Peripheral GAPRole Parameters
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&initialAdvertEnable);
GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
&advertOffTime);
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData),
scanRspData);
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData);
GAPRole_SetParameter(GAPROLE_PARAM_UPDATE_ENABLE, sizeof(uint8_t),
&enableUpdateRequest);
GAPRole_SetParameter(GAPROLE_MIN_CONN_INTERVAL, sizeof(uint16_t),
&desiredMinInterval);
GAPRole_SetParameter(GAPROLE_MAX_CONN_INTERVAL, sizeof(uint16_t),
&desiredMaxInterval);
GAPRole_SetParameter(GAPROLE_SLAVE_LATENCY, sizeof(uint16_t),
&desiredSlaveLatency);
GAPRole_SetParameter(GAPROLE_TIMEOUT_MULTIPLIER, sizeof(uint16_t),
&desiredConnTimeout);
}
// Set the Device Name characteristic in the GAP GATT Service
// For more information, see the section in the User's Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);
// Set GAP Parameters to set the advertising interval
// For more information, see the GAP section of the User's Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html
{
// Use the same interval for general and limited advertising.
// Note that only general advertising will occur based on the above configuration
uint16_t advInt = DEFAULT_ADVERTISING_INTERVAL;
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_LIM_DISC_ADV_INT_MAX, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_GEN_DISC_ADV_INT_MAX, advInt);
}
// Setup the GAP Bond Manager. For more information see the section in the
// User's Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html/
{
// Don't send a pairing request after connecting; the peer device must
// initiate pairing
uint8_t pairMode = GAPBOND_PAIRING_MODE_WAIT_FOR_REQ;
// Use authenticated pairing: require passcode.
uint8_t mitm = TRUE;
// This device only has display capabilities. Therefore, it will display the
// passcode during pairing. However, since the default passcode is being
// used, there is no need to display anything.
uint8_t ioCap = GAPBOND_IO_CAP_DISPLAY_ONLY;
// Request bonding (storing long-term keys for re-encryption upon subsequent
// connections without repairing)
uint8_t bonding = TRUE;
GAPBondMgr_SetParameter(GAPBOND_PAIRING_MODE, sizeof(uint8_t), &pairMode);
GAPBondMgr_SetParameter(GAPBOND_MITM_PROTECTION, sizeof(uint8_t), &mitm);
GAPBondMgr_SetParameter(GAPBOND_IO_CAPABILITIES, sizeof(uint8_t), &ioCap);
GAPBondMgr_SetParameter(GAPBOND_BONDING_ENABLED, sizeof(uint8_t), &bonding);
}
// Initialize GATT attributes
GGS_AddService(GATT_ALL_SERVICES); // GAP GATT Service
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT Service
DevInfo_AddService(); // Device Information Service
SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile
// Setup the SimpleProfile Characteristic Values
// For more information, see the sections in the User's Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html/
{
uint8_t charValue1 = 1;
uint8_t charValue2 = 2;
uint8_t charValue3 = 3;
uint8_t charValue4 = 4;
uint8_t charValue5[SIMPLEPROFILE_CHAR5_LEN] = { 1, 2, 3, 4, 5 };
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR1, sizeof(uint8_t),
&charValue1);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR2, sizeof(uint8_t),
&charValue2);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR3, sizeof(uint8_t),
&charValue3);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
&charValue4);
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR5, SIMPLEPROFILE_CHAR5_LEN,
charValue5);
}
// Register callback with SimpleGATTprofile
SimpleProfile_RegisterAppCBs(&SimpleBLEPeripheral_simpleProfileCBs);
// Start the Device
VOID GAPRole_StartDevice(&SimpleBLEPeripheral_gapRoleCBs);
// Start Bond Manager and register callback
VOID GAPBondMgr_Register(&simpleBLEPeripheral_BondMgrCBs);
// Register with GAP for HCI/Host messages. This is needed to receive HCI
// events. For more information, see the section in the User's Guide:
// http://software-dl.ti.com/lprf/sdg-latest/html
GAP_RegisterForMsgs(selfEntity);
// Register for GATT local events and ATT Responses pending for transmission
GATT_RegisterForMsgs(selfEntity);
//Set default values for Data Length Extension
{
//Set initial values to maximum, RX is set to max. by default(251 octets, 2120us)
#define APP_SUGGESTED_PDU_SIZE 251 //default is 27 octets(TX)
#define APP_SUGGESTED_TX_TIME 2120 //default is 328us(TX)
//This API is documented in hci.h
//See the LE Data Length Extension section in the BLE-Stack User's Guide for information on using this command:
//http://software-dl.ti.com/lprf/sdg-latest/html/cc2640/index.html
//HCI_LE_WriteSuggestedDefaultDataLenCmd(APP_SUGGESTED_PDU_SIZE, APP_SUGGESTED_TX_TIME);
}
#if !defined (USE_LL_CONN_PARAM_UPDATE)
// Get the currently set local supported LE features
// The HCI will generate an HCI event that will get received in the main
// loop
HCI_LE_ReadLocalSupportedFeaturesCmd();
#endif // !defined (USE_LL_CONN_PARAM_UPDATE)
Display_print0(dispHandle, 0, 0, "BLE Peripheral");
}
/*********************************************************************
* @fn SimpleBLEPeripheral_taskFxn
*
* @brief Application task entry point for the Simple Peripheral.
*
* @param a0, a1 - not used.
*
* @return None.
*/
static void SimpleBLEPeripheral_taskFxn(UArg a0, UArg a1)
{
//fuheng3 force cc2640 entering standby
uint32_t standbyDuration = 10;
// Initialize application
SimpleBLEPeripheral_init();
// Application main loop
for (;;)
{
//fuheng2 force cc2640 entering standby
sleep(standbyDuration);
uint32_t 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
events = Event_pend(syncEvent, Event_Id_NONE, SBP_ALL_EVENTS,
ICALL_TIMEOUT_FOREVER);
if (events)
{
ICall_EntityID dest;
ICall_ServiceEnum src;
ICall_HciExtEvt *pMsg = NULL;
// Fetch any available messages that might have been sent from the stack
if (ICall_fetchServiceMsg(&src, &dest,
(void **)&pMsg) == ICALL_ERRNO_SUCCESS)
{
uint8 safeToDealloc = TRUE;
if ((src == ICALL_SERVICE_CLASS_BLE) && (dest == selfEntity))
{
ICall_Stack_Event *pEvt = (ICall_Stack_Event *)pMsg;
// Check for BLE stack events first
if (pEvt->signature == 0xffff)
{
// The GATT server might have returned a blePending as it was trying
// to process an ATT Response. Now that we finished with this
// connection event, let's try sending any remaining ATT Responses
// on the next connection event.
if (pEvt->event_flag & SBP_HCI_CONN_EVT_END_EVT)
{
// Try to retransmit pending ATT Response (if any)
SimpleBLEPeripheral_sendAttRsp();
}
}
else
{
// Process inter-task message
safeToDealloc = SimpleBLEPeripheral_processStackMsg((ICall_Hdr *)pMsg);
}
}
if (pMsg && safeToDealloc)
{
ICall_freeMsg(pMsg);
}
}
// If RTOS queue is not empty, process app message.
if (events & SBP_QUEUE_EVT)
{
while (!Queue_empty(appMsgQueue))
{
sbpEvt_t *pMsg = (sbpEvt_t *)Util_dequeueMsg(appMsgQueue);
if (pMsg)
{
// Process message.
SimpleBLEPeripheral_processAppMsg(pMsg);
// Free the space from the message.
ICall_free(pMsg);
}
}
}
if (events & SBP_PERIODIC_EVT)
{
Util_startClock(&periodicClock);
// Perform periodic application task
SimpleBLEPeripheral_performPeriodicTask();
}
}
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processStackMsg
*
* @brief Process an incoming stack message.
*
* @param pMsg - message to process
*
* @return TRUE if safe to deallocate incoming message, FALSE otherwise.
*/
static uint8_t SimpleBLEPeripheral_processStackMsg(ICall_Hdr *pMsg)
{
uint8_t safeToDealloc = TRUE;
switch (pMsg->event)
{
case GATT_MSG_EVENT:
// Process GATT message
safeToDealloc = SimpleBLEPeripheral_processGATTMsg((gattMsgEvent_t *)pMsg);
break;
case HCI_GAP_EVENT_EVENT:
{
// Process HCI message
switch(pMsg->status)
{
case HCI_COMMAND_COMPLETE_EVENT_CODE:
// Process HCI Command Complete Event
{
#if !defined (USE_LL_CONN_PARAM_UPDATE)
// This code will disable the use of the LL_CONNECTION_PARAM_REQ
// control procedure (for connection parameter updates, the
// L2CAP Connection Parameter Update procedure will be used
// instead). To re-enable the LL_CONNECTION_PARAM_REQ control
// procedures, define the symbol USE_LL_CONN_PARAM_UPDATE
// The L2CAP Connection Parameter Update procedure is used to
// support a delta between the minimum and maximum connection
// intervals required by some iOS devices.
// Parse Command Complete Event for opcode and status
hciEvt_CmdComplete_t* command_complete = (hciEvt_CmdComplete_t*) pMsg;
uint8_t pktStatus = command_complete->pReturnParam[0];
//find which command this command complete is for
switch (command_complete->cmdOpcode)
{
case HCI_LE_READ_LOCAL_SUPPORTED_FEATURES:
{
if (pktStatus == SUCCESS)
{
uint8_t featSet[8];
// Get current feature set from received event (bits 1-9
// of the returned data
memcpy( featSet, &command_complete->pReturnParam[1], 8 );
// Clear bit 1 of byte 0 of feature set to disable LL
// Connection Parameter Updates
CLR_FEATURE_FLAG( featSet[0], LL_FEATURE_CONN_PARAMS_REQ );
// Update controller with modified features
HCI_EXT_SetLocalSupportedFeaturesCmd( featSet );
}
}
break;
default:
//do nothing
break;
}
#endif // !defined (USE_LL_CONN_PARAM_UPDATE)
}
break;
case HCI_BLE_HARDWARE_ERROR_EVENT_CODE:
AssertHandler(HAL_ASSERT_CAUSE_HARDWARE_ERROR,0);
break;
default:
break;
}
}
break;
default:
// do nothing
break;
}
return (safeToDealloc);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processGATTMsg
*
* @brief Process GATT messages and events.
*
* @return TRUE if safe to deallocate incoming message, FALSE otherwise.
*/
static uint8_t SimpleBLEPeripheral_processGATTMsg(gattMsgEvent_t *pMsg)
{
// See if GATT server was unable to transmit an ATT response
if (pMsg->hdr.status == blePending)
{
// No HCI buffer was available. Let's try to retransmit the response
// on the next connection event.
if (HCI_EXT_ConnEventNoticeCmd(pMsg->connHandle, selfEntity,
SBP_HCI_CONN_EVT_END_EVT) == SUCCESS)
{
// First free any pending response
SimpleBLEPeripheral_freeAttRsp(FAILURE);
// Hold on to the response message for retransmission
pAttRsp = pMsg;
// Don't free the response message yet
return (FALSE);
}
}
else if (pMsg->method == ATT_FLOW_CTRL_VIOLATED_EVENT)
{
// ATT request-response or indication-confirmation flow control is
// violated. All subsequent ATT requests or indications will be dropped.
// The app is informed in case it wants to drop the connection.
// Display the opcode of the message that caused the violation.
Display_print1(dispHandle, 5, 0, "FC Violated: %d", pMsg->msg.flowCtrlEvt.opcode);
}
else if (pMsg->method == ATT_MTU_UPDATED_EVENT)
{
// MTU size updated
Display_print1(dispHandle, 5, 0, "MTU Size: %d", pMsg->msg.mtuEvt.MTU);
}
// Free message payload. Needed only for ATT Protocol messages
GATT_bm_free(&pMsg->msg, pMsg->method);
// It's safe to free the incoming message
return (TRUE);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_sendAttRsp
*
* @brief Send a pending ATT response message.
*
* @param none
*
* @return none
*/
static void SimpleBLEPeripheral_sendAttRsp(void)
{
// See if there's a pending ATT Response to be transmitted
if (pAttRsp != NULL)
{
uint8_t status;
// Increment retransmission count
rspTxRetry++;
// Try to retransmit ATT response till either we're successful or
// the ATT Client times out (after 30s) and drops the connection.
status = GATT_SendRsp(pAttRsp->connHandle, pAttRsp->method, &(pAttRsp->msg));
if ((status != blePending) && (status != MSG_BUFFER_NOT_AVAIL))
{
// Disable connection event end notice
HCI_EXT_ConnEventNoticeCmd(pAttRsp->connHandle, selfEntity, 0);
// We're done with the response message
SimpleBLEPeripheral_freeAttRsp(status);
}
else
{
// Continue retrying
Display_print1(dispHandle, 5, 0, "Rsp send retry: %d", rspTxRetry);
}
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_freeAttRsp
*
* @brief Free ATT response message.
*
* @param status - response transmit status
*
* @return none
*/
static void SimpleBLEPeripheral_freeAttRsp(uint8_t status)
{
// See if there's a pending ATT response message
if (pAttRsp != NULL)
{
// See if the response was sent out successfully
if (status == SUCCESS)
{
Display_print1(dispHandle, 5, 0, "Rsp sent retry: %d", rspTxRetry);
}
else
{
// Free response payload
GATT_bm_free(&pAttRsp->msg, pAttRsp->method);
Display_print1(dispHandle, 5, 0, "Rsp retry failed: %d", rspTxRetry);
}
// Free response message
ICall_freeMsg(pAttRsp);
// Reset our globals
pAttRsp = NULL;
rspTxRetry = 0;
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processAppMsg
*
* @brief Process an incoming callback from a profile.
*
* @param pMsg - message to process
*
* @return None.
*/
static void SimpleBLEPeripheral_processAppMsg(sbpEvt_t *pMsg)
{
switch (pMsg->hdr.event)
{
case SBP_STATE_CHANGE_EVT:
{
SimpleBLEPeripheral_processStateChangeEvt((gaprole_States_t)pMsg->
hdr.state);
}
break;
case SBP_CHAR_CHANGE_EVT:
{
SimpleBLEPeripheral_processCharValueChangeEvt(pMsg->hdr.state);
}
break;
// Pairing event
case SBP_PAIRING_STATE_EVT:
{
SimpleBLEPeripheral_processPairState(pMsg->hdr.state, *pMsg->pData);
ICall_free(pMsg->pData);
break;
}
// Passcode event
case SBP_PASSCODE_NEEDED_EVT:
{
SimpleBLEPeripheral_processPasscode(*pMsg->pData);
ICall_free(pMsg->pData);
break;
}
default:
// Do nothing.
break;
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_stateChangeCB
*
* @brief Callback from GAP Role indicating a role state change.
*
* @param newState - new state
*
* @return None.
*/
static void SimpleBLEPeripheral_stateChangeCB(gaprole_States_t newState)
{
SimpleBLEPeripheral_enqueueMsg(SBP_STATE_CHANGE_EVT, newState, 0);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processStateChangeEvt
*
* @brief Process a pending GAP Role state change event.
*
* @param newState - new state
*
* @return None.
*/
static void SimpleBLEPeripheral_processStateChangeEvt(gaprole_States_t newState)
{
#ifdef PLUS_BROADCASTER
static bool firstConnFlag = false;
#endif // PLUS_BROADCASTER
switch ( newState )
{
case GAPROLE_STARTED:
{
uint8_t ownAddress[B_ADDR_LEN];
uint8_t systemId[DEVINFO_SYSTEM_ID_LEN];
GAPRole_GetParameter(GAPROLE_BD_ADDR, ownAddress);
// use 6 bytes of device address for 8 bytes of system ID value
systemId[0] = ownAddress[0];
systemId[1] = ownAddress[1];
systemId[2] = ownAddress[2];
// set middle bytes to zero
systemId[4] = 0x00;
systemId[3] = 0x00;
// shift three bytes up
systemId[7] = ownAddress[5];
systemId[6] = ownAddress[4];
systemId[5] = ownAddress[3];
DevInfo_SetParameter(DEVINFO_SYSTEM_ID, DEVINFO_SYSTEM_ID_LEN, systemId);
// Display device address
Display_print0(dispHandle, 1, 0, Util_convertBdAddr2Str(ownAddress));
Display_print0(dispHandle, 2, 0, "Initialized");
}
break;
case GAPROLE_ADVERTISING:
Display_print0(dispHandle, 2, 0, "Advertising");
break;
#ifdef PLUS_BROADCASTER
// After a connection is dropped, a device in PLUS_BROADCASTER will continue
// sending non-connectable advertisements and shall send this change of
// state to the application. These are then disabled here so that sending
// connectable advertisements can resume.
case GAPROLE_ADVERTISING_NONCONN:
{
uint8_t advertEnabled = FALSE;
// Disable non-connectable advertising.
GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
&advertEnabled);
advertEnabled = TRUE;
// Enabled connectable advertising.
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&advertEnabled);
// Reset flag for next connection.
firstConnFlag = false;
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
}
break;
#endif //PLUS_BROADCASTER
case GAPROLE_CONNECTED:
{
linkDBInfo_t linkInfo;
uint8_t numActive = 0;
//Util_startClock(&periodicClock);
numActive = linkDB_NumActive();
// Use numActive to determine the connection handle of the last
// connection
if ( linkDB_GetInfo( numActive - 1, &linkInfo ) == SUCCESS )
{
Display_print1(dispHandle, 2, 0, "Num Conns: %d", (uint16_t)numActive);
Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(linkInfo.addr));
}
else
{
uint8_t peerAddress[B_ADDR_LEN];
GAPRole_GetParameter(GAPROLE_CONN_BD_ADDR, peerAddress);
Display_print0(dispHandle, 2, 0, "Connected");
Display_print0(dispHandle, 3, 0, Util_convertBdAddr2Str(peerAddress));
}
#ifdef PLUS_BROADCASTER
// Only turn advertising on for this state when we first connect
// otherwise, when we go from connected_advertising back to this state
// we will be turning advertising back on.
if (firstConnFlag == false)
{
uint8_t advertEnabled = FALSE; // Turn on Advertising
// Disable connectable advertising.
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&advertEnabled);
// Set to true for non-connectable advertising.
advertEnabled = TRUE;
// Enable non-connectable advertising.
GAPRole_SetParameter(GAPROLE_ADV_NONCONN_ENABLED, sizeof(uint8_t),
&advertEnabled);
firstConnFlag = true;
}
#endif // PLUS_BROADCASTER
}
break;
case GAPROLE_CONNECTED_ADV:
Display_print0(dispHandle, 2, 0, "Connected Advertising");
break;
case GAPROLE_WAITING:
Util_stopClock(&periodicClock);
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
Display_print0(dispHandle, 2, 0, "Disconnected");
// Clear remaining lines
Display_clearLines(dispHandle, 3, 5);
break;
case GAPROLE_WAITING_AFTER_TIMEOUT:
SimpleBLEPeripheral_freeAttRsp(bleNotConnected);
Display_print0(dispHandle, 2, 0, "Timed Out");
// Clear remaining lines
Display_clearLines(dispHandle, 3, 5);
#ifdef PLUS_BROADCASTER
// Reset flag for next connection.
firstConnFlag = false;
#endif // PLUS_BROADCASTER
break;
case GAPROLE_ERROR:
Display_print0(dispHandle, 2, 0, "Error");
break;
default:
Display_clearLine(dispHandle, 2);
break;
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_charValueChangeCB
*
* @brief Callback from Simple Profile indicating a characteristic
* value change.
*
* @param paramID - parameter ID of the value that was changed.
*
* @return None.
*/
static void SimpleBLEPeripheral_charValueChangeCB(uint8_t paramID)
{
SimpleBLEPeripheral_enqueueMsg(SBP_CHAR_CHANGE_EVT, paramID, 0);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processCharValueChangeEvt
*
* @brief Process a pending Simple Profile characteristic value change
* event.
*
* @param paramID - parameter ID of the value that was changed.
*
* @return None.
*/
static void SimpleBLEPeripheral_processCharValueChangeEvt(uint8_t paramID)
{
uint8_t newValue;
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR1, &newValue);
Display_print1(dispHandle, 4, 0, "Char 1: %d", (uint16_t)newValue);
break;
case SIMPLEPROFILE_CHAR3:
SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &newValue);
Display_print1(dispHandle, 4, 0, "Char 3: %d", (uint16_t)newValue);
break;
default:
// should not reach here!
break;
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_performPeriodicTask
*
* @brief Perform a periodic application task. This function gets called
* every five seconds (SBP_PERIODIC_EVT_PERIOD). In this example,
* the value of the third characteristic in the SimpleGATTProfile
* service is retrieved from the profile, and then copied into the
* value of the the fourth characteristic.
*
* @param None.
*
* @return None.
*/
static void SimpleBLEPeripheral_performPeriodicTask(void)
{
uint8_t valueToCopy;
// Call to retrieve the value of the third characteristic in the profile
if (SimpleProfile_GetParameter(SIMPLEPROFILE_CHAR3, &valueToCopy) == SUCCESS)
{
// Call to set that value of the fourth characteristic in the profile.
// Note that if notifications of the fourth characteristic have been
// enabled by a GATT client device, then a notification will be sent
// every time this function is called.
SimpleProfile_SetParameter(SIMPLEPROFILE_CHAR4, sizeof(uint8_t),
&valueToCopy);
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_pairStateCB
*
* @brief Pairing state callback.
*
* @return none
*/
static void SimpleBLEPeripheral_pairStateCB(uint16_t connHandle, uint8_t state,
uint8_t status)
{
uint8_t *pData;
// Allocate space for the event data.
if ((pData = ICall_malloc(sizeof(uint8_t))))
{
*pData = status;
// Queue the event.
SimpleBLEPeripheral_enqueueMsg(SBP_PAIRING_STATE_EVT, state, pData);
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processPairState
*
* @brief Process the new paring state.
*
* @return none
*/
static void SimpleBLEPeripheral_processPairState(uint8_t state, uint8_t status)
{
if (state == GAPBOND_PAIRING_STATE_STARTED)
{
Display_print0(dispHandle, 2, 0, "Pairing started");
}
else if (state == GAPBOND_PAIRING_STATE_COMPLETE)
{
if (status == SUCCESS)
{
Display_print0(dispHandle, 2, 0, "Pairing success");
}
else
{
Display_print1(dispHandle, 2, 0, "Pairing fail: %d", status);
}
}
else if (state == GAPBOND_PAIRING_STATE_BONDED)
{
if (status == SUCCESS)
{
Display_print0(dispHandle, 2, 0, "Bonding success");
}
}
else if (state == GAPBOND_PAIRING_STATE_BOND_SAVED)
{
if (status == SUCCESS)
{
Display_print0(dispHandle, 2, 0, "Bond save success");
}
else
{
Display_print1(dispHandle, 2, 0, "Bond save failed: %d", status);
}
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_passcodeCB
*
* @brief Passcode callback.
*
* @return none
*/
static void SimpleBLEPeripheral_passcodeCB(uint8_t *deviceAddr, uint16_t connHandle,
uint8_t uiInputs, uint8_t uiOutputs)
{
uint8_t *pData;
// Allocate space for the passcode event.
if ((pData = ICall_malloc(sizeof(uint8_t))))
{
*pData = uiOutputs;
// Enqueue the event.
SimpleBLEPeripheral_enqueueMsg(SBP_PASSCODE_NEEDED_EVT, 0, pData);
}
}
/*********************************************************************
* @fn SimpleBLEPeripheral_processPasscode
*
* @brief Process the Passcode request.
*
* @return none
*/
static void SimpleBLEPeripheral_processPasscode(uint8_t uiOutputs)
{
// This app uses a default passcode. A real-life scenario would handle all
// pairing scenarios and likely generate this randomly.
uint32_t passcode = B_APP_DEFAULT_PASSCODE;
// Display passcode to user
if (uiOutputs != 0)
{
Display_print1(dispHandle, 4, 0, "Passcode: %d", passcode);
}
uint16_t connectionHandle;
GAPRole_GetParameter(GAPROLE_CONNHANDLE, &connectionHandle);
// Send passcode response
GAPBondMgr_PasscodeRsp(connectionHandle, SUCCESS, passcode);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_clockHandler
*
* @brief Handler function for clock timeouts.
*
* @param arg - event type
*
* @return None.
*/
static void SimpleBLEPeripheral_clockHandler(UArg arg)
{
// Wake up the application.
Event_post(syncEvent, arg);
}
/*********************************************************************
* @fn SimpleBLEPeripheral_enqueueMsg
*
* @brief Creates a message and puts the message in RTOS queue.
*
* @param event - message event.
* @param state - message state.
* @param pData - message data pointer.
*
* @return TRUE or FALSE
*/
static uint8_t SimpleBLEPeripheral_enqueueMsg(uint8_t event, uint8_t state,
uint8_t *pData)
{
sbpEvt_t *pMsg = ICall_malloc(sizeof(sbpEvt_t));
// Create dynamic pointer to message.
if (pMsg)
{
pMsg->hdr.event = event;
pMsg->hdr.state = state;
pMsg->pData = pData;
// Enqueue the message.
return Util_enqueueMsg(appMsgQueue, syncEvent, (uint8_t *)pMsg);
}
return FALSE;
}
/*********************************************************************
*********************************************************************/
5、My developing environment
CCS:Code Composer Studio 7.2.0
SDK:simplelink_cc2640r2_sdk_1_40_00_45
hardware:CC26640R2 launchpad develop kit
system:win7 64 bit