欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【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