nrf54l15-dk + Long Range + Pawr

Hi,Team,

I am developing Long Range and Pawr using nrf54l15-dk.

For the Long Range example I refer to E:\NCS\v2.8.0\nrf\samples\bluetooth\central_and_peripheral_hr and peripheral_hr_coded.

For the Pawr  example I refer to E:\NCS\v2.8.0\zephyr\samples\bluetooth\periodic_adv_rsp and periodic_sync_rsp.

I wrote the relevant configuration of the Long Range example into the Pawr example, used vscode to compile the Pawr example and downloaded it to nrf54l15-dk, and found that the communication could not be normal.

Here is the log I captured:

[11:22:00.596]收←◆*** Booting n
[11:22:00.621]收←◆RF Connect SDK v2.8.0-a2386bfc8401 ***
*** Using Zephyr OS v3.7.99-0bc3393fb112 ***
Starting Periodic Advertising Demo
I: SoftDevice Controller build revision: 
I: fe 2c f9 6a 7f 36 22 2e |.,.j.6".
I: a0 79 c0 40 be 2c 03 20 |.y.@.,. 
I: 40 c2 f3 32             |@..2    
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF54Lx (0x0005)
I: Firmware: Standard Bluetooth controller (0x00) Version 254.63788 Build 573996906
I: Identity: DF:61:6B:4C:94:22 (random)
I: HCI: version 6.0 (0x0e) revision 0x304e, manufacturer 0x0059
I: LMP: version 6.0 (0x0e) subver 0x304e
Created adv: 0x20002140
Start Periodic Advertising
Start Extended Advertising
Scanning successfully started

[11:22:02.675]收←◆*** Booting nRF Connect SDK v2.8.0-a2386bfc8401 ***
*** Using Zephyr OS v3.7.99-0bc3393fb112 ***
Starting Periodic Advertising with Responses Synchronization Demo
I: SoftDevice Controller build revision: 
I: fe 2c f9 6a 7f 36 22 2e |.,.j.6".
I: a0 79 c0 40 be 2c 03 20 |.y.@.,. 
I: 40 c2 f3 32             |@..2    
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF54Lx (0x0005)
I: Firmware: Standard Bluetooth controller (0x00) Version 254.63788 Build 573996906
I: Identity: EB:DE:45:CF:A5:B5 (random)
I: HCI: version 6.0 (0x0e) revision 0x304e, manufacturer 0x0059
I: LMP: version 6.0 (0x0e) subver 0x304e
Created adv: 0x20002130
Start Extended Advertising
Waiting for periodic sync...

[11:22:12.740]收←◆Timed out while synchronizing
Failed to start advertising set (err -120)

Here is part of the code for the modified periodic_sync_rsp example:

/*
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/sys/util.h>

#include <dk_buttons_and_leds.h>
#include "my_lbs.h"
#include <zephyr/logging/log.h>

static uint8_t counter = 0XFF ;

#define USER_LED0 DK_LED1 
#define USER_LED1 DK_LED2
#define USER_LED2 DK_LED3
#define USER_LED3 DK_LED4
#define USER_BUTTON DK_BTN1_MSK
#define USER_BUTTON1 DK_BTN2_MSK
#define USER_BUTTON2 DK_BTN3_MSK
#define USER_BUTTON3 DK_BTN4_MSK
#define STACKSIZE 1024

#define THREAD0_PRIORITY 7
#define THREAD1_PRIORITY 7

#define RUN_LED_BLINK_INTERVAL 1000
static bool app_button_state;
static uint32_t app_sensor_value = 100;
#define NOTIFY_INTERVAL 500

static struct bt_le_per_adv_sync *default_sync;

int periodicflag = 0;
static void simulate_data(void)
{
	app_sensor_value++;
	if (app_sensor_value == 200) {
		app_sensor_value = 100;
	}
}
void send_data_thread(void)
{
	while (1) {
		/* Simulate data */
		simulate_data();
		/* Send notification, the function sends notifications only if a client is subscribed */
		my_lbs_send_sensor_notify(app_sensor_value);

		k_sleep(K_MSEC(NOTIFY_INTERVAL));
	}
}


#define NAME_LEN 30

static K_SEM_DEFINE(sem_per_adv, 0, 1);
static K_SEM_DEFINE(sem_per_sync, 0, 1);
static K_SEM_DEFINE(sem_per_sync_lost, 0, 1);

static struct bt_conn *default_conn;

static struct __packed {
	uint8_t subevent;
	uint8_t response_slot;

} pawr_timing;

static void sync_cb(struct bt_le_per_adv_sync *sync, struct bt_le_per_adv_sync_synced_info *info)
{
	struct bt_le_per_adv_sync_subevent_params params;
	uint8_t subevents[1];
	char le_addr[BT_ADDR_LE_STR_LEN];
	int err;

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
	printk("Synced to %s with %d subevents\n", le_addr, info->num_subevents);

	default_sync = sync;


	// pawr_timing.subevent = 2;
	// pawr_timing.response_slot = 1;
	params.properties = 0;
	params.num_subevents = 1;
	params.subevents = subevents;
	subevents[0] = pawr_timing.subevent;

	err = bt_le_per_adv_sync_subevent(sync, &params);
	if (err) {
		printk("Failed to set subevents to sync to (err %d)\n", err);
	} else {
		printk("Changed sync to subevent %d\n", subevents[0]);
	}

	k_sem_give(&sem_per_sync);
}

static void term_cb(struct bt_le_per_adv_sync *sync,
		    const struct bt_le_per_adv_sync_term_info *info)
{
	char le_addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));

	printk("Sync terminated (reason %d)\n", info->reason);
	default_sync = NULL;
	k_sem_give(&sem_per_sync_lost);
}

static bool print_ad_field(struct bt_data *data, void *user_data)
{
	ARG_UNUSED(user_data);

	printk(" data->type   0x%02X: ", data->type);
	//printk(" data->data_len   %d: \n", data->data_len);
	for (size_t i = 0; i < data->data_len; i++) {
		printk("%02X", data->data[i]);
	}

	printk("\n");

	return true;
}

