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.

CC2541: central and peripheral data communicaion cc2541

Part Number: CC2541

hey

I made a connection between two BLE devices one as peripheral and other as central. I am using CC2541 ibeacon for both central and peripheral. 

I am facing two problems

1. Connection is established between central and peripheral and i am able to send a string of max 20 bytes from central to peripheral through characteristic 5. From central i am able to sent exact length and data to peripheral, but at the peripheral end when i am checking at writeCBs i am receiving data correctly but the length as 255 bytes(0xFF) for any string and also not able to receive second string/data from central. Only once it is receiving the write data wrong length. below is the code for both central and peripheral. I am using UART at both ends for writing and reading data at runtime.

#CENTRAL

if (keys)
{
msgPtr = (keyChange_t *)osal_msg_allocate( sizeof(keyChange_t) );
if (msgPtr)
{
msgPtr->keys = keys;
msgPtr->hdr.event = KEY_CHANGE;
msgPtr->state = false;
osal_msg_send (simpleBLETaskId, (uint8 *)msgPtr);
}
}

if (uartPktReceived)
{
uartPktReceived = 0;

req.pValue = GATT_bm_alloc( simpleBLEConnHandle, ATT_WRITE_REQ, uartPktSize, NULL );
if ( req.pValue != NULL )
{
// req.handle = simpleBLECharHdl;
req.handle = 0x0032;  //connection handle for characteristic 5
req.len = uartPktSize;

for (i=0; i <= uartPktSize; i++)
{
req.pValue[i] = uartRxBuffer [i];
}

req.sig = 0;
req.cmd = 0;
status = GATT_WriteCharValue( simpleBLEConnHandle, &req, simpleBLETaskId );
if ( status != SUCCESS )
{
GATT_bm_free( (gattMsg_t *)&req, ATT_WRITE_REQ );
}
}

uartPktSize = 0; 
}

 #peripheral

static bStatus_t simpleProfile_WriteAttrCB( uint16 connHandle, gattAttribute_t *pAttr,
                                            uint8 *pValue, uint8 len, uint16 offset,
                                            uint8 method )
{
  bStatus_t status = SUCCESS;
  uint8 notifyApp = 0xFF;
  
  // If attribute permissions require authorization to write, return error
  if ( gattPermitAuthorWrite( pAttr->permissions ) )  //0x20 //!< Write requires Authorization
  {
    // Insufficient authorization
    return ( ATT_ERR_INSUFFICIENT_AUTHOR );
  }
  
  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:
      case SIMPLEPROFILE_CHAR3_UUID:
        //Validate the value
        // Make sure it's not a blob oper
        if ( offset == 0 )
        {
          if ( len != 1 )
          {
            status = ATT_ERR_INVALID_VALUE_SIZE;
          }
        }
        else
        {
          status = ATT_ERR_ATTR_NOT_LONG;
        }
        
        //Write the value
        if ( status == SUCCESS )
        {
          uint8 *pCurValue = (uint8 *)pAttr->pValue;        
          *pCurValue = pValue[0];
          if( pAttr->pValue == &simpleProfileChar1 )
          {
            notifyApp = SIMPLEPROFILE_CHAR1;        
          }
          else
          {
            notifyApp = SIMPLEPROFILE_CHAR3;           
          }
        }
break;
        
      case SIMPLEPROFILE_CHAR5_UUID:
       UARTWrite1 (pValue, len);         // here i am receiving pvalue as data written from central but len as 0xFF
        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 charactersitic value changed then callback function to notify application of change
  if ( (notifyApp != 0xFF ) && simpleProfile_AppCBs && simpleProfile_AppCBs->pfnSimpleProfileChange )
  {
    simpleProfile_AppCBs->pfnSimpleProfileChange( notifyApp );  
  }
  
  return ( status );
}

2. From peripheral I would like send a notification to central after connection and the below program gives the notification sending part peripheral and also notification enabled code in central. 

#peripheral

attHandleValueNoti_t noti;

noti.pValue = GATT_bm_alloc( 0, ATT_HANDLE_VALUE_NOTI, uartRxPktSize, NULL );
if ( noti.pValue != NULL )
{
noti.handle = 0x32; // attr value 5 handle
noti.len = uartRxPktSize;
memcpy (noti.pValue, uartRxBuffer, uartRxPktSize);

if ( GATT_Notification( 0, &noti, FALSE ) != SUCCESS )
{
GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
}
}

#central

