Dialog的DA145XX系列BLE芯片可以配置允许多连接,需要修改SDK,下面主要说明如何实现多连接配置。
1、新增宏定义:__EXCLUDE_ROM_APP_TASK__
用于取消ROM里关于APP部分函数的调用,改为使用自定义的函数
2、部分宏定义(DA1458x_config_basic.h文件):
修改宏定义,配置支持的连接数,1453X系列最多支持3个连接:
/****************************************************************************************************************/
/* Determines maximum concurrent connections supported by application. It configures the heap memory allocated */
/* to service multiple connections. It is used for GAP central role applications. For GAP peripheral role it */
/* should be set to 1 for optimizing memory utilization. */
/* - MAX value for DA14535: 3 */
/****************************************************************************************************************/
#define CFG_MAX_CONNECTIONS (2)
新增宏定义:
/****************************************************************************************************************/
/* Enable multiple connections configuration */
/****************************************************************************************************************/
#if CFG_MAX_CONNECTIONS > (1)
#define CFG_ENABLE_MULTIPLE_CONN
#endif
3、app_task.h里修改宏定义:
/// Number of APP Task Instances
#ifndef CFG_ENABLE_MULTIPLE_CONN
#define APP_IDX_MAX (1)
#else
#define APP_IDX_MAX (APP_EASY_MAX_ACTIVE_CONNECTION)
#endif
4、app.h里修改宏定义:
/// Max connections supported by application task
#ifdef CFG_ENABLE_MULTIPLE_CONN
#define APP_EASY_MAX_ACTIVE_CONNECTION (BLE_CONNECTION_MAX)
#else
#define APP_EASY_MAX_ACTIVE_CONNECTION (1)
#endif
5、APP_task.c 修改部分函数:使用__WEAK关键字,用于在其它区域覆盖该函数,主要更改连接和断连两个回调函数:
gapc_disconnect_ind_handler
gapc_connection_req_ind_handler
/**
****************************************************************************************
* @brief Handles connection complete event from the GAP. Will enable profile.
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
#ifdef CFG_ENABLE_MULTIPLE_CONN
__WEAK int gapc_connection_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_connection_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
#else
static int gapc_connection_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_connection_req_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
#endif
{
// Connection Index
if (ke_state_get(dest_id) == APP_CONNECTABLE)
{
uint8_t conidx = KE_IDX_GET(src_id);
ASSERT_WARNING(conidx < APP_EASY_MAX_ACTIVE_CONNECTION);
app_env[conidx].conidx = conidx;
if (conidx != GAP_INVALID_CONIDX)
{
app_env[conidx].connection_active = true;
ke_state_set(TASK_APP, APP_CONNECTED);
// Retrieve the connection info from the parameters
app_env[conidx].conhdl = param->conhdl;
app_env[conidx].peer_addr_type = param->peer_addr_type;
memcpy(app_env[conidx].peer_addr.addr, param->peer_addr.addr, BD_ADDR_LEN);
#if (BLE_APP_SEC)
// send connection confirmation
app_easy_gap_confirm(conidx, (enum gap_auth) app_sec_env[conidx].auth, 1);
#else
app_easy_gap_confirm(conidx, GAP_AUTH_REQ_NO_MITM_NO_BOND, 1);
#endif
}
CALLBACK_ARGS_2(user_app_callbacks.app_on_connection, conidx, param)
}
else
{
// APP_CONNECTABLE state is used to wait the GAP_LE_CREATE_CONN_REQ_CMP_EVT message
ASSERT_ERROR(0);
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles disconnection complete event from the GAP.
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
#ifdef CFG_ENABLE_MULTIPLE_CONN
__WEAK int gapc_disconnect_ind_handler(ke_msg_id_t const msgid,
struct gapc_disconnect_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
#else
static int gapc_disconnect_ind_handler(ke_msg_id_t const msgid,
struct gapc_disconnect_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
#endif
{
uint8_t state = ke_state_get(dest_id);
uint8_t conidx = KE_IDX_GET(src_id);
if (state == APP_CONNECTED)
{
app_env[conidx].conidx = GAP_INVALID_CONIDX;
app_env[conidx].connection_active = false;
CALLBACK_ARGS_1(user_app_callbacks.app_on_disconnect, param)
}
else
{
// We are not in Connected State
ASSERT_ERROR(0);
}
return (KE_MSG_CONSUMED);
}
6、app.c里修改部分函数:主要是根据CFG_ENABLE_MULTIPLE_CONN宏定义是否开启,来重新配置函数app_db_init_start和app_db_init_next
/**
****************************************************************************************
* @brief Initialize the database for all the included profiles.
* @return true if succeeded, else false
****************************************************************************************
*/
#if (!defined (__DA14531__) || defined (__EXCLUDE_ROM_APP_TASK__)) && !defined (CFG_ENABLE_MULTIPLE_CONN)
static bool app_db_init_next(void)
#else
bool app_db_init_next(void)
#endif
{
static uint8_t i __SECTION_ZERO("retention_mem_area0"); //@RETENTION MEMORY;
static uint8_t k __SECTION_ZERO("retention_mem_area0"); //@RETENTION MEMORY;
// initialise the databases for all the included profiles
while(user_prf_funcs[k].task_id != TASK_ID_INVALID)
{
if (user_prf_funcs[k].db_create_func != NULL)
{
user_prf_funcs[k++].db_create_func();
return false;
}
else k++;
}
// initialise the databases for all the included profiles
while(prf_funcs[i].task_id != TASK_ID_INVALID)
{
if ((prf_funcs[i].db_create_func != NULL)
&& (!app_task_in_user_app(prf_funcs[i].task_id))) //case that the this task has an entry in the user_prf as well
{
prf_funcs[i++].db_create_func();
return false;
}
else i++;
}
#if (BLE_CUSTOM_SERVER)
{
static uint8_t j __SECTION_ZERO("retention_mem_area0"); //@RETENTION MEMORY;
while(cust_prf_funcs[j].task_id != TASK_ID_INVALID)
{
if(cust_prf_funcs[j].db_create_func != NULL)
{
cust_prf_funcs[j++].db_create_func();
return false;
}
else j++;
}
j = 0;
}
#endif
k = 0;
i = 0;
return true;
}
#if !defined (__DA14531__) || defined (__EXCLUDE_ROM_APP_TASK__)
#if !defined (CFG_ENABLE_MULTIPLE_CONN)
bool app_db_init_start(void)
{
// Indicate if more services need to be added in the database
bool end_db_create;
// We are now in Initialization State
ke_state_set(TASK_APP, APP_DB_INIT);
end_db_create = app_db_init_next();
return end_db_create;
}
#endif
7、在工程自定义的其它文件中重新实现前面在ROM里不支持多连接的函数,使其支持多连接:
/**
****************************************************************************************
* @brief Handles connection complete event from the GAP. Will enable profile.
* Custom function for multi-connection peripheral
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
int gapc_connection_req_ind_handler(ke_msg_id_t const msgid,
struct gapc_connection_req_ind const *param,
ke_task_id_t const dest_id, // dest_id -> TASK_APP
ke_task_id_t const src_id) // src_id -> TASK_GAPC
{
uint8_t conidx = KE_IDX_GET(src_id);
uint8_t current_state = ke_state_get(KE_BUILD_ID(KE_TYPE_GET(dest_id), conidx));
// Connection Index
if (current_state == APP_CONNECTABLE)
{
ASSERT_WARNING(conidx < APP_EASY_MAX_ACTIVE_CONNECTION);
app_env[conidx].conidx = conidx;
if (conidx != GAP_INVALID_CONIDX)
{
app_env[conidx].connection_active = true;
ke_state_set(KE_BUILD_ID(KE_TYPE_GET(dest_id), conidx), APP_CONNECTED); //SUPBLE_6975
// Retrieve the connection info from the parameters
app_env[conidx].conhdl = param->conhdl;
app_env[conidx].peer_addr_type = param->peer_addr_type;
memcpy(app_env[conidx].peer_addr.addr, param->peer_addr.addr, BD_ADDR_LEN);
#if (BLE_APP_SEC)
// send connection confirmation
app_easy_gap_confirm(conidx, (enum gap_auth) app_sec_env[conidx].auth, 1);
#else
app_easy_gap_confirm(conidx, GAP_AUTH_REQ_NO_MITM_NO_BOND, 1);
#endif
}
CALLBACK_ARGS_2(user_app_callbacks.app_on_connection, conidx, param)
}
else
{
// APP_CONNECTABLE state is used to wait the GAP_LE_CREATE_CONN_REQ_CMP_EVT message
ASSERT_ERROR(0);
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Handles disconnection complete event from the GAP. Custom function for the
* multiconnection.
* @param[in] msgid Id of the message received.
* @param[in] param Pointer to the parameters of the message.
* @param[in] dest_id ID of the receiving task instance (TASK_GAP).
* @param[in] src_id ID of the sending task instance.
* @return If the message was consumed or not.
****************************************************************************************
*/
int gapc_disconnect_ind_handler(ke_msg_id_t const msgid,
struct gapc_disconnect_ind const *param,
ke_task_id_t const dest_id,
ke_task_id_t const src_id)
{
uint8_t conidx = KE_IDX_GET(src_id);
uint8_t state = ke_state_get(KE_BUILD_ID(KE_TYPE_GET(dest_id), conidx));
if (state == APP_CONNECTED)
{
app_env[conidx].conidx = GAP_INVALID_CONIDX;
app_env[conidx].connection_active = false;
ke_state_set(KE_BUILD_ID(KE_TYPE_GET(dest_id), conidx), APP_CONNECTABLE);
CALLBACK_ARGS_1(user_app_callbacks.app_on_disconnect, param);
}
else
{
// We are not in Connected State
ASSERT_ERROR(0);
}
return (KE_MSG_CONSUMED);
}
/**
****************************************************************************************
* @brief Start placing services in the database.
* @return true if succeeded, else false
****************************************************************************************
*/
bool app_db_init_start(void)
{
// Indicate if more services need to be added in the database
bool end_db_create;
// We are now in Initialization State
for(uint8_t idx = 0; idx < APP_IDX_MAX; idx++)
ke_state_set(KE_BUILD_ID(TASK_APP, idx), APP_DB_INIT);
end_db_create = app_db_init_next();
return end_db_create;
}
8、修改da145xx_symbols.txt文件(在sdk\common_project_files\misc目录下),去除app.c、app_entry_point.c、app_task.c部分函数引用
原先为:
; app.c (controlled by __EXCLUDE_ROM_APP_TASK__)
0x07f22b35 T app_db_init_start
0x07f22b51 T app_db_init
0x07f22b5d T app_easy_gap_confirm
0x07f22b89 T append_device_name
0x07f22bad T app_easy_gap_update_adv_data
0x07f22bf5 T active_conidx_to_conhdl
0x07f22c19 T active_conhdl_to_conidx
0x07f22c55 T app_easy_gap_disconnect
0x07f22c91 T app_easy_gap_advertise_stop
0x07f22cad T app_timer_set
0x07f22cc9 T app_easy_gap_set_data_packet_length
0x07f22d09 T get_user_prf_srv_perm
0x07f22d31 T app_set_prf_srv_perm
0x07f22d61 T prf_init_srv_perm
0x07f22d85 T app_gattc_svc_changed_cmd_send
0x07f231fd T app_gap_process_handler
; app_entry_point.c (controlled by __EXCLUDE_ROM_APP_TASK__)
0x07f23219 T app_entry_point_handler
0x07f23261 T app_std_process_event
; app_task.c (controlled by __EXCLUDE_ROM_APP_TASK__)
0x07f23b98 D app_default_handler
更改为:
; app.c (controlled by __EXCLUDE_ROM_APP_TASK__)
0x07f23515 T append_device_name
;0x07f23715 T app_gattc_svc_changed_cmd_send
; app_entry_point.c (controlled by __EXCLUDE_ROM_APP_TASK__)
;0x07f23219 T app_entry_point_handler
;0x07f23261 T app_std_process_event
; app_task.c (controlled by __EXCLUDE_ROM_APP_TASK__)
;0x07f23b98 D app_default_handler
至此修改完毕。