Cmake error

Hi!

I have been developing a GATTClient and GATTServer on two separate nrf52840dk boards and have been doing so for a long time.

This Friday I got everything to work when it comes to notifications and write without response. Offline I tried adding functionality for extending the data length and setting the PHY to 2 on the server. Once I tried to build this code and flash it to my Server the whole functionality just crashed.

It went from looking like this (GATTClient --> GATTServer) on the left and GATTServer output on the right:
 

To now the dev-kits are connecting but the Client does not discover the service I have built on the Server side which it has done flawlessly so far.

I THINK I have narrowed it down to some sort of Cmake issue on the Client side for some reason, and I get the following error messages in my output console of the NRF Connect for VSCode:



I have tried:

- Restarting VSCode and my computer several times.

- Updating every extension I have and also VSCode

- Re-installed the nRF Connect extension pack for VSCode

- Re-installed the SDK Toolchain to get a newer version, from 2.7.0 to 2.9.1 

And still this issue is there, please help me how to proceed?

Regards,
Björn

PS: Just for reference, I attach the Client code below:

/*
 * Copyright (c) 2020 SixOctets Systems
 *
 * SPDX-License-Identifier: Apache-2.0
 */

 #include <stdio.h>
 #include <stddef.h>
 #include <errno.h>
 
 #include <zephyr/kernel.h>
 #include <zephyr/sys/printk.h>
 #include <zephyr/sys/byteorder.h>
 
 #include <zephyr/bluetooth/bluetooth.h>
 #include <zephyr/bluetooth/hci.h>
 #include <zephyr/bluetooth/conn.h>
 #include <zephyr/bluetooth/uuid.h>
 #include <zephyr/bluetooth/gatt.h>
 
 /* --------------------- START OF FROG UUID:s ---------------- */
 
 #define FROG_SERVICE BT_UUID_128_ENCODE(0xd099cd20, 0xb2ea, 0x11e5, 0xbf01, 0x0002a5d5c51b)
 // Notify characteristics
 #define FROG_TXDATA_UUID BT_UUID_128_ENCODE(0x388706a0, 0xb2eb, 0x11e5, 0xa790, 0x0002a5d5c51b)
 #define FROG_RXCREDIT BT_UUID_128_ENCODE(0x43802b40, 0xb2eb, 0x11e5, 0xb6c5, 0x0002a5d5c51b)
 
 // Write without response characteristics
 #define FROG_TXCREDIT_UUID BT_UUID_128_ENCODE(0x2c1b1820, 0xb2eb, 0x11e5, 0x8f66, 0x0002a5d5c51b)
 #define FROG_RXDATA BT_UUID_128_ENCODE(0x2016ec20, 0xb2eb, 0x11e5, 0xa307, 0x0002a5d5c51b)
 
 // Macros for service and characteristics
 
 #define BT_UUID_FROG BT_UUID_DECLARE_128(FROG_SERVICE)
 #define BT_UUID_TXDATA BT_UUID_DECLARE_128(FROG_TXDATA_UUID)
 #define BT_UUID_RXCREDIT BT_UUID_DECLARE_128(FROG_RXCREDIT)
 
 #define BT_UUID_TXCREDIT BT_UUID_DECLARE_128(FROG_TXCREDIT_UUID)
 #define BT_UUID_RXDATA BT_UUID_DECLARE_128(FROG_RXDATA)
 
 /* ----------------------------- END ------------------------- */
 
 #define STACKSIZE 1024
 #define PRIORITY 7
 static uint16_t txcredit_wor_data = 2U;
 
 
 static int scan_start(void);
 
 static struct bt_conn *default_conn;
 /* Variable for write without response*/
 static uint16_t char_handle = 0;
 
 static struct bt_uuid_16 frog_ccc_discover_uuid = BT_UUID_INIT_16(0);
 static struct bt_uuid_128 frog_discover_uuid = BT_UUID_INIT_128(0);
 //static const struct bt_uuid *ccc_uuid = BT_UUID_GATT_CCC;
 //static const struct bt_uuid *ccc_uuid2 = BT_UUID_GATT_CCC;
 //static const struct bt_uuid *ccc_uuid2;
 static struct bt_gatt_discover_params discover_params;
 static struct bt_gatt_subscribe_params subscribe_params_txdata;
 static struct bt_gatt_subscribe_params subscribe_params_rxcredit;
 
 static uint8_t notify_func(struct bt_conn *conn,
				struct bt_gatt_subscribe_params *params,
				const void *data, uint16_t length)
 {
 
	 if (!data) {
		 printk("[UNSUBSCRIBED]\n");
		 params->value_handle = 0U;
		 return BT_GATT_ITER_STOP;
	 }
 
 
	 printf("[NOTIFICATION]: Data from server %p.\n", data);
	 uint8_t* uint8data = (uint8_t *)data;
	 printf("[NOTIFICATION]: Data from server");
	 int i;
	 for (i = 0; i < length; ++i)
	 {
		 printf(" 0x%02x", uint8data[i]);
	 }
	 printf("\n");	
 
	 return BT_GATT_ITER_CONTINUE;
 }
 
 static uint8_t discover_func(struct bt_conn *conn,
				  const struct bt_gatt_attr *attr,
				  struct bt_gatt_discover_params *params)
 {
	 int err;
 
	 if (!attr) {
		 printk("Discover complete\n");
		 (void)memset(params, 0, sizeof(*params));
		 return BT_GATT_ITER_STOP;
	 }
 
	 printk("[ATTRIBUTE] handle %u\n", attr->handle);
 
	 if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_FROG)) {
		 printk("Discovering TxData\n");
 
		 //What attribute in the table are we looking for
		 //Copy that UUID information into the &frog_discover_uuid address
		 //Put the information into the discover parameters and call the bt_gatt_discover to find that characteristic
		 //BUT search in the next start_handle, otherwise we are looking in the same place. 
		 memcpy(&frog_discover_uuid, BT_UUID_TXDATA, sizeof(frog_discover_uuid));
		 discover_params.uuid = &frog_discover_uuid.uuid;
		 discover_params.start_handle = attr->handle + 1;
		 discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
 
		 err = bt_gatt_discover(conn, &discover_params);
		 if (err) {
			 printk("Discover failed (err %d)\n", err);
		 }
 
	 //	
	 } else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_TXDATA)) {
 
		 printk("Discovering CCCD TxData\n");
	 
		 memcpy(&frog_ccc_discover_uuid, BT_UUID_GATT_CCC, sizeof(frog_ccc_discover_uuid));
		 discover_params.uuid = &frog_ccc_discover_uuid.uuid;
		 discover_params.start_handle = bt_gatt_attr_value_handle(attr);//attr->handle + 1;
		 discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
 
		 subscribe_params_txdata.value_handle = bt_gatt_attr_value_handle(attr);
 
		 err = bt_gatt_discover(conn, &discover_params);
		 if (err) {
			 printk("Discover failed (err %d)\n", err);
		 }
	 } else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_RXCREDIT)) {
		 
		 printk("[CHARACTERISTIC] RxCredit handle %u\n", attr->handle);
		 printk("Discovering CCC RxCredit\n");
		 //memcpy(&frog_discover_uuid, BT_UUID_GATT_CCC, sizeof(frog_discover_uuid));
 
		 memcpy(&frog_ccc_discover_uuid, BT_UUID_GATT_CCC, sizeof(frog_ccc_discover_uuid));
		 discover_params.uuid = &frog_ccc_discover_uuid.uuid;
		 discover_params.start_handle = bt_gatt_attr_value_handle(attr);
		 discover_params.type = BT_GATT_DISCOVER_DESCRIPTOR;
 
		 printk("Value handle RxCredit: %d \n", bt_gatt_attr_value_handle(attr));
 
		 subscribe_params_rxcredit.value_handle = bt_gatt_attr_value_handle(attr);
 
		 err = bt_gatt_discover(conn, &discover_params);
		 if (err) {
			 printk("Discover failed (err %d)\n", err);
		 }
	 } else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_GATT_CCC)){
		 //printk("Discover params Start handle:%d\n", discover_params.start_handle);
		 //printk("Discover params Value handle: TxData %d\n", subscribe_params_txdata.value_handle);
 
		 printk("Discovered CCCD \n");
 
		 if (attr->handle-1 == subscribe_params_txdata.value_handle)
		 {
			 printk("[SUBSCRIBE PARAMS] TxData\n");
			 subscribe_params_txdata.notify = notify_func;
			 subscribe_params_txdata.value = BT_GATT_CCC_NOTIFY;
			 subscribe_params_txdata.ccc_handle = attr->handle;
	 
			 err = bt_gatt_subscribe(conn, &subscribe_params_txdata);
			 if (err && err != -EALREADY) {
				 printk("Subscribe failed (err %d)\n", err);
			 } else {
				 printk("[SUBSCRIBED] TxData \n");
			 }
 
			 printk("Discovering RxCredit\n");
			 //memcpy(&frog_discover_uuid, BT_UUID_GATT_CCC, sizeof(frog_discover_uuid));
			 memcpy(&frog_discover_uuid, BT_UUID_RXCREDIT, sizeof(frog_discover_uuid));
			 discover_params.uuid = &frog_discover_uuid.uuid;
			 discover_params.start_handle = attr->handle + 1;
			 discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;	
		 } 
 
		 else if (attr->handle-1 == subscribe_params_rxcredit.value_handle)
		 {
			 printk("[SUBSCRIBE PARAMS] RxCredit\n");
			 subscribe_params_rxcredit.notify = notify_func;
			 subscribe_params_rxcredit.value = BT_GATT_CCC_NOTIFY;
			 subscribe_params_rxcredit.ccc_handle = attr->handle;
	 
			 err = bt_gatt_subscribe(conn, &subscribe_params_rxcredit);
			 if (err && err != -EALREADY) {
				 printk("Subscribe failed (err %d)\n", err);
			 } else {
				 printk("[SUBSCRIBED] RxCredit\n");
			 }
			 
			 printk("Discovering TxCredit\n");
			 memcpy(&frog_discover_uuid, BT_UUID_TXCREDIT, sizeof(frog_discover_uuid));
			 discover_params.uuid = &frog_discover_uuid.uuid;
			 discover_params.start_handle = attr->handle + 1;
			 discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;	
 
			 
			 
		 } 
		 
		 //subscribe_params_rxcredit.value_handle = bt_gatt_attr_value_handle(attr); 
		 
 
		 err = bt_gatt_discover(conn, &discover_params);
		 if (err) {
			 printk("Discover failed (err %d)\n", err);
		 }
		 
	 } else if (!bt_uuid_cmp(discover_params.uuid, BT_UUID_TXCREDIT)) {
 
		 // Saving TxCredit handle in char_handle for write without response
		 char_handle = bt_gatt_attr_value_handle(attr);
 
		 printk("Discovering RxData \n");
		 memcpy(&frog_discover_uuid, BT_UUID_RXDATA, sizeof(frog_discover_uuid));
		 discover_params.uuid = &frog_discover_uuid.uuid;
		 discover_params.start_handle = attr->handle + 1;
		 discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
 
		 err = bt_gatt_discover(conn, &discover_params);
		 if (err) {
			 printk("Discover failed (err %d)\n", err);
		 }
 
 
		 return BT_GATT_ITER_STOP;
	 }
 
	 return BT_GATT_ITER_STOP;
 }
 
 static void connected(struct bt_conn *conn, uint8_t conn_err)
 {
	 char addr[BT_ADDR_LE_STR_LEN];
	 int err;
 
	 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
 
	 if (conn_err) {
		 printk("Failed to connect to %s (%u)\n", addr, conn_err);
 
		 bt_conn_unref(default_conn);
		 default_conn = NULL;
 
		 scan_start();
		 return;
	 }
 
	 printk("Connected: %s\n", addr);
 
	 if (conn == default_conn) {
		 memcpy(&frog_discover_uuid, BT_UUID_FROG, sizeof(frog_discover_uuid));
		 discover_params.uuid = &frog_discover_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_PRIMARY;
 
		 err = bt_gatt_discover(default_conn, &discover_params);
		 if (err) {
			 printk("Discover failed(err %d)\n", err);
			 return;
		 }
	 }
 }
 
 static bool eir_found(struct bt_data *data, void *user_data)
 {
	 bt_addr_le_t *addr = user_data;
	 int i;
 
	 printk("[AD]: %u data_len %u\n", data->type, data->data_len);
	 switch (data->type) {
	 case BT_DATA_UUID128_SOME:
	 case BT_DATA_UUID128_ALL:
		 if (data->data_len % BT_UUID_SIZE_128 != 0U) {
			 printk("AD malformed\n");
			 return true;
		 }
		 
		 printk("INSIDE SWITCH\n");
 
		 for (i = 0; i < data->data_len; i += BT_UUID_SIZE_128) {
			 struct bt_uuid *uuid128;
			 uint8_t btadvData[16];
			 memcpy(btadvData, data->data, 16);
			 uuid128 = (struct bt_uuid *)btadvData;
			 int err;
			 printk("INSIDE FOR LOOP\n");
 
 
			 if (bt_uuid_cmp(uuid128, BT_UUID_TXDATA)) {
				 //printk("COMPARISON OK!\n");
				 printk("uuid128 == TXDATA\n");				
					 err = bt_le_scan_stop();
					 if(err) {
						 printk("Stop LE scan failed (err %d)\n", err);					
					 }
				 printk("make connection\n");
 
				 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
						 BT_LE_CONN_PARAM_DEFAULT,
						 &default_conn);
 
				 printk("err: %d\n", err);
 
				 if (err) {
					 printk("Create connection failed (err %d)\n",
						 err);
				 }
				 //continue;
				 return false;
			 } if (bt_uuid_cmp(uuid128, BT_UUID_RXCREDIT)) {
				 //printk("COMPARISON OK!\n");
				 printk("uuid128 == RXCREDIT\n");				
					 err = bt_le_scan_stop();
					 if(err) {
						 printk("Stop LE scan failed (err %d)\n", err);					
					 }
				 printk("make connection");
 
				 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
						 BT_LE_CONN_PARAM_DEFAULT,
						 &default_conn);
 
				 printk("err: %d\n", err);
 
				 if (err) {
					 printk("Create connection failed (err %d)\n",
						 err);
				 }
				 //continue;
				 return false;				
			 }
		 }
	 }
	 return true;
 }
 
 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
			  struct net_buf_simple *ad)
 {
	 char dev[BT_ADDR_LE_STR_LEN];
 
	 bt_addr_le_to_str(addr, dev, sizeof(dev));
	 printk("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i\n",
			dev, type, ad->len, rssi);
 
	 /* We're only interested in connectable events */
	 if (type == BT_HCI_ADV_IND || type == BT_HCI_ADV_DIRECT_IND) {
		 bt_data_parse(ad, eir_found, (void *)addr);
	 }
 }
 
 static int scan_start(void)
 {
	 /* Use active scanning and disable duplicate filtering to handle any
	  * devices that might update their advertising data at runtime.
	  */
	 struct bt_le_scan_param scan_param = {
		 .type       = BT_LE_SCAN_TYPE_ACTIVE,
		 .options    = BT_LE_SCAN_OPT_NONE,
		 .interval   = BT_GAP_SCAN_FAST_INTERVAL,
		 .window     = BT_GAP_SCAN_FAST_WINDOW,
	 };
 
	 return bt_le_scan_start(&scan_param, device_found);
 }
 
 static void disconnected(struct bt_conn *conn, uint8_t reason)
 {
	 char addr[BT_ADDR_LE_STR_LEN];
	 int err;
 
	 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
 
	 printk("Disconnected: %s (reason 0x%02x)\n", addr, reason);
 
	 if (default_conn != conn) {
		 return;
	 }
 
	 bt_conn_unref(default_conn);
	 default_conn = NULL;
 
	 err = scan_start();
	 if (err) {
		 printk("Scanning failed to start (err %d)\n", err);
	 }
 }
 
 BT_CONN_CB_DEFINE(conn_callbacks) = {
	 .connected = connected,
	 .disconnected = disconnected,
 };
 
 int frog_txcredit_wor(uint16_t txcredit_val) {
	 return bt_gatt_write_without_response(default_conn, char_handle, &txcredit_val, sizeof(txcredit_val), false);
 }
 
 
 static void simulate_data(void)
 {
	 txcredit_wor_data++;
	 if (txcredit_wor_data == 200) {
		 txcredit_wor_data = 2;
	 }
 
 }
 
 /* Function to send data using Write Without Response */
 void write_without_resp_data_thread(void) { //uint16_t *data, uint16_t len
 
	 printk("[CHAR] WWOR Handle: %u\n", char_handle);
 
 
 
	 printk("DO WE EVEN GET HERE?!?!\n");
 
	 while (1) {
 
		 if (!default_conn || !char_handle) {
			 printk("No connection or characteristic handle found!\n");
			 //return;
		 }
 
		 printk("[CHAR] WWOR Handle: %u\n", char_handle);
 
		 simulate_data();
 
		 int err = frog_txcredit_wor(txcredit_wor_data);
 
		 if (err) {
			 printk("Write Without Response failed (err %d)\n", err);
		 } else {
			 printk("Write Without Response sent: %u\n", txcredit_wor_data); //len,
		 }
		 k_sleep(K_MSEC(500));
 
	 }
 
 }
 
 
 
 
 int main(void)
 {
	 int err;
 
	 err = bt_enable(NULL);
	 if (err) {
		 printk("Bluetooth init failed (err %d)\n", err);
		 return 0;
	 }
 
	 printk("Bluetooth initialized\n");
 
	 err = scan_start();
 
	 if (err) {
		 printk("Scanning failed to start (err %d)\n", err);
		 return 0;
	 }
 
	 printk("Scanning successfully started\n");
 
	 /* Wait for connection */
	 while (!default_conn) {
		 k_sleep(K_MSEC(100));
	 }
 
 
	 return 0;
 }
 K_THREAD_DEFINE(write_without_resp_thread, STACKSIZE, write_without_resp_data_thread, NULL, NULL,
	 NULL, PRIORITY, 0, 0);

  • Hi

    This CMake error is common when using NCS and VS Code, so I'm guessing you had this one before seeing these runtime issues as well.

    You say you have increased the data length and changed the PHY to 2 on the server side. Can you explain more on this. What is the new data length you've set. Is PHY 2 referring to the 2Mbps PHY or the S=2 Coded PHY (which isn't supported). Have you also set this on the client side or just on the server side? I assume the build still completes on both server and client side afterwards, and it is during runtime after flashing that it fails/crashes.

    Make sure the PHY you've set in the server side is supported on the client side as well, and how exactly and to how much did you change the data length on your end? From the latest log it seems like the MTU (throughput) is down to 23 bytes, but I assume you've increased the data length to more than 23 bytes? Please see more on maximizing Bluetooth data throughput here.

    Best regards,

    Simon

  • Hello Simon!

    I have reverted both my Client and Server back to my last working code base and I have also tried making new builds for on both sides and it still does not work.

    I understand how throughput and maximizing it works so this is not the issue. But I can ask about this, in the Bluetooth basics course in DevAcademy, in lesson 3 exercise 2 a solution is made for data length extension and PHY, this is adaptable in my GATTServer right?

    This is my GATTServer that was working before together with the GATTClient that I have attached in the original forum post:

    /* 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 <string.h>
     #include <errno.h>
     #include <zephyr/sys/printk.h>
     #include <zephyr/sys/byteorder.h>
     #include <zephyr/kernel.h>
     #include <zephyr/logging/log.h>
     
     #include <zephyr/settings/settings.h>
     
     #include <zephyr/bluetooth/bluetooth.h>
     #include <zephyr/bluetooth/hci.h>
     #include <zephyr/bluetooth/conn.h>
     #include <zephyr/bluetooth/uuid.h>
     #include <zephyr/bluetooth/gatt.h>
     
     #define NOTIFY_INTERVAL 500
     #define VND_MAX_LEN 20
     
    
     static uint8_t frog_txd_frames = 100U;
     static uint16_t frog_rxc_frames = 2U;
     static bool frog_txdnotify_enabled;
     static bool frog_rxcnotify_enabled;
     
     
     #define STACKSIZE 1024
     #define PRIORITY 7
     
     /* ---------------------- FROG SERVICE UUIDs -------------------------- */
     
     #define BT_UUID_FROG_SERVICE_VAL \
    	 BT_UUID_128_ENCODE(0x2016ec20, 0xb2eb, 0x11e5, 0xa307, 0x0002a5d5c51b)
     
     static const struct bt_uuid_128 frog_uuid = BT_UUID_INIT_128(
    	 BT_UUID_FROG_SERVICE_VAL);
     
     static const struct bt_uuid_128 frog_txcredit_uuid = BT_UUID_INIT_128(
    	 BT_UUID_128_ENCODE(0x2c1b1820, 0xb2eb, 0x11e5, 0x8f66, 0x0002a5d5c51b));
     
     static const struct bt_uuid_128 frog_txdata_uuid = BT_UUID_INIT_128(
    	 BT_UUID_128_ENCODE(0x388706a0, 0xb2eb, 0x11e5, 0xa790, 0x0002a5d5c51b));
     
     static const struct bt_uuid_128 frog_rxdata_uuid = BT_UUID_INIT_128(
    	 BT_UUID_128_ENCODE(0x2016ec20, 0xb2eb, 0x11e5, 0xa307, 0x0002a5d5c51b));
     
     static const struct bt_uuid_128 frog_rxcredit_uuid = BT_UUID_INIT_128(
    	 BT_UUID_128_ENCODE(0x43802b40, 0xb2eb, 0x11e5, 0xb6e5, 0x0002a5d5c51b));
     
     
     // Setting up CCCD
     static void frog_txdccc_cfg_changed(const struct bt_gatt_attr *attr,
    				   uint16_t value)
     {
    	 frog_txdnotify_enabled = (value == BT_GATT_CCC_NOTIFY);
     }
     
     static void frog_rxcccc_cfg_changed(const struct bt_gatt_attr *attr,
    				   uint16_t value)
     {
    	 frog_rxcnotify_enabled = (value == BT_GATT_CCC_NOTIFY);
     }
     
     /* ---------------------------- END ------------------------------------*/		
     
     
     
     static ssize_t write_without_rsp_vnd(struct bt_conn *conn,
    					  const struct bt_gatt_attr *attr,
    					  const void *buf, uint16_t len, uint16_t offset,
    					  uint8_t flags)
     {
    	 uint16_t *value = attr->user_data;
     
    	 printk("user_data: %p \n", attr->user_data);
     
    	 if (!(flags & BT_GATT_WRITE_FLAG_CMD)) {
    		 /* Write Request received. Reject it since this Characteristic
    		  * only accepts Write Without Response.
    		  */
    		 return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED);
    	 }
     
    	 if (offset + len > VND_MAX_LEN) {
    		 return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
    	 }
     
    	 memcpy(value + offset, buf, len);
    	 value[offset + len] = 0;
     
    	 return len;
     }
     
     
     /* Callback for handling Write Without Response */
     ssize_t my_write_handler(struct bt_conn *conn, 
    	 const struct bt_gatt_attr *attr, 
    	 const void *buf, 
    	 uint16_t len, 
    	 uint16_t offset, 
    	 uint8_t flags) {
     printk("Received data: %.*s\n", len, (char *)buf);
     return len;  // Return the number of bytes written
     }
     
     /* ----------- FROG SERVICE DECLARATION -----------  */
     
     BT_GATT_SERVICE_DEFINE(frog_srv,
    	 BT_GATT_PRIMARY_SERVICE(&frog_uuid),
    	 BT_GATT_CHARACTERISTIC(&frog_txdata_uuid.uuid, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, NULL, NULL, NULL),
    	 BT_GATT_CCC(frog_txdccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),
    	 BT_GATT_CHARACTERISTIC(&frog_rxcredit_uuid.uuid, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ, NULL, NULL, NULL),
    	 BT_GATT_CCC(frog_rxcccc_cfg_changed, BT_GATT_PERM_READ | BT_GATT_PERM_WRITE),	
    	 BT_GATT_CHARACTERISTIC(&frog_txcredit_uuid.uuid, BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE, NULL, my_write_handler /*write_without_rsp_vnd*/, NULL /*&txcredit_cli_value*/),
    	 BT_GATT_CHARACTERISTIC(&frog_rxdata_uuid.uuid, BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_WRITE, NULL, my_write_handler /*write_without_rsp_vnd*/, NULL /*&rxdata_value*/),
     );
     
     
     /*-------------------- END ------------------------ */
     
     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_UUID128_ALL, BT_UUID_FROG_SERVICE_VAL),
     };
     
     static const struct bt_data sd[] = {
    	 BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
     };
     
     /* Update Maximum Transfer Unit */
     
     void mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx)
     {
    	 printk("Updated MTU: TX: %d RX: %d bytes\n", tx, rx);
     }
     
     /* Register callback functions */
     static struct bt_gatt_cb gatt_callbacks = {
    	 .att_mtu_updated = mtu_updated
     };
     
     static void connected(struct bt_conn *conn, uint8_t err)
     {
    	 if (err) {
    		 printk("Connection failed (err 0x%02x)\n", err);
    	 } else {
    		 printk("Connected\n");
    	 }
     }
     
     static void disconnected(struct bt_conn *conn, uint8_t reason)
     {
    	 printk("Disconnected (reason 0x%02x)\n", reason);
     }
     
     BT_CONN_CB_DEFINE(conn_callbacks) = {
    	 .connected = connected,
    	 .disconnected = disconnected,
     };
     
     static void bt_ready(void)
     {
    	 int err;
     
    	 printk("Bluetooth initialized\n");
     
     
    	 if (IS_ENABLED(CONFIG_SETTINGS)) {
    		 settings_load();
    	 }
     
    	 err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
    	 if (err) {
    		 printk("Advertising failed to start (err %d)\n", err);
    		 return;
    	 }
     
    	 printk("Advertising successfully started\n");
     }
     
     
     // Notify for frog
     
     int frog_txd_notify(uint8_t txd_val)
     {
    	 if (!frog_txdnotify_enabled) {
    		 return -EACCES;
    	 }
     
    	 return bt_gatt_notify(NULL, &frog_srv.attrs[1], 
    				   &txd_val,
    				   sizeof(txd_val));
     }
     
     int frog_rxc_notify(uint8_t rxc_val)
     {
    	 if (!frog_rxcnotify_enabled) {
    		 return -EACCES;
    	 }
     
    	 return bt_gatt_notify(NULL, &frog_srv.attrs[4], 
    				   &rxc_val,
    				   sizeof(rxc_val));
     }
     
     static void simulate_data(void)
     {
    	 frog_txd_frames++;
    	 if (frog_txd_frames == 200) {
    		 frog_txd_frames = 100;
    	 }
     
    	 frog_rxc_frames++;
    	 if (frog_rxc_frames == 150)
    	 {
    		 frog_rxc_frames = 2;
    	 }
    	 
     
     }
     
     void send_data_thread(void)
     {
    	 while(1){
    		 /* Simulate data */
    		 simulate_data();
    		 /* Send notification, the function sends notifications only if a client is subscribed */
    		 frog_txd_notify(frog_txd_frames);
     
    		 frog_rxc_notify(frog_rxc_frames);
     
    		 k_sleep(K_MSEC(NOTIFY_INTERVAL));
    	 }
    		 
     }
     
     
     
     int main(void)
     {
     
    	 int err;
     
    	 err = bt_enable(NULL);
    	 if (err) {
    		 printk("Bluetooth init failed (err %d)\n", err);
    		 return 0;
    	 }
     
    	 bt_ready();
     
    	 bt_gatt_cb_register(&gatt_callbacks);
     
    	 /* Implement notification. At the moment there is no suitable way
    	  * of starting delayed work so we do it here
    	  */
     
    	 while (1) {
    		 k_sleep(K_SECONDS(1));
     
     
    		 //printk("frog_txd_frames: %d \n", frog_txd_frames);
    		 //printk("txcredit_cli_value: %d \n", *txcredit_cli_value);
    		 //printk("rxdata_value: %d \n\n\n", *rxdata_value);
    		 //printk("frog_rxc_frames: %d \n\n\n", frog_rxc_frames);
    		 /* Vendor indication simulation */
    	 }
    	 return 0;
     }
     K_THREAD_DEFINE(send_data_thread_id, STACKSIZE, send_data_thread, NULL, NULL,
    		 NULL, PRIORITY, 0, 0);


    On the GATTServer side I also get this output in the terminal:



    Can these be the issue?

    Regards,
    Björn

  • Hi

    Okay, thank you for the additional info. From the latest screenshot it looks like you're trying to use the NCS v2.9.1 but that the activated toolchain is v2.6.1, which will likely cause these "outdated" messages.

    In the VS Code extension, when building your project, please make sure the SDK and toolchain versions match before pressing the build button. I attached a screenshot from a sample environment on my end. You can open a dropdown menu to choose the toolchain in the "Add Build Configuration" window.

    Best regards,

    Simon

  • Thank you again! Yesterday after I uninstalled everything and installed it again everything started working again so I don't know if there were some driver mismatch somewhere but nonetheless now it is working again.

    Follow up question, can I use the PHY and data length extension used here: https://github.com/NordicDeveloperAcademy/bt-fund/tree/main/v2.9.0-v2.7.0/l3/l3_e2_sol 

    To implement in my GATTServer/Peripheral or would this not work?

    Regards,
    Björn

  • Updating the PHY and data length as per the DevAcademy exercises should work just fine. Just remember that the client needs to support this as well.

    Best regards,

    Simon 

Related