This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/CC2640R2F: CC2640R2F

Part Number: CC2640R2F
Other Parts Discussed in Thread: SIMPLELINK-CC2640R2-SDK,

Tool/software: Code Composer Studio

Hello All,

I am working on SIMPLELINK-CC2640R2-SDK_3.10.00.15


Currently i am working on ble cc2640r2f launchpad.

Below i have attached my code that receive data ,store data and send/.write same data to uart.

But facing issue when write or read data to/from external flash, the data getting duplicate or over written on other data when writing on uart.  

In this multi role project i will receive the sensor data from 2 or more BLE module periodically in simplegattprofile.c file then will store/write data in external flash and the read it and then written on uart. 

But in below code duplication and loss is found.

So please help me out to solve this issue or provide your valuable suggestion.

Here my code and the function that i am using....

 

@file multi_role.c

 

// How often to perform periodic event (in msec)
int READ_PERIOD = 149;
int WRITE_UART = 79;

 

#define flashbufsize 5000

#define extbuffer 0x61000

uint8_t simple1handle = 45;//34;
uint8_t simple3handle = 51;//40;

void write_to_flash(uint8_t *buf,int buf_size)
{
if(writecount>=flashbufsize)
{
n=0;
writecount=0;
readcount=0;
ExtFlash_open();
ExtFlash_erase(extbuffer,flashbufsize*5);
ExtFlash_close();
}
ExtFlash_open();
writereturn = ExtFlash_write(extbuffer+(writecount*buf_size),buf_size,buf);
DELAY_MS(10);
ExtFlash_close();
writecount++;
n++;
}

void read_from_flash(uint8_t *buf,int buf_size)
{
if(readcount<writecount)
{
ExtFlash_open();
readreturn = ExtFlash_read(extbuffer+(readcount*buf_size),buf_size,buf);
//DELAY_MS(10);
ExtFlash_close();
readcount++;
}
}

static void readCallback(UART_Handle uart, void *rxBuf, size_t size)
{
//rxBytes = UART_read(uart, startaddress, wantedRxBytes);
return;
}

static void writeCallback(UART_Handle uart, void *rxBuf, size_t size)
{
return;
}

static void multi_role_init(void)
{
// ******************************************************************
// 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);

PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_ON);
DELAY_MS(100);
PIN_setOutputValue(hGpioPin, Board_RLED, Board_LED_OFF);

// Create an RTOS queue for message from profile to be sent to app.
appMsgQueue = Util_constructQueue(&appMsg);

init_whatch();

// Create one-shot clocks for internal periodic events.
Util_constructClock(&read_clock, multi_role_clockHandler,
READ_PERIOD, 0, false,READ_UART_DATA_EVT);
Util_constructClock(&buffer_clock, multi_role_clockHandler,
SEND_PERIOD, 0, false,SEND_BUFFER_DATA);
Util_constructClock(&write_uart_clock, multi_role_clockHandler,
WRITE_UART, 0, false,UART_WRITE_EVT);
Util_constructClock(&ack_clock, multi_role_clockHandler,
ACK_PERIOD, 0, false, ACK_TIMEOUT_EVT);
Util_constructClock(&reset_clock, multi_role_clockHandler,
RESET_PERIOD, 0, false,RESET_EVT);
Util_constructClock(&time_rqt_clock, multi_role_clockHandler,
TIME_RQT_PERIOD, 0, false,TIME_RQT_EVT);
//Util_constructClock(&signal_clock, multi_role_clockHandler,
//SIGNAL_PERIOD, 0, false,SIGNAL_EVT );
Util_constructClock(&ble_stat_clock, multi_role_clockHandler,
BLE_STAT_PERIOD, 0, false,BLE_STAT_EVT);

HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_5_DBM);

// Setup the GAP
{
// Set advertising interval the same for all scenarios
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);
GAP_SetParamValue(TGAP_CONN_ADV_INT_MIN, advInt);
GAP_SetParamValue(TGAP_CONN_ADV_INT_MAX, advInt);

// Set scan duration
GAP_SetParamValue(TGAP_GEN_DISC_SCAN, DEFAULT_SCAN_DURATION);

// Scan interval and window the same for all scenarios
GAP_SetParamValue(TGAP_CONN_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_HIGH_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_GEN_DISC_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_GEN_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_LIM_DISC_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_LIM_DISC_SCAN_WIND, DEFAULT_SCAN_WIND);
GAP_SetParamValue(TGAP_CONN_EST_SCAN_INT, DEFAULT_SCAN_INT);
GAP_SetParamValue(TGAP_CONN_EST_SCAN_WIND, DEFAULT_SCAN_WIND);