int bt_le_per_adv_set_response_data(struct bt_le_per_adv_sync *per_adv_sync,
				    const struct bt_le_per_adv_response_params *params,
				    const struct net_buf_simple *data);

static struct bt_le_per_adv_response_params rsp_params;

NET_BUF_SIMPLE_DEFINE_STATIC(rsp_buf, 247);

static void recv_cb(struct bt_le_per_adv_sync *sync,
		    const struct bt_le_per_adv_sync_recv_info *info, struct net_buf_simple *buf)
{
	int err;

	if (buf && buf->len) {
		/* Echo the data back to the advertiser */
		net_buf_simple_reset(&rsp_buf);
		//printk("22 periodicflag(err %d)\n", periodicflag);
		if(periodicflag == 1)
		{
			buf->data[buf->len-1] = counter;
		} 
		else buf->data[buf->len-1] = 0xFF;
		net_buf_simple_add_mem(&rsp_buf, buf->data, buf->len);

		// printk(" data->data   \n");
		// for (size_t i = 0; i < buf->len; i++) {
		// 	printk("%02X", buf->data[i]);
		// }
		// printk("\n");
		rsp_params.request_event = info->periodic_event_counter;
		rsp_params.request_subevent = info->subevent;
		/* Respond in current subevent and assigned response slot */
		rsp_params.response_subevent = info->subevent;
		rsp_params.response_slot = pawr_timing.response_slot;

		printk("Indication: subevent %d, responding in slot %d\n", info->subevent,  pawr_timing.response_slot);
		//bt_data_parse(buf, print_ad_field, NULL);

		err = bt_le_per_adv_set_response_data(sync, &rsp_params, &rsp_buf);
		if (err) {
			printk("Failed to send response (err %d)\n", err);
		}
	} else if (buf) {
		printk("Received empty indication: subevent %d\n", info->subevent);
	} else {
		printk("Failed to receive indication: subevent %d\n", info->subevent);
	}
	if(periodicflag == 1)
	{
		counter = 0xFF;
		bt_le_per_adv_sync_recv_disable(default_sync);
	}
	//printk("33 periodicflag(err %d)\n", periodicflag);
	
}

static struct bt_le_per_adv_sync_cb sync_callbacks = {
	//The periodic advertising has been successfully synced.
	.synced = sync_cb,

	.term = term_cb,
	//Periodic advertising data received.
	.recv = recv_cb,
};

static const struct bt_uuid_128 pawr_svc_uuid =
	BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef0));
static const struct bt_uuid_128 pawr_char_uuid =
	BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef1));

static ssize_t write_timing(struct bt_conn *conn, const struct bt_gatt_attr *attr, const void *buf,
			    uint16_t len, uint16_t offset, uint8_t flags)
{
	if (offset) {
		return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
	}

	if (len != sizeof(pawr_timing)) {
		return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
	}

	memcpy(&pawr_timing, buf, len);

	printk("New timing: subevent %d, response slot %d\n", pawr_timing.subevent,
	       pawr_timing.response_slot);

	struct bt_le_per_adv_sync_subevent_params params;
	uint8_t subevents[1];
	int err;
	//pawr_timing.subevent = 2;
	//pawr_timing.response_slot = 3;

	params.properties = 0;
	params.num_subevents = 1;
	params.subevents = subevents;
	subevents[0] = pawr_timing.subevent;

	if (default_sync) {
		err = bt_le_per_adv_sync_subevent(default_sync, &params);
		if (err) {
			printk("Failed to set subevents to sync to (err %d)\n", err);
		} else {
			printk("Changed sync to subevent %d\n", subevents[0]);
		}
	} else {
		printk("Not synced yet\n");
	}

	return len;
}

BT_GATT_SERVICE_DEFINE(pawr_svc, BT_GATT_PRIMARY_SERVICE(&pawr_svc_uuid.uuid),
		       BT_GATT_CHARACTERISTIC(&pawr_char_uuid.uuid, BT_GATT_CHRC_WRITE,
					      BT_GATT_PERM_WRITE, NULL, write_timing,
					      &pawr_timing));

void connected(struct bt_conn *conn, uint8_t err)
{
	printk("Connected, err 0x%02X %s\n", err, bt_hci_err_to_str(err));

	if (err) {
		default_conn = NULL;

		return;
	}

	default_conn = bt_conn_ref(conn);
	//dk_set_led_on(CON_STATUS_LED);
}

void disconnected(struct bt_conn *conn, uint8_t reason)
{
	bt_conn_unref(default_conn);
	default_conn = NULL;

	printk("Disconnected, reason 0x%02X %s\n", reason, bt_hci_err_to_str(reason));
	periodicflag = 1;
	//printk("11 periodicflag(err %d)\n", periodicflag);
}

