Found valid connection in connected state

Hope you are doing good!

I am using two nrf52833DK's one as a Central and the other as a Peripheral. I am also using another custom board (nrf52833) as a second peripheral.

NCS 2.2.0 for multi NUS central and 2.3.0 for peripheral_uart

Multi-NUS (github.com/.../multi-NUS), working fine.Able to connect the two peripherals.can send and receive data. Now issues i am facing are the following.

  1. When I connect and disconnect the peripheral and connect again(repeating this step every 20 secs), the following message on RTT [00:19:51.936,981] central_uart: ATT error code: 0x20011C0C
    [00:19:56.497,711] bt_conn: Found valid connection in the connected state
    [00:19:56.507,873] bt_conn: Found valid connection in the connected state
    [00:19:56.507,873] central_uart: Connecting failed
    [00:19:59.988,037] central_uart: Disconnected: E8:2B:FD:17:14:C2 (random) (reason 8)
    [00:20:25.330,444] central_uart: Disconnected: F7:13:07:67:2D:04 (random) (reason 8)
  2. Central (Multi-NUS) becomes unresponsive. So peripheral reset has no impact on it. Need to reset the central.
    I followed the https://github.com/NordicMatt/multi-NUS/issues/1 but still the same issue as discussed.

        3. I observed the same that after 

            err = bt_conn_ctx_free(&conns_ctx_lib, conn);  // code added
            Multi-NUS unresponsive 

main.c

   

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

/** @file
 *  @brief Nordic UART Service Client sample
 */

#include <errno.h>
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/sys/byteorder.h>
#include <zephyr/sys/printk.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>
#include <nrfx_rtc.h>                          // RTC // code added by luis pc// code added by usman

#include <bluetooth/services/nus.h>
#include <bluetooth/services/nus_client.h>
#include <bluetooth/gatt_dm.h>
#include <bluetooth/scan.h>
#include <bluetooth/conn_ctx.h>

#include <zephyr/settings/settings.h>

#include <zephyr/drivers/uart.h>

#include <zephyr/logging/log.h>

#include <zephyr/drivers/spi.h>
#include<zephyr/devicetree.h>
#include <zephyr/sys/printk.h>
#include <stdio.h>


#include <zephyr/drivers/gpio.h>

 uint8_t num = 0;


 int8_t Rsrp_Usigned;
const char Rsrp_Quant[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F};
uint8_t Central_Con_Array[6]={0xAA,0xA0,0x00,'&',')',0x00};    //(20A )0xA nrf9160 as gateway (sensor in peripheral),(20B) LTE RSSI it will be fill in nrf9160 ,(21A) BLE RSSI , (21B) simultenous connections  and last element is & ,(20,21)


uint8_t   Central_Arr[30];	
//#include <bluetooth/conn.h>

#define LOG_MODULE_NAME central_uart
LOG_MODULE_REGISTER(LOG_MODULE_NAME,LOG_LEVEL_DBG);

/* UART payload buffer element size. */
#define UART_BUF_SIZE 251   // 20

#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK

#define NUS_WRITE_TIMEOUT K_MSEC(150)
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_RX_TIMEOUT 50

#define ROUTED_MESSAGE_CHAR '*'
#define BROADCAST_INDEX 99


#define SPI_DEV_NAME "spi_3" 
#define cs  DT_ALIAS(led1)// 11 for nrf52833
#define pdn DT_ALIAS(led2)// 28 for nrf52833



static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
static struct k_work_delayable uart_work;

static K_SEM_DEFINE(nus_write_sem, 0, 1);

struct uart_data_t {
	void *fifo_reserved;
	uint8_t  data[UART_BUF_SIZE];
	uint16_t len;
};




BT_CONN_CTX_DEF(conns, CONFIG_BT_MAX_CONN, sizeof(struct bt_nus_client));

static K_FIFO_DEFINE(fifo_uart_tx_data);
static K_FIFO_DEFINE(fifo_uart_rx_data);

static struct bt_conn *default_conn;

static bool routedMessage = false;
static bool messageStart = true;

static struct bt_nus_client nus_client;

struct bt_le_scan_param m_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
	};
/*
static void ble_data_sent(struct bt_nus_client *nus, uint8_t err,
					const uint8_t *const data, uint16_t len)
{
	ARG_UNUSED(nus);

	struct uart_data_t *buf;

	// Retrieve buffer context. //
	buf = CONTAINER_OF(data, struct uart_data_t, data);
	k_free(buf);

	k_sem_give(&nus_write_sem);

	if (err) {
		LOG_WRN("ATT error code: 0x%02X", err);
	}
}
*/
static void ble_data_sent(uint8_t err, const uint8_t *const data, uint16_t len)
{

	k_sem_give(&nus_write_sem);

	if (err) {
		LOG_WRN("ATT error code: 0x%02X", err);
	}
}