// Set connection parameters
GAP_SetParamValue(TGAP_CONN_EST_INT_MIN, 8);
GAP_SetParamValue(TGAP_CONN_EST_INT_MAX, DEFAULT_CONN_INT);
GAP_SetParamValue(TGAP_CONN_EST_SUPERV_TIMEOUT, DEFAULT_CONN_TIMEOUT);
GAP_SetParamValue(TGAP_CONN_EST_LATENCY, DEFAULT_CONN_LATENCY);

// Register to receive GAP and HCI messages
GAP_RegisterForMsgs(selfEntity);
}

// Setup the GAP Role Profile
{
/*--------PERIPHERAL-------------*/
uint8_t initialAdvertEnable = TRUE;
uint16_t advertOffTime = 0;

// device starts advertising upon initialization
GAPRole_SetParameter(GAPROLE_ADVERT_ENABLED, sizeof(uint8_t),
&initialAdvertEnable, NULL);

// 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 the enabler is set back to TRUE
GAPRole_SetParameter(GAPROLE_ADVERT_OFF_TIME, sizeof(uint16_t),
&advertOffTime, NULL);

// Set scan response data
GAPRole_SetParameter(GAPROLE_SCAN_RSP_DATA, sizeof(scanRspData1),
scanRspData1, NULL);

// Set advertising data
GAPRole_SetParameter(GAPROLE_ADVERT_DATA, sizeof(advertData), advertData, NULL);

// set max amount of scan responses
uint8_t scanRes = DEFAULT_MAX_SCAN_RES;

// Set the max amount of scan responses
GAPRole_SetParameter(GAPROLE_MAX_SCAN_RES, sizeof(uint8_t),
&scanRes, NULL);

// Start the GAPRole and negotiate max number of connections
VOID GAPRole_StartDevice(&multi_role_gapRoleCBs, &maxNumBleConns);

// Allocate memory for index to connection handle map
if (connHandleMap = ICall_malloc(sizeof(connHandleMapEntry_t) * maxNumBleConns))
{
// Init index to connection handle map
for (uint8_t i = 0; i < maxNumBleConns; i++)
{
connHandleMap[i].connHandle = INVALID_CONNHANDLE;
}
}

// Allocate memory for per connection discovery information
if (discInfo = ICall_malloc(sizeof(discInfo_t) * maxNumBleConns))
{
// Init index to connection handle map to 0's
for (uint8_t i = 0; i < maxNumBleConns; i++)
{
discInfo[i].charHdl = 0;
discInfo[i].discState = BLE_DISC_STATE_IDLE;
discInfo[i].svcEndHdl = 0;
discInfo[i].svcStartHdl = 0;
}
}
}

//oad
// Open the OAD module and add the OAD service to the application
if(OAD_SUCCESS != OAD_open(OAD_DEFAULT_INACTIVITY_TIME))
{
/*
* OAD cannot be opened, steps must be taken in the application to
* handle this gracefully, this can mean an error, assert,
* or print statement.
*/
}
else
{
// Register the OAD callback with the application
OAD_register(&multi_role_oadCBs);
}

// GATT
{
// Set the GAP Characteristics
GGS_SetParameter(GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, attDeviceName);

// Initialize GATT Server Services
GGS_AddService(GATT_ALL_SERVICES); // GAP
GATTServApp_AddService(GATT_ALL_SERVICES); // GATT attributes
DevInfo_AddService(); // Device Information Service
SimpleProfile_AddService(GATT_ALL_SERVICES); // Simple GATT Profile

// Register callback with SimpleGATTprofile
SimpleProfile_RegisterAppCBs(&multi_role_simpleProfileCBs);

/*-----------------CLIENT------------------*/
// Initialize GATT Client
VOID GATT_InitClient();

// Register for GATT local events and ATT Responses pending for transmission
GATT_RegisterForMsgs(selfEntity);

// Register to receive incoming ATT Indications/Notifications
GATT_RegisterForInd(selfEntity);
}

count_store();

#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)

Util_startClock(&time_rqt_clock);
Util_startClock(&read_clock);
}

