Seeed Xiao nRF52840 BLE Mesh Could Not Be Detectable

Hi Everyone! currently I’ve been working on my BLE Mesh network using Seeed Xiao nRF52840 sense and the non sense one in nRF SDK VS Code by flashing uf2 file. I tried to run some examples project from Zephyr called mesh_provisioner, the program can be flashed without any problem but when i try to scan it by using nRF Mesh App, my phone can not detect anything from that program (which it should appear as Zephyr device). Another one, when i try to run example project from nrf called mesh sensor and mesh observer, when i flash the uf2 file, the COM port just missing. I tried 2.4.0, 2.5.1, and 2.5.2 version and all of those versions gave me the same result.

I did not make any modification with the example project provided that i tried before. I am really stuck at this point and i could not run any Mesh project both on Seeed Xiao nRF52840 sense and non sense one. Please, can anyone here help me to solve this problem? Thank you very much

Hi there,

So ok that’s a lot to unpack here. The uf2 file is drag and drop? file
You do understand that part right?
You put the device in bootloader mode it shows up as a drive and you drag the Uf2 file to it, Period. (it resets itself and reboots)
Are you doing that?

Have you looked (scanned) with BLE in Nrf_connect_for Desktop or the mobile App version? What is your mobile device. (old iphones) don’t do mesh for example, BTW :v:

Lots of folks on here working in the mesh stuff so Reply and others will also jump in to help. You using a dev board or Raw dogging it (chip only) :grin:

HTH
GL :slight_smile: PJ :v:

Hi PJ_Glasso thank you so much for replying this.

Yes, i’m doing like you said. I put my xiao in bootloader mode and it shows up as a driver, then i drag the uf2 file from nrf SDK I have programmed before. Is there anything wrong with that? (sorry, i got this tutorial on youtube so i just followed it straight away)

Well, for scanning the BLE Mesh, I am using the nRF Mesh that i downloaded it from App Store with my iphone. I also have tried to scan it using nRF connect for desktop mobile app, but still the BLE Mesh device did not appear.

I really need your help, thank you so much

Hi there,

Ok , well sounds like your doing it properly then. :+1:
Which file are you using ? you have a link to it?

HTH
GL :slight_smile: Pj :v:

It is Bluetooth Mesh Provisioner, i think you can look up to it in nRF Connect VS Code extension->browse samples->2.5.2[nrf]-> Bluetooth Mesh Provisioner or here’s the main.c and configuration file

main.c

/*
 * Copyright (c) 2019 Tobias Svehagen
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/sys/printk.h>
#include <zephyr/settings/settings.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/mesh.h>
#include <zephyr/drivers/gpio.h>

#define SW0_NODE	DT_ALIAS(sw0)

static const uint16_t net_idx;
static const uint16_t app_idx;
static uint16_t self_addr = 1, node_addr;
static const uint8_t dev_uuid[16] = { 0xdd, 0xdd };
static uint8_t node_uuid[16];

K_SEM_DEFINE(sem_unprov_beacon, 0, 1);
K_SEM_DEFINE(sem_node_added, 0, 1);
#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
K_SEM_DEFINE(sem_button_pressed, 0, 1);
#endif

static struct bt_mesh_cfg_cli cfg_cli = {
};

static void health_current_status(struct bt_mesh_health_cli *cli, uint16_t addr,
				  uint8_t test_id, uint16_t cid, uint8_t *faults,
				  size_t fault_count)
{
	size_t i;

	printk("Health Current Status from 0x%04x\n", addr);

	if (!fault_count) {
		printk("Health Test ID 0x%02x Company ID 0x%04x: no faults\n",
		       test_id, cid);
		return;
	}

	printk("Health Test ID 0x%02x Company ID 0x%04x Fault Count %zu:\n",
	       test_id, cid, fault_count);

	for (i = 0; i < fault_count; i++) {
		printk("\t0x%02x\n", faults[i]);
	}
}

static struct bt_mesh_health_cli health_cli = {
	.current_status = health_current_status,
};

static struct bt_mesh_model root_models[] = {
	BT_MESH_MODEL_CFG_SRV,
	BT_MESH_MODEL_CFG_CLI(&cfg_cli),
	BT_MESH_MODEL_HEALTH_CLI(&health_cli),
};

static struct bt_mesh_elem elements[] = {
	BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE),
};

static const struct bt_mesh_comp mesh_comp = {
	.cid = BT_COMP_ID_LF,
	.elem = elements,
	.elem_count = ARRAY_SIZE(elements),
};

static void setup_cdb(void)
{
	struct bt_mesh_cdb_app_key *key;
	uint8_t app_key[16];
	int err;

	key = bt_mesh_cdb_app_key_alloc(net_idx, app_idx);
	if (key == NULL) {
		printk("Failed to allocate app-key 0x%04x\n", app_idx);
		return;
	}

	bt_rand(app_key, 16);

	err = bt_mesh_cdb_app_key_import(key, 0, app_key);
	if (err) {
		printk("Failed to import appkey into cdb. Err:%d\n", err);
		return;
	}

	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
		bt_mesh_cdb_app_key_store(key);
	}
}

static void configure_self(struct bt_mesh_cdb_node *self)
{
	struct bt_mesh_cdb_app_key *key;
	uint8_t app_key[16];
	uint8_t status = 0;
	int err;

	printk("Configuring self...\n");

	key = bt_mesh_cdb_app_key_get(app_idx);
	if (key == NULL) {
		printk("No app-key 0x%04x\n", app_idx);
		return;
	}

	err = bt_mesh_cdb_app_key_export(key, 0, app_key);
	if (err) {
		printk("Failed to export appkey from cdb. Err:%d\n", err);
		return;
	}

	/* Add Application Key */
	err = bt_mesh_cfg_cli_app_key_add(self->net_idx, self->addr, self->net_idx, app_idx,
					  app_key, &status);
	if (err || status) {
		printk("Failed to add app-key (err %d, status %d)\n", err,
		       status);
		return;
	}

	err = bt_mesh_cfg_cli_mod_app_bind(self->net_idx, self->addr, self->addr, app_idx,
					   BT_MESH_MODEL_ID_HEALTH_CLI, &status);
	if (err || status) {
		printk("Failed to bind app-key (err %d, status %d)\n", err,
		       status);
		return;
	}

	atomic_set_bit(self->flags, BT_MESH_CDB_NODE_CONFIGURED);

	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
		bt_mesh_cdb_node_store(self);
	}

	printk("Configuration complete\n");
}