/*	New function for sending data into the multi-NUS
* 	Extensions to the behavior of message routing can be made here.
*	If the first character is *, this indicates a routed message.
*	If the first character is not *, then this is a broadcast message sent to all peers.
* 	Iaf the message is routed, the two characters after the * will be read as the peer number
*	and the message will be sent only to that peer. Numbers must be written as two digits, i.e 01 for 1.
*	The default behavior will be to broadcast in the case of failure of message parsing.
*/
static int multi_nus_send(struct uart_data_t *buf){
	
	int err = 0;
	char * message = buf->data;
	int length = buf->len;
	
	static bool broadcast = false;
	static int nus_index = 0;

	LOG_INF("Multi-Nus Send");

	/*How many connections are there in the Connection Context Library?*/
	const size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib);


	/*Handle the routing of the message only at the beginning of the message*/
	if (messageStart) {
		messageStart = false;

		/*Check if it's a routed message*/
		if (message[0] == ROUTED_MESSAGE_CHAR) {
			
			routedMessage = true;
			/*Determine who the intended recipient is*/
			char str[2];
			str[0] = message[1];
			str[1] = message[2];
			nus_index = atoi(str);

			/*Is this a number that makes sense?*/
			if ((nus_index >= 0) && (nus_index < num_nus_conns)){
				broadcast = false;

				/*Move the data buffer pointer to after the recipient info and 
				shorten the length*/
				message =  &message[3];
				length = length - 3;

				
			} else if (nus_index == BROADCAST_INDEX) {
				broadcast = true;
				message =  &message[3];
				length = length - 3;
			}
		} else {
			broadcast = true;
		}
	}


	/*	If it's a routed message, send it to that guy. 
	*	If it's not, broadcast it to everyone.
	*/
	if (broadcast == false){
		const struct bt_conn_ctx *ctx =
				bt_conn_ctx_get_by_id(&conns_ctx_lib, nus_index);
		
		LOG_INF("Trying to send to server %d", nus_index);

		if (ctx) {
			struct bt_nus_client *nus_client = ctx->data;

			if (nus_client) {
				err = bt_nus_client_send(nus_client,
								     message,
								     length);
				if (err) {
					LOG_WRN("Failed to send data over BLE connection"
						"(err %d)",
						err);
				}else{
					LOG_INF("Sent to server %d: %s", nus_index, log_strdup(message));
				}
			
				

				err = k_sem_take(&nus_write_sem,
							NUS_WRITE_TIMEOUT);
				if (err) {
					LOG_WRN("NUS send timeout");
				}
			}

			bt_conn_ctx_release(&conns_ctx_lib,
							(void *)ctx->data);
		}

	}else{//Broadcast message
		LOG_INF("Broadcast");

		printk("broad cast message to : %d " ,num_nus_conns);
		for (int i = 0; i < num_nus_conns; i++) {
			const struct bt_conn_ctx *ctx =
				bt_conn_ctx_get_by_id(&conns_ctx_lib, i);
		
			if (ctx) {
				struct bt_nus_client *nus_client = ctx->data;
				
				if (nus_client) {
					err = bt_nus_client_send(nus_client,
								     message,
								     length);
					if (err) {
						LOG_WRN("Failed to send data over BLE connection"
							"(err %d)",
							err);
					}else{
						LOG_INF("Sent to server %d: %s", i, log_strdup(message));
					}

					bt_conn_ctx_release(&conns_ctx_lib,
							    (void *)ctx->data);

					err = k_sem_take(&nus_write_sem,
							 NUS_WRITE_TIMEOUT);
					if (err) {
						LOG_WRN("NUS send timeout");
					}
				}
			}
		}
	}

	if ( (message[length-1] == '\n') || (message[length-1] == '\r') ) {
		messageStart = true;
		routedMessage = false;
	}

	return err;
}

/*	This function has been updated to add the ability for a peer to route a message by
*	appending a '*' as in the multi-NUS send function. So a peer could send the message
*	*00 to send a message to peer 0. If the peer sends a *99, that message is broadcast to 
*	all peers
*/

void print_uart(const struct device * dev,char *buf)
{
	int msg_len = 25; //strlen(buf);    //

	for (int i = 0; i < msg_len; i++) {
		uart_poll_out(dev, buf[i]);
	}
}