void DataSend(uint8* dataToSend,uint8 size,uint8_t chandle)
{
ack_data_counter++;
attPrepareWriteReq_t req;
req.pValue = GATT_bm_alloc(connHandleMap[cindex].connHandle, ATT_WRITE_REQ, size, NULL);
if ( req.pValue != NULL )
{
req.handle = chandle;
req.offset = 0;
req.len = size;
memcpy(req.pValue, dataToSend,size);
status = GATT_WriteLongCharValue(connHandleMap[cindex].connHandle, &req, selfEntity);
if ( status != SUCCESS )
GATT_bm_free((gattMsg_t *)&req, ATT_WRITE_REQ);
}
}

// UART Parameters
void UART_parameter(void)
{
/* Create a UART with data processing off. */
UART_Params_init(&uartParams);
uartParams.readMode = UART_MODE_CALLBACK;
uartParams.writeMode = UART_MODE_BLOCKING;
uartParams.writeDataMode = UART_DATA_BINARY;
uartParams.readDataMode = UART_DATA_BINARY;
uartParams.readCallback = readCallback;
uartParams.writeCallback = writeCallback;
uartParams.readReturnMode = UART_RETURN_FULL;
uartParams.readEcho = UART_ECHO_OFF;
uartParams.dataLength = UART_LEN_8;
uartParams.stopBits = UART_STOP_ONE;
uartParams.parityType = UART_PAR_NONE;
uartParams.baudRate = 115200;
// startaddress = &rxBuf[0];
}

/*********************************************************************
* @fn multi_role_processRoleEvent
*
* @brief Multi role event processing function.
*
* @param pEvent - pointer to event structure
*
* @return none
*/
static void multi_role_processRoleEvent(gapMultiRoleEvent_t *pEvent)
{
switch (pEvent->gap.opcode)
{

// Connection has been established
case GAP_LINK_ESTABLISHED_EVENT:
{
scan_count=0;

// If succesfully established
if (pEvent->gap.hdr.status == SUCCESS)
{
ix=0;
jx=0;
device_connected=1;
Util_startClock(&reset_clock);
PIN_setOutputValue(hGpioPin, Board_GLED, Board_LED_ON);

// Add index-to-connHandle mapping entry and update menus
cindex = multi_role_addMappingEntry(pEvent->linkCmpl.connectionHandle, pEvent->linkCmpl.devAddr);

memcpy(connected_device_address,pEvent->linkCmpl.devAddr,GATEWAY_DATA);

connRole=pEvent->linkCmpl.connRole;
if(connRole == GAP_PROFILE_CENTRAL)
{
ack_data_counter++; ///-----------------------------------------------------------
ptr=&coin_buffer[ix][0];
memcpy(packet_to_send,ptr,COIN_DATA);
DataSend(packet_to_send,COIN_DATA,simple3handle);

if (status!=SUCCESS)
{
disconnect_and_update_buffer(ix);
}
else if (status==SUCCESS)
{
Util_startClock(&ack_clock);
}
if(packet_to_send[1]==0x45 && buffer_counter==1)
buffer_counter=0;
//}
}
}
}
break;

}

/*********************************************************************
* @fn multi_role_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 multi_role_processCharValueChangeEvt(uint8_t paramID)
{
// Print new value depending on which characteristic was updated
switch(paramID)
{
case SIMPLEPROFILE_CHAR1:
if(connRole==GAP_PROFILE_PERIPHERAL)
{
ack_packet[0]=ack;
ack_packet[1]=++jx;

DataSend(ack_packet,2,simple1handle);

time_total=UTC_getClock();
if(time_total>=86400)
{
UTC_setClock(0);
time_hr=0;
time_min=0;
time_sec=0;
}
else if(time_total>86400)
{
time_remainder=time_total-86400;
UTC_setClock(time_remainder);
time_hr=time_remainder/3600;
time_remainder_dup=time_remainder%3600;
time_min=time_remainder_dup/60;
time_sec=time_remainder_dup%60;
}
else
{
time_hr=time_total/3600;
time_total_dup=time_total%3600;
time_min=time_total_dup/60;

time_sec=time_total_dup%60;

}

utc_time_data[0]=coindata[0];
utc_time_data[1]=coindata[1];
utc_time_data[2]=coindata[2];
utc_time_data[3]=coindata[3];
utc_time_data[4]=time_hr;
utc_time_data[5]=time_min;
utc_time_data[6]=time_sec;
if((first_data==1)||((coindata[0]!=last_received_packet[0] || coindata[0]==last_received_packet[0]) && coindata[4]!=last_received_packet[4])||(coindata[0]!=last_received_packet[0] && coindata[4]==last_received_packet[4]))
{
if(coindata[0]!=0 && coindata[1]!=0)
{
write_to_flash(&utc_time_data[0],UART_WRITE_SIZE);
memcpy(last_received_packet,coindata,COIN_DATA);
}
if(first_data==1)
first_data=0;
}
/* memcpy(in_data_buffer[in_data_count],coindata,COIN_DATA);
in_data_count++;*/

}
break;

}

