FuShenxiao 发表于 2024-8-27 09:34

小熊派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>&nbsp;</p>

<div style="text-align: center;"></div>

<p>&nbsp;</p>

<p><span style="font-size:16px;"><strong>配置SLE UART Server</strong></span></p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p>选择协议</p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">配置完成,对代码进行编译烧录。</p>

<p><strong><span style="font-size:16px;">配置SLE UART Client</span></strong></p>

<p align="center"> &nbsp;</p>

<p>选择协议</p>

<p align="center"> &nbsp;</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;">&nbsp;接着初始化SLE,并进入SLE任务</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">接着配置与开启ADV</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">&nbsp;</p>

<p><strong><span style="font-size:16px;">Client初始化</span></strong></p>

<p>首先初始化SDK</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">接着初始化SLE任务并进入SLE任务;配置ADV参数</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">与主机配对,发现特征值</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;">&nbsp;</p>

<p><strong><span style="font-size:16px;">Client初始化完成后Server的日志显示</span></strong></p>

<p>扫描到从机的ADV数据,与从机配对</p>

<p align="center"> &nbsp;</p>

<p style="text-align: justify;"><span style="font-size:16px;"><strong>发送测试</strong></span></p>

<p><strong>Server发送Client接收</strong></p>

<p align="center"> &nbsp;&nbsp;&nbsp;</p>

<p><strong>Client发送Server接收</strong></p>

<p style="text-align: center;"> &nbsp;&nbsp;&nbsp;</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) &gt;&gt; 0x8);
    *(uint8_t *)(_ptr) = (uint8_t)(data);
}

static void sle_uuid_set_base(sle_uuid_t *out)
{
    errcode_t ret;
    ret = memcpy_s(out-&gt;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-&gt;len = 0;
      return ;
    }
    out-&gt;len = UUID_LEN_2;
}

static void sle_uuid_setu2(uint16_t u2, sle_uuid_t *out)
{
    sle_uuid_set_base(out);
    out-&gt;len = UUID_LEN_2;
    encode2byte_little(&amp;out-&gt;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-&gt;len == UUID_16BIT_LEN) {
      sample_at_log_print("%s uuid: %02x %02x.\n", SLE_UART_SERVER_LOG,
            uuid-&gt;uuid, uuid-&gt;uuid); /* 14 15: uuid index */
    } else if (uuid-&gt;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-&gt;uuid, uuid-&gt;uuid,
            uuid-&gt;uuid, uuid-&gt;uuid);
      sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid-&gt;uuid, uuid-&gt;uuid,
            uuid-&gt;uuid, uuid-&gt;uuid);
      sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid-&gt;uuid, uuid-&gt;uuid,
            uuid-&gt;uuid, uuid-&gt;uuid);
      sample_at_log_print("%s 0x%02x 0x%02x 0x%02x \n", SLE_UART_SERVER_LOG, uuid-&gt;uuid, uuid-&gt;uuid,
            uuid-&gt;uuid, uuid-&gt;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-&gt;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(&amp;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, &amp;service_uuid);
    ret = ssaps_add_service_sync(g_server_id, &amp;service_uuid, 1, &amp;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, &amp;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, &amp;property,&amp;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, &amp;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(&amp;app_uuid, &amp;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, &amp;param.uuid);
    ret = ssaps_notify_indicate_by_uuid(g_server_id, g_sle_conn_hdl, &amp;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, &amp;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-&gt;addr, addr-&gt;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-&gt;addr, addr-&gt;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, &amp;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(&amp;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 &lt; 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(&amp;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(&amp;adv_data, SLE_ADV_DATA_LEN_MAX - idx, &amp;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(&amp;adv_data, SLE_ADV_DATA_LEN_MAX - idx, &amp;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, &amp;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(&amp;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 &lt; 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, &amp;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&lt;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&lt;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, &amp;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(&amp;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 &lt; 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(&amp;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 &amp;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(&amp;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-&gt;data);
    if (seek_result_data == NULL) {
      osal_printk("status error\r\n");
    } else if (strstr((const char *)seek_result_data-&gt;data, SLE_UART_SERVER_NAME) != NULL) {
      memcpy_s(&amp;g_sle_uart_remote_addr, sizeof(sle_addr_t), &amp;seek_result_data-&gt;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(&amp;g_sle_uart_remote_addr);
      sle_connect_remote_device(&amp;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(&amp;g_sle_dev_mgr_cbk);
#if (CORE_NUMS &lt; 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(&amp;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(), &amp;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(&amp;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(&amp;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-&gt;addr, addr-&gt;addr, addr-&gt;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, &amp;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(&amp;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-&gt;mtu_size, param-&gt;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, &amp;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-&gt;start_hdl, service-&gt;end_hdl, service-&gt;uuid.len);
    g_sle_uart_find_service_result.start_hdl = service-&gt;start_hdl;
    g_sle_uart_find_service_result.end_hdl = service-&gt;end_hdl;
    memcpy_s(&amp;g_sle_uart_find_service_result.uuid, sizeof(sle_uuid_t), &amp;service-&gt;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-&gt;handle %d\r\n", SLE_UART_CLIENT_LOG,
                client_id, conn_id, property-&gt;operate_indication,
                property-&gt;descriptors_count, status, property-&gt;handle);
    g_sle_uart_send_param.handle = property-&gt;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-&gt;type, structure_result-&gt;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-&gt;handle, write_result-&gt;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(&amp;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(&amp;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, &amp;pin_config, &amp;attr, NULL, &amp;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-&gt;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-&gt;handle, status);
    if ((write_cb_para-&gt;length &gt; 0) &amp;&amp; write_cb_para-&gt;value) {
      uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)write_cb_para-&gt;value, write_cb_para-&gt;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(&amp;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 *)&amp;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, &amp;rx_length);
      sle_uart_server_receive_msgqueue(rx_buf, &amp;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-&gt;data);
    uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;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-&gt;data);
    uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;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-&gt;data_len = length;
    sle_uart_send_param-&gt;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, &amp;rx_length);
      sle_uart_server_receive_msgqueue(rx_buf, &amp;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(&amp;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 &lt; 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(&amp;app_uuid, &amp;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 &lt; 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, &amp;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&lt;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&lt;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, &amp;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 *)&amp;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(&amp;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(&amp;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(&amp;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(&amp;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-&gt;data);
    uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;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-&gt;data);
    uapi_uart_write(CONFIG_SLE_UART_BUS, (uint8_t *)(data-&gt;data), data-&gt;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-&gt;data_len = length;
    sle_uart_send_param-&gt;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(&amp;g_sle_dev_mgr_cbk);
#if (CORE_NUMS &lt; 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(&amp;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(&amp;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(&amp;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(&amp;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]
查看完整版本: 小熊派BearPi-Pico H2821星闪开发板测评(六)——SLE串口透传测试