添加用户代码
开发者需要根据自己的需求,修改ble_app_example中相应的代码。
修改主函数
以下为典型的main.c文件的内容。
/**@brief Stack global variables for Bluetooth protocol stack. */
STACK_HEAP_INIT(heaps_table);
…
int main (void)
{
/** Initialize user peripherals. */
app_periph_init();
/** Initialize BLE Stack. */
ble_stack_init(&&m_app_ble_callback, &heaps_table);
// Main Loop
while (1)
{
/*
* Add Application code here, e.g. GUI Update.
*/
app_log_flush();
pwr_mgmt_schedule();
}
}
- STACK_HEAP_INIT(heaps_table)定义了四个全局数组,供BLE协议栈作为Heap使用。开发者不可修改此定义,否则BLE协议栈无法正常运行。关于Heap的大小,参考配置custom_config.h的CFG_MAX_CONNECTIONS。
- 开发者可以在app_periph_init()中初始化外设。在开发调试阶段,该函数中的SYS_SET_BD_ADDR可用于设置临时的Public Address。该函数所在的user_periph_setup.c包含以下主要代码:
/**@brief Bluetooth device address. */
static const uint8_t s_bd_addr[SYS_BD_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11,0x11, 0x11};
…
void app_periph_init(void)
{
SYS_SET_BD_ADDR(s_bd_addr);
bsp_uart_init();
app_log_assert_init();
pwr_mgmt_mode_set(PMR_MGMT_SLEEP_MODE);
}
- 开发者应该在while(1) { }中添加Application的Main Loop代码,比如处理外部输入、更新GUI。
- 如果开发者使用了App Log模块,则需要在Main Loop中调用app_log_flush()。这可以保证在系统进入Sleep状态之前,Logs被完整输出。关于App Log模块使用,参考输出调试Log。
- 需调用pwr_mgmt_shcedule()以实现自动功耗管理,降低系统功耗。
实现BLE业务逻辑
Application的BLE相关业务逻辑是通过GR551x SDK中定义的若干BLE SDK Callback来驱动的。Application需要注册这些Callback到SDK中,以获得BLE Stack的运行结果或者状态改变通知。由于BLE SDK Callback是在BLE SDK IRQ的中断上下文(Interrupt Context)中被调用的,因此开发者不能在Callback中执行比较耗时的操作,比如阻塞式函数调用、无限循环等;否则,将阻塞整个系统运行,导致BLE Stack和SDK BLE模块无法按照正常的时序运行。
BLE SDK Callback按照GAP、Security Manager、L2CAP、GATT Common和GATT Client来分类。表 10中罗列了GR551x SDK支持的所有Callback Functions。
File Name | Callbacks Struct | Callback Function |
---|---|---|
user_app.c |
app_callback_t |
app_ble_init_cmp_callback |
user_gap_callback.c |
gap_cb_fun_t |
app_gap_param_set_cb |
app_gap_psm_manager_cb |
||
app_gap_phy_update_cb |
||
app_gap_dev_info_get_cb |
||
app_gap_adv_start_cb |
||
app_gap_adv_stop_cb |
||
app_gap_scan_req_ind_cb |
||
app_gap_adv_data_update_cb |
||
app_gap_scan_start_cb |
||
app_gap_scan_stop_cb |
||
app_gap_adv_report_ind_cb |
||
app_gap_sync_establish_cb |
||
app_gap_stop_sync_cb |
||
app_gap_sync_lost_cb |
||
app_gap_connect_cb |
||
app_gap_disconnect_cb |
||
app_gap_connect_cancel_cb |
||
app_gap_auto_connection_timeout_cb |
||
app_gap_peer_name_ind_cb |
||
app_gap_connection_update_cb |
||
app_gap_connection_update_req_cb |
||
app_gap_connection_info_get_cb |
||
app_gap_peer_info_get_cb |
||
app_gap_le_pkt_size_info_cb |
||
app_rslv_addr_read_cb |
||
user_l2cap_callback.c |
l2cap_lecb_cb_fun_t |
app_l2cap_lecb_conn_req_cb |
app_l2cap_lecb_conn_cb |
||
app_l2cap_lecb_add_credits_ind_cb |
||
app_l2cap_lecb_disconn_cb |
||
app_l2cap_lecb_sdu_recv_cb |
||
app_l2cap_lecb_sdu_send_cb |
||
app_l2cap_lecb_credit_add_cmp_cb |
||
user_sm_callback.c |
sec_cb_fun_t |
app_sec_enc_req_cb |
app_sec_enc_ind_cb |
||
app_sec_keypress_notify_cb |
||
user_gatt_common_callback.c |
gatt_common_cb_func_t |
app_gatt_mtu_exchange_cb |
app_gatt_prf_register_cb |
||
user_gattc_callback.c |
gattc_cb_fun_t |
app_gattc_srvc_disc_cb |
app_gattc_inc_srvc_disc_cb |
||
app_gattc_char_disc_cb |
||
app_gattc_char_desc_disc_cb |
||
app_gattc_read_cb |
||
app_gattc_write_cb |
||
app_gattc_ntf_ind_cb |
||
app_gattc_srvc_browse_cb |
||
app_gattc_cache_update_cb |
开发者需要根据产品的功能需求实现所需的BLE SDK Callback。例如,如果产品不支持Security Manager,则可以不实现对应的Callback;如果产品只支持GATT Server而不支持GATT Client,则可以不实现GATT Client对应的Callback。每一类Callback里的Callback Function也不一定需要全部实现,开发者只需要实现产品所必须的那些Callback Function。
关于BLE API和Callback API的用法,请参考GR551x BLE Stack用户指南、SDK_Folder\documentation\GR551x_API_Reference以及SDK_Folder\projects\ble中的BLE示例源代码。
BLE_Stack_IRQ、BLE_SDK_IRQ与Application的调度机制
BLE Stack是低功耗蓝牙协议栈实现核心,它直接操作Bluetooth 5.1 Core硬件(参考软件架构)。因此,BLE_Stack_IRQ具有整个系统中次高的优先级(SVCall IRQ具有最高优先级),以保证BLE Stack严格按照Bluetooth Core Spec规定的时序运行。
SDK_Folder\toolchain\gr551x\source\system_gr55xx.c中的system_priority_init()设置了系统各模块默认的中断优先级。
BLE Stack的状态改变会触发优先级较低的BLE_SDK_IRQ中断。在该中断处理函数中会调用Application实现的BLE SDK Callback,将BLE Stack的状态改变通知以及相关的业务数据发送到Application。开发者在这些Callback中应避免操作耗时的业务,应当将耗时业务转移到Main Loop或者用户级线程中处理。开发者可使用SDK_Folder\components\libraries\app_queue模块从BLE SDK Callback向Main Loop传递事件,或者使用自己的Application Framework。关于在用户线程中处理的方法,参考GR551x FreeRTOS示例手册。