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

基于ESP32的Bluedroid蓝牙协议栈架构分析(2)--- ADV广播流程分析

程序员文章站 2022-07-13 17:21:49
...

 为了分析ESP32的蓝牙接口,是如何在协议栈上运行的,现在以最简单的启动广播为例,分析Bluedroid蓝牙协议栈整体流程。

 具体过程如下:


esp_ble_gap_start_advertising()

esp_err_t esp_ble_gap_start_advertising(esp_ble_adv_params_t *adv_params)
{
    btc_msg_t msg;
    btc_ble_gap_args_t arg;

    ESP_BLUEDROID_STATUS_CHECK(ESP_BLUEDROID_STATUS_ENABLED);

    msg.sig = BTC_SIG_API_CALL;
    msg.pid = BTC_PID_GAP_BLE;
    msg.act = BTC_GAP_BLE_ACT_START_ADV;//执行事件
    memcpy(&arg.start_adv.adv_params, adv_params, sizeof(esp_ble_adv_params_t));

    return (btc_transfer_context(&msg, &arg, sizeof(btc_ble_gap_args_t), NULL) == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL);
}

//函数走向
btc_transfer_context()
---------->>btc_task_post()
----------------------->>> btc_thread_handler()
----------------------------->>profile_tab()
------------------------------->>>>btc_gap_ble_call_handler()
------------------------------------>>>btc_ble_start_advertising()
-------------------------------------------BTA_DmSetBleAdvParamsAll()


//传递事件,调用响应函数进行数据下发

void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max,
                               UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own,
                               tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol,
                               tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb)
{
        p_msg->hdr.event = BTA_DM_API_BLE_ADV_PARAM_All_EVT;
        ...
        p_msg->p_start_adv_cback    = p_start_adv_cb;
        ...
        bta_sys_sendmsg(p_msg);
}

bta_sys_sendmsg()
---------->>>>>btu_task_post()
------------->>>>>osi_thread_post(btu_thread, bta_sys_event, param, 0, timeout);
------------------------>>>>>bta_sys_event()


void bta_sys_event(void * param)
{
    BT_HDR *p_msg = (BT_HDR *)param;
    UINT8       id;
    BOOLEAN     freebuf = TRUE;

    APPL_TRACE_EVENT("BTA got event 0x%x\n", p_msg->event);

    /* get subsystem id from event */
    id = (UINT8) (p_msg->event >> 8); //事件ID 通过BTA_DM_API_BLE_ADV_PARAM_All_EVT映射传递

    /* verify id and call subsystem event handler */
    if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL)) {
        freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
    } else {
        APPL_TRACE_WARNING("BTA got unregistered event id %d\n", id);
    }

    if (freebuf) {
        osi_free(p_msg);
    }
}

bta_sys_cb是函数指针集,这个函数指针的初始化在使能BT时会被初始化到。

<bta_sys_main.c>
void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
{
    bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
    bta_sys_cb.is_reg[id] = TRUE;
}




//sm的意思是statemachine,状态机管理穿插在整个蓝牙管理中。
static const tBTA_SYS_REG bta_dm_reg =
{
    bta_dm_sm_execute,
    bta_dm_sm_disable
};

static const tBTA_SYS_REG bta_dm_search_reg =
{
    bta_dm_search_sm_execute,
    bta_dm_search_sm_disable
};


tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
{
   ...
    memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));

    bta_sys_register (BTA_ID_DM, &bta_dm_reg );
    bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
    ...
}


根据之前传递的事件ID = BTA_DM_API_BLE_ADV_PARAM_All_EVT 其调用bta_dm_sm_execute处理消息.
根据事件的不同会调用不同的注册函数。如果是事件ID BTA_DM_API_SEARCH_EVT将调用 bta_dm_search_sm_execute


//映射分配事件处理函数
BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
{
    UINT16  event = p_msg->event & 0x00ff;

    APPL_TRACE_EVENT("bta_dm_sm_execute event:0x%x", event);

    /* execute action functions */
    if (event < BTA_DM_NUM_ACTIONS) {
        (*bta_dm_action[event])( (tBTA_DM_MSG *) p_msg);
    }

    return TRUE;
}
const tBTA_DM_ACTION bta_dm_action[BTA_DM_MAX_EVT] = {

    bta_dm_ble_set_adv_params_all,          /* BTA_DM_API_BLE_ADV_PARAM_All_EVT */
    }

根据数据传递相关信息 广播事件也即bta_dm_ble_set_adv_params_all


bta_dm_ble_set_adv_params_all()
--------->>>>>BTM_BleStartAdv()
------------------>>>>>>>>btm_ble_start_adv()
------------------------------>>>>btsnd_hcic_ble_set_adv_enable()
------------------------------>>>> btu_hcif_send_cmd ();
-------------------------------------->>>>hci_layer_get_interface()->transmit_command();
------------------------------------直接操作HCI接口进行发送处理。

(仅供参考,如有问题请留言)