static void simpleBLECentralProcessGATTMsg( gattMsgEvent_t *pMsg )
{
if ( simpleBLEState != BLE_STATE_CONNECTED )
{
// In case a GATT message came after a connection has dropped,
// ignore the message
return;
}
if (pMsg->method == ATT_HANDLE_VALUE_NOTI)
{
UARTWrite ("working-now");
}
else
if ( ( pMsg->method == ATT_READ_RSP ) ||
( ( pMsg->method == ATT_ERROR_RSP ) &&
( pMsg->msg.errorRsp.reqOpcode == ATT_READ_REQ ) ) )
{
if ( pMsg->method == ATT_ERROR_RSP )
{
uint8 status = pMsg->msg.errorRsp.errCode;

LCD_WRITE_STRING_VALUE( "Read Error", status, 10, HAL_LCD_LINE_1 );
}
else
{
// After a successful read, display the read value
uint8 valueRead = pMsg->msg.readRsp.pValue[0];

LCD_WRITE_STRING_VALUE( "Read rsp:", valueRead, 10, HAL_LCD_LINE_1 );
}

simpleBLEProcedureInProgress = FALSE;
}
else if ( ( pMsg->method == ATT_WRITE_RSP ) ||
( ( pMsg->method == ATT_ERROR_RSP ) &&
( pMsg->msg.errorRsp.reqOpcode == ATT_WRITE_REQ ) ) )
{

if ( pMsg->method == ATT_ERROR_RSP == ATT_ERROR_RSP )
{
uint8 status = pMsg->msg.errorRsp.errCode;

LCD_WRITE_STRING_VALUE( "Write Error", status, 10, HAL_LCD_LINE_1 );
}
else
{
// After a succesful write, display the value that was written and increment value
LCD_WRITE_STRING_VALUE( "Write sent:", simpleBLECharVal++, 10, HAL_LCD_LINE_1 ); 
}

simpleBLEProcedureInProgress = FALSE;

}
else if ( simpleBLEDiscState != BLE_DISC_STATE_IDLE )
{
simpleBLEGATTDiscoveryEvent( pMsg );
}

GATT_bm_free( &pMsg->msg, pMsg->method );
}

please help me to sort it out if any one faced this issue.

  • Hi,
    For you first question, have you been able to sniff the air and see what is actually transmitted over the air?

    I am not sure I understand your second question although if you want to send a notification, you can trigger that from the application by updating characteristic 5 from there, i.e. by using API SimpleProfile_SetParameter.

    Also, what do you mean by the statement that you are using iBeacon? Are you not using the default peripheral/central projects?
  • Hi,

    I tried to sniff the air but unable to understand what it is transmitting since lot of packets are being transmitted at a time.

    Coming to second question I am using Characteristic 5 for sending data from central to peripheral. Since i am unable to transmit the data for second time I am choosing to send notification packet from peripheral to central.

    Yes i am using default peripheral and central projects. The hardware module i am using CC2541 is ibeacon module. It does not have any lcd, led or button as keyfob. I am using UART communication(connecting to PC) for both sending and receiving data.

    Regards,
    Sumanth
  • hey i solved my first problem and working on second. I am able to send the notification from peripheral but unable to receive notification at central side
  • Sumanth,

    Are you sending the notification by the code previously shared or by invoking the service SetParameter API?

    Either way, what is the return status of GATT_Notification the second time it's called? 

  • Joakim lindh,

    I am sending the data as mentioned previously in forum and also enabled the notify(ATT_HANDLE_VALUE_NOTI) in central file as below

    static void simpleBLECentralProcessGATTMsg( gattMsgEvent_t *pMsg )
    {
    if ( simpleBLEState != BLE_STATE_CONNECTED )
    {
    // In case a GATT message came after a connection has dropped,
    // ignore the message
    return;
    }
    if (pMsg->method == ATT_HANDLE_VALUE_NOTI )
    {
    UARTWrite ("working-now");
    }

    The control is not coming in the UARTwrite after sending the notification from peripheral. UARTwrite is the function declared by me to print the data in serial monitor. The status of GATT_Notification is returning SUCCESS from peripheral side.

    Regards
    sumanth
  • Hi,
    I would still like to know where exactly things go wrong. I would assume that the packet for OTA since GATT_Notification returns success although there is no way to know for sure unless you observe it in a sniffer. You could use a counter to help identifying the packet in the sniffer and you should also be able to filter based on access address once connection is up and running.

    Have you tried setting breakpoints on the central side to capture the incoming notification? (instead of relying on the last output step by using UART)
  • Yeah i have tried using break point in Central at UARTwrite the control did not come and when i am using above UARTwrite

    if (pMsg->method == ATT_HANDLE_VALUE_NOTI )

    The control is coming here but before while exactly establishing the connection.
  • I need to understand if the notification is sent OTA in order to move further with this investigation. Have you reduced your custom code towards the vanilla simple central/peripheral sample applications to narrow down the amount of code needing review. As far as I know, the peripheral/central are default setup to demonstrate this.
  • Also, have you already seen this SimpleLink Academy module:

    dev.ti.com/.../ble_01_custom_profile.html
  • Hey the issue is solved i am able to receive notification from peripheral to central .
  • Thank you for the update.