void write_on_uart(void)
{

read_from_flash(&extdata[0],UART_WRITE_SIZE);
DELAY_MS(10);
converttoascii();

onuart[0] = BLEADDRESS_ASCII[0];
onuart[1] = BLEADDRESS_ASCII[1];
onuart[2] = BLEADDRESS_ASCII[2];
onuart[3] = BLEADDRESS_ASCII[3];
onuart[4] = BLEADDRESS_ASCII[4];
onuart[5] = BLEADDRESS_ASCII[5];
onuart[6] = BLEADDRESS_ASCII[6];
onuart[7] = BLEADDRESS_ASCII[7];
onuart[8] = BLEADDRESS_ASCII[8];
onuart[9] = BLEADDRESS_ASCII[9];
onuart[10] = BLEADDRESS_ASCII[10];
onuart[11] = BLEADDRESS_ASCII[11];
onuart[12] = uartdata[0];
onuart[13] = uartdata[1];
onuart[14] = uartdata[2];
onuart[15] = uartdata[3];
onuart[16] = uartdata[4];
onuart[17] = uartdata[5];
onuart[18] = uartdata[6];
onuart[19] = uartdata[7];
onuart[20] = uartdata[8];
onuart[21] = uartdata[9];
onuart[22] = uartdata[10];
onuart[23] = uartdata[11];
onuart[24] = uartdata[12];
onuart[25] = uartdata[13];
onuart[26] = '\n';

UART_write(uart,onuart,sizeof(onuart));

}

 

 

/******************************************************************************

 @file  simple_gatt_profile.c

 @brief This file contains the Simple GATT profile sample GATT service profile
        for use with the BLE sample application.

 Group: WCS, BTS
 Target Device: cc2640r2

 ******************************************************************************
 
 Copyright (c) 2010-2019, 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.

 ******************************************************************************
 
 
 *****************************************************************************/

/*********************************************************************
 * INCLUDES
 */
#include <string.h>
#include <icall.h>
#include "util.h"
/* This Header file contains all BLE API and icall structure definition */
#include "icall_ble_api.h"

#include "simple_gatt_profile.h"

/*********************************************************************
 * MACROS
 */

/*********************************************************************
 * CONSTANTS
 */

#define SERVAPP_NUM_ATTR_SUPPORTED        17
extern uint8_t ack_packet[2];

/*********************************************************************
 * TYPEDEFS
 */

/*********************************************************************
 * GLOBAL VARIABLES
 */
// Simple GATT Profile Service UUID: 0xFFF0
CONST uint8 simpleProfileServUUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_SERV_UUID), HI_UINT16(SIMPLEPROFILE_SERV_UUID)
};

// Characteristic 1 UUID: 0xFFF1
CONST uint8 simpleProfilechar1UUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_CHAR1_UUID), HI_UINT16(SIMPLEPROFILE_CHAR1_UUID)
};

// Characteristic 2 UUID: 0xFFF2
CONST uint8 simpleProfilechar2UUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_CHAR2_UUID), HI_UINT16(SIMPLEPROFILE_CHAR2_UUID)
};

// Characteristic 3 UUID: 0xFFF3
CONST uint8 simpleProfilechar3UUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_CHAR3_UUID), HI_UINT16(SIMPLEPROFILE_CHAR3_UUID)
};

// Characteristic 4 UUID: 0xFFF4
CONST uint8 simpleProfilechar4UUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_CHAR4_UUID), HI_UINT16(SIMPLEPROFILE_CHAR4_UUID)
};

// Characteristic 5 UUID: 0xFFF5
CONST uint8 simpleProfilechar5UUID[ATT_BT_UUID_SIZE] =
{
  LO_UINT16(SIMPLEPROFILE_CHAR5_UUID), HI_UINT16(SIMPLEPROFILE_CHAR5_UUID)
};

/*********************************************************************
 * EXTERNAL VARIABLES
 */

/*********************************************************************
 * EXTERNAL FUNCTIONS
 */

/*********************************************************************
 * LOCAL VARIABLES
 */