BT_CONN_CB_DEFINE(conn_cb) = {
	.connected = connected,
	.disconnected = disconnected,
};
#define ADFALAG 1
#if ADFALAG == 0
static const struct bt_data ad[] = {
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

#elif ADFALAG == 1
static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
					  BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
					  BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)),
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1)
};
#endif
static void button_changed(uint32_t button_state, uint32_t has_changed)
{
	uint32_t user_button_state; 
	if (has_changed & USER_BUTTON) {
		user_button_state = button_state & USER_BUTTON;
		app_button_state = user_button_state ? true : false;
		
		if(  app_button_state == true )
		{
			counter = 0x00;
			printk("USER_BUTTON0 Press\n");
			if(periodicflag == 0)
			{
				//k_thread_start(&threadA_data);	
			}
			else if(periodicflag == 1)
			{
				bt_le_per_adv_sync_recv_enable(default_sync);
			}
			dk_set_led_on(USER_LED0);	
		}
		else if(  app_button_state == false )
		{
			printk("USER_BUTTON0 Release\n");
			dk_set_led_off(USER_LED0);
		}
		
	}
	else if (has_changed & USER_BUTTON1) {
		user_button_state = button_state & USER_BUTTON1;
		app_button_state = user_button_state ? true : false;
		if(  app_button_state == true )
		{
			counter = 0x01;
			printk("USER_BUTTON1 Press\n");
			if(periodicflag == 0)
			{
				//k_thread_start(&threadA_data);	
			}
			else if(periodicflag == 1)
			{
				bt_le_per_adv_sync_recv_enable(default_sync);
			}
			dk_set_led_on(USER_LED1);	
		}
		else if(  app_button_state == false )
		{
			printk("USER_BUTTON1 Release\n");
			dk_set_led_off(USER_LED1);
		}
	}
	else if (has_changed & USER_BUTTON2) {
		user_button_state = button_state & USER_BUTTON2;
		app_button_state = user_button_state ? true : false;
		//dk_set_led_off(RUN_STATUS_LED);
		if(  app_button_state == true )
		{
			counter = 0x02;
			printk("USER_BUTTON2 Press\n");
			if(periodicflag == 0)
			{
				//k_thread_start(&threadA_data);	
			}
			else if(periodicflag == 1)
			{
				bt_le_per_adv_sync_recv_enable(default_sync);
			}
			dk_set_led_on(USER_LED2);	
		}
		else if(  app_button_state == false )
		{
			printk("USER_BUTTON2 Release\n");
			dk_set_led_off(USER_LED2);
		}
	}
	else if (has_changed & USER_BUTTON3) {
		user_button_state = button_state & USER_BUTTON3;
		app_button_state = user_button_state ? true : false;
		if(  app_button_state == true )
		{
			counter = 0x03;
			printk("USER_BUTTON3 Press\n");
			if(periodicflag == 0)
			{
				//k_thread_start(&threadA_data);	
			}
			else if(periodicflag == 1)
			{
				bt_le_per_adv_sync_recv_enable(default_sync);
			}
			dk_set_led_on(USER_LED3);	
		}
		else if(  app_button_state == false )
		{
			printk("USER_BUTTON3 Release\n");
			dk_set_led_off(USER_LED3);
		}
	}
}
static int init_button(void)
{
	int err;

	err = dk_buttons_init(button_changed);
	if (err) {
		printk("Cannot init buttons (err: %d)\n", err);
	}

	return err;
}


int main(void)
{
	struct bt_le_per_adv_sync_transfer_param past_param;
	int err;

	err = dk_leds_init();
	if (err) {
		printk("LEDs init failed (err %d)\n", err);
		return -1;
	}

	err = init_button();
	if (err) {
		printk("Button init failed (err %d)\n", err);
		return -1;
	}

	printk("Starting Periodic Advertising with Responses Synchronization Demo\n");
 	
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);

		return 0;
	}
	
	bt_le_per_adv_sync_cb_register(&sync_callbacks);
	static struct bt_le_ext_adv *adv;
	past_param.skip = 1;
	past_param.timeout = 1000; /* 10 seconds */
	past_param.options = BT_LE_PER_ADV_SYNC_TRANSFER_OPT_NONE;
	err = bt_le_per_adv_sync_transfer_subscribe(NULL, &past_param);
	if (err) {
		printk("PAST subscribe failed (err %d)\n", err);

		return 0;
	}

	struct bt_le_adv_param param =
		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
				     BT_LE_ADV_OPT_EXT_ADV |
				     BT_LE_ADV_OPT_CODED,
				     BT_GAP_ADV_FAST_INT_MIN_2,
				     BT_GAP_ADV_FAST_INT_MAX_2,
				     NULL);

	err = bt_le_ext_adv_create(&param, NULL, &adv);
	//err = bt_le_ext_adv_create(&param,  &adv_cb, &pawr_adv);
	if (err) {
		printk("Failed to create advertising set (err %d)\n", err);
		return 0;
	}
	printk("Created adv: %p\n", adv);

 	printk("Start Extended Advertising\n");

	do
	 {
		err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
		if (err) {
			printk("Failed to start advertising set (err %d)\n", err);
			return 0 ;
		}
		//err = bt_le_adv_start(
		// 		BT_LE_ADV_PARAM(BT_LE_ADV_OPT_ONE_TIME | BT_LE_ADV_OPT_CONNECTABLE,
		// 				BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL),
		// 		ad, ARRAY_SIZE(ad), NULL, 0);
		//  if (err && err != -EALREADY) {
		// 	printk("Advertising failed to start (err %d)\n", err);

		// 	return 0;
		// }
		printk("Waiting for periodic sync...\n");
		err = k_sem_take(&sem_per_sync, K_SECONDS(10));
		if (err) {
			printk("Timed out while synchronizing\n");

			continue;
		}

		printk("Periodic sync established.\n");

		err = k_sem_take(&sem_per_sync_lost, K_FOREVER);
		if (err) {
			printk("failed (err %d)\n", err);

			return 0;
		}

		printk("Periodic sync lost.\n");
	} 
	while (true);
	return 0;
}

Here is a modified example of periodic_sync_rsp 's prj.conf file:

CONFIG_BT=y
CONFIG_BT_OBSERVER=y
CONFIG_BT_BROADCASTER=y
CONFIG_BT_EXT_ADV=y
CONFIG_BT_PER_ADV_SYNC=y
CONFIG_BT_DEVICE_NAME="PAwR sync sample"

CONFIG_BT_MAX_CONN=1
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y
CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER=y

CONFIG_BT_PER_ADV_SYNC_RSP=y
CONFIG_BT_PER_ADV_SYNC_BUF_SIZE=247

CONFIG_LOG=y

CONFIG_DK_LIBRARY=y

# Bluetooth LE
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_BAS=y
CONFIG_BT_HRS=y

CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_CTLR_ADV_EXT=y

CONFIG_BT_EXT_ADV=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_NCS_SAMPLES_DEFAULTS=y

Here is part of the code for the modified periodic_adv_rsp example:

