[资料分享]

CC2541之开启广播过程

[复制链接]
624|6
手机看帖
扫描二维码
随时随地手机跟帖
nawu|  楼主 | 2019-7-10 11:40 | 显示全部楼层

实验步骤

1、开启广播(simpleBLEPeripheral.c的SimpleBLEPeripheral_Init中)


在应用层开启广播功能其实非常简单,只要把TRUE传给GAPRole_SetParameter函数中的GAPROLE_ADVERT_ENABLED就可以了。



使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:40 | 显示全部楼层
七、解析协议栈在开启广播的操作后做了什么

1、GAPRole_SetParameter函数中的GAPROLE_ADVERT_ENABLED

    case GAPROLE_ADVERT_ENABLED:
      if ( len == sizeof( uint8 ) )
      {
        uint8 oldAdvEnabled = gapRole_AdvEnabled;
        gapRole_AdvEnabled = *((uint8*)pValue);

        if ( (oldAdvEnabled) && (gapRole_AdvEnabled == FALSE) )
        {
          // Turn off Advertising
          if ( gapRole_state == GAPROLE_ADVERTISING )
          {
            VOID GAP_EndDiscoverable( gapRole_TaskID );
          }
        }
        else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) )
        {
          // Turn on Advertising
          if ( (gapRole_state == GAPROLE_STARTED)
              || (gapRole_state == GAPROLE_WAITING)
              || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) )
          {
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }
      }
      else
      {
        ret = bleInvalidRange;
      }
      break;

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:41 | 显示全部楼层
其中gapRole_AdvEnabled默认是TRUE

static uint8  gapRole_AdvEnabled = TRUE;
首先,每次进到这个函数里,就会把gapRole_AdvEnabled的值保存到oldAdvEnabled,再把新的状态写到gapRole_AdvEnabled。也就是这两句:

        uint8 oldAdvEnabled = gapRole_AdvEnabled;
        gapRole_AdvEnabled = *((uint8*)pValue);

其次,对oldAdvEnabled(旧的广播开关状态)和gapRole_AdvEnabled(新传入的广播开关状态)这两个变量进行了判断:

1)在广播状态下,想关闭广播----->关闭广播

2)在不广播的状态下,想开启广播--->开启广播



然而代码中并没有将另外两种情况编写进来,也就是

3)在广播状态下,还想开启广播

4)在不广播的状态下,还想关闭广播

协议栈把这两种情况划入了else的bleInvalidRange。



第2)种情况的开广播,调用了gapRole_TaskID任务中的START_ADVERTISING_EVT事件。

        else if ( (oldAdvEnabled == FALSE) && (gapRole_AdvEnabled) )
        {
          // Turn on Advertising
          if ( (gapRole_state == GAPROLE_STARTED)
              || (gapRole_state == GAPROLE_WAITING)
              || (gapRole_state == GAPROLE_WAITING_AFTER_TIMEOUT) )
          {
            VOID osal_set_event( gapRole_TaskID, START_ADVERTISING_EVT );
          }
        }

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:41 | 显示全部楼层
2、START_ADVERTISING_EVT事件

  if ( events & START_ADVERTISING_EVT )
  {
    if ( gapRole_AdvEnabled )
    {
      gapAdvertisingParams_t params;

      // Setup advertisement parameters
      params.eventType = gapRole_AdvEventType;
      params.initiatorAddrType = gapRole_AdvDirectType;
      VOID osal_memcpy( params.initiatorAddr, gapRole_AdvDirectAddr, B_ADDR_LEN );
      params.channelMap = gapRole_AdvChanMap;
      params.filterPolicy = gapRole_AdvFilterPolicy;

      if ( GAP_MakeDiscoverable( gapRole_TaskID, ¶ms ) != SUCCESS )
      {
        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 );
  }
事件中调用GAP_MakeDiscoverable即可开启广播。
如果广播不成功,则会调用函数指针pGapRoles_AppCGs指向的回调函数,并且传入参数GAPROLE_ERROR,以此来通知应用层广播不成功。

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:41 | 显示全部楼层
那么调用的又是哪个回调函数呢?

追踪一下pGapRoles_AppCGs发现有个注册回调函数的函数

/*********************************************************************
* @brief   Does the device initialization.
*
* Public function defined in peripheral.h.
*/
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 );
  }
}

再追踪一下这个注册函数,发现在应用层的SBP_START_DEVICE_EVT事件中对此进行了注册

  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, SBP_PERIODIC_EVT, SBP_PERIODIC_EVT_PERIOD );

    return ( events ^ SBP_START_DEVICE_EVT );
  }

使用特权

评论回复
nawu|  楼主 | 2019-7-10 11:42 | 显示全部楼层
所以当广播开启不成功之后,会调用simpleBLEPeripheral_PeripheralCBs的回调函数peripheralStateNotificationCB的GAPROLE_ERROR

// GAP Role Callbacks
static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =
{
  peripheralStateNotificationCB,  // Profile State Change Callbacks
  NULL                            // When a valid RSSI is read from controller (not used by application)
};
    case GAPROLE_ERROR:
      {
        #if (defined HAL_LCD) && (HAL_LCD == TRUE)
          HalLcdWriteString( "Error",  HAL_LCD_LINE_3 );
        #endif // (defined HAL_LCD) && (HAL_LCD == TRUE)
      }
      break;
到此,广播过程就结束了,很简单吧,哈哈。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

3307

帖子

3

粉丝