nrf51822程序的分析(二)

本文详细解析了NRF51822蓝牙协议栈的工作原理,包括蓝牙协议栈的初始化过程、事件调度机制以及连接参数的管理方式等内容。
AI助手已提取文章相关产品:

nrf51822程序的分析( 二)

接着上篇分析,这次从主函数的协议栈开始分析。


1.3.蓝牙协议栈

1.3.1.协议栈中的变量

蓝牙协议栈开源的部分程序主要放在ble_conn_params.c,softdevice_handler.c等文件中。中间包括一些蓝牙协议栈的变量。
softdevice_handler中会存储一些softdevice相关的变量(整个蓝牙设备)
蓝牙系统主要靠事件驱动进行调度。下面是蓝牙事件的结构体定义:

/**@brief BLE事件头部. */
typedef struct
{
  uint16_t evt_id;                      /**< BLE_<module>_EVT 对应时间编号 */
  uint16_t evt_len;                     /**< 除头部外其他数据的字节长度 */
} ble_evt_hdr_t;

typedef struct
{
  ble_evt_hdr_t header;               /**< 事件头部*/
  union
  {
    ble_common_evt_t  common_evt;     /**< 公共时间, evt_id in BLE_EVT_* series. */
    ble_gap_evt_t     gap_evt;        /**< GAP生成事件, evt_id in BLE_GAP_EVT_* series. */
    ble_l2cap_evt_t   l2cap_evt;      /**< L2CAP生成事件, evt_id in BLE_L2CAP_EVT* series. */
    ble_gattc_evt_t   gattc_evt;      /**< GATT客户端生成事件, evt_id in BLE_GATTC_EVT* series.*/
    ble_gatts_evt_t   gatts_evt;      /**< GATT服务器生成时间, evt_id in BLE_GATTS_EVT* series.*/
  } evt;
} ble_evt_t;

前一部分是事件的头部,用来标识是具体哪种类型的事件。后面是用共用体表示的具体事件的值。

1.3.2.协议栈的初始化

主函数中调用ble_stack_init对蓝牙进行初始化

static void ble_stack_init(void)
{
    uint32_t err_code;

    // 初始化softdevice
    SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);

    //使能协议栈
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // 注册SoftDevice处理模块
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);
}

BLE协议栈的主要工作为:
1>.初始化蓝牙协议栈的事件处理
2>.绑定ble事件调度函数
3>.绑定sys事件调度函数。

先分析初始化代码。EVT_BUFFER作为存储传入事件缓存传入蓝牙的协议栈内。函数内确定一下事件缓冲区的指向和大小,确定一下回调函数softdevice_evt_schedule,最后进行使能和开中断。其中sd_softdevice_enable和sd_nvic_EnableIRQ为协议栈中不开源的代码,只需要传入对应参数即可。

#define SOFTDEVICE_HANDLER_INIT(CLOCK_SOURCE,                             \
                                USE_SCHEDULER)                          \
    do                                                           \
    {                                                             \
        static uint32_t EVT_BUFFER[CEIL_DIV(MAX(                    \
                                          MAX(BLE_STACK_EVT_MSG_BUF_SIZE, \
                                                    ANT_STACK_EVT_STRUCT_SIZE), \
                                                SYS_EVT_MSG_BUF_SIZE \
                                               ),                               \
                                            sizeof(uint32_t))];             \
        uint32_t ERR_CODE;                                               \
        ERR_CODE = softdevice_handler_init((CLOCK_SOURCE),                \
                                           EVT_BUFFER,                 \
                                           sizeof(EVT_BUFFER),               \
                                  (USE_SCHEDULER) ? softdevice_evt_schedule : NULL);\
        APP_ERROR_CHECK(ERR_CODE);                                         \
    } while (0)

uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t           clock_source,
                                 void *                         p_evt_buffer,
                                 uint16_t                       evt_buffer_size,
                                 softdevice_evt_schedule_func_t evt_schedule_func)
{
    uint32_t err_code;
    // 保存参数
#if defined (BLE_STACK_SUPPORT_REQD) || defined (ANT_STACK_SUPPORT_REQD)
    if (p_evt_buffer == NULL)
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    if (!is_word_aligned(p_evt_buffer))
    {
        return NRF_ERROR_INVALID_PARAM;
    }
    m_evt_buffer = (uint8_t *)p_evt_buffer;        //现在使用蓝牙协议栈
#else
    //如果不在蓝牙协议站或者ANT协议栈下p_evt_buffer不是必须的
    UNUSED_PARAMETER(p_evt_buffer);
#endif

#if defined (BLE_STACK_SUPPORT_REQD)     
    m_ble_evt_buffer_size = evt_buffer_size;
#else
    UNUSED_PARAMETER(evt_buffer_size);
#endif

    m_evt_schedule_func = evt_schedule_func;

    // 初始化
    err_code = sd_softdevice_enable(clock_source, softdevice_assertion_handler);
    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    m_softdevice_enabled = true;

    // 使能蓝牙中断(优先级早就被栈设置好).
    return sd_nvic_EnableIRQ(SWI2_IRQn);
}

softdevice_evt_schedule回调函数只有在SWI2_IRQHandler中断发生才被使用。SWI2_IRQHandler中断函数和在开启调度后发送事件的回调函数softdevice_evt_get最终调用的都是intern_softdevice_events_execute函数。

void intern_softdevice_events_execute(void)
{
    if (!m_softdevice_enabled)
         return;

    bool no_more_soc_evts = (m_sys_evt_handler == NULL);    //ble_evt_dispatch
#ifdef BLE_STACK_SUPPORT_REQD
    bool no_more_ble_evts = (m_ble_evt_handler == NULL);   //sys_evt_dispatch
#endif

您可能感兴趣的与本文相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值