static simpleProfileCBs_t *simpleProfile_AppCBs = NULL;

/*********************************************************************
 * Profile Attributes - variables
 */

// Simple Profile Service attribute
static CONST gattAttrType_t simpleProfileService = { ATT_BT_UUID_SIZE, simpleProfileServUUID };


// Simple Profile Characteristic 1 Properties
static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;

// Characteristic 1 Value
uint8 simpleProfileChar1[COIN_DATA] = {0};

// Simple Profile Characteristic 1 User Description
static uint8 simpleProfileChar1UserDesp[17] = "Characteristic 1";


// Simple Profile Characteristic 2 Properties
static uint8 simpleProfileChar2Props = GATT_PROP_READ;

// Characteristic 2 Value
static uint8 simpleProfileChar2 = 0;

// Simple Profile Characteristic 2 User Description
static uint8 simpleProfileChar2UserDesp[17] = "Characteristic 2";


// Simple Profile Characteristic 3 Properties
static uint8 simpleProfileChar3Props = GATT_PROP_WRITE;

// Characteristic 3 Value
static uint8 simpleProfileChar3[COIN_DATA] = {0};

// Simple Profile Characteristic 3 User Description
static uint8 simpleProfileChar3UserDesp[17] = "Characteristic 3";


// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY;

// Characteristic 4 Value
static uint8 simpleProfileChar4 = 0;

// Simple Profile Characteristic 4 Configuration Each client has its own
// instantiation of the Client Characteristic Configuration. Reads of the
// Client Characteristic Configuration only shows the configuration for
// that client and writes only affect the configuration of that client.
static gattCharCfg_t *simpleProfileChar4Config;

// Simple Profile Characteristic 4 User Description
static uint8 simpleProfileChar4UserDesp[17] = "Characteristic 4";


// Simple Profile Characteristic 5 Properties
static uint8 simpleProfileChar5Props = GATT_PROP_READ;

// Characteristic 5 Value
static uint8 simpleProfileChar5[SIMPLEPROFILE_CHAR5_LEN] = { 0, 0, 0, 0, 0 };

// Simple Profile Characteristic 5 User Description
static uint8 simpleProfileChar5UserDesp[17] = "Characteristic 5";

/*********************************************************************
 * Profile Attributes - Table
 */

static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
  // Simple Profile Service
  {
    { ATT_BT_UUID_SIZE, primaryServiceUUID }, /* type */
    GATT_PERMIT_READ,                         /* permissions */
    0,                                        /* handle */
    (uint8 *)&simpleProfileService            /* pValue */
  },

    // Characteristic 1 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar1Props
    },

      // Characteristic Value 1
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar1UUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        &simpleProfileChar1[0]
      },

      // Characteristic 1 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar1UserDesp
      },

    // Characteristic 2 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar2Props
    },

      // Characteristic Value 2
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar2UUID },
        GATT_PERMIT_READ,
        0,
        &simpleProfileChar2
      },

      // Characteristic 2 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar2UserDesp
      },

    // Characteristic 3 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar3Props
    },

      // Characteristic Value 3
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar3UUID },
        GATT_PERMIT_WRITE,
        0,
        &simpleProfileChar3[0]
      },

      // Characteristic 3 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar3UserDesp
      },

    // Characteristic 4 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar4Props
    },

      // Characteristic Value 4
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar4UUID },
        0,
        0,
        &simpleProfileChar4
      },

      // Characteristic 4 configuration
      {
        { ATT_BT_UUID_SIZE, clientCharCfgUUID },
        GATT_PERMIT_READ | GATT_PERMIT_WRITE,
        0,
        (uint8 *)&simpleProfileChar4Config
      },

      // Characteristic 4 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar4UserDesp
      },

    // Characteristic 5 Declaration
    {
      { ATT_BT_UUID_SIZE, characterUUID },
      GATT_PERMIT_READ,
      0,
      &simpleProfileChar5Props
    },

      // Characteristic Value 5
      {
        { ATT_BT_UUID_SIZE, simpleProfilechar5UUID },
        GATT_PERMIT_AUTHEN_READ,
        0,
        simpleProfileChar5
      },

      // Characteristic 5 User Description
      {
        { ATT_BT_UUID_SIZE, charUserDescUUID },
        GATT_PERMIT_READ,
        0,
        simpleProfileChar5UserDesp
      },
};

