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.

Related