/*
 * Copyright (c) 2023 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/bluetooth/att.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>

#include <bluetooth/scan.h>

#include <dk_buttons_and_leds.h>
#include "my_lbs.h"
#include <zephyr/logging/log.h>

#define USER_LED0 DK_LED1 
#define USER_LED1 DK_LED2
#define USER_LED2 DK_LED3
#define USER_LED3 DK_LED4

#define NUM_RSP_SLOTS 5
#define NUM_SUBEVENTS 5
#define PACKET_SIZE   5
#define NAME_LEN      30

static K_SEM_DEFINE(sem_connected, 0, 1);
static K_SEM_DEFINE(sem_discovered, 0, 1);
static K_SEM_DEFINE(sem_written, 0, 1);
static K_SEM_DEFINE(sem_disconnected, 0, 1);

static struct bt_uuid_128 pawr_char_uuid =
	BT_UUID_INIT_128(BT_UUID_128_ENCODE(0x12345678, 0x1234, 0x5678, 0x1234, 0x56789abcdef1));
static uint16_t pawr_attr_handle;
static const struct bt_le_per_adv_param per_adv_params = {
	.interval_min = 0xFF,
	.interval_max = 0xFF,
	.options = 0,
	.num_subevents = NUM_SUBEVENTS,
	.subevent_interval = 0x30,
	.response_slot_delay = 0x5,
	.response_slot_spacing = 0x50,
	.num_response_slots = NUM_RSP_SLOTS,
};

static struct bt_le_per_adv_subevent_data_params subevent_data_params[NUM_SUBEVENTS];
static struct net_buf_simple bufs[NUM_SUBEVENTS];
static uint8_t backing_store[NUM_SUBEVENTS][PACKET_SIZE];

BUILD_ASSERT(ARRAY_SIZE(bufs) == ARRAY_SIZE(subevent_data_params));
BUILD_ASSERT(ARRAY_SIZE(backing_store) == ARRAY_SIZE(subevent_data_params));

static uint8_t counter = 0;

static void request_cb(struct bt_le_ext_adv *adv, const struct bt_le_per_adv_data_request *request)
{
	int err;
	uint8_t to_send;
	struct net_buf_simple *buf;

	to_send = MIN(request->count, ARRAY_SIZE(subevent_data_params));

	for (size_t i = 0; i < to_send; i++) {
		buf = &bufs[i];
		buf->data[buf->len - 1] = counter;

		subevent_data_params[i].subevent =
			(request->start + i) % per_adv_params.num_subevents;
		subevent_data_params[i].response_slot_start = 0;
		subevent_data_params[i].response_slot_count = NUM_RSP_SLOTS;
		subevent_data_params[i].data = buf;
	}

	err = bt_le_per_adv_set_subevent_data(adv, to_send, subevent_data_params);
	if (err) {
		printk("Failed to set subevent data (err %d)\n", err);
	} else {
		// printk("Subevent data set %d\n", counter);
	}
}

static bool print_ad_field(struct bt_data *data, void *user_data)
{
	ARG_UNUSED(user_data);

	printk("    0x%02X: ", data->type);
	for (size_t i = 0; i < data->data_len; i++) {
		printk("%02X", data->data[i]);
	}

	printk("\n");

	return true;
}

static struct bt_conn *default_conn;
/*单位是毫秒*/
#define SLEEP_TIME  100
static void response_cb(struct bt_le_ext_adv *adv, struct bt_le_per_adv_response_info *info,
		     struct net_buf_simple *buf)
{
	if (buf) {
		 printk("Response: subevent %d, slot %d\n", info->subevent, info->response_slot);
		// bt_data_parse(buf, print_ad_field, NULL);
		if(buf->data[buf->len -1] == 0x00)
		{
			printk("sync device USER_BUTTON0 Press\n");
			dk_set_led_on(USER_LED0);
			k_msleep(SLEEP_TIME);
			dk_set_led_off(USER_LED0);
		}
		else if(buf->data[buf->len -1] == 0x01)
		{
			printk("sync device USER_BUTTON1 Press\n");
			dk_set_led_on(USER_LED1);
			k_msleep(SLEEP_TIME);
			dk_set_led_off(USER_LED1);
		}
		else if(buf->data[buf->len -1] == 0x02)
		{
			printk("sync device USER_BUTTON2 Press\n");
			dk_set_led_on(USER_LED2);
			k_msleep(SLEEP_TIME);
			dk_set_led_off(USER_LED2);
		}
		else if(buf->data[buf->len -1] == 0x03)
		{
			printk("sync device USER_BUTTON3 Press\n");
			dk_set_led_on(USER_LED3);
			k_msleep(SLEEP_TIME);
			dk_set_led_off(USER_LED3);
		}
	}
}

static const struct bt_le_ext_adv_cb adv_cb = {
	.pawr_data_request = request_cb,
	.pawr_response = response_cb,
};

void connected_cb(struct bt_conn *conn, uint8_t err)
{
	printk("Connected (err 0x%02X)\n", err);

	__ASSERT(conn == default_conn, "Unexpected connected callback");

	if (err) {
		bt_conn_unref(default_conn);
		default_conn = NULL;
	}
}

void disconnected_cb(struct bt_conn *conn, uint8_t reason)
{
	printk("Disconnected, reason 0x%02X %s\n", reason, bt_hci_err_to_str(reason));

	bt_conn_unref(default_conn);
	default_conn = NULL;

	k_sem_give(&sem_disconnected);
}

void remote_info_available_cb(struct bt_conn *conn, struct bt_conn_remote_info *remote_info)
{
	/* Need to wait for remote info before initiating PAST 
	在启动PAST之前需要等待远程信息*/
	k_sem_give(&sem_connected);
}

BT_CONN_CB_DEFINE(conn_cb) = {
	.connected = connected_cb,
	.disconnected = disconnected_cb,
	.remote_info_available = remote_info_available_cb,
};

static bool data_cb(struct bt_data *data, void *user_data)
{
	char *name = user_data;
	uint8_t len;

	switch (data->type) {
	case BT_DATA_NAME_SHORTENED:
	case BT_DATA_NAME_COMPLETE:
		len = MIN(data->data_len, NAME_LEN - 1);
		memcpy(name, data->data, len);
		name[len] = '\0';
		return false;
	default:
		return true;
	}
}

