【IoT】CC2541 BLE 4.0 底层协议栈广播连接过程解析
程序员文章站
2022-07-13 17:50:53
...
1、主逻辑
int main(void)
{
// 初始化时钟和使能缓存预取模式
HAL_BOARD_INIT();
// 冷启动,关闭 LED 与中断,避免接下来的各种初始化受干扰
InitBoard( OB_COLD );
// 各种驱动的初始化、如按键、lcd、adc、usb、uart 等
HalDriverInit();
// SNV 内部用于保存配对数据或你的用户自定义数据的一段 flash 4kB 空间
osal_snv_init();
// OSAL 操作系统初始化:内存分配、消息队列、定时器、电源管理和任务等
osal_init_system();
// 开启全局中断
HAL_ENABLE_INTERRUPTS();
//设置标志标示系统初始化完毕
InitBoard( OB_READY );
......
}
2、系统初始化
uint8 osal_init_system( void )
{
// 初始化内存分配系统
osal_mem_init();
// 初始化消息队列
osal_qHead = NULL;
// 初始化定时器
osalTimerInit();
// 初始化电源管理系统
osal_pwrmgr_init();
// 初始化系统任务
osalInitTasks();
// Setup efficient search for the first free block of heap.
osal_mem_kick();
return ( SUCCESS );
}
3、任务初始化
void osalInitTasks( void )
{
/* L2CAP Task */
L2CAP_Init( taskID++ );
/* GAP Task */
GAP_Init( taskID++ );
/* GATT Task */
GATT_Init( taskID++ );
/* SM Task */
SM_Init( taskID++ );
/* Profiles */
// 链路角色初始化
GAPRole_Init( taskID++ );
// 链路绑定初始化
GAPBondMgr_Init( taskID++ );
GATTServApp_Init( taskID++ );
// 应用任务初始化
SimpleBLEPeripheral_Init( taskID );
}
4、链路角色初始化
void GAPRole_Init( uint8 task_id )
{
// 定义任务地址
gapRole_TaskID = task_id;
// 链路状态设置为 GAPROLE_INIT
gapRole_state = GAPROLE_INIT;
// 设置链路连接句柄为 0xFFFF
gapRole_ConnectionHandle = INVALID_CONNHANDLE;
// 注册控制接口的任务 ID
GAP_RegisterForHCIMsgs( gapRole_TaskID );
// Initialize the Profile Advertising and Connection Parameters
gapRole_profileRole = GAP_PROFILE_PERIPHERAL; // 链路配置角色为从机
VOID osal_memset( gapRole_IRK, 0, KEYLEN ); // **缓冲器清零
VOID osal_memset( gapRole_SRK, 0, KEYLEN );
gapRole_signCounter = 0; // **计数标志位清零
gapRole_AdvEventType = GAP_ADTYPE_ADV_IND; // 广播类型为可连接无定向广播
gapRole_AdvDirectType = ADDRTYPE_PUBLIC; // 广播方式为通过广播(可被发现扫描连接)
gapRole_AdvChanMap = GAP_ADVCHAN_ALL ; // 广播所有通道 37、38、39
gapRole_AdvFilterPolicy = GAP_FILTER_POLICY_ALL; // 允许扫描,允许连接
// Restore Items from NV
VOID osal_snv_read( BLE_NVID_IRK, KEYLEN, gapRole_IRK ); //读出存储的**和**计数标志位
VOID osal_snv_read( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
VOID osal_snv_read( BLE_NVID_SIGNCOUNTER, sizeof( uint32 ), &gapRole_signCounter );
}
5、启动设备
void SimpleBLEPeripheral_Init( uint8 task_id )
{
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); // 启动设备开始事件
}
uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events )
{
if ( events & SBP_START_DEVICE_EVT )
{
// Start the Device
VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs ); // 配置链路事件通知回调函数
// Start Bond Manager
VOID GAPBondMgr_Register( &simpleBLEPeripheral_BondMgrCBs ); // 配置配对消息回调函数
// Set timer for first periodic event
osal_start_timerEx( simpleBLEPeripheral_TaskID, POWER_DETECT_EVT, DetectPowerPeriod );
return ( events ^ SBP_START_DEVICE_EVT );
}
}
6、配置链路事件回调
bStatus_t GAPRole_StartDevice( gapRolesCBs_t *pAppCallbacks )
{
if ( gapRole_state == GAPROLE_INIT ) // 如果链路状态是初始化状态
{
// Clear all of the Application callbacks
if ( pAppCallbacks )
{
pGapRoles_AppCGs = pAppCallbacks; // 设置回调函数
}
// Start the GAP
gapRole_SetupGAP();//开始建立链路
return ( SUCCESS );
}
// 否则返回已经在请求模式状态
else
{
return ( bleAlreadyInRequestedMode );
}
}
static void gapRole_SetupGAP( void )
{
VOID GAP_DeviceInit( gapRole_TaskID,
gapRole_profileRole, 0,
gapRole_IRK, gapRole_SRK,
&gapRole_signCounter );
}
bStatus_t GAP_DeviceInit( uint8 taskID,
uint8 profileRole,
uint8 maxScanResponses,
uint8 *pIRK,
uint8 *pSRK,
uint32 *pSignCounter )
{
// Setup the device configuration parameters
stat = GAP_ParamsInit( taskID, profileRole ); //设置设备配置参数
#if ( HOST_CONFIG & ( CENTRAL_CFG | PERIPHERAL_CFG ) )
{
GAP_SecParamsInit( pIRK, pSRK, pSignCounter );
}
#endif
#if ( HOST_CONFIG & ( PERIPHERAL_CFG | BROADCASTER_CFG ) )
{
// Initialize GAP Peripheral Device Manager
VOID GAP_PeriDevMgrInit(); //初始化从机设备管理
#if ( HOST_CONFIG & PERIPHERAL_CFG )
{
// Initialize SM Responder
VOID SM_ResponderInit(); //回应者初始化
}
#endif
}
#endif
}
当 GAP_DeviceInit 初始化完成后,将产生 GAP_DEVICE_INIT_DONE_EVENT 事件;
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events ) // 链路处理事件
static void gapRole_ProcessOSALMsg( osal_event_hdr_t *pMsg ) // 链路系统消息事件
7、处理消息
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) // 链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
// GAP_DeviceInit 初始化完成后,将产生此事件
case GAP_DEVICE_INIT_DONE_EVENT:
{
gapDeviceInitDoneEvent_t *pPkt = (gapDeviceInitDoneEvent_t *)pMsg;
bStatus_t stat = pPkt->hdr.status;
if ( stat == SUCCESS )
{
// Save off the generated keys
VOID osal_snv_write( BLE_NVID_IRK, KEYLEN, gapRole_IRK ); // 保存生成的**
VOID osal_snv_write( BLE_NVID_CSRK, KEYLEN, gapRole_SRK );
// Save off the information
VOID osal_memcpy( gapRole_bdAddr, pPkt->devAddr, B_ADDR_LEN ); // 保存设备地址
gapRole_state = GAPROLE_STARTED; // 链路开始
// Update the advertising data
stat = GAP_UpdateAdvertisingData( gapRole_TaskID,//更新广播数据
TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
}
notify = TRUE; // 通知回调函数链路的状态
}
break;
if ( notify == TRUE )
{
// Notify the application with the new state change
// 判断是否设置了回调函数
if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
{
// 调用设置的回调函数,通知 gapRole_state 当前状态
pGapRoles_AppCGs->pfnStateChange( gapRole_state );
}
}
}
// 更新广播数据后,将产生 GAP_ADV_DATA_UPDATE_DONE_EVENT 事件
stat=GAP_UpdateAdvertisingData( gapRole_TaskID,TRUE, gapRole_AdvertDataLen, gapRole_AdvertData );
8、处理连接消息
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) // 链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_ADV_DATA_UPDATE_DONE_EVENT:
{
gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;
if ( pPkt->hdr.status == SUCCESS )
{
if ( pPkt->adType )
{
// Setup the Response Data
pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData ); // 更新扫描回应数据
}
else
{
// Start advertising
VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); // 启动广播事件
}
}
if ( pPkt->hdr.status != SUCCESS ) // 如果不成功将通知回调函数,否则不通知
{
// Set into Error state
gapRole_state = GAPROLE_ERROR;
notify = TRUE;
}
}
break;
......
}
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) // 链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_ADV_DATA_UPDATE_DONE_EVENT:
{
gapAdvDataUpdateEvent_t *pPkt = (gapAdvDataUpdateEvent_t *)pMsg;
if ( pPkt->hdr.status == SUCCESS )
{
if ( pPkt->adType )
{
// Setup the Response Data
pPkt->hdr.status = GAP_UpdateAdvertisingData( gapRole_TaskID,
FALSE, gapRole_ScanRspDataLen, gapRole_ScanRspData );//更新扫描回应数据
}
else
{
// Start advertising
VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT ); //启动广播事件
}
}
if ( pPkt->hdr.status != SUCCESS ) //如果不成功将通知回调函数,否则不通知
{
// Set into Error state
gapRole_state = GAPROLE_ERROR;
notify = TRUE;
}
}
break;
......
}
9、执行广播事件
uint16 GAPRole_ProcessEvent( uint8 task_id, uint16 events )
{
VOID task_id; // OSAL required parameter that isn't used in this function
if ( events & START_ADVERTISING_EVT )
{
if ( gapRole_AdvEnabled )
{
gapAdvertisingParams_t params;
// Setup advertisement parameters
params.eventType = gapRole_AdvEventType; // GAP_ADTYPE_ADV_IND; 广播类型为可连接无定向广播
params.initiatorAddrType = gapRole_AdvDirectType; // ADDRTYPE_PUBLIC; 广播方式为通用广播
VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN ); // 发起者地址配置
params.channelMap = gapRole_AdvChanMap; // 广播通道配置:广播所有通道37、38、39
params.filterPolicy = gapRole_AdvFilterPolicy;// 过滤策略 GAP_FILTER_POLICY_ALL 允许扫描,允许连接
if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS ) // 配置广播参数,并产生一个GAP_MakeDiscoverable 消息事件
{
gapRole_state = GAPROLE_ERROR; // 如果不成功将通知回调函数-链路错误
// Notify the application with the new state change
if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange )
{
pGapRoles_AppCGs->pfnStateChange( gapRole_state );
}
}
}
return ( events ^ START_ADVERTISING_EVT );
}
10、处理 GAP_MakeDiscoverable 消息事件
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) // 链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_MAKE_DISCOVERABLE_DONE_EVENT: // 使能可被发现完成事件即开始广播了
case GAP_END_DISCOVERABLE_DONE_EVENT: // 结束可被发现完成事件即停止广播了
{
gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;
if ( pPkt->hdr.status == SUCCESS )
{
if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
{
gapRole_state = GAPROLE_ADVERTISING; // 设置当前链路状态
}
else // GAP_END_DISCOVERABLE_DONE_EVENT // 结束可被发现完成事件即停止广播了
{
if ( gapRole_AdvertOffTime != 0 ) // 如果gapRole_AdvertOffTime等于0,将不再广播,否则启动定时广播件
{
if ( ( gapRole_AdvEnabled ) ) // 如果使能广播
{
VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime ); // 启动周期广播事件
}
}
else
{
// Since gapRole_AdvertOffTime is set to 0, the device should not
// automatically become discoverable again after a period of time.
// Set enabler to FALSE; device will become discoverable again when
// this value gets set to TRUE
gapRole_AdvEnabled = FALSE;
}
// In the Advertising Off period
gapRole_state = GAPROLE_WAITING;//如果GAP_END_DISCOVERABLE_DONE_EVENT,链路当前状态为等待状态
}
}
else
{
gapRole_state = GAPROLE_ERROR;
}
notify = TRUE;//通知回调函数
}
break;
if ( notify == TRUE )
{
// Notify the application with the new state change
if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) //判断是否设置了回调函数
{
pGapRoles_AppCGs->pfnStateChange( gapRole_state );//调用设置的回调函数,通知gapRole_state当前状态
}
}
.....
}
这时候底层已经使能硬件在广播了,要么广播超时产生一个GAP_END_DISCOVERABLE_DONE_EVENT消息,要么被连接事件 GAP_LINK_ESTABLISHED_EVENT;
11、广播超时产生一个 GAP_END_DISCOVERABLE_DONE_EVENT 消息
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) //链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_MAKE_DISCOVERABLE_DONE_EVENT: //使能可被发现完成事件即开始广播了
case GAP_END_DISCOVERABLE_DONE_EVENT: //结束可被发现完成事件即停止广播了
{
gapMakeDiscoverableRspEvent_t *pPkt = (gapMakeDiscoverableRspEvent_t *)pMsg;
if ( pPkt->hdr.status == SUCCESS )
{
if ( pMsg->opcode == GAP_MAKE_DISCOVERABLE_DONE_EVENT )
{
gapRole_state = GAPROLE_ADVERTISING; //设置当前链路状态
}
else // GAP_END_DISCOVERABLE_DONE_EVENT//结束可被发现完成事件即停止广播了
{
if ( gapRole_AdvertOffTime != 0 ) //如果gapRole_AdvertOffTime不等于0,启动定时广播事件,否则将关闭广播
{
if ( ( gapRole_AdvEnabled ) )//如果使能广播
{
VOID osal_start_timerEx( gapRole_TaskID, START_ADVERTISING_EVT, gapRole_AdvertOffTime );//启动周期广播事件
}
}
else
{
// Since gapRole_AdvertOffTime is set to 0, the device should not
// automatically become discoverable again after a period of time.
// Set enabler to FALSE; device will become discoverable again when
// this value gets set to TRUE
gapRole_AdvEnabled = FALSE; //关闭广播
}
// In the Advertising Off period
gapRole_state = GAPROLE_WAITING;//如果GAP_END_DISCOVERABLE_DONE_EVENT,链路当前状态为等待状态,或不再广播或等待周期广播
}
}
else
{
gapRole_state = GAPROLE_ERROR;
}
notify = TRUE;//通知回调函数
}
break;
if ( notify == TRUE )
{
// Notify the application with the new state change
if ( pGapRoles_AppCGs && pGapRoles_AppCGs->pfnStateChange ) //判断是否设置了回调函数
{
pGapRoles_AppCGs->pfnStateChange( gapRole_state );//调用设置的回调函数,通知gapRole_state当前状态
}
}
......
}
12、广播时产生一个 GAP_LINK_ESTABLISHED_EVENT 消息
static void gapRole_ProcessGAPMsg( gapEventHdr_t *pMsg ) //链路处理连接消息
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_LINK_ESTABLISHED_EVENT:
{
gapEstLinkReqEvent_t *pPkt = (gapEstLinkReqEvent_t *)pMsg;
if ( pPkt->hdr.status == SUCCESS )
{
VOID osal_memcpy( gapRole_ConnectedDevAddr, pPkt->devAddr, B_ADDR_LEN );//保存主机的地址
gapRole_ConnectionHandle = pPkt->connectionHandle; //保存主机连接句柄
gapRole_state = GAPROLE_CONNECTED; //通知链路状态:连接成功
notify = TRUE;
}
}
}
......
}
refer:
http://www.it610.com/article/5111811.htm