bool Data_Integrity_Check(uint8_t * Peri_Data){


 /*  printf("Data_Integrity_Check .......\n");                     

	for(char i=0; i<31; i++){											// print data coming from peripheral Via BLE , 31 bytes 					

     printf(" %x  ",Peri_Data[i]);

	}

	printf("checksum from peripheral is %x \n",Peri_Data[30]);
*/
    uint16_t crc = crc16_ccitt(0x1021,Peri_Data,30);      			 // crc polynomial 0x1021 , input arguments , Array and no. of bytes to calc checksum

    crc =(crc&0x00FF);												 //Only LSB is required 
//    printf("CRC: 0x%04X\n", crc);

	if(crc==Peri_Data[30]){										   // compare the crc calculated by received data , and the checksum send by peripheral @ index # 30 and byte # 31

	//	printf("check sum matched ....\n");

		return true;

	}

	else {
   
     printf("check sum Not matched ....\n");
       
	  return false; 
	}

   return false;

}

void Central_frame(uint8_t * Peri_Data){

	//char * index;
   
	
	uint8_t * Source_Ptr;
	uint8_t * Dest_Ptr;

	Source_Ptr = Peri_Data+11;             						 // Peri_Data(i+11);
    Dest_Ptr =   Central_Arr;									// &Central_Arr[0];             //  both are same , &Central_Arr[0]  OR  Central_Arr;


    for(char i=0; i<19; i++){

    *Dest_Ptr = *Source_Ptr;

	Dest_Ptr++;
	Source_Ptr++;

	}
  
    Central_Arr[0]=0xB0;
	Central_Arr[2]=0xB2;
    Central_Arr[3]=0xB3;
	
   /*
    printf(" Array extraction Central Array");
	for(char i=0; i<18; i++){

    printf(" %x ",Central_Arr[i]);

	}

	*/

/*	Central_Arr[0]=0xB0;
	Central_Arr[1]=Peri_Data[12];

	Central_Arr[2]=0xB2;
	Central_Arr[3]=0xB3;

	//while(*Peri_Data!=NULL){
    Central_Arr[4]=Peri_Data[15];
    Central_Arr[5]=Peri_Data[16];
	Central_Arr[6]=Peri_Data[17];

*/

	//}


}
static uint8_t ble_data_received(struct bt_nus_client *nus,
						const uint8_t *data, uint16_t len)
{
	ARG_UNUSED(nus);

	int err;
	bool Data_Valid;



	for (uint16_t pos = 0; pos != len;) {
		struct uart_data_t *tx = k_malloc(sizeof(*tx));

		if (!tx) {
			LOG_WRN("Not able to allocate UART send data buffer");
			return BT_GATT_ITER_CONTINUE;
		}

		/* Keep the last byte of TX buffer for potential LF char. */
		size_t tx_data_size = sizeof(tx->data) ;//- 1; Added 

		if ((len - pos) > tx_data_size) {
			tx->len = tx_data_size;
		} else {
			tx->len = (len - pos);
		}

		memcpy(tx->data, &data[pos], tx->len);

		pos += tx->len;

		/* Append the LF character when the CR character triggered
		 * transmission from the peer.
		 */
		if ((pos == len) && (data[len - 1] == '\r')) {
			tx->data[tx->len] = '\n';
			tx->len++;
		}

        /*	Routed messages. See the comments above. 
		*	Check for *, if there's a star, send it over to the multi-nus send function
		*/

	    if (( data[0] == '*') || (routedMessage == true) ) {
			multi_nus_send(tx);
		}

		// printf("number of connections .....   %d",num);

      
		Data_Valid = Data_Integrity_Check(tx->data);                 //    Data_Integrity_Check , data is valid or not ?
        Central_frame(tx->data);
	

       
       if(Data_Valid==true){						               // if data is valid then proceed further else return, varify check sum
        
		printk("($");                                              // data send to gateway nrf9160 should be between $ (31 bytes ) &
	
	 //  err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);    //send the packet to uart for nrf9160
	  //  err = uart_tx(uart, Central_Arr, 18, SYS_FOREVER_MS);    //send the packet to uart for nrf9160
    
		
	 /* for(char i=0; i<18; i++){
		   printk("%x ",Central_Arr[i]);                          // & is the last element of Central_Con_Array
		} 
    	
       */
	    
		Central_Con_Array[2]=(Central_Con_Array[2]&0xF0)|(num&0x0F);       // ( 21B)  // Nibble to write in Lower 4 bits (0xF0 = 11110000)

        for(char i=0; i<6; i++){
		//printk("0x%02X ",Central_Con_Array[i]);                          // & is the last element of Central_Con_Array
		Central_Arr[i+19]=Central_Con_Array[i];
		}
        
		//Central_Arr[22]=NULL;

		print_uart(uart,Central_Arr);                           // set the value of 25 characters , plz go inside the fn
	   }

	   else if (Data_Valid==false){                              // if data is NOT valid then NOT send the packet to uart for nrf9160

        printf("DO Nothing ...... \n");

	   }

	   k_free(tx);
		if (err) {
			k_fifo_put(&fifo_uart_tx_data, tx);
		}
	}

	return BT_GATT_ITER_CONTINUE;
}

