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.

Using GattNotification(...) in Application Project cc2640

Other Parts Discussed in Thread: CC2541, CC2640

Hello,

I want to use the GattNotification commande like :

GATT_Notification(0, &noti, FALSE);

but i have an error : No source available for "xdc_runtime_Timestamp_get32__E__mangled__() at ....


I want to precise i worked on a CC2541 before, with the BleBridge project. My cc2541 project worked fine, and now i work on cc2640 and i try to translate the code to send a notification over UART.

I think GattNotification can only used in Stack Project.
I want to use GattNotification in my Application Project. How ?


This is my code :

	case ID_COMMANDE_NOTIFY:
		len_notification = pCmdMsg->pData[2];
		len_notification = 2;
		uint8_t packets_sent = 0;
		//on s'assure que la file d'attente de la notification est réussie
		bool send_error = FALSE;
		//la valeur de retour pour mettre à jour la queue et envoyer ack
		uint8_t bytes_sent = 0;
		attHandleValueNoti_t noti;
		//dummy handle

		noti.handle = 0x59;

		//counter
		uint8_t i = 0;

		while ((packets_sent < 4) && (len_notification >= 20) && (send_error == FALSE)) {
			value = &rxdata[0];
			//send 20 bytes
			noti.len = 20;
			for (i = 0; i < 20; i++) {
				noti.pValue[i] = rxdata[bytes_sent + i];
			}
			//connection handle hardcoded
			if (!(GATT_Notification(0, &noti, FALSE))) //if sucessful
			{
				bytes_sent += 20;
				len_notification -= 20;
				packets_sent++;
			} else {
				send_error = TRUE;
			}
		}
		//last packet
		if ((packets_sent < 4) && (len_notification > 0)
				&& (send_error == FALSE)) {
			noti.len = len_notification;
			for (i = 0; i < len_notification; i++) {
				noti.pValue[i] = rxdata[bytes_sent + i];
			}
			if (!(GATT_Notification(0, &noti, FALSE))) //if sucessful
			{
				bytes_sent += i;
				len_notification -= i; //number of byte send
			} else {
				send_error = TRUE;
			}
		}
		break;

Thank you.

Best regards,

Steeve

  • My probleme is always here.

    If someone have a solution or an alternative..

    Thank you

  • Can you post the full error you are receiving? It sounds like you aren't including a necessary file.

    In any case, there is an example of using this command in gattServApp_SendNotiInd(). I would recommend looking at section 5.3.5 of the software developer's guide included with the 2.1.0 installer as it doesn't look like you are using the command correctly.
  • Hy,
    I pretty much had the same issue when porting my code from 2540 to 2640. My problem was the memory usage of application and stack.

    My solution is as follows:
    I define one global notification object:

    static attHandleValueNoti_t sendDataNotificationObject;
    //During startup (in the function _AddService of my own profile I initialize the notification object:
    gattAttribute_t *pAttr = GATTServApp_FindAttr(dataProfileAttrTbl,
    	GATT_NUM_ATTRS(dataProfileAttrTbl), dataProfileReadPage); // where "dataProfileReadPage" is the characteristic that I want to send notifications over 
    								  // and dataProfileAttrTbl is the array of characteristics in my own profile
    sendDataNotificationObject.handle = pAttr->handle;
    // When trying to finally send data per notification, I need to do a couple of tests, because, different to CC2540, sendig "illegal" notification lead to a crash:
    if (SendDataNotificationObject != NULL)
    {
    	// SendDataNotificationObject correctly initialised
    	uint16_t curBurstConnHandle;
    	uint16_t curBurstConfigs = GATTServApp_ReadCharCfg(curBurstConnHandle,
    	dataProfileReadPageConfigs);
    	GAPRole_GetParameter(GAPROLE_CONNHANDLE, &curBurstConnHandle);
    	if (curBurstConfigs & GATT_CLIENT_CFG_NOTIFY)
    	{
    		// notifications enabled. Don't send if not!
    		CurSendDataNotificationObject->pValue = GATT_bm_alloc(
    			curBurstConnHandle, ATT_HANDLE_VALUE_NOTI, len, NULL);
    		if (CurSendDataNotificationObject->pValue != NULL)
    		{
    			// memory correctly allocated in stack area. Use it
    			memcpy(CurSendDataNotificationObject->pValue, start, len);
    			CurSendDataNotificationObject->len = len;
    
    			if (GATT_Notification(curBurstConnHandle,
    				CurSendDataNotificationObject, FALSE) == SUCCESS)
    			{
    				retVal = 1;
    			}


    So this works just fine now. All of the if cases can fail, especially the GATT_bm_alloc returns NULL regularly. So call this function again later, eventually there will be some memory free.
    Best regards
    Harald

  • Hello
    I will try your solution Harald, but it seems... little "hacked" no ? :)

    Tim.C : i create an another post where i give more informations : e2e.ti.com/.../443452
    i go check section 5.3.5. Thank's
  • I don't know if it is "hacked", this is the only solution that works for me. It would be interesting to get a feedback from TI...
  • There is a significant difference between using GATT Notification from 1.4.0 to newer releases as now payloads must be allocated to account for fragmentation. This is documented in both the 1.4.0 and 2.1.0 software developer guides. It is also mentioned in the 1.4.0 to 1.4.1 porting guide:

    Allocating Memory for Over-the-Air Messages

    As stated above, there have been changes made to prepare for a possible future fragmentation implementation. Therefore, it is now necessary to allocate memory for data sent over-the-air for ATT / GATT commands.
    For example, a buffer must be allocated when sending a GATT_Notification. Note that this is done by the stack if the preferred method to send a GATT notification / indication is to used. That is, using a profile’s SetParameter function (i.e. SimpleProfile_SetParameter()) and calling GATTServApp_ProcessCharCfg(). See the simpleGATTProfile.c for an example of this.
    If using GATT_Notification() or GATT_Indication() directly, this memory management will need to be added:
    1. Attempt to allocate memory for the notification / indication using GATT_bm_alloc().
    2. If allocation succeeds, send notification / indication using GATT_Notification() / GATT_Indication().
    3. If the return value of the notification / indication is SUCCESS (0x00), this means the memory was freed by the stack. If the return value is something other than SUCCESS (i.e. blePending), free the memory using GATT_bm_free(). There is an example of this in the gattServApp_SendNotiInd() function in gattservapp_util.c:

    noti.pValue = (uint8 *)GATT_bm_alloc( connHandle, ATT_HANDLE_VALUE_NOTI,
    GATT_MAX_MTU, &len );
    if ( noti.pValue != NULL )
    {
    status = (*pfnReadAttrCB)( connHandle, pAttr, noti.pValue, &noti.len,
    0, len, GATT_LOCAL_READ );
    if ( status == SUCCESS )
    {
    noti.handle = pAttr->handle;

    if ( cccValue & GATT_CLIENT_CFG_NOTIFY )
    {
    status = GATT_Notification( connHandle, &noti, authenticated );
    }
    else // GATT_CLIENT_CFG_INDICATE
    {
    status = GATT_Indication( connHandle, (attHandleValueInd_t *)&noti,
    authenticated, taskId );
    }
    }

    if ( status != SUCCESS )
    {
    GATT_bm_free( (gattMsg_t *)&noti, ATT_HANDLE_VALUE_NOTI );
    }
    }
    else
    {
    status = bleNoResources;
    }