Other Parts Discussed in Thread: CC2640,
Tool/software:
hi Experts,
please let me know how to send periodic notification data using CC2640.
thanks
regards,
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.
Hi Clement
my customer would like to send notify data every 1 sec using CC2642R
However, the system stops after only one notification has been sent.
attached their source code. please point out the error.
/*
ble 동작 흐름
기존
cc2642 설정
- da01, da04, da20 : write, read
app : da20으로 write
cc2642 : da20으로 받은 데이터에 맞는 행동을 하고 da01과 da04 데이터를 갱신
app : da01과 da04 read요청
cc2642 : da01과 da04 응답
신규
cc2642 설정
- da01, da04, da99 : write, read, notify
- da20 : write
app : da20으로 데이터 전송
cc2642 : da20으로 받은 데이터에 맞는 행동을 하고 da01과 da04 데이터를 app에 전송(notify)
*/
/*
증상
app과 연결되기 전까지 Notification is not enabled for DA01 메세지 1초마다 반복
app과 연결 후 0-GATT_Notification 메세지 나온 후 멈춤
예상
SimpleProfile_SetParameter 함수 동작 후 멈춤
SimpleProfile_SetParameter - gattServApp_SendNotiInd - GATT_Notification 함수에서 멈춤
*/
// 1초에 한번씩 전송
static void user_main_taskFxn(UArg a0, UArg a1)
{
for(;;)
{
if(gpram1->ble_test_cnt >= 1000){
gpram1->ble_test_cnt = 0;
if (gpram1->connHandle_tmp != LINKDB_CONNHANDLE_INVALID)
{
uint8_t notifyValue = 0;
notifyValue++;
simpleProfileChar1[0] = notifyValue;
simpleProfileChar1[1] = notifyValue+10;
SimpleProfile_SetParameter(SIMPLEPROFILE_DA01, SIMPLEPROFILE_DA01_LEN, simpleProfileChar1);
}
else{
System_printf("Invalid connection handle.\r\n");
}
}
fn_UART_Read();
fn_Interface_DelayTimer();
}
}
// ble 설정
static uint8 simpleProfileChar1Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;
uint8 simpleProfileChar1[SIMPLEPROFILE_DA01_LEN] = {0,};
uint8 simpleProfileChar1Length = SIMPLEPROFILE_DA01_LEN;
static gattCharCfg_t *simpleProfileChar1Config; //da01
static gattCharCfg_t *simpleProfileChar2Config; //da04
// static gattCharCfg_t *simpleProfileChar3Config; //da20
static gattCharCfg_t *simpleProfileChar7Config; //da99
// Simple Profile Characteristic 1 User Description
static uint8 simpleProfileChar1UserDesp[16] = "Key Press State";
// Simple Profile Characteristic 2 Properties
uint8 simpleProfileChar2Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;
// Characteristic 2 Value 0 1 2 3 4 5 6 7 8 9
uint8 simpleProfileChar2[SIMPLEPROFILE_DA04_LEN] = {0,};//{0, 0, 'a', 'b', 'c', 'd', '0', '1', '2', '3'};
uint8 simpleProfileChar2Length = SIMPLEPROFILE_DA04_LEN;
// Simple Profile Characteristic 3 Properties
uint8 simpleProfileChar3Props = GATT_PROP_WRITE | GATT_PROP_WRITE_NO_RSP; //GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;
// Characteristic 3 Value
uint8 simpleProfileChar3[SIMPLEPROFILE_DA20_LEN] = {0,};
uint8 simpleProfileChar3Length = SIMPLEPROFILE_DA20_LEN;
// Simple Profile Characteristic 4 Properties
static uint8 simpleProfileChar4Props = GATT_PROP_NOTIFY;
// Characteristic 4 Value
uint8 simpleProfileChar4[SIMPLEPROFILE_FFE1_LEN] = {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[16] = "Key Press State";
// Simple Profile Characteristic 5 Properties
uint8 simpleProfileChar5Props = GATT_PROP_READ | GATT_PROP_WRITE;
// Characteristic 5 Value
uint8 simpleProfileChar5[SIMPLEPROFILE_AF01_LEN] = {0,};
uint8 simpleProfileChar5Length = SIMPLEPROFILE_AF01_LEN;
// Simple Profile Characteristic 6 Properties
uint8 simpleProfileChar6Props = GATT_PROP_READ | GATT_PROP_WRITE;
// Characteristic 6 Value
uint8 simpleProfileChar6[SIMPLEPROFILE_AF02_LEN] = {0,};
uint8 simpleProfileChar6Length = SIMPLEPROFILE_AF02_LEN;
// static gattCharCfg_t *simpleProfileChar7Config;
// Simple Profile Characteristic 7 Properties
uint8 simpleProfileChar7Props = GATT_PROP_READ | GATT_PROP_WRITE | GATT_PROP_NOTIFY;
// Characteristic 7 Value
uint8 simpleProfileChar7[SIMPLEPROFILE_DA99_LEN] = {1,};
uint8 simpleProfileChar7Length = SIMPLEPROFILE_DA99_LEN;
#define SERVAPP_NUM_ATTR_SUPPORTED 12
static gattAttribute_t simpleProfileAttrTbl[SERVAPP_NUM_ATTR_SUPPORTED] =
{
// Simple Profile Service
{
{ATT_BT_UUID_SIZE, primaryServiceUUID },
GATT_PERMIT_READ,
0,
(uint8 *)&simpleProfileService
},
// Characteristic 1 Declaration (DA01)
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar1Props
},
// Characteristic Value 1 (DA01)
{
{ ATT_BT_UUID_SIZE, simpleProfileDA01UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
simpleProfileChar1
},
// Characteristic 1 configuration (CCCD for Notification)
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&simpleProfileChar1Config
},
// Characteristic 2 Declaration (DA04)
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar2Props
},
// Characteristic Value 2 (DA04)
{
{ ATT_BT_UUID_SIZE, simpleProfileDA04UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
simpleProfileChar2
},
// Characteristic 2 configuration (CCCD for Notification)
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&simpleProfileChar2Config
},
// Characteristic 3 Declaration (DA20)
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar3Props
},
// Characteristic Value 3 (DA20)
{
{ ATT_BT_UUID_SIZE, simpleProfileDA20UUID },
GATT_PERMIT_WRITE,
0,
simpleProfileChar3
},
// Characteristic 7 Declaration (DA99)
{
{ ATT_BT_UUID_SIZE, characterUUID },
GATT_PERMIT_READ,
0,
&simpleProfileChar7Props
},
// Characteristic Value 7 (DA99)
{
{ ATT_BT_UUID_SIZE, simpleProfileDA99UUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
simpleProfileChar7
},
// Characteristic 7 configuration (CCCD for Notification)
{
{ ATT_BT_UUID_SIZE, clientCharCfgUUID },
GATT_PERMIT_READ | GATT_PERMIT_WRITE,
0,
(uint8 *)&simpleProfileChar7Config
}
};
bStatus_t SimpleProfile_AddService( uint32 services )
{
uint8 status;
// Allocate Client Characteristic Configuration table
// simpleProfileChar4Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
// MAX_NUM_BLE_CONNS );
// if ( simpleProfileChar4Config == NULL )
// {
// return ( bleMemAllocError );
// }
simpleProfileChar1Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
MAX_NUM_BLE_CONNS );
if ( simpleProfileChar1Config == NULL )
{
return ( bleMemAllocError );
}
simpleProfileChar2Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
MAX_NUM_BLE_CONNS );
if ( simpleProfileChar2Config == NULL )
{
return ( bleMemAllocError );
}
// simpleProfileChar3Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
// MAX_NUM_BLE_CONNS );
// if ( simpleProfileChar3Config == NULL )
// {
// return ( bleMemAllocError );
// }
simpleProfileChar7Config = (gattCharCfg_t *)ICall_malloc( sizeof(gattCharCfg_t) *
MAX_NUM_BLE_CONNS );
if ( simpleProfileChar7Config == NULL )
{
return ( bleMemAllocError );
}
// Initialize Client Characteristic Configuration attributes
// GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar4Config );
GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar1Config );
GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar2Config );
// GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar3Config );
GATTServApp_InitCharCfg( LINKDB_CONNHANDLE_INVALID, simpleProfileChar7Config );
// simpleProfileChar1Config[0].connHandle = 0x0000;
// simpleProfileChar1Config[0].value = 0x0000;
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 );
}
bStatus_t SimpleProfile_SetParameter( uint8 param, uint8 len, void *value )
{ // GATT 서버의 특성 값을 설정할 때 호출되며, 이는 BLE 장치의 애플리케이션 코드에서 사용되어 데이터를 업데이트하거나 특성 값을 설정
bStatus_t ret = SUCCESS;
switch ( param )
{
case SIMPLEPROFILE_DA01:
// System_printf("s-1 : %d\r\n", len);
if ( len == SIMPLEPROFILE_DA01_LEN )
{
VOID memcpy( simpleProfileChar1, value, len );
// See if Notification has been enabled
// GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar1, FALSE,
// simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
// INVALID_TASK_ID, simpleProfile_ReadAttrCB );
if (simpleProfileChar1Config[gpram1->connHandle_tmp].value & GATT_CLIENT_CFG_NOTIFY)
{
System_printf("0-GATT_Notification\r\n");
if (gpram1->connHandle_tmp != LINKDB_CONNHANDLE_INVALID)
{
// status = GATT_Notification(connHandle, ¬i, FALSE);
GATTServApp_ProcessCharCfg( simpleProfileChar1Config, simpleProfileChar1, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
System_printf("Invalid connection handle.\r\n");
}
System_printf("1-GATT_Notification\r\n");
}
else
{
System_printf("Notification is not enabled for DA01\r\n");
}
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_DA04:
// System_printf("s-4 : %d\r\n", len);
if ( len == SIMPLEPROFILE_DA04_LEN )
{
VOID memcpy( simpleProfileChar2, value, len );
System_printf("DA04 SET: ");
for(int i=0; i<SIMPLEPROFILE_DA04_LEN; i++)
{
System_printf("%02x ", simpleProfileChar2[i]);
}
System_printf("\r\n");
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( simpleProfileChar2Config, simpleProfileChar2, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
// GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar2, FALSE,
// simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
// INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_AF01:
if ( len == simpleProfileChar5Length )
{
VOID memcpy( simpleProfileChar5, value, len );
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar5, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_AF02:
if ( len == simpleProfileChar6Length )
{
VOID memcpy( simpleProfileChar6, value, len );
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar6, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
break;
case SIMPLEPROFILE_DA99:
{
// System_printf("s-9 : %d\r\n", len);
if ( len == SIMPLEPROFILE_DA99_LEN )
{
VOID memcpy( simpleProfileChar7, value, len );
// See if Notification has been enabled
GATTServApp_ProcessCharCfg( simpleProfileChar4Config, simpleProfileChar7, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
}
else
{
ret = bleInvalidRange;
}
}
break;
default:
ret = INVALIDPARAMETER;
break;
}
return ( ret );
}
thanks
regards,
Hello,
This is the current situation.
The issue where it stopped at GATTServApp_ProcessCharCfg
has been resolved, but sending data through notifications is not working.
I want to send data via notifications anytime the data is updated.
When I check the state using state = GATTServApp_ProcessCharCfg
, the state shows as 0x1b (blePending)
.
Please let me know how I can debug this.
Below is the BLE transmission flow:
fn_Interface_BleState()
.multi_role_performPeriodicTask()
, every 200ms, the queue is checked, and if there is data, SimpleProfile_SetParameter
is called.SimpleProfile_SetParameter
function, data is sent using GATTServApp_ProcessCharCfg
.Below is the code I have configured. Please check if anything is incorrect or missing.
The error code 0x1B
was not blePending
, but actually bleInvalidMtuSize
.
#define ATT_MTU_SIZE L2CAP_MTU_SIZE //!< Minimum ATT MTU size
#define L2CAP_MTU_SIZE 23 //!< Minimum supported information payload for the Basic information frame (B-frame)
GATTServApp_ProcessCharCfg( simpleProfileChar1Config, simpleProfileChar1, FALSE,
simpleProfileAttrTbl, GATT_NUM_ATTRS( simpleProfileAttrTbl ),
INVALID_TASK_ID, simpleProfile_ReadAttrCB );
The size of simpleProfileChar1
was 22, which likely caused the bleInvalidMtuSize
error.
After making the following modification, communication through notifications started working: When connected to the app (GAP_LINK_ESTABLISHED_EVENT), I added:
attExchangeMTUReq_t req; req.clientRxMTU = 247; uint8_t status = GATT_ExchangeMTU(connHandle, &req, selfEntity);
This resolved the issue.
thank you.