How to send LE extended adv on nrf5340DK

Hello!

I tried to send extended adv on nrf5340, but encountered some problems.The extended adv packet type i want to send is Non-connectable and Non-scannable and directed, my code configuration is as follows:

/* main.c - Application main entry point */

/*
 * Copyright (c) 2015-2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>
#include <zephyr/kernel.h>
// #include <zephyr/logging/log.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/addr.h>

typedef struct adv_mfg_data {
    // uint8_t id;              /* company id */
	// uint8_t integer;	    /* integer part */
	// uint8_t mantissa;      /* mantissa part */
    float temp;
} adv_mfg_data_type;


static adv_mfg_data_type adv_temperature_data = {-25.11};


static const struct bt_data ad[] = {
	BT_DATA(BT_DATA_MANUFACTURER_DATA,(unsigned char *)&adv_temperature_data, sizeof(adv_temperature_data))
};


static const bt_addr_le_t addr = {
    .type = 1,
    .a = {
        .val = {0x0a,0x62,0x24,0x06,0x53,0x3e}
    }
};

static struct bt_le_adv_param * adv_param = BT_LE_ADV_PARAM((BT_LE_ADV_OPT_EXT_ADV|BT_LE_ADV_OPT_USE_IDENTITY|  \
                                                            BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY|BT_LE_ADV_OPT_NO_2M),
                                                            400,
                                                            400,
                                                            &addr);

void main(void)
{
	int err;

	printk("Starting Beacon Demo\n");

	/* Initialize the Bluetooth Subsystem */
    err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
		return;
	}

    printk("Bluetooth initialized\n");

	err = bt_le_adv_start(adv_param, ad, ARRAY_SIZE(ad),
			      (void*)NULL, 0);
	if (err) {
		printk("Advertising failed to start (err %d)\n", err);
		return;
	}
	printk("Advertising successfully started\n");

    for (;;) {

        k_sleep(K_SECONDS(2));
    }
}

And I also enabled extended adv in prj.conf:

CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_DEVICE_NAME="beacon"
CONFIG_BT_EXT_ADV=y

However, when i run the code,it can't start advertising and the output is as follows:

*** Booting Zephyr OS build v3.2.99-ncs2 ***
Starting Beacon Demo
[00:00:00.289,550] <inf> bt_hci_core: hci_vs_init: HW Platform: Nordic Semiconductor (0x0002)
[00:00:00.289,611] <inf> bt_hci_core: hci_vs_init: HW Variant: nRF53x (0x0003)
[00:00:00.289,611] <inf> bt_hci_core: hci_vs_init: Firmware: Standard Bluetooth controller (0x00) Version 216.11532 Build 3803067951
[00:00:00.291,320] <inf> bt_hci_core: bt_dev_show_info: Identity: CD:B8:1D:7E:27:B0 (random)
[00:00:00.291,351] <inf> bt_hci_core: bt_dev_show_info: HCI: version 5.3 (0x0c) revision 0x224b, manufacturer 0x0059
[00:00:00.291,381] <inf> bt_hci_core: bt_dev_show_info: LMP: version 5.3 (0x0c) subver 0x224b
Bluetooth initialized
[00:00:00.291,809] <wrn> bt_hci_core: bt_hci_cmd_send_sync: opcode 0x2036 status 0x01
Advertising failed to start (err -5)

the err code is -5,corresponding the EIO.I tried to debug to trace the error, and I found that the error was generated when calling bt_hci_cmd_send_sync in the le_ext_adv_param_set call,but  i can't understand.

And i also have questions about the adv.c code:

int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
			const struct bt_le_adv_param *param,
			const struct bt_data *ad, size_t ad_len,
			const struct bt_data *sd, size_t sd_len)
{
	struct bt_le_ext_adv_start_param start_param = {
		.timeout = 0,
		.num_events = 0,
	};
	bool dir_adv = (param->peer != NULL);
	struct bt_conn *conn = NULL;
	int err;

	if (!atomic_test_bit(bt_dev.flags, BT_DEV_READY)) {
		return -EAGAIN;
	}

	if (!valid_adv_param(param)) {
		return -EINVAL;
	}

	if (atomic_test_bit(adv->flags, BT_ADV_ENABLED)) {
		return -EALREADY;
	}

	adv->id = param->id;
	err = le_ext_adv_param_set(adv, param, sd != NULL);
	if (err) {
		return err;
	}

	if (!dir_adv) {
		err = bt_le_ext_adv_set_data(adv, ad, ad_len, sd, sd_len);
		if (err) {
			return err;
		}
	} else {
		if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
			start_param.timeout =
				BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT;
			atomic_set_bit(adv->flags, BT_ADV_LIMITED);
		}
	}

	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
	    (param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
		err = le_adv_start_add_conn(adv, &conn);
		if (err) {
			if (err == -ENOMEM && !dir_adv &&
			    !(param->options & BT_LE_ADV_OPT_ONE_TIME)) {
				goto set_adv_state;
			}

			return err;
		}
	}

	err = bt_le_adv_set_enable_ext(adv, true, &start_param);
	if (err) {
		LOG_ERR("Failed to start advertiser");
		if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
			bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
			bt_conn_unref(conn);
		}

		return err;
	}

	if (IS_ENABLED(CONFIG_BT_PERIPHERAL) && conn) {
		/* If undirected connectable advertiser we have created a
		 * connection object that we don't yet give to the application.
		 * Since we don't give the application a reference to manage in
		 * this case, we need to release this reference here
		 */
		bt_conn_unref(conn);
	}

set_adv_state:
	/* Flag always set to false by le_ext_adv_param_set */
	atomic_set_bit_to(adv->flags, BT_ADV_PERSIST, !dir_adv &&
			  !(param->options & BT_LE_ADV_OPT_ONE_TIME));

	return 0;
}


static bool valid_adv_param(const struct bt_le_adv_param *param)
{
	if (param->options & BT_LE_ADV_OPT_EXT_ADV) {
		return false;
	}

	if (param->peer && !(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
		return false;
	}

	return valid_adv_ext_param(param);
}

When I want to send extended adv, I have to add the BT_LE_ADV_OPT_EXT_ADV option, but why does valid_adv_param have these two judgment statements? Does this mean that the system does not support sending extended adv by default (I commented out these two judgment statements when I used them)?

is there an example or demo I can refer to?

looking forward to your reply!

Related