static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
	ARG_UNUSED(dev);

	static size_t aborted_len;
	struct uart_data_t *buf;
	static uint8_t *aborted_buf;
	static bool disable_req;

	switch (evt->type) {
	case UART_TX_DONE:
		LOG_DBG("UART_TX_DONE");
		if ((evt->data.tx.len == 0) ||
		    (!evt->data.tx.buf)) {
			return;
		}

		if (aborted_buf) {
			buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
					   data);
			aborted_buf = NULL;
			aborted_len = 0;
		} else {
			buf = CONTAINER_OF(evt->data.tx.buf,
					   struct uart_data_t,
					   data);
		}

		k_free(buf);

		buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
		if (!buf) {
			return;
		}

		if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
			LOG_WRN("Failed to send data over UART");
		}

		break;

	case UART_RX_RDY:
		LOG_DBG("UART_RX_RDY");
		buf = CONTAINER_OF(evt->data.rx.buf, struct uart_data_t, data);
		buf->len += evt->data.rx.len;

		if (disable_req) {
			return;
		}

		if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
		    (evt->data.rx.buf[buf->len - 1] == '\r')) {
			disable_req = true;
			uart_rx_disable(uart);
		}

		break;

	case UART_RX_DISABLED:
		LOG_DBG("UART_RX_DISABLED");
		disable_req = false;

		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf->len = 0;
		} else {
			LOG_WRN("Not able to allocate UART receive buffer");
			k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
			return;
		}

		uart_rx_enable(uart, buf->data, sizeof(buf->data),
			       UART_RX_TIMEOUT);


       
		break;

	case UART_RX_BUF_REQUEST:
		LOG_DBG("UART_RX_BUF_REQUEST");
		buf = k_malloc(sizeof(*buf));
		if (buf) {
			buf->len = 0;
			uart_rx_buf_rsp(uart, buf->data, sizeof(buf->data));
		} else {
			LOG_WRN("Not able to allocate UART receive buffer");
		}

		break;

	case UART_RX_BUF_RELEASED:
		LOG_DBG("UART_RX_BUF_RELEASED");
		buf = CONTAINER_OF(evt->data.rx_buf.buf, struct uart_data_t,
				   data);

		if (buf->len > 0) {
			k_fifo_put(&fifo_uart_rx_data, buf);
		} else {
			k_free(buf);
		}

		break;

	case UART_TX_ABORTED:
		LOG_DBG("UART_TX_ABORTED");
		if (!aborted_buf) {
			aborted_buf = (uint8_t *)evt->data.tx.buf;
		}

		aborted_len += evt->data.tx.len;
		buf = CONTAINER_OF(aborted_buf, struct uart_data_t,
				   data);

		uart_tx(uart, &buf->data[aborted_len],
			buf->len - aborted_len, SYS_FOREVER_MS);

		break;

	default:
		break;
	}
}

static void uart_work_handler(struct k_work *item)
{
	struct uart_data_t *buf;

	buf = k_malloc(sizeof(*buf));
	if (buf) {
		buf->len = 0;
	} else {
		LOG_WRN("Not able to allocate UART receive buffer");
		k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
		return;
	}

	uart_rx_enable(uart, buf->data, sizeof(buf->data), UART_RX_TIMEOUT);
}

static int uart_init(void)
{
	int err;
	struct uart_data_t *rx;

	if (!device_is_ready(uart)) {
		LOG_ERR("UART device not ready");
		return -ENODEV;
	}

	rx = k_malloc(sizeof(*rx));
	if (rx) {
		rx->len = 0;
	} else {
		return -ENOMEM;
	}

	k_work_init_delayable(&uart_work, uart_work_handler);

	err = uart_callback_set(uart, uart_cb, NULL);
	if (err) {
		return err;
	}

	return uart_rx_enable(uart, rx->data, sizeof(rx->data),
			      UART_RX_TIMEOUT);
}