static void configure_node(struct bt_mesh_cdb_node *node)
{
	NET_BUF_SIMPLE_DEFINE(buf, BT_MESH_RX_SDU_MAX);
	struct bt_mesh_comp_p0_elem elem;
	struct bt_mesh_cdb_app_key *key;
	uint8_t app_key[16];
	struct bt_mesh_comp_p0 comp;
	uint8_t status;
	int err, elem_addr;

	printk("Configuring node 0x%04x...\n", node->addr);

	key = bt_mesh_cdb_app_key_get(app_idx);
	if (key == NULL) {
		printk("No app-key 0x%04x\n", app_idx);
		return;
	}

	err = bt_mesh_cdb_app_key_export(key, 0, app_key);
	if (err) {
		printk("Failed to export appkey from cdb. Err:%d\n", err);
		return;
	}

	/* Add Application Key */
	err = bt_mesh_cfg_cli_app_key_add(net_idx, node->addr, net_idx, app_idx, app_key, &status);
	if (err || status) {
		printk("Failed to add app-key (err %d status %d)\n", err, status);
		return;
	}

	/* Get the node's composition data and bind all models to the appkey */
	err = bt_mesh_cfg_cli_comp_data_get(net_idx, node->addr, 0, &status, &buf);
	if (err || status) {
		printk("Failed to get Composition data (err %d, status: %d)\n",
		       err, status);
		return;
	}

	err = bt_mesh_comp_p0_get(&comp, &buf);
	if (err) {
		printk("Unable to parse composition data (err: %d)\n", err);
		return;
	}

	elem_addr = node->addr;
	while (bt_mesh_comp_p0_elem_pull(&comp, &elem)) {
		printk("Element @ 0x%04x: %u + %u models\n", elem_addr,
		       elem.nsig, elem.nvnd);
		for (int i = 0; i < elem.nsig; i++) {
			uint16_t id = bt_mesh_comp_p0_elem_mod(&elem, i);

			if (id == BT_MESH_MODEL_ID_CFG_CLI ||
			    id == BT_MESH_MODEL_ID_CFG_SRV) {
				continue;
			}
			printk("Binding AppKey to model 0x%03x:%04x\n",
			       elem_addr, id);

			err = bt_mesh_cfg_cli_mod_app_bind(net_idx, node->addr, elem_addr, app_idx,
							   id, &status);
			if (err || status) {
				printk("Failed (err: %d, status: %d)\n", err,
				       status);
			}
		}

		for (int i = 0; i < elem.nvnd; i++) {
			struct bt_mesh_mod_id_vnd id =
				bt_mesh_comp_p0_elem_mod_vnd(&elem, i);

			printk("Binding AppKey to model 0x%03x:%04x:%04x\n",
			       elem_addr, id.company, id.id);

			err = bt_mesh_cfg_cli_mod_app_bind_vnd(net_idx, node->addr, elem_addr,
							       app_idx, id.id, id.company, &status);
			if (err || status) {
				printk("Failed (err: %d, status: %d)\n", err,
				       status);
			}
		}

		elem_addr++;
	}

	atomic_set_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED);

	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
		bt_mesh_cdb_node_store(node);
	}

	printk("Configuration complete\n");
}

