一、实验目的
1、在实验过程中遇到很多问题,都不知道从何下手,所以决定深入了解蓝牙协议栈的底层,看是如何运行的,了解后,遇到问题就知道从哪里开始找问题,你懂得;
二、说明
1、由于空间有限,这里只是贴出部分代码,有些不能理解的要配合源代码来理解,这里只是大概指向(红色部分),能让你大部分明白是怎么跑起来的,细节上自己去理解,不懂可以提问;
三、实验平台
1、蓝牙协议栈:1.3.2
2、软件平台:IAR For 8051 8.10.3
5、硬件平台:Smart RF开发板(从机),Android_Lightblue(主机)
四、实验步骤
int main(void)
{
/* Initialize hardware */
HAL_BOARD_INIT();//初始化时钟和使能缓存预取模式
// Initialize board I/O
InitBoard( OB_COLD );//冷启动,关闭了led灯与中断,避免接下来的各种初始化受干扰
/* Initialze the HAL driver */
HalDriverInit();//各种驱动的初始化、如按键、lcd、adc、usb、uart等8
/* Initialize NV system */
osal_snv_init();//snv 内部用于保存配对数据或你的用户自定义数据的一段flash,4kB空间
/* Initialize LL */
/* Initialize the operating system */
osal_init_system();//oasl 操作系统初始化, 包含内存分配、消息队列、定时器、电源管理和任务等
/* Enable interrupts */
HAL_ENABLE_INTERRUPTS();// 开启全局中断
// Final board initialization
InitBoard( OB_READY ); //设置标志标示系统初始化完毕
uint8 osal_init_system( void )
{
// Initialize the Memory Allocation System
osal_mem_init();//初始化内存分配系统
// Initialize the message queue
osal_qHead = NULL;//初始化消息队列
// Initialize the timers
osalTimerInit();//初始化定时器
// Initialize the Power Management System
osal_pwrmgr_init();//初始化电源管理系统
// Initialize the system tasks.
osalInitTasks();//初始化系统任务, 这一个任务初始花非常关键
// Setup efficient search for the first free block of heap.
osal_mem_kick();
return ( SUCCESS );
}
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++ );
/* Application */
SimpleBLEPeripheral_Init( taskID );
}
void GAPRole_Init( uint8 task_id )
{
gapRole_TaskID = task_id; //定义任务地址
gapRole_state = GAPROLE_INIT; //链路状态设置为GAPROLE_INIT
gapRole_ConnectionHandle = INVALID_CONNHANDLE; //设置链路连接句柄为0xFFFF
GAP_RegisterForHCIMsgs( gapRole_TaskID );//注册控制接口的任务ID
// 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 );
}
//初始化完成后
{
osal_set_event( simpleBLEPeripheral_TaskID, SBP_START_DEVICE_EVT ); //启动设备开始事件
}
6、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 );
}
}
{
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 );
}
}
{
VOID GAP_DeviceInit( gapRole_TaskID,
gapRole_profileRole, 0,
gapRole_IRK, gapRole_SRK,
&gapRole_signCounter );
}
{
// 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
}
{
uint8 notify = FALSE; // State changed notify the app? (default no)
switch ( pMsg->opcode )
{
case GAP_DEVICE_INIT_DONE_EVENT: //当GAP_DeviceInit初始化完成后,将产生此事件
{
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 ) //判断是否设置了回调函数
{
pGapRoles_AppCGs->pfnStateChange( gapRole_state );//调用设置的回调函数,通知gapRole_state当前状态
}
}
}
{
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;
{
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;
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 );
}
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当前状态
}
}
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当前状态
}
}
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;
}
}
}
六、总结
1、广播连接的过程分析下来还算是比较简单的;
2、有什么不足的地方欢迎讨论QQ群:127442605