/*********************************************************************
 * LOCAL FUNCTIONS
 */
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                          gattAttribute_t *pAttr,
                                          uint8_t *pValue, uint16_t *pLen,
                                          uint16_t offset, uint16_t maxLen,
                                          uint8_t method);
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                           gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t len,
                                           uint16_t offset, uint8_t method);

/*********************************************************************
 * PROFILE CALLBACKS
 */

// Simple Profile Service Callbacks
// Note: When an operation on a characteristic requires authorization and
// pfnAuthorizeAttrCB is not defined for that characteristic's service, the
// Stack will report a status of ATT_ERR_UNLIKELY to the client.  When an
// operation on a characteristic requires authorization the Stack will call
// pfnAuthorizeAttrCB to check a client's authorization prior to calling
// pfnReadAttrCB or pfnWriteAttrCB, so no checks for authorization need to be
// made within these functions.
CONST gattServiceCBs_t simpleProfileCBs =
{
  simpleProfile_ReadAttrCB,  // Read callback function pointer
  simpleProfile_WriteAttrCB, // Write callback function pointer
  NULL                       // Authorization callback function pointer
};

/*********************************************************************
 * PUBLIC FUNCTIONS
 */

/*********************************************************************
 * @fn      SimpleProfile_AddService
 *
 * @brief   Initializes the Simple Profile service by registering
 *          GATT attributes with the GATT server.
 *
 * @param   services - services to add. This is a bit map and can
 *                     contain more than one service.
 *
 * @return  Success or Failure
 */
bStatus_t SimpleProfile_AddService( uint32 services )
{
  uint8 status;

  // Allocate Client Characteristic Configuration table
  simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
                                                            linkDBNumConns );
  if ( simpleProfileChar4Config == NULL )
  {
    return ( bleMemAllocError );
  }

  // Initialize Client Characteristic Configuration attributes
  GATTServApp_InitCharCfg( INVALID_CONNHANDLE, simpleProfileChar4Config );

  if ( services & SIMPLEPROFILE_SERVICE )
  {
    // Register GATT attribute list and CBs with GATT Server App
    status = GATTServApp_RegisterService( simpleProfileAttrTbl,
                                          GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                          GATT_MAX_ENCRYPT_KEY_SIZE,
                                          &simpleProfileCBs );
  }
  else
  {
    status = SUCCESS;
  }

  return ( status );
}

/*********************************************************************
 * @fn      SimpleProfile_RegisterAppCBs
 *
 * @brief   Registers the application callback function. Only call
 *          this function once.
 *
 * @param   callbacks - pointer to application callbacks.
 *
 * @return  SUCCESS or bleAlreadyInRequestedMode
 */
bStatus_t SimpleProfile_RegisterAppCBs( simpleProfileCBs_t *appCallbacks )
{
  if ( appCallbacks )
  {
    simpleProfile_AppCBs = appCallbacks;

    return ( SUCCESS );
  }
  else
  {
    return ( bleAlreadyInRequestedMode );
  }
}

