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

本文详细解析了NRF51822蓝牙协议栈的工作原理,包括蓝牙协议栈的初始化过程、事件调度机制以及连接参数的管理方式等内容。



被折叠的 条评论
为什么被折叠?



