nrf5340 netcore callback after each transmission

Good afternoon!

I didn't find a post with a solution to my problem. If I overlooked something, please feel free to just redirect me :)

Goal:
In our project we want the device to send measurement data to phones and gateways via BLE. Since multiple devices should be able to listen at the same time, we want to use connectionless broadcasting in the form of extended advertising, so we can send larger data packets. (Redundancy and encryption are handled inside the payload itself, so that part is not relevant yet.)
Our plan is to broadcast a new data packet for every advertising event, while keeping the device as energy-efficient as possible.

Background:
We are using the nRF5340, with the Netcore running the Controller and the Appcore running the Host part of the Bluetooth stack. From what I understand, the SoftDevice Controller is better optimized for the nRF5340 than the Zephyr controller (eventhough I then can not edit anything on the firmware of the Netcore).
To achieve "new data per event", the Appcore needs to deliver updated advertising data to the Netcore before each broadcast. The challenge is synchronization. For example, if we had an advertising intervall of 20 ms, there is also the random advertising delay (0–10 ms), so we can not simply update the data on a fixed timer.
Instead, we would need the Netcore to notify the Appcore whenever either a packet was actually transmitted, or is about to be transmitted, so that the payload can be updated before the next broadcast.

Problem:
The radio notification mechanism does not seem to work the same way on the nRF5340, right?
With bt_le_ext_adv_create() we can register a .sent callback, but it only fires when the set number of events has been reached.
If we configure num_events = 1, the callback arrives after every single event — but this means the advertising set stops and has to be restarted each time. In this case, the configured advertising interval is also not followed anymore. We could add a wait timer before restarting, but this does not seem elegant at all.

Question:
Is there a proper way on the nRF5340 to get a callback from the controller before/after each advertising transmission, so that the payload can be updated in sync with every event, without having to constantly stop and restart the advertising set?

Setup: nRF5340, nRF Connect SDK v3.0.0
The code below is just a basic extended advertising code I use to experiment.

Any examples or guidance would be much appreciated. Thanks!

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/hci.h>

static int start_advertising(struct bt_le_ext_adv *adv)
{
	int err;

	printk("Starting Extended Advertising\n");
	err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT);
	if (err) {
		printk("Failed to start extended advertising (err %d)\n", err);
	}

	return err;
}

static const struct bt_data ad[] = {
	BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};

static int create_advertising_set(struct bt_le_ext_adv **adv)
{
    int err;


    struct bt_le_adv_param param = {
        .id = BT_ID_DEFAULT,
        .sid = 0,
        .secondary_max_skip = 0,
        .options = BT_LE_ADV_OPT_EXT_ADV | BT_LE_ADV_OPT_USE_IDENTITY | BT_LE_ADV_OPT_NO_2M,
        .interval_min = 3200, // 2000 ms in 0.625 ms steps
        .interval_max = 3200,
        .peer = NULL,
    };

    err = bt_le_ext_adv_create(&param, NULL, adv);
    if (err) {
        printk("Failed to create advertising set (err %d)\n", err);
        return err;
    }

    return 0;
}

int main(void)
{
	int err;
	struct bt_le_ext_adv *adv;

	printk("Starting main loop\n");

	/* Initialize the Bluetooth Subsystem */
	err = bt_enable(NULL);
	if (err) {
		printk("Bluetooth init failed (err %d)\n", err);
		return err;
	}
	
	/* Create a nonconnectable advertising set with the custom parameters */
	err = create_advertising_set(&adv);
	if (err) {
		return err;
	}

	/* Set advertising data to have complete local name set */
	err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		printk("Failed to set advertising data (err %d)\n", err);
		return 0;
	}

	err = start_advertising(adv);
	if (err) {
		return err;
	}

    /* Just keep running, no connections possible */
    for (;;) {
        k_sleep(K_SECONDS(1));
    }

    return err;
}
1122.prj.conf

Parents Reply Children
No Data
Related