static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
			 struct net_buf_simple *ad)
{
	char addr_str[BT_ADDR_LE_STR_LEN];
	char name[NAME_LEN];
	int err;

	if (default_conn) {
		return;
	}

	/* We're only interested in connectable events */
	if (type != BT_GAP_ADV_TYPE_ADV_IND && type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
		return;
	}

	(void)memset(name, 0, sizeof(name));
	bt_data_parse(ad, data_cb, name);

	if (strcmp(name, "PAwR sync sample")) {
		return;
	}

	if (bt_le_scan_stop()) {
		return;
	}

	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT,
				&default_conn);
	if (err) {
		printk("Create conn to %s failed (%u)\n", addr_str, err);
	}
}

static uint8_t discover_func(struct bt_conn *conn, const struct bt_gatt_attr *attr,
			     struct bt_gatt_discover_params *params)
{
	struct bt_gatt_chrc *chrc;
	char str[BT_UUID_STR_LEN];

	printk("Discovery: attr %p\n", attr);

	if (!attr) {
		return BT_GATT_ITER_STOP;
	}

	chrc = (struct bt_gatt_chrc *)attr->user_data;

	bt_uuid_to_str(chrc->uuid, str, sizeof(str));
	printk("UUID %s\n", str);

	if (!bt_uuid_cmp(chrc->uuid, &pawr_char_uuid.uuid)) {
		pawr_attr_handle = chrc->value_handle;

		printk("Characteristic handle: %d\n", pawr_attr_handle);

		k_sem_give(&sem_discovered);
	}

	return BT_GATT_ITER_STOP;
}

static void write_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_write_params *params)
{
	if (err) {
		printk("Write failed (err %d)\n", err);

		return;
	}

	k_sem_give(&sem_written);
}

void init_bufs(void)
{
	for (size_t i = 0; i < ARRAY_SIZE(backing_store); i++) {
		backing_store[i][0] = ARRAY_SIZE(backing_store[i]) - 1;
		backing_store[i][1] = BT_DATA_MANUFACTURER_DATA;
		backing_store[i][2] = 0x59; /* Nordic */
		backing_store[i][3] = 0x00;

		net_buf_simple_init_with_data(&bufs[i], &backing_store[i],
					      ARRAY_SIZE(backing_store[i]));
	}
}

#define MAX_SYNCS (NUM_SUBEVENTS * NUM_RSP_SLOTS)
struct pawr_timing {
	uint8_t subevent;
	uint8_t response_slot;
} __packed;
#define ADFALAG 1
#if ADFALAG == 0
static const struct bt_data ad[] = {
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

#elif ADFALAG == 1
static const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
					  BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
					  BT_UUID_16_ENCODE(BT_UUID_DIS_VAL)),
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1)
};
#endif
static uint8_t num_synced;

static void scan_filter_match(struct bt_scan_device_info *device_info,
			      struct bt_scan_filter_match *filter_match,
			      bool connectable)
{
	int err;
	char addr[BT_ADDR_LE_STR_LEN];
	struct bt_conn_le_create_param *conn_params;

	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));

	printk("Filters matched. Address: %s connectable: %s\n",
		addr, connectable ? "yes" : "no");

	err = bt_scan_stop();
	if (err) {
		printk("Stop LE scan failed (err %d)\n", err);
	}

	conn_params = BT_CONN_LE_CREATE_PARAM(
			BT_CONN_LE_OPT_CODED | BT_CONN_LE_OPT_NO_1M,
			BT_GAP_SCAN_FAST_INTERVAL,
			BT_GAP_SCAN_FAST_INTERVAL);

	err = bt_conn_le_create(device_info->recv_info->addr, conn_params,
				BT_LE_CONN_PARAM_DEFAULT,
				&default_conn);
	if (err) {
		printk("Create conn failed (err %d)\n", err);

		err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
		if (err) {
			printk("Scanning failed to start (err %d)\n", err);
			return;
		}
	}

	printk("Connection pending\n");
}

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL, NULL, NULL);