static void discovery_complete(struct bt_gatt_dm *dm,
			       void *context)
{
	struct bt_nus_client *nus = context;
	LOG_INF("Service discovery completed");

	bt_gatt_dm_data_print(dm);

	bt_nus_handles_assign(dm, nus);
	bt_nus_subscribe_receive(nus);

	bt_gatt_dm_data_release(dm);

    // Added code from multinus

	int err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)", err);
	} else {
		LOG_INF("Scanning started");
	}

	/*	Send a message to the new NUS server informing it of its ID in this 
	*	mini-network
	*	The new NUS will have been added to the connection context library and so
	* 	will be the highest index as they are added incrementally upwards.
	*	This is a bit of a workaround because in this function, I don't know
	*	the ID of this connection which is the piece of info I want to transmit.
	*/
	size_t num_nus_conns = bt_conn_ctx_count(&conns_ctx_lib);

	
	size_t nus_index = 99;

	/*	This is a little inelegant but we must get the index of the device to
	* 	convey it. This bit sends the index number to the peripheral.
	*/
	for (size_t i = 0; i < num_nus_conns; i++) {
		const struct bt_conn_ctx *ctx =
			bt_conn_ctx_get_by_id(&conns_ctx_lib, i);

		if (ctx) {
			if (ctx->data == nus) {
				nus_index = i;
				char message[3];
				sprintf(message, "%d", nus_index);
				message[2] = '\r';
				int length = 3;

				err = bt_nus_client_send(nus, message, length);
				if (err) {
					LOG_WRN("Failed to send data over BLE connection"
						"(err %d)",
						err);
				} else {
					LOG_INF("Sent to server %d: %s",
						nus_index, log_strdup(message));
				}

				bt_conn_ctx_release(&conns_ctx_lib,
						    (void *)ctx->data);
				break;
			} else {
				bt_conn_ctx_release(&conns_ctx_lib,
						    (void *)ctx->data);
			}
		}
	}


}

static void discovery_service_not_found(struct bt_conn *conn,
					void *context)
{
	LOG_INF("Service not found");
}

static void discovery_error(struct bt_conn *conn,
			    int err,
			    void *context)
{
	LOG_WRN("Error while discovering GATT database: (%d)", err);
}

struct bt_gatt_dm_cb discovery_cb = {
	.completed         = discovery_complete,
	.service_not_found = discovery_service_not_found,
	.error_found       = discovery_error,
};
/*
static void gatt_discover(struct bt_conn *conn)
{
	int err;

	if (conn != default_conn) {
		return;
	}

	err = bt_gatt_dm_start(conn,
			       BT_UUID_NUS_SERVICE,
			       &discovery_cb,
			       &nus_client);
	if (err) {
		LOG_ERR("could not start the discovery procedure, error "
			"code: %d", err);
	}
}

*/


static void gatt_discover(struct bt_conn *conn)
{
	int err;

	struct bt_nus_client *nus_client = bt_conn_ctx_get(&conns_ctx_lib, conn);


	if (!nus_client) {
		return;
	}

	err = bt_gatt_dm_start(conn,
			       BT_UUID_NUS_SERVICE,
			       &discovery_cb,
			       nus_client);
	if (err) {
		LOG_ERR("could not start the discovery procedure, error "
			"code: %d", err);
	}

	bt_conn_ctx_release(&conns_ctx_lib, (void *) nus_client);

}
static void exchange_func(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params)
{
	if (!err) {
		LOG_INF("MTU exchange done");
	} else {
		LOG_WRN("MTU exchange failed (err %" PRIu8 ")", err);
	}
}


/*MTU exchange*/

static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
			    struct bt_gatt_exchange_params *params)
{
    LOG_INF("MTU exchange %u %s (%u)", bt_conn_index(conn),
	       err == 0U ? "successful" : "failed", bt_gatt_get_mtu(conn));
}

static struct bt_gatt_exchange_params mtu_exchange_params[CONFIG_BT_MAX_CONN];

static int mtu_exchange(struct bt_conn *conn)
{
    uint8_t conn_index;
    int err;

    conn_index = bt_conn_index(conn);

    LOG_INF("MTU (%u): %u", conn_index, bt_gatt_get_mtu(conn));

    mtu_exchange_params[conn_index].func = mtu_exchange_cb;

    err = bt_gatt_exchange_mtu(conn, &mtu_exchange_params[conn_index]);
    if (err) LOG_INF("MTU exchange failed (err %d)", err);
    else LOG_INF("Exchange pending...");


    return err;
}