static void unprovisioned_beacon(uint8_t uuid[16],
				 bt_mesh_prov_oob_info_t oob_info,
				 uint32_t *uri_hash)
{
	memcpy(node_uuid, uuid, 16);
	k_sem_give(&sem_unprov_beacon);
}

static void node_added(uint16_t idx, uint8_t uuid[16], uint16_t addr, uint8_t num_elem)
{
	node_addr = addr;
	k_sem_give(&sem_node_added);
}

static const struct bt_mesh_prov prov = {
	.uuid = dev_uuid,
	.unprovisioned_beacon = unprovisioned_beacon,
	.node_added = node_added,
};

static int bt_ready(void)
{
	uint8_t net_key[16], dev_key[16];
	int err;

	err = bt_mesh_init(&prov, &mesh_comp);
	if (err) {
		printk("Initializing mesh failed (err %d)\n", err);
		return err;
	}

	printk("Mesh initialized\n");

	if (IS_ENABLED(CONFIG_BT_SETTINGS)) {
		printk("Loading stored settings\n");
		settings_load();
	}

	bt_rand(net_key, 16);

	err = bt_mesh_cdb_create(net_key);
	if (err == -EALREADY) {
		printk("Using stored CDB\n");
	} else if (err) {
		printk("Failed to create CDB (err %d)\n", err);
		return err;
	} else {
		printk("Created CDB\n");
		setup_cdb();
	}

	bt_rand(dev_key, 16);

	err = bt_mesh_provision(net_key, BT_MESH_NET_PRIMARY, 0, 0, self_addr,
				dev_key);
	if (err == -EALREADY) {
		printk("Using stored settings\n");
	} else if (err) {
		printk("Provisioning failed (err %d)\n", err);
		return err;
	} else {
		printk("Provisioning completed\n");
	}

	return 0;
}

static uint8_t check_unconfigured(struct bt_mesh_cdb_node *node, void *data)
{
	if (!atomic_test_bit(node->flags, BT_MESH_CDB_NODE_CONFIGURED)) {
		if (node->addr == self_addr) {
			configure_self(node);
		} else {
			configure_node(node);
		}
	}

	return BT_MESH_CDB_ITER_CONTINUE;
}

#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET_OR(SW0_NODE, gpios, {0});
static struct gpio_callback button_cb_data;

static void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
	k_sem_give(&sem_button_pressed);
}

static void button_init(void)
{
	int ret;

	if (!gpio_is_ready_dt(&button)) {
		printk("Error: button device %s is not ready\n", button.port->name);
		return;
	}
	ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
	if (ret != 0) {
		printk("Error %d: failed to configure %s pin %d\n", ret, button.port->name,
		       button.pin);
		return;
	}
	ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
	if (ret != 0) {
		printk("Error %d: failed to configure interrupt on %s pin %d\n", ret,
		       button.port->name, button.pin);
		return;
	}
	gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
	gpio_add_callback(button.port, &button_cb_data);
}
#endif

int main(void)
{
	char uuid_hex_str[32 + 1];
	int err;

	printk("Initializing...\n");

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

	printk("Bluetooth initialized\n");
	bt_ready();

#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
	button_init();
#endif

	while (1) {
		k_sem_reset(&sem_unprov_beacon);
		k_sem_reset(&sem_node_added);
		bt_mesh_cdb_node_foreach(check_unconfigured, NULL);

		printk("Waiting for unprovisioned beacon...\n");
		err = k_sem_take(&sem_unprov_beacon, K_SECONDS(10));
		if (err == -EAGAIN) {
			continue;
		}

		bin2hex(node_uuid, 16, uuid_hex_str, sizeof(uuid_hex_str));

#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
		k_sem_reset(&sem_button_pressed);
		printk("Device %s detected, press button 1 to provision.\n", uuid_hex_str);
		err = k_sem_take(&sem_button_pressed, K_SECONDS(30));
		if (err == -EAGAIN) {
			printk("Timed out, button 1 wasn't pressed in time.\n");
			continue;
		}
#endif

		printk("Provisioning %s\n", uuid_hex_str);
		err = bt_mesh_provision_adv(node_uuid, net_idx, 0, 0);
		if (err < 0) {
			printk("Provisioning failed (err %d)\n", err);
			continue;
		}

		printk("Waiting for node to be added...\n");
		err = k_sem_take(&sem_node_added, K_SECONDS(10));
		if (err == -EAGAIN) {
			printk("Timeout waiting for node to be added\n");
			continue;
		}

		printk("Added node 0x%04x\n", node_addr);
	}
	return 0;
}