int main(void)
{
	int err;
	struct bt_le_ext_adv *pawr_adv;
	struct bt_gatt_discover_params discover_params;
	struct bt_gatt_write_params write_params;
	struct pawr_timing sync_config;

	
	err = dk_leds_init();
	if (err) {
		printk("LEDs init failed (err %d)\n", err);
		return -1;
	}
	init_bufs();
	printk("Starting Periodic Advertising Demo\n");

	/* Initialize the Bluetooth Subsystem */
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
		return 0;
	}
		struct bt_le_adv_param param =
		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
				     BT_LE_ADV_OPT_EXT_ADV |
				     BT_LE_ADV_OPT_CODED,
				     BT_GAP_ADV_FAST_INT_MIN_2,
				     BT_GAP_ADV_FAST_INT_MAX_2,
				     NULL);
	
	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CODED_NCONN, &adv_cb, &pawr_adv);
	//err = bt_le_ext_adv_create(&param,  &adv_cb, &pawr_adv);
	if (err) {
		printk("Failed to create advertising set (err %d)\n", err);
		return 0;
	}
	printk("Created adv: %p\n", pawr_adv);
	
	// 设置广播数据
	err = bt_le_ext_adv_set_data(pawr_adv, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		printk("Failed to set advertising data (err %d)\n", err);
		return err;
	}

	/* Set periodic advertising parameters */
	err = bt_le_per_adv_set_param(pawr_adv, &per_adv_params);
	if (err) {
		printk("Failed to set periodic advertising parameters (err %d)\n", err);
		return 0;
	}

	
	/* Enable Periodic Advertising */
	printk("Start Periodic Advertising\n");
	err = bt_le_per_adv_start(pawr_adv);
	if (err) {
		printk("Failed to enable periodic advertising (err %d)\n", err);
		return 0;
	}
	// 启动扩展广播
	printk("Start Extended Advertising\n");
	err = bt_le_ext_adv_start(pawr_adv, BT_LE_EXT_ADV_START_DEFAULT);
	if (err) {
		printk("Failed to start extended advertising (err %d)\n", err);
		return 0;
	}

	struct bt_le_scan_param scan_param = {
		.type     = BT_LE_SCAN_TYPE_ACTIVE,
		.interval = BT_GAP_SCAN_FAST_INTERVAL,
		.window   = BT_GAP_SCAN_FAST_WINDOW,
		.options  = BT_LE_SCAN_OPT_CODED | BT_LE_SCAN_OPT_NO_1M
	};

	struct bt_scan_init_param scan_init = {
		.connect_if_match = 0,
		.scan_param = &scan_param,
		.conn_param = NULL
	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);


	while (num_synced < MAX_SYNCS) {
		/* Enable continuous scanning BT_LE_SCAN_PASSIVE_CONTINUOUS*/		  
		err = bt_le_scan_start(BT_LE_SCAN_PASSIVE_CONTINUOUS, device_found);
		if (err) {
			printk("Scanning failed to start (err %d)\n", err);
			return 0;
		}

		printk("Scanning successfully started\n");

		k_sem_take(&sem_connected, K_FOREVER);
	
		err = bt_le_per_adv_set_info_transfer(pawr_adv, default_conn, 0);
		if (err) {
			printk("Failed to send PAST (err %d)\n", err);

			goto disconnect;
		}

		printk("PAST sent\n");

		discover_params.uuid = &pawr_char_uuid.uuid;
		discover_params.func = discover_func;
		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
		err = bt_gatt_discover(default_conn, &discover_params);
		if (err) {
			printk("Discovery failed (err %d)\n", err);

			goto disconnect;
		}

		printk("Discovery started\n");

		err = k_sem_take(&sem_discovered, K_SECONDS(10));
		if (err) {
			printk("Timed out during GATT discovery\n");

			goto disconnect;
		}

		sync_config.subevent =  num_synced; //% NUM_SUBEVENTS;
		sync_config.response_slot = num_synced; /// NUM_RSP_SLOTS;
		num_synced++;

		write_params.func = write_func;
		write_params.handle = pawr_attr_handle;
		write_params.offset = 0;
		write_params.data = &sync_config;
		write_params.length = sizeof(sync_config);

		err = bt_gatt_write(default_conn, &write_params);
		if (err) {
			printk("Write failed (err %d)\n", err);
			num_synced--;

			goto disconnect;
		}

		printk("Write started\n");

		err = k_sem_take(&sem_written, K_SECONDS(10));
		if (err) {
			printk("Timed out during GATT write\n");
			num_synced--;

			goto disconnect;
		}

		printk("PAwR config written to sync %d, disconnecting\n", num_synced - 1);

disconnect:
		/* Adding delay (2ms * interval value, using 2ms intead of the 1.25ms
		 * used by controller) to ensure sync is established before
		 * disconnection.
		 */
		k_sleep(K_MSEC(per_adv_params.interval_max * 2));

		err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
		if (err) {
			return 0;
		}

		k_sem_take(&sem_disconnected, K_FOREVER);
	}

	printk("Maximum numnber of syncs onboarded\n");

	while (true) {
		k_sleep(K_SECONDS(1));
	}

	return 0;
}

Here is a modified example of periodic_adv_rsp's prj.conf file:

CONFIG_BT=y
CONFIG_BT_BROADCASTER=y
CONFIG_BT_EXT_ADV=y
CONFIG_BT_PER_ADV=y
CONFIG_BT_DEVICE_NAME="PAwR adv sample"

CONFIG_BT_MAX_CONN=1
CONFIG_BT_CENTRAL=y
CONFIG_BT_PER_ADV_SYNC_TRANSFER_SENDER=y

CONFIG_BT_PER_ADV_RSP=y

CONFIG_BT_REMOTE_INFO=y
CONFIG_BT_GATT_CLIENT=y

CONFIG_LOG=y


# Button and LED library
CONFIG_DK_LIBRARY=y

# Bluetooth LE
CONFIG_BT_PERIPHERAL=y

CONFIG_NCS_SAMPLES_DEFAULTS=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1

CONFIG_BT_CTLR_ADV_EXT=y
CONFIG_BT_CTLR_PHY_CODED=y


CONFIG_BT_USER_PHY_UPDATE=y

I am not sure if the code configuration is correct.

Thanks.