/*********************************************************************
 * @fn      SimpleProfile_SetParameter
 *
 * @brief   Set a Simple Profile parameter.
 *
 * @param   param - Profile parameter ID
 * @param   len - length of data to write
 * @param   value - pointer to data to write.  This is dependent on
 *          the parameter ID and WILL be cast to the appropriate
 *          data type (example: data type of uint16 will be cast to
 *          uint16 pointer).
 *
 * @return  bStatus_t
 */
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case SIMPLEPROFILE_CHAR1:
      if ( len <= COIN_DATA )
      {
        memcpy(simpleProfileChar1,value,COIN_DATA);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case SIMPLEPROFILE_CHAR2:
      if ( len == sizeof ( uint8 ) )
      {
        simpleProfileChar2 = *((uint8*)value);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case SIMPLEPROFILE_CHAR3:
      if ( len <= COIN_DATA )
      {
        memcpy(simpleProfileChar3,value,COIN_DATA);
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case SIMPLEPROFILE_CHAR4:
      if ( len == sizeof ( uint8 ) )
      {
        simpleProfileChar4 = *((uint8*)value);

        // See if Notification has been enabled
        GATTServApp_ProcessCharCfg( simpleProfileChar4Config, &simpleProfileChar4, FALSE,
                                    simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
                                    INVALID_TASK_ID, simpleProfile_ReadAttrCB );
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    case SIMPLEPROFILE_CHAR5:
      if ( len == SIMPLEPROFILE_CHAR5_LEN )
      {
        VOID memcpy( simpleProfileChar5, value, SIMPLEPROFILE_CHAR5_LEN );
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

    default:
      ret = INVALIDPARAMETER;
      break;
  }

  return ( ret );
}

/*********************************************************************
 * @fn      SimpleProfile_GetParameter
 *
 * @brief   Get a Simple Profile parameter.
 *
 * @param   param - Profile parameter ID
 * @param   value - pointer to data to put.  This is dependent on
 *          the parameter ID and WILL be cast to the appropriate
 *          data type (example: data type of uint16 will be cast to
 *          uint16 pointer).
 *
 * @return  bStatus_t
 */
bStatus_t SimpleProfile_GetParameter( uint8 param, void *value )
{
  bStatus_t ret = SUCCESS;
  switch ( param )
  {
    case SIMPLEPROFILE_CHAR1:
      memcpy(value,simpleProfileChar1,COIN_DATA);
      break;

    case SIMPLEPROFILE_CHAR2:
      *((uint8*)value) = simpleProfileChar2;
      break;

    case SIMPLEPROFILE_CHAR3:
      memcpy(value,simpleProfileChar3,COIN_DATA);
      break;

    case SIMPLEPROFILE_CHAR4:
      *((uint8*)value) = simpleProfileChar4;
      break;

    case SIMPLEPROFILE_CHAR5:
      VOID memcpy( value, simpleProfileChar5, SIMPLEPROFILE_CHAR5_LEN );
      break;

    default:
      ret = INVALIDPARAMETER;
      break;
  }

  return ( ret );
}

/*********************************************************************
 * @fn          simpleProfile_ReadAttrCB
 *
 * @brief       Read an attribute.
 *
 * @param       connHandle - connection message was received on
 * @param       pAttr - pointer to attribute
 * @param       pValue - pointer to data to be read
 * @param       pLen - length of data to be read
 * @param       offset - offset of the first octet to be read
 * @param       maxLen - maximum length of data to be read
 * @param       method - type of read message
 *
 * @return      SUCCESS, blePending or Failure
 */
static bStatus_t simpleProfile_ReadAttrCB(uint16_t connHandle,
                                          gattAttribute_t *pAttr,
                                          uint8_t *pValue, uint16_t *pLen,
                                          uint16_t offset, uint16_t maxLen,
                                          uint8_t method)
{
  bStatus_t status = SUCCESS;

  // Make sure it's not a blob operation (no attributes in the profile are long)
  if ( offset > 0 )
  {
    return ( ATT_ERR_ATTR_NOT_LONG );
  }

  if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    switch ( uuid )
    {
      // No need for "GATT_SERVICE_UUID" or "GATT_CLIENT_CHAR_CFG_UUID" cases;
      // gattserverapp handles those reads

      // characteristics 1 and 2 have read permissions
      // characteritisc 3 does not have read permissions; therefore it is not
      //   included here
      // characteristic 4 does not have read permissions, but because it
      //   can be sent as a notification, it is included here
      case SIMPLEPROFILE_CHAR1_UUID:
      case SIMPLEPROFILE_CHAR2_UUID:
      case SIMPLEPROFILE_CHAR4_UUID:
        *pLen = 1;
        pValue[0] = *pAttr->pValue;
        break;

      case SIMPLEPROFILE_CHAR5_UUID:
        *pLen = SIMPLEPROFILE_CHAR5_LEN;
        VOID memcpy( pValue, pAttr->pValue, SIMPLEPROFILE_CHAR5_LEN );
        break;

      default:
        // Should never get here! (characteristics 3 and 4 do not have read permissions)
        *pLen = 0;
        status = ATT_ERR_ATTR_NOT_FOUND;
        break;
    }
  }
  else
  {
    // 128-bit UUID
    *pLen = 0;
    status = ATT_ERR_INVALID_HANDLE;
  }

  return ( status );
}

/*********************************************************************
 * @fn      simpleProfile_WriteAttrCB
 *
 * @brief   Validate attribute data prior to a write operation
 *
 * @param   connHandle - connection message was received on
 * @param   pAttr - pointer to attribute
 * @param   pValue - pointer to data to be written
 * @param   len - length of data
 * @param   offset - offset of the first octet to be written
 * @param   method - type of write message
 *
 * @return  SUCCESS, blePending or Failure
 */
static bStatus_t simpleProfile_WriteAttrCB(uint16_t connHandle,
                                           gattAttribute_t *pAttr,
                                           uint8_t *pValue, uint16_t len,
                                           uint16_t offset, uint8_t method)
{
  bStatus_t status = SUCCESS;
  uint8 notifyApp = 0xFF;

  if ( pAttr->type.len == ATT_BT_UUID_SIZE )
  {
    // 16-bit UUID
    uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
    switch ( uuid )
    {
      case SIMPLEPROFILE_CHAR1_UUID:
        if ( offset == 0 )
        {
            if ( len < COIN_DATA )
            {
                status = ATT_ERR_INVALID_VALUE_SIZE;
            }
        }
        else
        {
            status = ATT_ERR_ATTR_NOT_LONG;
        }

        //Write the value
        if ( status == SUCCESS)
        {
            memcpy( simpleProfileChar1, pValue, COIN_DATA);
            memcpy( coindata, simpleProfileChar1, COIN_DATA);
            notifyApp = SIMPLEPROFILE_CHAR1;

            /*memcpy( coindata, pValue, COIN_DATA);
            memcpy( profile_data_buffer[profile_data_count], pValue, COIN_DATA);
            profile_data_count++;
            simple_pro_counter++;*/

        }
        break;

      case SIMPLEPROFILE_CHAR3_UUID:
        if ( offset == 0 )
        {
          if ( len > COIN_DATA )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }

        //Write the value
        if ( status == SUCCESS )
        {
            if(len == COIN_DATA)
            {
                memcpy( simpleProfileChar3, pValue, COIN_DATA);
                memcpy( coindata, simpleProfileChar3, COIN_DATA);
                notifyApp = SIMPLEPROFILE_CHAR3;
            }
            else if (len == 2)
            {
                memcpy(ack_packet,pValue,2);
                notifyApp = SIMPLEPROFILE_CHAR3;
            }
        }
        break;

      case GATT_CLIENT_CHAR_CFG_UUID:
        status = GATTServApp_ProcessCCCWriteReq( connHandle, pAttr, pValue, len,
                                                 offset, GATT_CLIENT_CFG_NOTIFY );
        break;

      default:
        // Should never get here! (characteristics 2 and 4 do not have write permissions)
        status = ATT_ERR_ATTR_NOT_FOUND;
        break;
    }
  }
  else
  {
    // 128-bit UUID
    status = ATT_ERR_INVALID_HANDLE;
  }

  // If a characteristic value changed then callback function to notify application of change
  if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  {
    simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );
  }

  return ( status );
}

Waiting for your response.

Thanks and Regards,
Rohit


  • Hi Rohit,

    Are you using the UART for display as well (this is how the multi role example works per default)?

    Ar you calling UART operations from the application task or have you made a dedicated UART task?

  • Hi Marie,

    Thanks for your response.

    "Are you using the UART for display as well (this is how the multi role example works per default)?"

    No , i wanted to send data on Ethernet port.

    "Ar you calling UART operations from the application task or have you made a dedicated UART task?"

    Yes i am calling from application task..

    static void multi_role_taskFxn(UArg a0, UArg a1)


    Thanks and Regards,

    Rohit

  • Hi Marie,

    While debugging the above issue i found that if one BLE is sending some 2 or more data to other BLE at periodically.

    One or more data packet is missing.

    If i am sending 12,13 as data then 13 only receiving or duplication of that data as 13 13 instead of 12 13.

    I have kept acknowledgement period nearly 1 m sec on both device.

    At the receiving side only i am receiving missing data.

    Didn't got the root cause of it. And not finding solution also 

    Please help me out to solve this problem , i am stuck last few weeks in this problem only.

    Reagrds,

    Rohit

  • Hi Rohit, 

    Can you provide some logs so I can see the Bluetooth activity?

    Thanks, 
    Elin 

  • Hi Elin,

    Thanks for your response .

    Please check below images as i have created one buffer at receiving side . There only i am receiving same data with data loss of first data . As i have mention above comment that if i am sending 2 data as 

    F0F8F2DA093E01091F0E01D0A
    F0F8F2DA093E0110430001D0A

    I am receiving data as 

    F0F8F2DA093E0110430001D0A
    F0F8F2DA093E0110430001D0A

     

    Please check and suggest your inputs.

    Waiting for your response.

  • Hi Rohit, 

    Can you download the SmartRF Packet Sniffer and sniff the Bluetooth activity in that connection so we can see what is actually transmitted? The sniffer is available for download here: http://www.ti.com/tool/PACKET-SNIFFER

    Thanks, 
    Elin