static void connected(struct bt_conn *conn, uint8_t conn_err)
{
	char addr[BT_ADDR_LE_STR_LEN];
	int err;


    struct bt_nus_client_init_param init = {   // code added 
		.cb = {
			.received = ble_data_received,
			.sent = ble_data_sent,
		}
	};

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (conn_err) {
		LOG_INF("Failed to connect to %s (%d)", log_strdup(addr),
			conn_err);

			printk("Failed to connect to %s (%d)", log_strdup(addr),
			conn_err);

		if (default_conn == conn) {
			bt_conn_unref(default_conn);
			default_conn = NULL;

			err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
			if (err) {
				LOG_ERR("Scanning failed to start (err %d)",
					err);
					printk("Scanning failed to start (err %d)",
					err);
			}
		}

		return;
	}

	mtu_exchange(default_conn);

	LOG_INF("Connected: %s", log_strdup(addr));

	num++;
 
    printf("Connected.... ");



       


	// code added 
   
	/*Allocate memory for this connection using the connection context library. For reference,
	this code was taken from hids.c
	*/
	struct bt_nus_client *nus_client = bt_conn_ctx_alloc(&conns_ctx_lib, conn);

	if (!nus_client) {
		LOG_WRN("There is no free memory to "
			"allocate the connection context");
	}

	memset(nus_client, 0, bt_conn_ctx_block_size_get(&conns_ctx_lib));

	err = bt_nus_client_init(nus_client, &init);

	bt_conn_ctx_release(&conns_ctx_lib, (void *)nus_client);
	
	if (err) {
		LOG_ERR("NUS Client initialization failed (err %d)", err);
	}else{
		LOG_INF("NUS Client module initialized");
	}

	gatt_discover(conn);

   /*
	static struct bt_gatt_exchange_params exchange_params;

	exchange_params.func = exchange_func;
	err = bt_gatt_exchange_mtu(conn, &exchange_params);
	if (err) {
		LOG_WRN("MTU exchange failed (err %d)", err);
	}

	err = bt_conn_set_security(conn, BT_SECURITY_L2);
	if (err) {
		LOG_WRN("Failed to set security: %d", err);

		gatt_discover(conn);
	}
     */
	err = bt_scan_stop();
	if ((!err) && (err != -EALREADY)) {
		LOG_ERR("Stop LE scan failed (err %d)", err);
	}
}




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));

	LOG_INF("Disconnected...: %s (reason %u)", log_strdup(addr),
		reason);

   err = bt_conn_ctx_free(&conns_ctx_lib, conn);  // code added	

	if (err) {
		LOG_WRN("The memory was not allocated for the context of this "
			"connection.");
	}

	else{


       LOG_WRN("The memory allocated for the context of this "
			"connection.");

	}

	bt_conn_unref(conn);
	default_conn = NULL;
	

	num--;

	printf("Disconnected ");
	
	
/*
	if (default_conn != conn) {
		return;
	}

	bt_conn_unref(default_conn);
	default_conn = NULL;

	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)",
			err);
	}

	printf("Start Scanning again ..... ");
*/




	
}

static void security_changed(struct bt_conn *conn, bt_security_t level,
			     enum bt_security_err err)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	if (!err) {
		LOG_INF("Security changed: %s level %u", log_strdup(addr),
			level);
	} else {
		LOG_WRN("Security failed: %s level %u err %d", log_strdup(addr),
			level, err);
	}

	gatt_discover(conn);
}

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
	.security_changed = security_changed
};

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);
//BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting);

static void scan_connecting_error(struct bt_scan_device_info *device_info)
{
	   LOG_WRN("Connecting failed");

	    printk("RSSI VALUE IS %d",device_info->recv_info->rssi);

	
		Rsrp_Usigned=device_info->recv_info->rssi;   //-76 ---> 76 

		Rsrp_Usigned=(Rsrp_Usigned/6)*(-1);                   //76/6 = 12 , 

        Rsrp_Usigned=Rsrp_Quant[Rsrp_Usigned];         //Quantization range is (0-96) , divided into 16 level of 6 step each , 16*6 = 96, value will be = 0x0C

     //   printk("Rsrp_Usigned %d",Rsrp_Usigned);

		Central_Con_Array[2]=(Rsrp_Usigned<<4)|(Central_Con_Array[2]&0x0F);       // ( 21A)  // Nibble to write in upper 4 bits (0x0F = 00001111)

     //  printk("Central_Con_Array[1] %d",Central_Con_Array[1]);
}

static void scan_connecting(struct bt_scan_device_info *device_info,
			    struct bt_conn *conn)
{
	default_conn = bt_conn_ref(conn);
}

static int nus_client_init(void)
{
	int err;
	struct bt_nus_client_init_param init = {
		.cb = {
			.received = ble_data_received,
			.sent = ble_data_sent,
		}
	};

	err = bt_nus_client_init(&nus_client, &init);
	if (err) {
		LOG_ERR("NUS Client initialization failed (err %d)", err);
		return err;
	}

	LOG_INF("NUS Client module initialized");
	return err;
}

BT_SCAN_CB_INIT(scan_cb, scan_filter_match, NULL,scan_connecting_error, scan_connecting);


static void scan_init(void)
{
	int err;

	// Use active scanning and disable duplicate filtering to handle any
	 // devices that might update their advertising data at runtime. 
	
    const char *perName1="Nordic_UART_Service";

    struct bt_le_conn_param m_conn_param={
        .interval_min=120,
		.interval_max=220,
		.timeout=100,

	}; 
	struct bt_scan_init_param scan_init = {
		.connect_if_match = 1,            //1
		.scan_param = &m_scan_param,
		.conn_param = &m_conn_param,     //NULL              // 

	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);

	//err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
     err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_NAME,perName1);

	if (err) {
		printk("Scanning filters cannot be set (err %d)\n", err);

		return;
	}

	//err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
    err = bt_scan_filter_enable(BT_SCAN_NAME_FILTER, false);
	if (err) {
		printk("Filters cannot be turned on (err %d)\n", err);
	}
}