Parents
  • The main issue you have seems to be connected to this error

    Failed to start advertising set (err -120)

    The timeout print is something your application have added? 

    error -120 (-EALREADY) means that the operation is already in progress or has been started previously. This suggests that periodic advertising synchronization or extended advertising was already started and let it continue if you get the error -120, causing the failure.

    Whenever you start periodic advertising check if it already, you can use this template check for instance.

    static bool periodic_adv_started = false;
    
    if (!periodic_adv_started) {
        err = bt_le_per_adv_start(adv);
        if (err && err != -EALREADY) {
            printk("Failed to start periodic advertising (err %d)\n", err);
            return 0;
        }
        periodic_adv_started = true;
    }
    

  • Hi,

    Timeout printing is a feature added to my application.
    In the periodic_adv_rsp project I wrote the template you provided, and then retested it, but the result was still an error: Timed out while synchronizing. Failed to start advertising set (err -120).

    Maybe it's a broadcast configuration problem? I don't know how to check, can you check the sample configuration for periodic_adv_rsp and periodic_sync_rsp?

    Here is some of the code for the periodic_adv_rsp example that I have changed:

    int main(void)
    {
    	int err;
    	struct bt_le_ext_adv *pawr_adv;
    	struct bt_gatt_discover_params discover_params;
    	struct bt_gatt_write_params write_params;
    	struct pawr_timing sync_config;
    
    	
    	err = dk_leds_init();
    	if (err) {
    		printk("LEDs init failed (err %d)\n", err);
    		return -1;
    	}
    	init_bufs();
    	printk("Starting Periodic Advertising Demo\n");
    
    	/* Initialize the Bluetooth Subsystem */
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    		struct bt_le_adv_param param =
    		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
    				     BT_LE_ADV_OPT_EXT_ADV |
    				     BT_LE_ADV_OPT_CODED,
    				     BT_GAP_ADV_FAST_INT_MIN_2,
    				     BT_GAP_ADV_FAST_INT_MAX_2,
    				     NULL);
    	
    	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CODED_NCONN, &adv_cb, &pawr_adv);
    	//err = bt_le_ext_adv_create(&param,  &adv_cb, &pawr_adv);
    	if (err) {
    		printk("Failed to create advertising set (err %d)\n", err);
    		return 0;
    	}
    	printk("Created adv: %p\n", pawr_adv);
    	
    	// 设置广播数据
    	err = bt_le_ext_adv_set_data(pawr_adv, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Failed to set advertising data (err %d)\n", err);
    		return err;
    	}
    
    	/* Set periodic advertising parameters */
    	err = bt_le_per_adv_set_param(pawr_adv, &per_adv_params);
    	if (err) {
    		printk("Failed to set periodic advertising parameters (err %d)\n", err);
    		return 0;
    	}
    
    	
    	/* Enable Periodic Advertising */
    	// printk("Start Periodic Advertising\n");
    	// err = bt_le_per_adv_start(pawr_adv);
    	// if (err) {
    	// 	printk("Failed to enable periodic advertising (err %d)\n", err);
    	// 	return 0;
    	// }
    	static bool periodic_adv_started = false;
    
    	if (!periodic_adv_started) {
    		err = bt_le_per_adv_start(pawr_adv);
    		if (err && err != -EALREADY) {
    			printk("Failed to start periodic advertising (err %d)\n", err);
    			return 0;
    		}
    		periodic_adv_started = true;
    	}
    	// 启动扩展广播
    	printk("Start Extended Advertising\n");
    	err = bt_le_ext_adv_start(pawr_adv, BT_LE_EXT_ADV_START_DEFAULT);
    	if (err) {
    		printk("Failed to start extended advertising (err %d)\n", err);
    		return 0;
    	}
    
    	struct bt_le_scan_param scan_param = {
    		.type     = BT_LE_SCAN_TYPE_ACTIVE,
    		.interval = BT_GAP_SCAN_FAST_INTERVAL,
    		.window   = BT_GAP_SCAN_FAST_WINDOW,
    		.options  = BT_LE_SCAN_OPT_CODED | BT_LE_SCAN_OPT_NO_1M
    	};
    
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 0,
    		.scan_param = &scan_param,
    		.conn_param = NULL
    	};
    
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    
    	while (num_synced < MAX_SYNCS) {
    		/* Enable continuous scanning BT_LE_SCAN_PASSIVE_CONTINUOUS*/		  
    		err = bt_le_scan_start(BT_LE_SCAN_PASSIVE_CONTINUOUS, device_found);
    		if (err) {
    			printk("Scanning failed to start (err %d)\n", err);
    			return 0;
    		}
    
    		printk("Scanning successfully started\n");
    
    		k_sem_take(&sem_connected, K_FOREVER);
    	
    		err = bt_le_per_adv_set_info_transfer(pawr_adv, default_conn, 0);
    		if (err) {
    			printk("Failed to send PAST (err %d)\n", err);
    
    			goto disconnect;
    		}
    
    		printk("PAST sent\n");
    
    		discover_params.uuid = &pawr_char_uuid.uuid;
    		discover_params.func = discover_func;
    		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    		err = bt_gatt_discover(default_conn, &discover_params);
    		if (err) {
    			printk("Discovery failed (err %d)\n", err);
    
    			goto disconnect;
    		}
    
    		printk("Discovery started\n");
    
    		err = k_sem_take(&sem_discovered, K_SECONDS(10));
    		if (err) {
    			printk("Timed out during GATT discovery\n");
    
    			goto disconnect;
    		}
    
    		sync_config.subevent =  num_synced; //% NUM_SUBEVENTS;
    		sync_config.response_slot = num_synced; /// NUM_RSP_SLOTS;
    		num_synced++;
    
    		write_params.func = write_func;
    		write_params.handle = pawr_attr_handle;
    		write_params.offset = 0;
    		write_params.data = &sync_config;
    		write_params.length = sizeof(sync_config);
    
    		err = bt_gatt_write(default_conn, &write_params);
    		if (err) {
    			printk("Write failed (err %d)\n", err);
    			num_synced--;
    
    			goto disconnect;
    		}
    
    		printk("Write started\n");
    
    		err = k_sem_take(&sem_written, K_SECONDS(10));
    		if (err) {
    			printk("Timed out during GATT write\n");
    			num_synced--;
    
    			goto disconnect;
    		}
    
    		printk("PAwR config written to sync %d, disconnecting\n", num_synced - 1);
    
    disconnect:
    		/* Adding delay (2ms * interval value, using 2ms intead of the 1.25ms
    		 * used by controller) to ensure sync is established before
    		 * disconnection.
    		 */
    		k_sleep(K_MSEC(per_adv_params.interval_max * 2));
    
    		err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    		if (err) {
    			return 0;
    		}
    
    		k_sem_take(&sem_disconnected, K_FOREVER);
    	}
    
    	printk("Maximum numnber of syncs onboarded\n");
    
    	while (true) {
    		k_sleep(K_SECONDS(1));
    	}
    
    	return 0;
    }

    Thanks.