prj.conf

#CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=1408
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
# The Bluetooth API should not be used from a preemptive thread:
CONFIG_MAIN_THREAD_PRIORITY=-2

CONFIG_BT=y
#CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_OBSERVER=y
CONFIG_BT_BROADCASTER=y

CONFIG_BT_CTLR_DUP_FILTER_LEN=0
CONFIG_BT_CTLR_LE_ENC=n
CONFIG_BT_CTLR_LE_PING=n
CONFIG_BT_DATA_LEN_UPDATE=n
CONFIG_BT_PHY_UPDATE=n
CONFIG_BT_CTLR_MIN_USED_CHAN=n
CONFIG_BT_CTLR_PRIVACY=n
CONFIG_BT_CTLR_CHAN_SEL_2=n

CONFIG_BT_MESH=y
CONFIG_BT_MESH_SUBNET_COUNT=1
CONFIG_BT_MESH_APP_KEY_COUNT=1
CONFIG_BT_MESH_ADV_BUF_COUNT=10
CONFIG_BT_MESH_TX_SEG_MSG_COUNT=3
CONFIG_BT_MESH_RX_SEG_MAX=32
CONFIG_BT_MESH_MODEL_GROUP_COUNT=2
CONFIG_BT_MESH_LABEL_COUNT=0
CONFIG_BT_MESH_CFG_CLI=y
CONFIG_BT_MESH_HEALTH_CLI=y
CONFIG_BT_MESH_BEACON_ENABLED=n
CONFIG_BT_MESH_RELAY=y
CONFIG_BT_MESH_RELAY_RETRANSMIT_COUNT=3

CONFIG_BT_MESH_PROVISIONER=y
CONFIG_BT_MESH_PROV_DEVICE=n
CONFIG_BT_MESH_CDB=y
CONFIG_BT_MESH_CDB_NODE_COUNT=16
CONFIG_BT_MESH_CDB_SUBNET_COUNT=3
CONFIG_BT_MESH_CDB_APP_KEY_COUNT=3

CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y
CONFIG_BT_MESH_RPL_STORE_TIMEOUT=600

#CONFIG_BT_MESH_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_SETTINGS_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_NET_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_MODEL_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_TRANS_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_ACCESS_LOG_LEVEL_DBG=y

#CONFIG_BT_MESH_LOW_POWER=y
#CONFIG_BT_MESH_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_LOW_POWER_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_BEACON_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_CRYPTO_LOG_LEVEL_DBG=y
#CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y

hi can anyone help me with implementing ecdh encrypion on seed xiao nrf52840 mbed enabled board

HI there,

And welcome here…
So here is a video of it’s operation, is this for a BLE system?

Can you describe what it is you want to achieve?

HTH
GL :slight_smile: PJ :v:

So iwant to encrypt and decrypt the data using assymetric ECDh and symeetric Aes , thatvis data packet will come through ble using aes encryption but the aes key will be encrypted itself by aes , for implement aes i ho the resources but I am facing difficulty to implement ECDh , I am implementing it Arduino ide using mbed tls li raray the code is getting compiled and uploaded but it is not showing g output may be crashing . Any help would be greatly appreciated
Hardware -seeed xiao nef52840
Ide -arduino ide
Library mbed tls

Hi there,

Ok , so Looks like it’s common, I was surprised my colleagues agree
The combination of ECDH + AES encryption is a modern and secure design pattern, widely used in both consumer and industrial products for secure communication over constrained wireless channels like BLE.

From experience, here are the usual stumbling blocks:

1. Lack of Serial Output / Silent Failures

  • Often due to stack overflow, malloc failures, or MbedTLS entropy/seeding issues.
  • The Xiao nRF52840 has 256KB of RAM, but Arduino’s heap layout can be limiting.

:wrench: Fix tip: Make sure they run mbedtls_memory_buffer_alloc_init() and avoid heap-heavy objects unless needed.

2. Missing Platform Functions

  • Some MbedTLS features (like entropy collection or platform time) are stubbed or unimplemented in Arduino builds.
  • ECDH requires seeding RNG properly, and if that’s broken, the keygen silently fails.