/*
static int scan_init(void)
{
	int err;
	struct bt_scan_init_param scan_init = {
		.connect_if_match = 1,
	};

	bt_scan_init(&scan_init);
	bt_scan_cb_register(&scan_cb);

	err = bt_scan_filter_add(BT_SCAN_FILTER_TYPE_UUID, BT_UUID_NUS_SERVICE);
	if (err) {
		LOG_ERR("Scanning filters cannot be set (err %d)", err);
		return err;
	}

	err = bt_scan_filter_enable(BT_SCAN_UUID_FILTER, false);
	if (err) {
		LOG_ERR("Filters cannot be turned on (err %d)", err);
		return err;
	}

	LOG_INF("Scan module initialized");
	return err;
}

*/

static void auth_cancel(struct bt_conn *conn)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF("Pairing cancelled: %s", log_strdup(addr));
}


static void pairing_complete(struct bt_conn *conn, bool bonded)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_INF("Pairing completed: %s, bonded: %d", log_strdup(addr),
		bonded);
}


static void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));

	LOG_WRN("Pairing failed conn: %s, reason %d", log_strdup(addr),
		reason);
}

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.cancel = auth_cancel,
};

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed
};
///////////////////////////////  code added /////////////////////////////////////////

const struct device * spi_dev;
static struct spi_config spi_cfg = {
	.operation = SPI_WORD_SET(8)
	         | SPI_OP_MODE_MASTER
             | SPI_TRANSFER_MSB
            // | SPI_MODE_CPOL
            // | SPI_MODE_CPHA
             ,
	.frequency = 4000000,
	.slave = 0,
	//.cs=NULL,
};
static const struct gpio_dt_spec cs_low = GPIO_DT_SPEC_GET(cs, gpios);
static const struct gpio_dt_spec pdn_high = GPIO_DT_SPEC_GET(pdn, gpios);
static struct spi_buf rx;
const struct spi_buf_set rx_bufs = {
	.buffers = &rx,
	.count = 1
};

static struct spi_buf tx;
const struct spi_buf_set tx_bufs = {
	.buffers = &tx,
	.count = 1
};

static void spi_init(void)
{
	spi_dev = device_get_binding(SPI_DEV_NAME);

    // code added 
	   if (!spi_dev) {
        printk("SPI device not found\n");
        return;
    }

}


void Nrf21540_Write_Register()
{
    int err,ret;

   //static uint8_t tx_buffer[2] = {0xC0, 0x7D};   //  0x7D = 31 ,0x45 = 11 , 0x05
   static uint8_t tx_buffer[2] = {0xC1, 0x01};   //  enable the RX for confreg1 

    tx.buf = tx_buffer;
	tx.len = sizeof(tx_buffer);

	static uint8_t rx_buffer[2];
	rx.buf = rx_buffer;
	rx.len = sizeof(rx_buffer);

   
   
   // while (1) {

     
     ret = gpio_pin_set_dt(&cs_low,0);  // low
		if (ret < 0) {
			return;
		}
  
//err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs);   //rx_bufs
 err =  spi_write(spi_dev,&spi_cfg,&tx_bufs);
	if (err < 0) {
		printf("SPI error: %d\n", err);
	} else {
	

	   printf("write successfully : %d\n", err);
		for (int i = 0; i <2; i++){
			printf(" %x",rx_buffer[i]);
			
		}

    printf("\n");
	
	}

    
  
    ret = gpio_pin_set_dt(&cs_low,1);   // high
		if (ret < 0) {
			return;
		}
   
  
  //  }
}

void Nrf21540_Read_Register()
{
    int err,ret;
 //static uint8_t tx_buffer[2] = {0x80, 0x00};   //  0x80 for reading register confreg0 ,0x8 1000 0000 for reading 
    static uint8_t tx_buffer[2] = {0x90, 0x00};   // read the  confreg1 register 

    tx.buf = tx_buffer;
	tx.len = sizeof(tx_buffer);

	static uint8_t rx_buffer[2];
	rx.buf = rx_buffer;
	rx.len = sizeof(rx_buffer);

   
     ret = gpio_pin_set_dt(&cs_low,0);  // low
		if (ret < 0) {
			return;
		}
  
err = spi_transceive(spi_dev, &spi_cfg, &tx_bufs, &rx_bufs);   //rx_bufs
    
    //err =  spi_write(spi_dev,&spi_cfg,&tx_bufs);

//err =  spi_read(spi_dev,&spi_cfg,&rx_bufs);

	if (err < 0) {
		printk("SPI error: %d\n", err);
	} else if (err==0){
	
	    printf("Read successfully : %d\n", err);
		for (int i = 0; i <2; i++){
			printf(" %x",rx_buffer[i]);
		
		}
    printf("\n");
	}

    
  
    ret = gpio_pin_set_dt(&cs_low,1);   // high
		if (ret < 0) {
			return;
		}
   
  
 
}