Reply
  • Hi,

    Timeout printing is a feature added to my application.
    In the periodic_adv_rsp project I wrote the template you provided, and then retested it, but the result was still an error: Timed out while synchronizing. Failed to start advertising set (err -120).

    Maybe it's a broadcast configuration problem? I don't know how to check, can you check the sample configuration for periodic_adv_rsp and periodic_sync_rsp?

    Here is some of the code for the periodic_adv_rsp example that I have changed:

    int main(void)
    {
    	int err;
    	struct bt_le_ext_adv *pawr_adv;
    	struct bt_gatt_discover_params discover_params;
    	struct bt_gatt_write_params write_params;
    	struct pawr_timing sync_config;
    
    	
    	err = dk_leds_init();
    	if (err) {
    		printk("LEDs init failed (err %d)\n", err);
    		return -1;
    	}
    	init_bufs();
    	printk("Starting Periodic Advertising Demo\n");
    
    	/* Initialize the Bluetooth Subsystem */
    	err = bt_enable(NULL);
    	if (err) {
    		printk("Bluetooth init failed (err %d)\n", err);
    		return 0;
    	}
    		struct bt_le_adv_param param =
    		BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_CONNECTABLE |
    				     BT_LE_ADV_OPT_EXT_ADV |
    				     BT_LE_ADV_OPT_CODED,
    				     BT_GAP_ADV_FAST_INT_MIN_2,
    				     BT_GAP_ADV_FAST_INT_MAX_2,
    				     NULL);
    	
    	err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CODED_NCONN, &adv_cb, &pawr_adv);
    	//err = bt_le_ext_adv_create(&param,  &adv_cb, &pawr_adv);
    	if (err) {
    		printk("Failed to create advertising set (err %d)\n", err);
    		return 0;
    	}
    	printk("Created adv: %p\n", pawr_adv);
    	
    	// 设置广播数据
    	err = bt_le_ext_adv_set_data(pawr_adv, ad, ARRAY_SIZE(ad), NULL, 0);
    	if (err) {
    		printk("Failed to set advertising data (err %d)\n", err);
    		return err;
    	}
    
    	/* Set periodic advertising parameters */
    	err = bt_le_per_adv_set_param(pawr_adv, &per_adv_params);
    	if (err) {
    		printk("Failed to set periodic advertising parameters (err %d)\n", err);
    		return 0;
    	}
    
    	
    	/* Enable Periodic Advertising */
    	// printk("Start Periodic Advertising\n");
    	// err = bt_le_per_adv_start(pawr_adv);
    	// if (err) {
    	// 	printk("Failed to enable periodic advertising (err %d)\n", err);
    	// 	return 0;
    	// }
    	static bool periodic_adv_started = false;
    
    	if (!periodic_adv_started) {
    		err = bt_le_per_adv_start(pawr_adv);
    		if (err && err != -EALREADY) {
    			printk("Failed to start periodic advertising (err %d)\n", err);
    			return 0;
    		}
    		periodic_adv_started = true;
    	}
    	// 启动扩展广播
    	printk("Start Extended Advertising\n");
    	err = bt_le_ext_adv_start(pawr_adv, BT_LE_EXT_ADV_START_DEFAULT);
    	if (err) {
    		printk("Failed to start extended advertising (err %d)\n", err);
    		return 0;
    	}
    
    	struct bt_le_scan_param scan_param = {
    		.type     = BT_LE_SCAN_TYPE_ACTIVE,
    		.interval = BT_GAP_SCAN_FAST_INTERVAL,
    		.window   = BT_GAP_SCAN_FAST_WINDOW,
    		.options  = BT_LE_SCAN_OPT_CODED | BT_LE_SCAN_OPT_NO_1M
    	};
    
    	struct bt_scan_init_param scan_init = {
    		.connect_if_match = 0,
    		.scan_param = &scan_param,
    		.conn_param = NULL
    	};
    
    	bt_scan_init(&scan_init);
    	bt_scan_cb_register(&scan_cb);
    
    
    	while (num_synced < MAX_SYNCS) {
    		/* Enable continuous scanning BT_LE_SCAN_PASSIVE_CONTINUOUS*/		  
    		err = bt_le_scan_start(BT_LE_SCAN_PASSIVE_CONTINUOUS, device_found);
    		if (err) {
    			printk("Scanning failed to start (err %d)\n", err);
    			return 0;
    		}
    
    		printk("Scanning successfully started\n");
    
    		k_sem_take(&sem_connected, K_FOREVER);
    	
    		err = bt_le_per_adv_set_info_transfer(pawr_adv, default_conn, 0);
    		if (err) {
    			printk("Failed to send PAST (err %d)\n", err);
    
    			goto disconnect;
    		}
    
    		printk("PAST sent\n");
    
    		discover_params.uuid = &pawr_char_uuid.uuid;
    		discover_params.func = discover_func;
    		discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
    		discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
    		discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
    		err = bt_gatt_discover(default_conn, &discover_params);
    		if (err) {
    			printk("Discovery failed (err %d)\n", err);
    
    			goto disconnect;
    		}
    
    		printk("Discovery started\n");
    
    		err = k_sem_take(&sem_discovered, K_SECONDS(10));
    		if (err) {
    			printk("Timed out during GATT discovery\n");
    
    			goto disconnect;
    		}
    
    		sync_config.subevent =  num_synced; //% NUM_SUBEVENTS;
    		sync_config.response_slot = num_synced; /// NUM_RSP_SLOTS;
    		num_synced++;
    
    		write_params.func = write_func;
    		write_params.handle = pawr_attr_handle;
    		write_params.offset = 0;
    		write_params.data = &sync_config;
    		write_params.length = sizeof(sync_config);
    
    		err = bt_gatt_write(default_conn, &write_params);
    		if (err) {
    			printk("Write failed (err %d)\n", err);
    			num_synced--;
    
    			goto disconnect;
    		}
    
    		printk("Write started\n");
    
    		err = k_sem_take(&sem_written, K_SECONDS(10));
    		if (err) {
    			printk("Timed out during GATT write\n");
    			num_synced--;
    
    			goto disconnect;
    		}
    
    		printk("PAwR config written to sync %d, disconnecting\n", num_synced - 1);
    
    disconnect:
    		/* Adding delay (2ms * interval value, using 2ms intead of the 1.25ms
    		 * used by controller) to ensure sync is established before
    		 * disconnection.
    		 */
    		k_sleep(K_MSEC(per_adv_params.interval_max * 2));
    
    		err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
    		if (err) {
    			return 0;
    		}
    
    		k_sem_take(&sem_disconnected, K_FOREVER);
    	}
    
    	printk("Maximum numnber of syncs onboarded\n");
    
    	while (true) {
    		k_sleep(K_SECONDS(1));
    	}
    
    	return 0;
    }

    Thanks.

Children
No Data
Related