小熊派BearPi-Pico H2821星闪开发板测评(六)——SLE串口透传测试
本帖最后由 FuShenxiao 于 2024-8-27 09:33 编辑<p><strong><span style="font-size:18px;">官方案例实现</span></strong></p>
<p>官方案例通过两块开发板实现SLE数据传输测试,A开发板通过串口接收数据,然后通过SLE传输给B开发板,B开发板通过串口将接收到的数据打印出来;同样,B开发板通过串口接收数据,然后通过SLE传输给A开发板,A开发板通过串口将接收到的数据打印出来。在测试中需要一块开发板做为Server端,另外一块开发板做为Client端,两块开发板配对后即可互发消息。连接方式如下图所示:</p>
<p> </p>
<div style="text-align: center;"></div>
<p> </p>
<p><span style="font-size:16px;"><strong>配置SLE UART Server</strong></span></p>
<p align="center"> </p>
<p align="center"> </p>
<p align="center"> </p>
<p>选择协议</p>
<p align="center"> </p>
<p align="center"> </p>
<p align="center"> </p>
<p style="text-align: justify;">配置完成,对代码进行编译烧录。</p>
<p><strong><span style="font-size:16px;">配置SLE UART Client</span></strong></p>
<p align="center"> </p>
<p>选择协议</p>
<p align="center"> </p>
<p style="text-align: justify;">配置完成,对代码进行编译烧录</p>
<p><strong><span style="font-size:16px;">Server初始化</span></strong></p>
<p>首先进行SDK相关的初始化</p>
<p align="center"></p>
<p style="text-align: justify;"> 接着初始化SLE,并进入SLE任务</p>
<p align="center"> </p>
<p style="text-align: justify;">接着配置与开启ADV</p>
<p align="center"> </p>
<p style="text-align: justify;"> </p>
<p><strong><span style="font-size:16px;">Client初始化</span></strong></p>
<p>首先初始化SDK</p>
<p align="center"> </p>
<p style="text-align: justify;">接着初始化SLE任务并进入SLE任务;配置ADV参数</p>
<p align="center"> </p>
<p style="text-align: justify;">与主机配对,发现特征值</p>
<p align="center"> </p>
<p style="text-align: justify;"> </p>
<p><strong><span style="font-size:16px;">Client初始化完成后Server的日志显示</span></strong></p>
<p>扫描到从机的ADV数据,与从机配对</p>
<p align="center"> </p>
<p style="text-align: justify;"><span style="font-size:16px;"><strong>发送测试</strong></span></p>
<p><strong>Server发送Client接收</strong></p>
<p align="center"> </p>
<p><strong>Client发送Server接收</strong></p>
<p style="text-align: center;"> </p>
<p style="text-align: justify;"><strong><span style="font-size:18px;">代码实现</span></strong></p>
<p style="text-align: justify;"><strong>sle_uart_server代码</strong></p>
<pre>
<code>#include "common_def.h"
#include "securec.h"
#include "soc_osal.h"
#include "sle_errcode.h"
#include "sle_device_manager.h"
#include "sle_connection_manager.h"
#include "sle_device_discovery.h"
#include "sle_uart_server_adv.h"
#include "sle_uart_server.h"
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
#include "sle_low_latency.h"
#endif
#define OCTET_BIT_LEN 8
#define UUID_LEN_2 2
#define UUID_INDEX 14
#define BT_INDEX_4 4
#define BT_INDEX_0 0
#define UART_BUFF_LENGTH 0x100
/* 广播ID */
#define SLE_ADV_HANDLE_DEFAULT1
/* sle server app uuid for test */
static char g_sle_uuid_app_uuid = { 0x12, 0x34 };
/* server notify property uuid for test */
static char g_sle_property_value = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
/* sle connect acb handle */
static uint16_t g_sle_conn_hdl = 0;
/* sle server handle */
static uint8_t g_server_id = 0;
/* sle service handle */
static uint16_t g_service_handle = 0;
/* sle ntf property handle */
static uint16_t g_property_handle = 0;
/* sle pair acb handle */
uint16_t g_sle_pair_hdl;
#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16
#define sample_at_log_print(fmt, args...) osal_printk(fmt, ##args)
#define SLE_UART_SERVER_LOG ""
#define SLE_SERVER_INIT_DELAY_MS 1000
static sle_uart_server_msg_queue g_sle_uart_server_msg_queue = NULL;
static uint8_t g_sle_uart_base[] = { 0x37, 0xBE, 0xA8, 0x80, 0xFC, 0x70, 0x11, 0xEA, \
0xB7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint16_t get_connect_id(void)
{
return g_sle_conn_hdl;
}
static void encode2byte_little(uint8_t *_ptr, uint16_t data)
{
*(uint8_t *)((_ptr) + 1) = (uint8_t)((data) >> 0x8);
*(uint8_t *)(_ptr) = (uint8_t)(data);
}
static void sle_uuid_set_base(sle_uuid_t *out)
{
errcode_t ret;
ret = memcpy_s(out->uuid, SLE_UUID_LEN, g_sle_uart_base, SLE_UUID_LEN);
if (ret != EOK) {
sample_at_log_print("%s sle_uuid_set_base memcpy fail\n", SLE_UART_SERVER_LOG);
out->len = 0;
return ;
}
out->len = UUID_LEN_2;
}
static void sle_uuid_setu2(uint16_t u2, sle_uuid_t *out)
{
sle_uuid_set_base(out);
out->len = UUID_LEN_2;
encode2byte_little(&out->uuid, u2);
}
static void sle_uart_uuid_print(sle_uuid_t *uuid)
{
if (uuid == NULL) {
sample_at_log_print("%s uuid_print,uuid is null\r\n", SLE_UART_SERVER_LOG);
return;
}
if (uuid->len == UUID_16BIT_LEN) {
sample_at_log_print("%s uuid: %02x %02x.\n", SLE_UART_SERVER_LOG,
uuid->uuid, uuid->uuid); /* 14 15: uuid index */
} else if (uuid->len == UUID_128BIT_LEN) {
sample_at_log_print("%s uuid: \n", SLE_UART_SERVER_LOG); /* 14 15: uuid index */
sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid->uuid, uuid->uuid,
uuid->uuid, uuid->uuid);
sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid->uuid, uuid->uuid,
uuid->uuid, uuid->uuid);
sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid->uuid, uuid->uuid,
uuid->uuid, uuid->uuid);
sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid->uuid, uuid->uuid,
uuid->uuid, uuid->uuid);
}
}
static void ssaps_mtu_changed_cbk(uint8_t server_id, uint16_t conn_id,ssap_exchange_info_t *mtu_size,
errcode_t status)
{
sample_at_log_print("%s ssaps ssaps_mtu_changed_cbk callback server_id:%x, conn_id:%x, mtu_size:%x, status:%x\r\n",
SLE_UART_SERVER_LOG, server_id, conn_id, mtu_size->mtu_size, status);
if (g_sle_pair_hdl == 0) {
g_sle_pair_hdl = conn_id + 1;
}
}
static void ssaps_start_service_cbk(uint8_t server_id, uint16_t handle, errcode_t status)
{
sample_at_log_print("%s start service cbk callback server_id:%d, handle:%x, status:%x\r\n", SLE_UART_SERVER_LOG,
server_id, handle, status);
}
static void ssaps_add_service_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t handle, errcode_t status)
{
sample_at_log_print("%s add service cbk callback server_id:%x, handle:%x, status:%x\r\n", SLE_UART_SERVER_LOG,
server_id, handle, status);
sle_uart_uuid_print(uuid);
}
static void ssaps_add_property_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t service_handle,
uint16_t handle, errcode_t status)
{
sample_at_log_print("%s add property cbk callback server_id:%x, service_handle:%x,handle:%x, status:%x\r\n",
SLE_UART_SERVER_LOG, server_id, service_handle, handle, status);
sle_uart_uuid_print(uuid);
}
static void ssaps_add_descriptor_cbk(uint8_t server_id, sle_uuid_t *uuid, uint16_t service_handle,
uint16_t property_handle, errcode_t status)
{
sample_at_log_print("%s add descriptor cbk callback server_id:%x, service_handle:%x, property_handle:%x, \
status:%x\r\n", SLE_UART_SERVER_LOG, server_id, service_handle, property_handle, status);
sle_uart_uuid_print(uuid);
}
static void ssaps_delete_all_service_cbk(uint8_t server_id, errcode_t status)
{
sample_at_log_print("%s delete all service callback server_id:%x, status:%x\r\n", SLE_UART_SERVER_LOG,
server_id, status);
}
static errcode_t sle_ssaps_register_cbks(ssaps_read_request_callback ssaps_read_callback, ssaps_write_request_callback
ssaps_write_callback)
{
errcode_t ret;
ssaps_callbacks_t ssaps_cbk = {0};
ssaps_cbk.add_service_cb = ssaps_add_service_cbk;
ssaps_cbk.add_property_cb = ssaps_add_property_cbk;
ssaps_cbk.add_descriptor_cb = ssaps_add_descriptor_cbk;
ssaps_cbk.start_service_cb = ssaps_start_service_cbk;
ssaps_cbk.delete_all_service_cb = ssaps_delete_all_service_cbk;
ssaps_cbk.mtu_changed_cb = ssaps_mtu_changed_cbk;
ssaps_cbk.read_request_cb = ssaps_read_callback;
ssaps_cbk.write_request_cb = ssaps_write_callback;
ret = ssaps_register_callbacks(&ssaps_cbk);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_ssaps_register_cbks,ssaps_register_callbacks fail :%x\r\n", SLE_UART_SERVER_LOG,
ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
static errcode_t sle_uuid_server_service_add(void)
{
errcode_t ret;
sle_uuid_t service_uuid = {0};
sle_uuid_setu2(SLE_UUID_SERVER_SERVICE, &service_uuid);
ret = ssaps_add_service_sync(g_server_id, &service_uuid, 1, &g_service_handle);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle uuid add service fail, ret:%x\r\n", SLE_UART_SERVER_LOG, ret);
return ERRCODE_SLE_FAIL;
}
return ERRCODE_SLE_SUCCESS;
}
static errcode_t sle_uuid_server_property_add(void)
{
errcode_t ret;
ssaps_property_info_t property = {0};
ssaps_desc_info_t descriptor = {0};
uint8_t ntf_value[] = { 0x01, 0x02 };
property.permissions = SLE_UUID_TEST_PROPERTIES;
property.operate_indication = SLE_UUID_TEST_OPERATION_INDICATION;
sle_uuid_setu2(SLE_UUID_SERVER_NTF_REPORT, &property.uuid);
property.value = (uint8_t *)osal_vmalloc(sizeof(g_sle_property_value));
if (property.value == NULL) {
return ERRCODE_SLE_FAIL;
}
if (memcpy_s(property.value, sizeof(g_sle_property_value), g_sle_property_value,
sizeof(g_sle_property_value)) != EOK) {
osal_vfree(property.value);
return ERRCODE_SLE_FAIL;
}
ret = ssaps_add_property_sync(g_server_id, g_service_handle, &property,&g_property_handle);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle uart add property fail, ret:%x\r\n", SLE_UART_SERVER_LOG, ret);
osal_vfree(property.value);
return ERRCODE_SLE_FAIL;
}
descriptor.permissions = SLE_UUID_TEST_DESCRIPTOR;
descriptor.type = SSAP_DESCRIPTOR_CLIENT_CONFIGURATION;
descriptor.operate_indication = SLE_UUID_TEST_OPERATION_INDICATION;
descriptor.value = (uint8_t *)osal_vmalloc(sizeof(ntf_value));
if (descriptor.value == NULL) {
osal_vfree(property.value);
return ERRCODE_SLE_FAIL;
}
if (memcpy_s(descriptor.value, sizeof(ntf_value), ntf_value, sizeof(ntf_value)) != EOK) {
osal_vfree(property.value);
osal_vfree(descriptor.value);
return ERRCODE_SLE_FAIL;
}
ret = ssaps_add_descriptor_sync(g_server_id, g_service_handle, g_property_handle, &descriptor);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle uart add descriptor fail, ret:%x\r\n", SLE_UART_SERVER_LOG, ret);
osal_vfree(property.value);
osal_vfree(descriptor.value);
return ERRCODE_SLE_FAIL;
}
osal_vfree(property.value);
osal_vfree(descriptor.value);
return ERRCODE_SLE_SUCCESS;
}
static errcode_t sle_uart_server_add(void)
{
errcode_t ret;
sle_uuid_t app_uuid = {0};
sample_at_log_print("%s sle uart add service in\r\n", SLE_UART_SERVER_LOG);
app_uuid.len = sizeof(g_sle_uuid_app_uuid);
if (memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid)) != EOK) {
return ERRCODE_SLE_FAIL;
}
ssaps_register_server(&app_uuid, &g_server_id);
if (sle_uuid_server_service_add() != ERRCODE_SLE_SUCCESS) {
ssaps_unregister_server(g_server_id);
return ERRCODE_SLE_FAIL;
}
if (sle_uuid_server_property_add() != ERRCODE_SLE_SUCCESS) {
ssaps_unregister_server(g_server_id);
return ERRCODE_SLE_FAIL;
}
sample_at_log_print("%s sle uart add service, server_id:%x, service_handle:%x, property_handle:%x\r\n",
SLE_UART_SERVER_LOG, g_server_id, g_service_handle, g_property_handle);
ret = ssaps_start_service(g_server_id, g_service_handle);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle uart add service fail, ret:%x\r\n", SLE_UART_SERVER_LOG, ret);
return ERRCODE_SLE_FAIL;
}
sample_at_log_print("%s sle uart add service out\r\n", SLE_UART_SERVER_LOG);
return ERRCODE_SLE_SUCCESS;
}
/* device通过uuid向host发送数据:report */
errcode_t sle_uart_server_send_report_by_uuid(const uint8_t *data, uint8_t len)
{
errcode_t ret;
ssaps_ntf_ind_by_uuid_t param = {0};
param.type = SSAP_PROPERTY_TYPE_VALUE;
param.start_handle = g_service_handle;
param.end_handle = g_property_handle;
param.value_len = len;
param.value = (uint8_t *)osal_vmalloc(len);
if (param.value == NULL) {
sample_at_log_print("%s send report new fail\r\n", SLE_UART_SERVER_LOG);
return ERRCODE_SLE_FAIL;
}
if (memcpy_s(param.value, param.value_len, data, len) != EOK) {
sample_at_log_print("%s send input report memcpy fail\r\n", SLE_UART_SERVER_LOG);
osal_vfree(param.value);
return ERRCODE_SLE_FAIL;
}
sle_uuid_setu2(SLE_UUID_SERVER_NTF_REPORT, &param.uuid);
ret = ssaps_notify_indicate_by_uuid(g_server_id, g_sle_conn_hdl, &param);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_send_report_by_uuid,ssaps_notify_indicate_by_uuid fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
osal_vfree(param.value);
return ret;
}
osal_vfree(param.value);
return ERRCODE_SLE_SUCCESS;
}
/* device通过handle向host发送数据:report */
errcode_t sle_uart_server_send_report_by_handle(const uint8_t *data, uint16_t len)
{
ssaps_ntf_ind_t param = {0};
uint8_t receive_buf = { 0 }; /* max receive length. */
param.handle = g_property_handle;
param.type = SSAP_PROPERTY_TYPE_VALUE;
param.value = receive_buf;
param.value_len = len;
if (memcpy_s(param.value, param.value_len, data, len) != EOK) {
return ERRCODE_SLE_FAIL;
}
return ssaps_notify_indicate(g_server_id, g_sle_conn_hdl, &param);
}
void sle_uart_server_sample_set_mcs(uint16_t conn_id)
{
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
if (sle_set_mcs(conn_id, 10) != 0) { // mcs10
osal_printk("%s sle_set_mcs fail\r\n", SLE_UART_SERVER_LOG);
return;
}
osal_printk("%s sle_set_mcs success\r\n", SLE_UART_SERVER_LOG);
#else
unused(conn_id);
// 非跑流sample使用原mcs参数
#endif
return;
}
static void sle_connect_state_changed_cbk(uint16_t conn_id, const sle_addr_t *addr,
sle_acb_state_t conn_state, sle_pair_state_t pair_state, sle_disc_reason_t disc_reason)
{
uint8_t sle_connect_state[] = "sle_dis_connect";
sample_at_log_print("%s connect state changed callback conn_id:0x%02x, conn_state:0x%x, pair_state:0x%x, \
disc_reason:0x%x\r\n", SLE_UART_SERVER_LOG,conn_id, conn_state, pair_state, disc_reason);
sample_at_log_print("%s connect state changed callback addr:%02x:**:**:**:%02x:%02x\r\n", SLE_UART_SERVER_LOG,
addr->addr, addr->addr);
if (conn_state == SLE_ACB_STATE_CONNECTED) {
g_sle_conn_hdl = conn_id;
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_low_latency_tx_enable();
osal_printk("%s sle_low_latency_tx_enable \r\n", SLE_UART_SERVER_LOG);
#endif
} else if (conn_state == SLE_ACB_STATE_DISCONNECTED) {
g_sle_conn_hdl = 0;
g_sle_pair_hdl = 0;
if (g_sle_uart_server_msg_queue != NULL) {
g_sle_uart_server_msg_queue(sle_connect_state, sizeof(sle_connect_state));
}
}
}
static void sle_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_t status)
{
sample_at_log_print("%s pair complete conn_id:%02x, status:%x\r\n", SLE_UART_SERVER_LOG,
conn_id, status);
sample_at_log_print("%s pair complete addr:%02x:**:**:**:%02x:%02x\r\n", SLE_UART_SERVER_LOG,
addr->addr, addr->addr);
g_sle_pair_hdl = conn_id + 1;
ssap_exchange_info_t parameter = { 0 };
parameter.mtu_size = 520;
parameter.version = 1;
ssaps_set_info(g_server_id, &parameter);
}
static errcode_t sle_conn_register_cbks(void)
{
errcode_t ret;
sle_connection_callbacks_t conn_cbks = {0};
conn_cbks.connect_state_changed_cb = sle_connect_state_changed_cbk;
conn_cbks.pair_complete_cb = sle_pair_complete_cbk;
ret = sle_connection_register_callbacks(&conn_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_conn_register_cbks,sle_connection_register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
uint16_t sle_uart_client_is_connected(void)
{
return g_sle_pair_hdl;
}
/* 初始化uuid server */
errcode_t sle_uart_server_init(ssaps_read_request_callback ssaps_read_callback, ssaps_write_request_callback
ssaps_write_callback)
{
errcode_t ret;
ret = sle_uart_announce_register_cbks();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_uart_announce_register_cbks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
ret = sle_conn_register_cbks();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_conn_register_cbks fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
ret = sle_ssaps_register_cbks(ssaps_read_callback, ssaps_write_callback);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_ssaps_register_cbks fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
sample_at_log_print("%s init ok\r\n", SLE_UART_SERVER_LOG);
return ERRCODE_SLE_SUCCESS;
}
errcode_t sle_enable_server_cbk(void)
{
errcode_t ret;
ret = sle_uart_server_add();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_uart_server_add fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
ret = sle_uart_server_adv_init();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_uart_server_adv_init fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
void sle_uart_server_register_msg(sle_uart_server_msg_queue sle_uart_server_msg)
{
g_sle_uart_server_msg_queue = sle_uart_server_msg;
}
</code></pre>
<p style="text-align: justify;"><strong>sle_uart_server_adv代码</strong></p>
<pre>
<code>#include "securec.h"
#include "errcode.h"
#include "osal_addr.h"
#include "product.h"
#include "sle_common.h"
#include "sle_uart_server.h"
#include "sle_device_manager.h"
#include "sle_device_discovery.h"
#include "sle_errcode.h"
#include "osal_debug.h"
#include "osal_task.h"
#include "string.h"
#include "sle_uart_server_adv.h"
/* sle device name */
#define NAME_MAX_LENGTH 16
/* 连接调度间隔12.5ms,单位125us */
#define SLE_CONN_INTV_MIN_DEFAULT 0x64
/* 连接调度间隔12.5ms,单位125us */
#define SLE_CONN_INTV_MAX_DEFAULT 0x64
/* 连接调度间隔25ms,单位125us */
#define SLE_ADV_INTERVAL_MIN_DEFAULT 0xC8
/* 连接调度间隔25ms,单位125us */
#define SLE_ADV_INTERVAL_MAX_DEFAULT 0xC8
/* 超时时间5000ms,单位10ms */
#define SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT 0x1F4
/* 超时时间4990ms,单位10ms */
#define SLE_CONN_MAX_LATENCY 0x1F3
/* 广播发送功率 */
#define SLE_ADV_TX_POWER10
/* 广播ID */
#define SLE_ADV_HANDLE_DEFAULT 1
/* 最大广播数据长度 */
#define SLE_ADV_DATA_LEN_MAX 251
/* 广播名称 */
static uint8_t sle_local_name = "sle_uart_server";
#define SLE_SERVER_INIT_DELAY_MS 1000
#define sample_at_log_print(fmt, args...) osal_printk(fmt, ##args)
#define SLE_UART_SERVER_LOG ""
static uint16_t sle_set_adv_local_name(uint8_t *adv_data, uint16_t max_len)
{
errno_t ret;
uint8_t index = 0;
uint8_t *local_name = sle_local_name;
uint8_t local_name_len = sizeof(sle_local_name) - 1;
sample_at_log_print("%s local_name_len = %d\r\n", SLE_UART_SERVER_LOG, local_name_len);
sample_at_log_print("%s local_name: ", SLE_UART_SERVER_LOG);
for (uint8_t i = 0; i < local_name_len; i++) {
sample_at_log_print("0x%02x ", local_name);
}
sample_at_log_print("\r\n");
adv_data = local_name_len + 1;
adv_data = SLE_ADV_DATA_TYPE_COMPLETE_LOCAL_NAME;
ret = memcpy_s(&adv_data, max_len - index, local_name, local_name_len);
if (ret != EOK) {
sample_at_log_print("%s memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
return (uint16_t)index + local_name_len;
}
static uint16_t sle_set_adv_data(uint8_t *adv_data)
{
size_t len = 0;
uint16_t idx = 0;
errno_tret = 0;
len = sizeof(struct sle_adv_common_value);
struct sle_adv_common_value adv_disc_level = {
.length = len - 1,
.type = SLE_ADV_DATA_TYPE_DISCOVERY_LEVEL,
.value = SLE_ANNOUNCE_LEVEL_NORMAL,
};
ret = memcpy_s(&adv_data, SLE_ADV_DATA_LEN_MAX - idx, &adv_disc_level, len);
if (ret != EOK) {
sample_at_log_print("%s adv_disc_level memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
idx += len;
len = sizeof(struct sle_adv_common_value);
struct sle_adv_common_value adv_access_mode = {
.length = len - 1,
.type = SLE_ADV_DATA_TYPE_ACCESS_MODE,
.value = 0,
};
ret = memcpy_s(&adv_data, SLE_ADV_DATA_LEN_MAX - idx, &adv_access_mode, len);
if (ret != EOK) {
sample_at_log_print("%s adv_access_mode memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
idx += len;
return idx;
}
static uint16_t sle_set_scan_response_data(uint8_t *scan_rsp_data)
{
uint16_t idx = 0;
errno_t ret;
size_t scan_rsp_data_len = sizeof(struct sle_adv_common_value);
struct sle_adv_common_value tx_power_level = {
.length = scan_rsp_data_len - 1,
.type = SLE_ADV_DATA_TYPE_TX_POWER_LEVEL,
.value = SLE_ADV_TX_POWER,
};
ret = memcpy_s(scan_rsp_data, SLE_ADV_DATA_LEN_MAX, &tx_power_level, scan_rsp_data_len);
if (ret != EOK) {
sample_at_log_print("%s sle scan response data memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
idx += scan_rsp_data_len;
/* set local name */
idx += sle_set_adv_local_name(&scan_rsp_data, SLE_ADV_DATA_LEN_MAX - idx);
return idx;
}
static int sle_set_default_announce_param(void)
{
errno_t ret;
sle_announce_param_t param = {0};
uint8_t index;
unsigned char local_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
param.announce_mode = SLE_ANNOUNCE_MODE_CONNECTABLE_SCANABLE;
param.announce_handle = SLE_ADV_HANDLE_DEFAULT;
param.announce_gt_role = SLE_ANNOUNCE_ROLE_T_CAN_NEGO;
param.announce_level = SLE_ANNOUNCE_LEVEL_NORMAL;
param.announce_channel_map = SLE_ADV_CHANNEL_MAP_DEFAULT;
param.announce_interval_min = SLE_ADV_INTERVAL_MIN_DEFAULT;
param.announce_interval_max = SLE_ADV_INTERVAL_MAX_DEFAULT;
param.conn_interval_min = SLE_CONN_INTV_MIN_DEFAULT;
param.conn_interval_max = SLE_CONN_INTV_MAX_DEFAULT;
param.conn_max_latency = SLE_CONN_MAX_LATENCY;
param.conn_supervision_timeout = SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT;
param.own_addr.type = 0;
ret = memcpy_s(param.own_addr.addr, SLE_ADDR_LEN, local_addr, SLE_ADDR_LEN);
if (ret != EOK) {
sample_at_log_print("%s sle_set_default_announce_param data memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
sample_at_log_print("%s sle_uart_local addr: ", SLE_UART_SERVER_LOG);
for (index = 0; index < SLE_ADDR_LEN; index++) {
sample_at_log_print("0x%02x ", param.own_addr.addr);
}
sample_at_log_print("\r\n");
return sle_set_announce_param(param.announce_handle, &param);
}
static int sle_set_default_announce_data(void)
{
errcode_t ret;
uint8_t announce_data_len = 0;
uint8_t seek_data_len = 0;
sle_announce_data_t data = {0};
uint8_t adv_handle = SLE_ADV_HANDLE_DEFAULT;
uint8_t announce_data = {0};
uint8_t seek_rsp_data = {0};
uint8_t data_index = 0;
announce_data_len = sle_set_adv_data(announce_data);
data.announce_data = announce_data;
data.announce_data_len = announce_data_len;
sample_at_log_print("%s data.announce_data_len = %d\r\n", SLE_UART_SERVER_LOG, data.announce_data_len);
sample_at_log_print("%s data.announce_data: ", SLE_UART_SERVER_LOG);
for (data_index = 0; data_index<data.announce_data_len; data_index++) {
sample_at_log_print("0x%02x ", data.announce_data);
}
sample_at_log_print("\r\n");
seek_data_len = sle_set_scan_response_data(seek_rsp_data);
data.seek_rsp_data = seek_rsp_data;
data.seek_rsp_data_len = seek_data_len;
sample_at_log_print("%s data.seek_rsp_data_len = %d\r\n", SLE_UART_SERVER_LOG, data.seek_rsp_data_len);
sample_at_log_print("%s data.seek_rsp_data: ", SLE_UART_SERVER_LOG);
for (data_index = 0; data_index<data.seek_rsp_data_len; data_index++) {
sample_at_log_print("0x%02x ", data.seek_rsp_data);
}
sample_at_log_print("\r\n");
ret = sle_set_announce_data(adv_handle, &data);
if (ret == ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s set announce data success.\r\n", SLE_UART_SERVER_LOG);
} else {
sample_at_log_print("%s set adv param fail.\r\n", SLE_UART_SERVER_LOG);
}
return ERRCODE_SLE_SUCCESS;
}
static void sle_announce_enable_cbk(uint32_t announce_id, errcode_t status)
{
sample_at_log_print("%s sle announce enable callback id:%02x, state:%x\r\n", SLE_UART_SERVER_LOG, announce_id,
status);
}
static void sle_announce_disable_cbk(uint32_t announce_id, errcode_t status)
{
sample_at_log_print("%s sle announce disable callback id:%02x, state:%x\r\n", SLE_UART_SERVER_LOG, announce_id,
status);
}
static void sle_announce_terminal_cbk(uint32_t announce_id)
{
sample_at_log_print("%s sle announce terminal callback id:%02x\r\n", SLE_UART_SERVER_LOG, announce_id);
}
static void sle_power_on_cbk(uint8_t status)
{
sample_at_log_print("sle power on: %d\r\n", status);
enable_sle();
}
static void sle_enable_cbk(uint8_t status)
{
sample_at_log_print("sle enable: %d\r\n", status);
sle_enable_server_cbk();
}
errcode_t sle_dev_register_cbks(void)
{
errcode_t ret = 0;
sle_dev_manager_callbacks_t dev_mgr_cbks = {0};
dev_mgr_cbks.sle_power_on_cb = sle_power_on_cbk;
dev_mgr_cbks.sle_enable_cb = sle_enable_cbk;
ret = sle_dev_manager_register_callbacks(&dev_mgr_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_dev_register_cbks,register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
#if (CORE_NUMS < 2)
enable_sle();
#endif
return ERRCODE_SLE_SUCCESS;
}
errcode_t sle_uart_announce_register_cbks(void)
{
errcode_t ret = 0;
sle_announce_seek_callbacks_t seek_cbks = {0};
seek_cbks.announce_enable_cb = sle_announce_enable_cbk;
seek_cbks.announce_disable_cb = sle_announce_disable_cbk;
seek_cbks.announce_terminal_cb = sle_announce_terminal_cbk;
ret = sle_announce_seek_register_callbacks(&seek_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_announce_register_cbks,register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
errcode_t sle_uart_server_adv_init(void)
{
errcode_t ret;
sle_set_default_announce_param();
sle_set_default_announce_data();
ret = sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_adv_init,sle_start_announce fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p style="text-align: justify;"><strong>sle_uart_client代码</strong></p>
<pre>
<code>#include "common_def.h"
#include "soc_osal.h"
#include "securec.h"
#include "product.h"
#include "bts_le_gap.h"
#include "bts_device_manager.h"
#include "sle_device_manager.h"
#include "sle_device_discovery.h"
#include "sle_connection_manager.h"
#include "sle_uart_client.h"
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
#include "sle_low_latency.h"
#endif
#define SLE_MTU_SIZE_DEFAULT 520
#define SLE_SEEK_INTERVAL_DEFAULT 100
#define SLE_SEEK_WINDOW_DEFAULT 100
#define UUID_16BIT_LEN 2
#define UUID_128BIT_LEN 16
#define SLE_UART_TASK_DELAY_MS 1000
#define SLE_UART_WAIT_SLE_CORE_READY_MS 5000
#define SLE_UART_RECV_CNT 1000
#define SLE_UART_LOW_LATENCY_2K 2000
#ifndef SLE_UART_SERVER_NAME
#define SLE_UART_SERVER_NAME "sle_uart_server"
#endif
#define SLE_UART_CLIENT_LOG ""
static ssapc_find_service_result_t g_sle_uart_find_service_result = { 0 };
static sle_dev_manager_callbacks_t g_sle_dev_mgr_cbk = { 0 };
static sle_announce_seek_callbacks_t g_sle_uart_seek_cbk = { 0 };
static sle_connection_callbacks_t g_sle_uart_connect_cbk = { 0 };
static ssapc_callbacks_t g_sle_uart_ssapc_cbk = { 0 };
static sle_addr_t g_sle_uart_remote_addr = { 0 };
ssapc_write_param_t g_sle_uart_send_param = { 0 };
uint16_t g_sle_uart_conn_id = 0;
uint16_t get_g_sle_uart_conn_id(void)
{
return g_sle_uart_conn_id;
}
ssapc_write_param_t *get_g_sle_uart_send_param(void)
{
return &g_sle_uart_send_param;
}
void sle_uart_start_scan(void)
{
sle_seek_param_t param = { 0 };
param.own_addr_type = 0;
param.filter_duplicates = 0;
param.seek_filter_policy = 0;
param.seek_phys = 1;
param.seek_type = 1;
param.seek_interval = SLE_SEEK_INTERVAL_DEFAULT;
param.seek_window = SLE_SEEK_WINDOW_DEFAULT;
sle_set_seek_param(&param);
sle_start_seek();
}
static void sle_uart_client_sample_sle_power_on_cbk(uint8_t status)
{
osal_printk("sle power on: %d.\r\n", status);
enable_sle();
}
static void sle_uart_client_sample_sle_enable_cbk(uint8_t status)
{
osal_printk("sle enable: %d.\r\n", status);
sle_uart_client_init(sle_uart_notification_cb, sle_uart_indication_cb);
sle_uart_start_scan();
}
static void sle_uart_client_sample_seek_enable_cbk(errcode_t status)
{
if (status != 0) {
osal_printk("%s sle_uart_client_sample_seek_enable_cbk,status error\r\n", SLE_UART_CLIENT_LOG);
}
}
static void sle_uart_client_sample_seek_result_info_cbk(sle_seek_result_info_t *seek_result_data)
{
osal_printk("%s sle uart scan data :%s\r\n", SLE_UART_CLIENT_LOG, seek_result_data->data);
if (seek_result_data == NULL) {
osal_printk("status error\r\n");
} else if (strstr((const char *)seek_result_data->data, SLE_UART_SERVER_NAME) != NULL) {
memcpy_s(&g_sle_uart_remote_addr, sizeof(sle_addr_t), &seek_result_data->addr, sizeof(sle_addr_t));
sle_stop_seek();
}
}
static void sle_uart_client_sample_seek_disable_cbk(errcode_t status)
{
if (status != 0) {
osal_printk("%s sle_uart_client_sample_seek_disable_cbk,status error = %x\r\n", SLE_UART_CLIENT_LOG, status);
} else {
sle_remove_paired_remote_device(&g_sle_uart_remote_addr);
sle_connect_remote_device(&g_sle_uart_remote_addr);
}
}
void sle_uart_client_sample_dev_cbk_register(void)
{
g_sle_dev_mgr_cbk.sle_power_on_cb = sle_uart_client_sample_sle_power_on_cbk;
g_sle_dev_mgr_cbk.sle_enable_cb = sle_uart_client_sample_sle_enable_cbk;
sle_dev_manager_register_callbacks(&g_sle_dev_mgr_cbk);
#if (CORE_NUMS < 2)
enable_sle();
#endif
}
static void sle_uart_client_sample_seek_cbk_register(void)
{
g_sle_uart_seek_cbk.seek_enable_cb = sle_uart_client_sample_seek_enable_cbk;
g_sle_uart_seek_cbk.seek_result_cb = sle_uart_client_sample_seek_result_info_cbk;
g_sle_uart_seek_cbk.seek_disable_cb = sle_uart_client_sample_seek_disable_cbk;
sle_announce_seek_register_callbacks(&g_sle_uart_seek_cbk);
}
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
static void sle_uart_client_sample_set_phy_param(void)
{
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
sle_set_phy_t param = {0};
param.tx_format = 1; // 0 :无线帧类型1(GFSK); 1:无线帧类型2(QPSK)
param.rx_format = 1; //
param.tx_phy = 2; // 0:1M; 1:2M; 2:4M;
param.rx_phy = 2; //
param.tx_pilot_density = 0x2;// 导频密度16:1
param.rx_pilot_density = 0x2;// 导频密度16:1
param.g_feedback = 0;
param.t_feedback = 0;
if (sle_set_phy_param(get_g_sle_uart_conn_id(), &param) != 0) {
osal_printk("%s sle_set_phy_param fail\r\n", SLE_UART_CLIENT_LOG);
return;
}
osal_printk("%s sle_set_phy_param success\r\n", SLE_UART_CLIENT_LOG);
#else
// 非跑流sample使用原phy参数
#endif
return;
}
#endif
static void sle_uart_client_sample_connect_state_changed_cbk(uint16_t conn_id, const sle_addr_t *addr,
sle_acb_state_t conn_state, sle_pair_state_t pair_state,
sle_disc_reason_t disc_reason)
{
unused(addr);
unused(pair_state);
osal_printk("%s conn state changed disc_reason:0x%x\r\n", SLE_UART_CLIENT_LOG, disc_reason);
g_sle_uart_conn_id = conn_id;
if (conn_state == SLE_ACB_STATE_CONNECTED) {
osal_printk("%s SLE_ACB_STATE_CONNECTED\r\n", SLE_UART_CLIENT_LOG);
if (pair_state == SLE_PAIR_NONE) {
sle_pair_remote_device(&g_sle_uart_remote_addr);
}
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_uart_client_sample_set_phy_param();
osal_msleep(SLE_UART_TASK_DELAY_MS);
sle_low_latency_rx_enable();
sle_low_latency_set(get_g_sle_uart_conn_id(), true, SLE_UART_LOW_LATENCY_2K);
#endif
osal_printk("%s sle_low_latency_rx_enable \r\n", SLE_UART_CLIENT_LOG);
} else if (conn_state == SLE_ACB_STATE_NONE) {
osal_printk("%s SLE_ACB_STATE_NONE\r\n", SLE_UART_CLIENT_LOG);
} else if (conn_state == SLE_ACB_STATE_DISCONNECTED) {
osal_printk("%s SLE_ACB_STATE_DISCONNECTED\r\n", SLE_UART_CLIENT_LOG);
sle_remove_paired_remote_device(&g_sle_uart_remote_addr);
sle_uart_start_scan();
} else {
osal_printk("%s status error\r\n", SLE_UART_CLIENT_LOG);
}
}
voidsle_uart_client_sample_pair_complete_cbk(uint16_t conn_id, const sle_addr_t *addr, errcode_t status)
{
osal_printk("%s pair complete conn_id:%d, addr:%02x***%02x%02x\n", SLE_UART_CLIENT_LOG, conn_id,
addr->addr, addr->addr, addr->addr);
if (status == 0) {
ssap_exchange_info_t info = {0};
info.mtu_size = SLE_MTU_SIZE_DEFAULT;
info.version = 1;
ssapc_exchange_info_req(0, g_sle_uart_conn_id, &info);
}
}
static void sle_uart_client_sample_connect_cbk_register(void)
{
g_sle_uart_connect_cbk.connect_state_changed_cb = sle_uart_client_sample_connect_state_changed_cbk;
g_sle_uart_connect_cbk.pair_complete_cb =sle_uart_client_sample_pair_complete_cbk;
sle_connection_register_callbacks(&g_sle_uart_connect_cbk);
}
static void sle_uart_client_sample_exchange_info_cbk(uint8_t client_id, uint16_t conn_id, ssap_exchange_info_t *param,
errcode_t status)
{
osal_printk("%s exchange_info_cbk,pair complete client id:%d status:%d\r\n",
SLE_UART_CLIENT_LOG, client_id, status);
osal_printk("%s exchange mtu, mtu size: %d, version: %d.\r\n", SLE_UART_CLIENT_LOG,
param->mtu_size, param->version);
ssapc_find_structure_param_t find_param = { 0 };
find_param.type = SSAP_FIND_TYPE_PROPERTY;
find_param.start_hdl = 1;
find_param.end_hdl = 0xFFFF;
ssapc_find_structure(0, conn_id, &find_param);
}
static void sle_uart_client_sample_find_structure_cbk(uint8_t client_id, uint16_t conn_id,
ssapc_find_service_result_t *service,
errcode_t status)
{
osal_printk("%s find structure cbk client: %d conn_id:%d status: %d \r\n", SLE_UART_CLIENT_LOG,
client_id, conn_id, status);
osal_printk("%s find structure start_hdl:, end_hdl:, uuid len:%d\r\n", SLE_UART_CLIENT_LOG,
service->start_hdl, service->end_hdl, service->uuid.len);
g_sle_uart_find_service_result.start_hdl = service->start_hdl;
g_sle_uart_find_service_result.end_hdl = service->end_hdl;
memcpy_s(&g_sle_uart_find_service_result.uuid, sizeof(sle_uuid_t), &service->uuid, sizeof(sle_uuid_t));
}
static void sle_uart_client_sample_find_property_cbk(uint8_t client_id, uint16_t conn_id,
ssapc_find_property_result_t *property, errcode_t status)
{
osal_printk("%s sle_uart_client_sample_find_property_cbk, client id: %d, conn id: %d, operate ind: %d, "
"descriptors count: %d status:%d property->handle %d\r\n", SLE_UART_CLIENT_LOG,
client_id, conn_id, property->operate_indication,
property->descriptors_count, status, property->handle);
g_sle_uart_send_param.handle = property->handle;
g_sle_uart_send_param.type = SSAP_PROPERTY_TYPE_VALUE;
}
static void sle_uart_client_sample_find_structure_cmp_cbk(uint8_t client_id, uint16_t conn_id,
ssapc_find_structure_result_t *structure_result,
errcode_t status)
{
unused(conn_id);
osal_printk("%s sle_uart_client_sample_find_structure_cmp_cbk,client id:%d status:%d type:%d uuid len:%d \r\n",
SLE_UART_CLIENT_LOG, client_id, status, structure_result->type, structure_result->uuid.len);
}
static void sle_uart_client_sample_write_cfm_cb(uint8_t client_id, uint16_t conn_id,
ssapc_write_result_t *write_result, errcode_t status)
{
osal_printk("%s sle_uart_client_sample_write_cfm_cb, conn_id:%d client id:%d status:%d handle:%02x type:%02x\r\n",
SLE_UART_CLIENT_LOG, conn_id, client_id, status, write_result->handle, write_result->type);
}
static void sle_uart_client_sample_ssapc_cbk_register(ssapc_notification_callback notification_cb,
ssapc_notification_callback indication_cb)
{
g_sle_uart_ssapc_cbk.exchange_info_cb = sle_uart_client_sample_exchange_info_cbk;
g_sle_uart_ssapc_cbk.find_structure_cb = sle_uart_client_sample_find_structure_cbk;
g_sle_uart_ssapc_cbk.ssapc_find_property_cbk = sle_uart_client_sample_find_property_cbk;
g_sle_uart_ssapc_cbk.find_structure_cmp_cb = sle_uart_client_sample_find_structure_cmp_cbk;
g_sle_uart_ssapc_cbk.write_cfm_cb = sle_uart_client_sample_write_cfm_cb;
g_sle_uart_ssapc_cbk.notification_cb = notification_cb;
g_sle_uart_ssapc_cbk.indication_cb = indication_cb;
ssapc_register_callbacks(&g_sle_uart_ssapc_cbk);
}
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
#include "uart.h"
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
#include "tcxo.h"
static uint32_t g_sle_recv_count = 0;
static uint64_t g_sle_recv_start_time = 0;
static uint64_t g_sle_recv_end_time = 0;
static uint64_t g_sle_recv_param = { 0 };
#endif
void sle_uart_client_low_latency_recv_data_cbk(uint16_t len, uint8_t *value)
{
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
static uint64_t sle_throughput = 0;
if (value == NULL || len == 0) {
return;
}
g_sle_recv_count++;
if (g_sle_recv_count == 1) {
g_sle_recv_start_time = uapi_tcxo_get_us();
} else if (g_sle_recv_count == SLE_UART_RECV_CNT) {
g_sle_recv_end_time = uapi_tcxo_get_us();
g_sle_recv_param = g_sle_recv_count;
g_sle_recv_param = g_sle_recv_end_time - g_sle_recv_start_time;
g_sle_recv_count = 0;
g_sle_recv_end_time = 0;
g_sle_recv_start_time = 0;
uint64_t tmp;
tmp = g_sle_recv_param / 1000; // 1000 代表us转化成ms
sle_throughput = len * SLE_UART_RECV_CNT * 8 / tmp; // 8 代表1byte = 8bit
osal_printk("recv_len = %d, recv_count = %llu\r\n", len, g_sle_recv_param);
osal_printk("diff time:%lluus, throughput:%llukbps\r\n", g_sle_recv_param, sle_throughput);
}
#else
osal_printk("uart recv low latency data:\r\n");
uapi_uart_write(CONFIG_SLE_UART_BUS, value, len, 0);
#endif
}
void sle_uart_client_low_latency_recv_data_cbk_register(void)
{
osal_printk("uart recv low latency data register success\r\n");
sle_low_latency_rx_callbacks_t cbk_func = { NULL };
cbk_func.low_latency_rx_cb = (low_latency_general_rx_callback)sle_uart_client_low_latency_recv_data_cbk;
sle_low_latency_rx_register_callbacks(&cbk_func);
}
#endif
void sle_uart_client_init(ssapc_notification_callback notification_cb, ssapc_indication_callback indication_cb)
{
sle_uart_client_sample_seek_cbk_register();
sle_uart_client_sample_connect_cbk_register();
sle_uart_client_sample_ssapc_cbk_register(notification_cb, indication_cb);
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_uart_client_low_latency_recv_data_cbk_register();
#endif
}
</code></pre>
<p style="text-align: justify;"><strong>sle_uart代码</strong></p>
<pre>
<code>#include "common_def.h"
#include "soc_osal.h"
#include "app_init.h"
#include "pinctrl.h"
#include "uart.h"
#include "pm_clock.h"
#include "sle_low_latency.h"
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_SERVER)
#include "securec.h"
#include "sle_uart_server.h"
#include "sle_uart_server_adv.h"
#include "sle_device_discovery.h"
#include "sle_errcode.h"
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT)
#define SLE_UART_TASK_STACK_SIZE 0x600
#include "sle_connection_manager.h"
#include "sle_ssap_client.h"
#include "sle_uart_client.h"
#endif/* CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT */
#define SLE_UART_TASK_PRIO 28
#define SLE_UART_TASK_DURATION_MS 2000
#define SLE_UART_BAUDRATE 115200
#define SLE_UART_TRANSFER_SIZE 256
static uint8_t g_app_uart_rx_buff = { 0 };
static uart_buffer_config_t g_app_uart_buffer_config = {
.rx_buffer = g_app_uart_rx_buff,
.rx_buffer_size = SLE_UART_TRANSFER_SIZE
};
static void uart_init_pin(void)
{
if (CONFIG_SLE_UART_BUS == 0) {
uapi_pin_set_mode(CONFIG_UART_TXD_PIN, HAL_PIO_UART_L0_TXD);
uapi_pin_set_mode(CONFIG_UART_RXD_PIN, HAL_PIO_UART_L0_RXD);
}else if (CONFIG_SLE_UART_BUS == 1) {
uapi_pin_set_mode(CONFIG_UART_TXD_PIN, HAL_PIO_UART_H0_TXD);
uapi_pin_set_mode(CONFIG_UART_RXD_PIN, HAL_PIO_UART_H0_RXD);
}else if (CONFIG_SLE_UART_BUS == 2) {
uapi_pin_set_mode(CONFIG_UART_TXD_PIN, HAL_PIO_UART_L1_TXD);
uapi_pin_set_mode(CONFIG_UART_RXD_PIN, HAL_PIO_UART_L1_RXD);
}
}
static void uart_init_config(void)
{
uart_attr_t attr = {
.baud_rate = SLE_UART_BAUDRATE,
.data_bits = UART_DATA_BIT_8,
.stop_bits = UART_STOP_BIT_1,
.parity = UART_PARITY_NONE
};
uart_pin_config_t pin_config = {
.tx_pin = CONFIG_UART_TXD_PIN,
.rx_pin = CONFIG_UART_RXD_PIN,
.cts_pin = PIN_NONE,
.rts_pin = PIN_NONE
};
uapi_uart_deinit(CONFIG_SLE_UART_BUS);
uapi_uart_init(CONFIG_SLE_UART_BUS, &pin_config, &attr, NULL, &g_app_uart_buffer_config);
}
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_SERVER)
#define SLE_UART_SERVER_DELAY_COUNT 5
#define SLE_UART_TASK_STACK_SIZE 0x1200
#define SLE_ADV_HANDLE_DEFAULT 1
#define SLE_UART_SERVER_MSG_QUEUE_LEN 5
#define SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE32
#define SLE_UART_SERVER_QUEUE_DELAY 0xFFFFFFFF
#define SLE_UART_SERVER_BUFF_MAX_SIZE 800
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
#define SLE_UART_SERVER_SEND_BUFF_MAX_LEN 250
#else
#define SLE_UART_SERVER_SEND_BUFF_MAX_LEN 40
#endif
unsigned long g_sle_uart_server_msgqueue_id;
#define SLE_UART_SERVER_LOG ""
static void ssaps_server_read_request_cbk(uint8_t server_id, uint16_t conn_id, ssaps_req_read_cb_t *read_cb_para,
errcode_t status)
{
osal_printk("%s ssaps read request cbk callback server_id:%x, conn_id:%x, handle:%x, status:%x\r\n",
SLE_UART_SERVER_LOG, server_id, conn_id, read_cb_para->handle, status);
}
static void ssaps_server_write_request_cbk(uint8_t server_id, uint16_t conn_id, ssaps_req_write_cb_t *write_cb_para,
errcode_t status)
{
osal_printk("%s ssaps write request callback cbk server_id:%x, conn_id:%x, handle:%x, status:%x\r\n",
SLE_UART_SERVER_LOG, server_id, conn_id, write_cb_para->handle, status);
if ((write_cb_para->length > 0) && write_cb_para->value) {
uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)write_cb_para->value, write_cb_para->length, 0);
}
}
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
uint8_t g_buff = {0};
uint16_t g_uart_buff_len = 0;
uint8_t g_buff_data_valid = 0;
uint8_t g_mcs_flag = 0;
#endif
static void sle_uart_server_read_int_handler(const void *buffer, uint16_t length, bool error)
{
unused(error);
if (sle_uart_client_is_connected()) {
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
g_buff_data_valid = 1;
g_uart_buff_len = 0;
(void)memcpy_s(g_buff, SLE_UART_SERVER_SEND_BUFF_MAX_LEN, buffer, length);
g_uart_buff_len = length;
#else
sle_uart_server_send_report_by_handle(buffer, length);
#endif
} else {
osal_printk("%s sle client is not connected! \r\n", SLE_UART_SERVER_LOG);
}
}
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
uint8_t *sle_uart_low_latency_tx_cbk(uint16_t *len)
{
#ifdef CONFIG_SAMPLE_SUPPORT_PERFORMANCE_TYPE
if (g_mcs_flag == 0) {
sle_uart_server_sample_set_mcs(get_connect_id());
}
g_uart_buff_len = SLE_UART_SERVER_SEND_BUFF_MAX_LEN;
g_buff_data_valid = 1;
g_mcs_flag = 1;
#endif
if (g_buff_data_valid == 0) {
return NULL;
}
if (g_uart_buff_len == 0) {
return NULL;
}
*len = g_uart_buff_len;
g_buff_data_valid = 0;
return g_buff;
}
void sle_uart_low_latency_tx_cbk_register(void)
{
sle_low_latency_tx_callbacks_t cbk_func = {0};
cbk_func.low_latency_tx_cb = sle_uart_low_latency_tx_cbk;
sle_low_latency_tx_register_callbacks(&cbk_func);
}
#endif
static void sle_uart_server_create_msgqueue(void)
{
if (osal_msg_queue_create("sle_uart_server_msgqueue", SLE_UART_SERVER_MSG_QUEUE_LEN, \
(unsigned long *)&g_sle_uart_server_msgqueue_id, 0, SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE) != OSAL_SUCCESS) {
osal_printk("^%s sle_uart_server_create_msgqueue message queue create failed!\n", SLE_UART_SERVER_LOG);
}
}
static void sle_uart_server_delete_msgqueue(void)
{
osal_msg_queue_delete(g_sle_uart_server_msgqueue_id);
}
static void sle_uart_server_write_msgqueue(uint8_t *buffer_addr, uint16_t buffer_size)
{
osal_msg_queue_write_copy(g_sle_uart_server_msgqueue_id, (void *)buffer_addr, \
(uint32_t)buffer_size, 0);
}
static int32_t sle_uart_server_receive_msgqueue(uint8_t *buffer_addr, uint32_t *buffer_size)
{
return osal_msg_queue_read_copy(g_sle_uart_server_msgqueue_id, (void *)buffer_addr, \
buffer_size, SLE_UART_SERVER_QUEUE_DELAY);
}
static void sle_uart_server_rx_buf_init(uint8_t *buffer_addr, uint32_t *buffer_size)
{
*buffer_size = SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE;
(void)memset_s(buffer_addr, *buffer_size, 0, *buffer_size);
}
static void *sle_uart_server_task(const char *arg)
{
unused(arg);
uint8_t rx_buf = {0};
uint32_t rx_length = SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE;
uint8_t sle_connect_state[] = "sle_dis_connect";
sle_uart_server_create_msgqueue();
sle_uart_server_register_msg(sle_uart_server_write_msgqueue);
sle_uart_server_init(ssaps_server_read_request_cbk, ssaps_server_write_request_cbk);
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_uart_low_latency_tx_cbk_register();
#endif
/* UART pinmux. */
uart_init_pin();
/* UART init config. */
uart_init_config();
uapi_uart_unregister_rx_callback(CONFIG_SLE_UART_BUS);
errcode_t ret = uapi_uart_register_rx_callback(CONFIG_SLE_UART_BUS,
UART_RX_CONDITION_FULL_OR_IDLE,
1, sle_uart_server_read_int_handler);
if (ret != ERRCODE_SUCC) {
osal_printk("%s Register uart callback fail.[%x]\r\n", SLE_UART_SERVER_LOG, ret);
return NULL;
}
while (1) {
sle_uart_server_rx_buf_init(rx_buf, &rx_length);
sle_uart_server_receive_msgqueue(rx_buf, &rx_length);
if (strncmp((const char *)rx_buf, (const char *)sle_connect_state, sizeof(sle_connect_state)) == 0) {
ret = sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
if (ret != ERRCODE_SLE_SUCCESS) {
osal_printk("%s sle_connect_state_changed_cbk,sle_start_announce fail :%02x\r\n",
SLE_UART_SERVER_LOG, ret);
}
}
osal_msleep(SLE_UART_TASK_DURATION_MS);
}
sle_uart_server_delete_msgqueue();
return NULL;
}
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT)
void sle_uart_notification_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
errcode_t status)
{
unused(client_id);
unused(conn_id);
unused(status);
osal_printk("\n sle uart recived data : %s\r\n", data->data);
uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data->data), data->data_len, 0);
}
void sle_uart_indication_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
errcode_t status)
{
unused(client_id);
unused(conn_id);
unused(status);
osal_printk("\n sle uart recived data : %s\r\n", data->data);
uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data->data), data->data_len, 0);
}
static void sle_uart_client_read_int_handler(const void *buffer, uint16_t length, bool error)
{
unused(error);
ssapc_write_param_t *sle_uart_send_param = get_g_sle_uart_send_param();
uint16_t g_sle_uart_conn_id = get_g_sle_uart_conn_id();
sle_uart_send_param->data_len = length;
sle_uart_send_param->data = (uint8_t *)buffer;
ssapc_write_req(0, g_sle_uart_conn_id, sle_uart_send_param);
}
static void *sle_uart_client_task(const char *arg)
{
unused(arg);
/* UART pinmux. */
uart_init_pin();
/* UART init config. */
uart_init_config();
uapi_uart_unregister_rx_callback(CONFIG_SLE_UART_BUS);
errcode_t ret = uapi_uart_register_rx_callback(CONFIG_SLE_UART_BUS,
UART_RX_CONDITION_FULL_OR_IDLE,
1, sle_uart_client_read_int_handler);
if (ret != ERRCODE_SUCC) {
osal_printk("Register uart callback fail.");
return NULL;
}
return NULL;
}
#endif/* CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT */
static void sle_uart_entry(void)
{
osal_task *task_handle = NULL;
if (uapi_clock_control(CLOCK_CONTROL_FREQ_LEVEL_CONFIG, CLOCK_FREQ_LEVEL_HIGH) == ERRCODE_SUCC) {
osal_printk("Clock config succ.\r\n");
} else {
osal_printk("Clock config fail.\r\n");
}
osal_kthread_lock();
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_SERVER)
sle_dev_register_cbks();
task_handle = osal_kthread_create((osal_kthread_handler)sle_uart_server_task, 0, "SLEUartServerTask",
SLE_UART_TASK_STACK_SIZE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT)
sle_uart_client_sample_dev_cbk_register();
task_handle = osal_kthread_create((osal_kthread_handler)sle_uart_client_task, 0, "SLEUartDongleTask",
SLE_UART_TASK_STACK_SIZE);
#endif /* CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT */
if (task_handle != NULL) {
osal_kthread_set_priority(task_handle, SLE_UART_TASK_PRIO);
}
osal_kthread_unlock();
}
/* Run the sle_uart_entry. */
app_run(sle_uart_entry);</code></pre>
<p style="text-align: justify;"><strong><span style="font-size:18px;">代码解读</span></strong></p>
<p>代码首先进入sle_uart.c的sle_uart_entry任务入口,代码如下</p>
<pre>
<code>static void sle_uart_entry(void)
{
osal_task *task_handle = NULL;
if (uapi_clock_control(CLOCK_CONTROL_FREQ_LEVEL_CONFIG, CLOCK_FREQ_LEVEL_HIGH) == ERRCODE_SUCC) {
osal_printk("Clock config succ.\r\n");
} else {
osal_printk("Clock config fail.\r\n");
}
osal_kthread_lock();
#if defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_SERVER)
sle_dev_register_cbks();
task_handle = osal_kthread_create((osal_kthread_handler)sle_uart_server_task, 0, "SLEUartServerTask",
SLE_UART_TASK_STACK_SIZE);
#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT)
sle_uart_client_sample_dev_cbk_register();
task_handle = osal_kthread_create((osal_kthread_handler)sle_uart_client_task, 0, "SLEUartDongleTask",
SLE_UART_TASK_STACK_SIZE);
#endif /* CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT */
if (task_handle != NULL) {
osal_kthread_set_priority(task_handle, SLE_UART_TASK_PRIO);
}
osal_kthread_unlock();
}
/* Run the sle_uart_entry. */
app_run(sle_uart_entry);
</code></pre>
<p style="text-align: justify;">在这个过程中,需要完成Server和Client的初始化,并分别创建Server任务和Client任务</p>
<p style="text-align: justify;"><strong><span style="font-size:16px;">Server任务</span></strong></p>
<p style="text-align: justify;">对于Server任务,需要完成:</p>
<p>①注册SLE设备管理回调函数;②消息队列创建;③向消息队列中写入消息;④完成Server的uuid初始化;⑤如果定义了低时延,需注册低时延TX回调方法;⑥初始化uart引脚;⑦初始化uart;⑧注册接收回调函数</p>
<p >具体代码实现如下:</p>
<pre>
<code>static void *sle_uart_server_task(const char *arg)
{
unused(arg);
uint8_t rx_buf = {0};
uint32_t rx_length = SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE;
uint8_t sle_connect_state[] = "sle_dis_connect";
sle_uart_server_create_msgqueue();
sle_uart_server_register_msg(sle_uart_server_write_msgqueue);
sle_uart_server_init(ssaps_server_read_request_cbk, ssaps_server_write_request_cbk);
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_uart_low_latency_tx_cbk_register();
#endif
/* UART pinmux. */
uart_init_pin();
/* UART init config. */
uart_init_config();
uapi_uart_unregister_rx_callback(CONFIG_SLE_UART_BUS);
errcode_t ret = uapi_uart_register_rx_callback(CONFIG_SLE_UART_BUS,
UART_RX_CONDITION_FULL_OR_IDLE,
1, sle_uart_server_read_int_handler);
if (ret != ERRCODE_SUCC) {
osal_printk("%s Register uart callback fail.[%x]\r\n", SLE_UART_SERVER_LOG, ret);
return NULL;
}
while (1) {
sle_uart_server_rx_buf_init(rx_buf, &rx_length);
sle_uart_server_receive_msgqueue(rx_buf, &rx_length);
if (strncmp((const char *)rx_buf, (const char *)sle_connect_state, sizeof(sle_connect_state)) == 0) {
ret = sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
if (ret != ERRCODE_SLE_SUCCESS) {
osal_printk("%s sle_connect_state_changed_cbk,sle_start_announce fail :%02x\r\n",
SLE_UART_SERVER_LOG, ret);
}
}
osal_msleep(SLE_UART_TASK_DURATION_MS);
}
sle_uart_server_delete_msgqueue();
return NULL;
}
</code></pre>
<p style="text-align: justify;">1. 注册SLE设备管理回调函数</p>
<p>在这个过程中,首先使用sle_power_on_cbk使能SLE协议栈,接着使用sle_enable_cbk完成Server使能(包括添加Server和Server的ADV初始化)</p>
<p >具体代码如下:</p>
<pre>
<code>errcode_t sle_dev_register_cbks(void)
{
errcode_t ret = 0;
sle_dev_manager_callbacks_t dev_mgr_cbks = {0};
dev_mgr_cbks.sle_power_on_cb = sle_power_on_cbk;
dev_mgr_cbks.sle_enable_cb = sle_enable_cbk;
ret = sle_dev_manager_register_callbacks(&dev_mgr_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_dev_register_cbks,register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
#if (CORE_NUMS < 2)
enable_sle();
#endif
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>1.1. 使能SLE协议栈</p>
<pre>
<code>static void sle_power_on_cbk(uint8_t status)
{
sample_at_log_print("sle power on: %d\r\n", status);
enable_sle();
}
</code></pre>
<p>1.2. 使能Server</p>
<p style="text-align: justify;">对于使能Server,需要完成Server添加(包括注册ssap服务端、添加ssap服务、添加ssap特征、添加ssap特征描述符),以及Server的ADV初始化(包括设置设备公开参数、设置设备公开数据,最后开始设备公开)</p>
<pre>
<code>static void sle_enable_cbk(uint8_t status)
{
sample_at_log_print("sle enable: %d\r\n", status);
sle_enable_server_cbk();
}
</code></pre>
<p>1.2.1. Server添加</p>
<p>具体代码如下:</p>
<pre>
<code>static errcode_t sle_uart_server_add(void)
{
errcode_t ret;
sle_uuid_t app_uuid = {0};
sample_at_log_print("%s sle uart add service in\r\n", SLE_UART_SERVER_LOG);
app_uuid.len = sizeof(g_sle_uuid_app_uuid);
if (memcpy_s(app_uuid.uuid, app_uuid.len, g_sle_uuid_app_uuid, sizeof(g_sle_uuid_app_uuid)) != EOK) {
return ERRCODE_SLE_FAIL;
}
ssaps_register_server(&app_uuid, &g_server_id);
if (sle_uuid_server_service_add() != ERRCODE_SLE_SUCCESS) {
ssaps_unregister_server(g_server_id);
return ERRCODE_SLE_FAIL;
}
if (sle_uuid_server_property_add() != ERRCODE_SLE_SUCCESS) {
ssaps_unregister_server(g_server_id);
return ERRCODE_SLE_FAIL;
}
sample_at_log_print("%s sle uart add service, server_id:%x, service_handle:%x, property_handle:%x\r\n",
SLE_UART_SERVER_LOG, g_server_id, g_service_handle, g_property_handle);
ret = ssaps_start_service(g_server_id, g_service_handle);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle uart add service fail, ret:%x\r\n", SLE_UART_SERVER_LOG, ret);
return ERRCODE_SLE_FAIL;
}
sample_at_log_print("%s sle uart add service out\r\n", SLE_UART_SERVER_LOG);
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>1.2.2. Server的ADV初始化</p>
<p>具体代码如下:</p>
<pre>
<code>errcode_t sle_uart_server_adv_init(void)
{
errcode_t ret;
sle_set_default_announce_param();
sle_set_default_announce_data();
ret = sle_start_announce(SLE_ADV_HANDLE_DEFAULT);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_adv_init,sle_start_announce fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>1.2.2.1. 设置设备公开参数</p>
<pre>
<code>static int sle_set_default_announce_param(void)
{
errno_t ret;
sle_announce_param_t param = {0};
uint8_t index;
unsigned char local_addr = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
param.announce_mode = SLE_ANNOUNCE_MODE_CONNECTABLE_SCANABLE;
param.announce_handle = SLE_ADV_HANDLE_DEFAULT;
param.announce_gt_role = SLE_ANNOUNCE_ROLE_T_CAN_NEGO;
param.announce_level = SLE_ANNOUNCE_LEVEL_NORMAL;
param.announce_channel_map = SLE_ADV_CHANNEL_MAP_DEFAULT;
param.announce_interval_min = SLE_ADV_INTERVAL_MIN_DEFAULT;
param.announce_interval_max = SLE_ADV_INTERVAL_MAX_DEFAULT;
param.conn_interval_min = SLE_CONN_INTV_MIN_DEFAULT;
param.conn_interval_max = SLE_CONN_INTV_MAX_DEFAULT;
param.conn_max_latency = SLE_CONN_MAX_LATENCY;
param.conn_supervision_timeout = SLE_CONN_SUPERVISION_TIMEOUT_DEFAULT;
param.own_addr.type = 0;
ret = memcpy_s(param.own_addr.addr, SLE_ADDR_LEN, local_addr, SLE_ADDR_LEN);
if (ret != EOK) {
sample_at_log_print("%s sle_set_default_announce_param data memcpy fail\r\n", SLE_UART_SERVER_LOG);
return 0;
}
sample_at_log_print("%s sle_uart_local addr: ", SLE_UART_SERVER_LOG);
for (index = 0; index < SLE_ADDR_LEN; index++) {
sample_at_log_print("0x%02x ", param.own_addr.addr);
}
sample_at_log_print("\r\n");
return sle_set_announce_param(param.announce_handle, &param);
}
</code></pre>
<p>1.2.2.2. 设置设备公开数据</p>
<pre>
<code>static int sle_set_default_announce_data(void)
{
errcode_t ret;
uint8_t announce_data_len = 0;
uint8_t seek_data_len = 0;
sle_announce_data_t data = {0};
uint8_t adv_handle = SLE_ADV_HANDLE_DEFAULT;
uint8_t announce_data = {0};
uint8_t seek_rsp_data = {0};
uint8_t data_index = 0;
announce_data_len = sle_set_adv_data(announce_data);
data.announce_data = announce_data;
data.announce_data_len = announce_data_len;
sample_at_log_print("%s data.announce_data_len = %d\r\n", SLE_UART_SERVER_LOG, data.announce_data_len);
sample_at_log_print("%s data.announce_data: ", SLE_UART_SERVER_LOG);
for (data_index = 0; data_index<data.announce_data_len; data_index++) {
sample_at_log_print("0x%02x ", data.announce_data);
}
sample_at_log_print("\r\n");
seek_data_len = sle_set_scan_response_data(seek_rsp_data);
data.seek_rsp_data = seek_rsp_data;
data.seek_rsp_data_len = seek_data_len;
sample_at_log_print("%s data.seek_rsp_data_len = %d\r\n", SLE_UART_SERVER_LOG, data.seek_rsp_data_len);
sample_at_log_print("%s data.seek_rsp_data: ", SLE_UART_SERVER_LOG);
for (data_index = 0; data_index<data.seek_rsp_data_len; data_index++) {
sample_at_log_print("0x%02x ", data.seek_rsp_data);
}
sample_at_log_print("\r\n");
ret = sle_set_announce_data(adv_handle, &data);
if (ret == ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s set announce data success.\r\n", SLE_UART_SERVER_LOG);
} else {
sample_at_log_print("%s set adv param fail.\r\n", SLE_UART_SERVER_LOG);
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p style="text-align: justify;">2. SLE的Server任务创建</p>
<p>在这一步中,需要完成消息队列创建;向消息队列中写入消息;完成Server的uuid初始化;如果定义了低时延,需注册低时延TX回调方法;初始化uart引脚;初始化uart;注册接收回调函数</p>
<p >2.1. 消息队列创建</p>
<pre>
<code>static void sle_uart_server_create_msgqueue(void)
{
if (osal_msg_queue_create("sle_uart_server_msgqueue", SLE_UART_SERVER_MSG_QUEUE_LEN, \
(unsigned long *)&g_sle_uart_server_msgqueue_id, 0, SLE_UART_SERVER_MSG_QUEUE_MAX_SIZE) != OSAL_SUCCESS) {
osal_printk("^%s sle_uart_server_create_msgqueue message queue create failed!\n", SLE_UART_SERVER_LOG);
}
}
</code></pre>
<p>2.2. 向消息队列中写入消息</p>
<p>这一步用来输出消息队列地址信息</p>
<pre>
<code>sle_uart_server_register_msg(sle_uart_server_write_msgqueue);</code></pre>
<p>2.3. 完成Server的uuid初始化</p>
<p >在这一步中,需要完成注册SLE设备发现回调函数、注册SLE连接管理回调函数、注册ssap Server回调函数</p>
<p >整体代码如下:</p>
<pre>
<code>errcode_t sle_uart_server_init(ssaps_read_request_callback ssaps_read_callback, ssaps_write_request_callback
ssaps_write_callback)
{
errcode_t ret;
ret = sle_uart_announce_register_cbks();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_uart_announce_register_cbks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
ret = sle_conn_register_cbks();
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_conn_register_cbks fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
ret = sle_ssaps_register_cbks(ssaps_read_callback, ssaps_write_callback);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_server_init,sle_ssaps_register_cbks fail :%x\r\n", SLE_UART_SERVER_LOG, ret);
return ret;
}
sample_at_log_print("%s init ok\r\n", SLE_UART_SERVER_LOG);
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p style="text-align: justify;">2.3.1. 注册SLE设备发现回调函数</p>
<pre>
<code>errcode_t sle_uart_announce_register_cbks(void)
{
errcode_t ret = 0;
sle_announce_seek_callbacks_t seek_cbks = {0};
seek_cbks.announce_enable_cb = sle_announce_enable_cbk;
seek_cbks.announce_disable_cb = sle_announce_disable_cbk;
seek_cbks.announce_terminal_cb = sle_announce_terminal_cbk;
ret = sle_announce_seek_register_callbacks(&seek_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_uart_announce_register_cbks,register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>2.3.2. 注册SLE连接管理回调函数</p>
<p>在这里需要定义SLE连接状态变化的回调函数和匹配完成的回调函数</p>
<pre>
<code>static errcode_t sle_conn_register_cbks(void)
{
errcode_t ret;
sle_connection_callbacks_t conn_cbks = {0};
conn_cbks.connect_state_changed_cb = sle_connect_state_changed_cbk;
conn_cbks.pair_complete_cb = sle_pair_complete_cbk;
ret = sle_connection_register_callbacks(&conn_cbks);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_conn_register_cbks,sle_connection_register_callbacks fail :%x\r\n",
SLE_UART_SERVER_LOG, ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>2.3.3. 注册ssap Server回调函数</p>
<p>在这一步中,需要完成ssap添加服务、添加特征值、特征描述符、交换mtu的操作,并定义读请求和写请求时的回调函数</p>
<pre>
<code>static errcode_t sle_ssaps_register_cbks(ssaps_read_request_callback ssaps_read_callback, ssaps_write_request_callback
ssaps_write_callback)
{
errcode_t ret;
ssaps_callbacks_t ssaps_cbk = {0};
ssaps_cbk.add_service_cb = ssaps_add_service_cbk;
ssaps_cbk.add_property_cb = ssaps_add_property_cbk;
ssaps_cbk.add_descriptor_cb = ssaps_add_descriptor_cbk;
ssaps_cbk.start_service_cb = ssaps_start_service_cbk;
ssaps_cbk.delete_all_service_cb = ssaps_delete_all_service_cbk;
ssaps_cbk.mtu_changed_cb = ssaps_mtu_changed_cbk;
ssaps_cbk.read_request_cb = ssaps_read_callback;
ssaps_cbk.write_request_cb = ssaps_write_callback;
ret = ssaps_register_callbacks(&ssaps_cbk);
if (ret != ERRCODE_SLE_SUCCESS) {
sample_at_log_print("%s sle_ssaps_register_cbks,ssaps_register_callbacks fail :%x\r\n", SLE_UART_SERVER_LOG,
ret);
return ret;
}
return ERRCODE_SLE_SUCCESS;
}
</code></pre>
<p>2.4. 注册低时延TX回调方法</p>
<pre>
<code>void sle_uart_low_latency_tx_cbk_register(void)
{
sle_low_latency_tx_callbacks_t cbk_func = {0};
cbk_func.low_latency_tx_cb = sle_uart_low_latency_tx_cbk;
sle_low_latency_tx_register_callbacks(&cbk_func);
}
</code></pre>
<p>2.5. 初始化uart引脚</p>
<p >在这一步中,需要设置指定串口号以及TX/RX引脚</p>
<p >2.6. 初始化uart</p>
<p >在这一步中,设置波特率、数据位、停止位,并完成SLE的串口初始化</p>
<p >2.7. 注册接收回调函数,完成Server的任务创建</p>
<p style="text-align: justify;"><strong><span style="font-size:16px;">Client任务</span></strong></p>
<p>对于Client任务,需要完成:</p>
<p >①注册SLE设备管理回调函数;②初始化uart引脚;③初始化uart;④注册接收回调函数</p>
<p >具体代码实现如下:</p>
<pre>
<code>#elif defined(CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT)
void sle_uart_notification_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
errcode_t status)
{
unused(client_id);
unused(conn_id);
unused(status);
osal_printk("\n sle uart recived data : %s\r\n", data->data);
uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data->data), data->data_len, 0);
}
void sle_uart_indication_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
errcode_t status)
{
unused(client_id);
unused(conn_id);
unused(status);
osal_printk("\n sle uart recived data : %s\r\n", data->data);
uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data->data), data->data_len, 0);
}
static void sle_uart_client_read_int_handler(const void *buffer, uint16_t length, bool error)
{
unused(error);
ssapc_write_param_t *sle_uart_send_param = get_g_sle_uart_send_param();
uint16_t g_sle_uart_conn_id = get_g_sle_uart_conn_id();
sle_uart_send_param->data_len = length;
sle_uart_send_param->data = (uint8_t *)buffer;
ssapc_write_req(0, g_sle_uart_conn_id, sle_uart_send_param);
}
static void *sle_uart_client_task(const char *arg)
{
unused(arg);
/* UART pinmux. */
uart_init_pin();
/* UART init config. */
uart_init_config();
uapi_uart_unregister_rx_callback(CONFIG_SLE_UART_BUS);
errcode_t ret = uapi_uart_register_rx_callback(CONFIG_SLE_UART_BUS,
UART_RX_CONDITION_FULL_OR_IDLE,
1, sle_uart_client_read_int_handler);
if (ret != ERRCODE_SUCC) {
osal_printk("Register uart callback fail.");
return NULL;
}
return NULL;
}
#endif/* CONFIG_SAMPLE_SUPPORT_SLE_UART_CLIENT */
</code></pre>
<p>2-4步Client的配置与Server类似,因此这里只介绍注册SLE设备管理回调函数</p>
<p >整体代码如下:</p>
<pre>
<code>void sle_uart_client_sample_dev_cbk_register(void)
{
g_sle_dev_mgr_cbk.sle_power_on_cb = sle_uart_client_sample_sle_power_on_cbk;
g_sle_dev_mgr_cbk.sle_enable_cb = sle_uart_client_sample_sle_enable_cbk;
sle_dev_manager_register_callbacks(&g_sle_dev_mgr_cbk);
#if (CORE_NUMS < 2)
enable_sle();
#endif
}
</code></pre>
<p>在这一步中,需要使能SLE协议栈、使能SLE Client(包括注册SLE设备发现回调函数、注册连接管理回调函数、注册ssap客户端回调函数、设置设备公开扫描参数并开始设备公开扫描)</p>
<p>1. 使能SLE协议栈</p>
<pre>
<code>static void sle_uart_client_sample_sle_power_on_cbk(uint8_t status)
{
osal_printk("sle power on: %d.\r\n", status);
enable_sle();
}
</code></pre>
<p>2. 使能SLE Client</p>
<p >整体代码如下:</p>
<pre>
<code>static void sle_uart_client_sample_sle_enable_cbk(uint8_t status)
{
osal_printk("sle enable: %d.\r\n", status);
sle_uart_client_init(sle_uart_notification_cb, sle_uart_indication_cb);
sle_uart_start_scan();
}
</code></pre>
<p>这个过程包括了Client初始化(注册SLE设备发现回调函数、注册连接管理回调函数、注册ssap客户端回调函数)和设置设备公开扫描参数并开始设备公开扫描</p>
<p >2.1. Client初始化</p>
<p >整体代码如下:</p>
<pre>
<code>void sle_uart_client_init(ssapc_notification_callback notification_cb, ssapc_indication_callback indication_cb)
{
sle_uart_client_sample_seek_cbk_register();
sle_uart_client_sample_connect_cbk_register();
sle_uart_client_sample_ssapc_cbk_register(notification_cb, indication_cb);
#ifdef CONFIG_SAMPLE_SUPPORT_LOW_LATENCY_TYPE
sle_uart_client_low_latency_recv_data_cbk_register();
#endif
}
</code></pre>
<p>2.1.1. 注册SLE设备发现回调函数</p>
<pre>
<code>static void sle_uart_client_sample_seek_cbk_register(void)
{
g_sle_uart_seek_cbk.seek_enable_cb = sle_uart_client_sample_seek_enable_cbk;
g_sle_uart_seek_cbk.seek_result_cb = sle_uart_client_sample_seek_result_info_cbk;
g_sle_uart_seek_cbk.seek_disable_cb = sle_uart_client_sample_seek_disable_cbk;
sle_announce_seek_register_callbacks(&g_sle_uart_seek_cbk);
}
</code></pre>
<p>2.1.2. 注册连接管理回调函数</p>
<p>这里包含了连接状态变化和匹配完成两个回调函数</p>
<pre>
<code>static void sle_uart_client_sample_connect_cbk_register(void)
{
g_sle_uart_connect_cbk.connect_state_changed_cb = sle_uart_client_sample_connect_state_changed_cbk;
g_sle_uart_connect_cbk.pair_complete_cb =sle_uart_client_sample_pair_complete_cbk;
sle_connection_register_callbacks(&g_sle_uart_connect_cbk);
}
</code></pre>
<p>2.1.3. 注册ssap客户端回调函数</p>
<p>在这一步中,客户端需要查找特征、服务、描述符,定义接收到写请求触发回调函数,并定义接收到Server的notification和indication触发的回调函数</p>
<pre>
<code>static void sle_uart_client_sample_ssapc_cbk_register(ssapc_notification_callback notification_cb,
ssapc_notification_callback indication_cb)
{
g_sle_uart_ssapc_cbk.exchange_info_cb = sle_uart_client_sample_exchange_info_cbk;
g_sle_uart_ssapc_cbk.find_structure_cb = sle_uart_client_sample_find_structure_cbk;
g_sle_uart_ssapc_cbk.ssapc_find_property_cbk = sle_uart_client_sample_find_property_cbk;
g_sle_uart_ssapc_cbk.find_structure_cmp_cb = sle_uart_client_sample_find_structure_cmp_cbk;
g_sle_uart_ssapc_cbk.write_cfm_cb = sle_uart_client_sample_write_cfm_cb;
g_sle_uart_ssapc_cbk.notification_cb = notification_cb;
g_sle_uart_ssapc_cbk.indication_cb = indication_cb;
ssapc_register_callbacks(&g_sle_uart_ssapc_cbk);
}
</code></pre>
<p>2.2. 设置设备公开扫描参数并开始设备公开扫描</p>
<pre>
<code>void sle_uart_start_scan(void)
{
sle_seek_param_t param = { 0 };
param.own_addr_type = 0;
param.filter_duplicates = 0;
param.seek_filter_policy = 0;
param.seek_phys = 1;
param.seek_type = 1;
param.seek_interval = SLE_SEEK_INTERVAL_DEFAULT;
param.seek_window = SLE_SEEK_WINDOW_DEFAULT;
sle_set_seek_param(&param);
sle_start_seek();
}
</code></pre>
<p style="text-align: justify;">在完成以上操作之后,再进行uart引脚初始化,uart初始化,注册接收回调函数,就完成了Client的任务创建。</p>
<p style="text-align: justify;">之后就是扫描匹配,匹配成功之后Server和Client就可以互相收发数据了。</p>
<p style="text-align: justify;"><span style="font-size:18px;"><strong>总结</strong></span></p>
<p style="text-align: justify;">SLE的整体流程和BLE还是很像的,但是其中有些名字看上去就比较关键的函数,看不到背后的代码,这些函数应该就是SLE的核心所在了吧。我觉得照着官方案例做SLE的二次开发还是很有难度的,其中很多代码的细节我们只能通过函数名称猜测。希望后续官方的SDK更新能展示更多代码细节,方便做一些星闪开发和测试。</p>
页:
[1]