void main(void)
{
	int err,ret;

 //..................................... code added .......................................................


    spi_init();

	if (!device_is_ready(cs_low.port)) {
		return;
	}

	ret = gpio_pin_configure_dt(&cs_low, GPIO_OUTPUT_ACTIVE);
	ret = gpio_pin_configure_dt(&pdn_high ,GPIO_OUTPUT_ACTIVE);
	if (ret < 0) {
		return;
	}

	
 ret = gpio_pin_set_dt(&pdn_high,1);  // 0.28 nrf21540 always high 
		if (ret < 0) {
			return;
		}	

        else
         printk("PDN high at start up ...\n");

  
 //..................................... code added .......................................................

	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
	if (err) {
		LOG_ERR("Failed to register authorization callbacks.");
		return;
	}
/*
	err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
	if (err) {
		printk("Failed to register authorization info callbacks.\n");
		return;
	}

*/


 
	err = bt_enable(NULL);
	if (err) {
		LOG_ERR("Bluetooth init failed (err %d)", err);
		return;
	}
	LOG_INF("Bluetooth initialized");

	if (IS_ENABLED(CONFIG_SETTINGS)) {
		settings_load();
	}

  //  bt_conn_cb_register(&conn_callback);

	int (*module_init[])(void) = {uart_init, scan_init, nus_client_init};
	for (size_t i = 0; i < ARRAY_SIZE(module_init); i++) {
		err = (*module_init[i])();
		if (err) {
			return;
		}
	}

	printk("Starting Bluetooth Central UART example\n");


 // uint8_t input[18] = {0x01, 0x02, 0x03, 0x04, 0x55, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12};
  //  uint16_t crc = crc16_ccitt(0x1021,input,18);

//	 printf("CRC: 0x%04X\n", crc);
    //..................................... code added .......................................................

    Nrf21540_Write_Register();
	
    k_msleep(100);


    Nrf21540_Read_Register();
      
    k_msleep(100);



	  
  //.............................  code added .................................


	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
	if (err) {
		LOG_ERR("Scanning failed to start (err %d)", err);
		return;
	}
   
	LOG_INF("Scanning successfully started");

	for (;;) {
		// Wait indefinitely for data to be sent over Bluetooth //
		/*struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
						     K_FOREVER);

		err = bt_nus_client_send(&nus_client, buf->data, buf->len);
		if (err) {
			LOG_WRN("Failed to send data over BLE connection"
				"(err %d)", err);

				printk("Failed to send data over BLE connection"
        "(err %d)", err);
		}

		err = k_sem_take(&nus_write_sem, NUS_WRITE_TIMEOUT);
		if (err) {
			LOG_WRN("NUS send timeout");
			printk("NUS send timeout");
		} */


			/* Wait indefinitely for data to be sent over Bluetooth */
		struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
						     K_FOREVER);
		multi_nus_send(buf);	

		// Debug Variables

		k_free(buf);
	} 
}

prj.conf

#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
CONFIG_SPI=y
CONFIG_SPI_NRFX=y

# Enable the UART driver
CONFIG_UART_ASYNC_API=y
CONFIG_NRFX_UARTE0=y
CONFIG_SERIAL=y
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

# Enable the BLE stack with GATT Client configuration
CONFIG_BT=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_SMP=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_MAX_CONN=20
CONFIG_BT_MAX_PAIRED=20
CONFIG_BT_CONN_CTX=y


# Enable the BLE modules from NCS
CONFIG_BT_NUS_CLIENT=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=2048

# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Enable bonding
CONFIG_BT_SETTINGS=y
CONFIG_FLASH=y
CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_FLASH_MAP=y
CONFIG_NVS=y
CONFIG_SETTINGS=y

# Config logger
CONFIG_LOG=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG_BACKEND_UART=n

CONFIG_ASSERT=y

CONFIG_BT_EXT_ADV=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_SCAN_NAME_CNT=1



#CONFIG_BT_USER_DATA_LEN_UPDATE=y
#CONFIG_BT_AUTO_DATA_LEN_UPDATE=y
#CONFIG_BT_L2CAP_TX_MTU=247
#CONFIG_BT_BUF_ACL_TX_SIZE=251
#CONFIG_BT_BUF_ACL_RX_SIZE=251
#CONFIG_BT_CTLR_DATA_LENGTH_MAX=251


Please Note:

I tried with original example as well without any code addition 

NCS 1.4.1 for multi NUS central & peripheral_uart both.

But still get the same issue as discussed above .

Thanks in Advance,
Regards,

Related