:wrench: Fix tip: Explicitly seed using mbedtls_ctr_drbg_seed() with mbedtls_entropy_func and a real entropy source.

3. MbedTLS not linked correctly

  • Even though mbedtls compiles, not all features may be included in the build.
  • If they included mbedtls/config.h without proper flags (e.g., enabling MBEDTLS_ECDH_C and MBEDTLS_BIGNUM_C), the result can be undefined behavior or missing functions.

You must define config flags like:

#define MBEDTLS_ECDH_C
#define MBEDTLS_ECP_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C

Yes, it’s absolutely possible to:

  • Perform ECDH (e.g., using Curve25519 or secp256r1),
  • Derive a shared key,
  • Encrypt/decrypt with AES using MbedTLS on the Xiao nRF52840.

But Arduino IDE + MbedTLS is a tough combo without debug support, so you may want to:

  • Test smaller ECDH-only examples first,
  • Print intermediate steps (Serial.print()),
  • Consider switching to Zephyr or nRF SDK later for more stability and easier debugging.

The flow is valid and secure in principle:

  1. ECDH → derive a shared secret between two BLE peers.
  2. Use that shared secret to derive a symmetric AES key.
  3. Use AES (e.g. AES-GCM or AES-128-CBC) to encrypt/decrypt the BLE data payload.

This is a classic hybrid encryption scheme: asymmetric key agreement (ECDH) + symmetric encryption (AES). It’s widely used in secure communications (e.g. TLS, Signal protocol).

here is an older lightweight example for the Xiao with a different POV.
mind the header , i.e. must use BSP 1.1.1 for it to run.

/*
 * Xiao nRF52840 - ECDH Key Exchange + AES-128 Encryption Example
 * Uses MbedTLS (included with Seeed nRF52 BSP 1.1.1+)
 */

#include <mbedtls/ecdh.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/entropy.h>
#include <mbedtls/aes.h>

void setup() {
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Starting ECDH + AES example...");

  // === Setup ===
  mbedtls_ecdh_context ctx;
  mbedtls_entropy_context entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  const char *pers = "ecdh";

  mbedtls_ecdh_init(&ctx);
  mbedtls_ctr_drbg_init(&ctr_drbg);
  mbedtls_entropy_init(&entropy);

  if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                             (const unsigned char *)pers, strlen(pers)) != 0) {
    Serial.println("DRBG seed failed!");
    return;
  }

  // Load curve
  mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1);

  // Generate local keypair
  if (mbedtls_ecdh_gen_public(&ctx.grp, &ctx.d, &ctx.Q,
                              mbedtls_ctr_drbg_random, &ctr_drbg) != 0) {
    Serial.println("Keygen failed");
    return;
  }

  // For testing, simulate peer public key with own public key
  mbedtls_ecp_copy(&ctx.Qp, &ctx.Q);

  // Compute shared secret
  unsigned char shared_secret[32];
  if (mbedtls_ecdh_compute_shared(&ctx.grp, &ctx.z, &ctx.Qp, &ctx.d,
                                  mbedtls_ctr_drbg_random, &ctr_drbg) != 0) {
    Serial.println("Shared secret calc failed!");
    return;
  }

  mbedtls_mpi_write_binary(&ctx.z, shared_secret, 32);
  Serial.print("Shared Secret: ");
  for (int i = 0; i < 32; i++) Serial.printf("%02X", shared_secret[i]);
  Serial.println();

  // === AES encrypt with 128-bit key ===
  mbedtls_aes_context aes;
  mbedtls_aes_init(&aes);
  const char *plaintext = "HelloBLE12345678"; // 16 bytes
  uint8_t ciphertext[16];

  mbedtls_aes_setkey_enc(&aes, shared_secret, 128); // Use first 16 bytes
  mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, (const uint8_t *)plaintext, ciphertext);

  Serial.print("Ciphertext: ");
  for (int i = 0; i < 16; i++) Serial.printf("%02X", ciphertext[i]);
  Serial.println();

  mbedtls_aes_free(&aes);
  mbedtls_ecdh_free(&ctx);
  mbedtls_ctr_drbg_free(&ctr_drbg);
  mbedtls_entropy_free(&entropy);

  Serial.println("Done.");
}

void loop() {
delay (50); // allows time for bootloader if a crash occurs.
}

HTH
GL :slight_smile: PJ :v:

I will say , the nRF54L15 is a better fit However since it’s not out yet You can add more flash or use the grove Expansion base and add more Flash as in the examples for that.

thanks for the help i will try this and update you about the results

i tried these steps but its not working should i switch the platfrom because it is working in zehyr or nrf connect sdk