UART RX Callback not triggering

Hello devzone,

I am using Nordic's NUS(Nordic uart service) example and i changed pin configuration to according to our custom board.

TX_done callback working fine but there is a problem with RX_done callback it is not triggering once in a while 

here is a code snippet regarding the problem  

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

K_SEM_DEFINE(nus_write_sem, 0, 1);

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



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


		// TODO: newly added
		// if (evt->data.rx.buf[buf->len - 1] == '\n')
		if ((evt->data.rx.buf[buf->len - 1] == '\n') || (evt->data.rx.buf[buf->len - 1] == '\r'))
		{
			disable_req = true;
			uart_rx_disable(uart);
			
			data_from_host = 1;

			memset(host_data, '\0', sizeof(host_data));

			memcpy(host_data, evt->data.rx.buf, (strlen(evt->data.rx.buf) - 2));
		}

		break;

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

		//TODO:Commenting newly 
		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);
}

and am using NRF connect sdk (v2.3.0)

Parents
  • Hi Theja, 

    You need to give us the source code and also the context in which you are triggering UART trasactions (TX/RX). Without that, it is not possible for us to test and see why you are missing one UART_RX_RDY event.

    You could also attach the debug logs (LOG_DBG) of your run, so that we could see the sequence in which uart events are triggered and handled. This will aid us to attempt to replicate the problem at our end..

  • Hi Susheel,  

    Thanks for replying have attached a source file 

    /*
     * 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 <bluetooth/services/nus.h>
    #include <bluetooth/services/nus_client.h>
    #include <bluetooth/gatt_dm.h>
    #include <bluetooth/scan.h>
    
    #include <zephyr/settings/settings.h>
    
    #include <zephyr/drivers/uart.h>
    
    #include <zephyr/logging/log.h>
    
    #include "fstorage.h"
    // #include "led.h"
    #include "timers.h"
    #include "protocol.h"
    // #include <bluetooth/hci_vs.h>
    
    
    #define SLEEP_TIME_MS 1000
    #define LED_PIN 17
    #define LOG_MODULE_NAME central_uart
    LOG_MODULE_REGISTER(LOG_MODULE_NAME);
    
    /* UART payload buffer element size. */
    #define UART_BUF_SIZE 64
    
    #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)
    // TODO: newly added
    #define UART_RX_TIMEOUT 50
    // #define UART_RX_TIMEOUT 100
    
    
    extern int last_packet_number_received;
    extern uint32_t utc_seconds_received;
    extern uint8_t time_received_from_host;
    uint32_t global_time;
    uint8_t time_string[20] = {'\0'};
    uint8_t ack_received_from_host;
    
    extern uint8_t restart_scan;
    latest_config_t latest_config;
    char addr[30];
    volatile uint8_t host_data[64] = {'\0'};
    volatile uint8_t data_from_host = 0;
    volatile uint8_t data_received_over_connection[128] = {'\0'};
    volatile uint8_t data_received = 0;
    
    uint8_t recd_packet = 0;
    uint8_t max_response_wait_time_from_host = 0;
    
    uint8_t ack_string[15] = {'\0'};
    
    uint8_t buffer[20];
    
    static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
    static struct k_work_delayable uart_work;
    
    K_SEM_DEFINE(nus_write_sem, 0, 1);
    
    struct uart_data_t
    {
    	void *fifo_reserved;
    	uint8_t data[UART_BUF_SIZE];
    	uint16_t len;
    };
    
    static K_FIFO_DEFINE(fifo_uart_tx_data);
    static K_FIFO_DEFINE(fifo_uart_rx_data);
    
    static struct bt_conn *default_conn;
    static struct bt_nus_client nus_client;
    
    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. */
    
    	// thej
    
    	// 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);
    	// }
    
    	//to here
    }
    
    static uint8_t ble_data_received(struct bt_nus_client *nus, const uint8_t *data, uint16_t len)
    {
    	ARG_UNUSED(nus);
    
    	int err;
    
    	//if(data_received == 0)
    	{
    		memset(data_received_over_connection, '\0', sizeof(data_received_over_connection));
    		memcpy(data_received_over_connection, data, len);
    		data_received = 1;
    	}
    
    	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;
    	//thej
    	int len = 0;
    	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;
    		// }
    
    
    		// TODO: newly added
    		// if (evt->data.rx.buf[buf->len - 1] == '\n')
    
    		// TODO: need to remove the block
    		// for(int i=0; i<64; i++)
    		// {
    		// 	if(buf->data[i] == '\n')
    		// 	{
    		// 		len = i;
    		// 		break;
    		// 	}
    		// }
    		// if((buf->data[len] = '\r' ) ||  (buf->data[len] == '\n'))
    		// {
    		// 	disable_req = true;
    		// 	uart_rx_disable(uart);
    		// 	// buf->len = strlen(buf->data);
    
    		// 	memset(host_data, '0', sizeof(host_data));
    		// 	memcpy(host_data, buf->data, len);
    		// 	data_from_host = 1;
    
    		// }
    
    
    		if ((evt->data.rx.buf[buf->len - 1] == '\n') || (evt->data.rx.buf[buf->len - 1] == '\r'))
    		{
    			disable_req = true;
    			uart_rx_disable(uart);
    			
    			data_from_host = 1;
    
    			memset(host_data, '\0', sizeof(host_data));
    
    			memcpy(host_data, evt->data.rx.buf, (strlen(evt->data.rx.buf) - 2));
    		}
    
    		break;
    
    	case UART_RX_DISABLED:
    		LOG_DBG("UART_RX_DISABLED");
    		disable_req = false;
    
    		//TODO:Commenting newly 
    		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);
    }
    
    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 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);
    	}
    }
    
    static void connected(struct bt_conn *conn, uint8_t conn_err)
    {
    
    	int err;
    
    	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
    
    	if (conn_err)
    	{
    		LOG_INF("Failed to connect to %s (%d)", 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);
    			}
    		}
    
    		return;
    	}
    
    	LOG_INF("Connected: %s", addr);
    
    	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)", addr, reason);
    
    	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);
    	}
    }
    
    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", addr, level);
    	}
    	else
    	{
    		LOG_WRN("Security failed: %s level %u err %d", 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)
    {
    	char addr[BT_ADDR_LE_STR_LEN];
    
    	bt_addr_le_to_str(device_info->recv_info->addr, addr, sizeof(addr));
    
    	LOG_INF("Filters matched. Address: %s connectable: %d",
    			addr, connectable);
    }
    
    static void scan_connecting_error(struct bt_scan_device_info *device_info)
    {
    	LOG_WRN("Connecting failed");
    }
    
    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 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", 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", 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", 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};
    
    void bluetooth_init(void)
    {
    	int err;
    
    	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();
    	}
    }
    
    void scan_start(void)
    {
    	int err;
    	err = bt_scan_start(BT_SCAN_TYPE_SCAN_ACTIVE);
    	if (err)
    	{
    		LOG_ERR("Scanning failed to start (err %d)", err);
    		return;
    	}
    }
    
    
    
    void send_through_uart(uint8_t *data)
    {
    	uart_tx(uart, data, strlen(data), SYS_FOREVER_MS);
    	// TODO: newly added the comment
    	k_msleep(strlen(data));
    }
    
    static void wait_for_time_from_host(void)
    {
    	uint8_t counter = 0;
    	send_time_request_to_host_controller();
    
    
    	while (!time_received_from_host)
    	{
    
    		//TODO: newly implemented
    		if(data_from_host)
    		{
    			data_from_host = 0;
    			parse_the_incoming_data_from_host(host_data);
    		}
    
    		counter++;
    		k_msleep(100);
    
    		if (counter > 50)
    		{
    			break;
    		}
    	}
    }
    static void wait_for_ack_from_host_controller(void)
    {
    	max_response_wait_time_from_host = 0;
    	while (!ack_received_from_host)
    	{
    		k_msleep(5);
    		max_response_wait_time_from_host++;
    		if(data_from_host)
    		{
    			// TODO: need to remove the below line
    			// sprintf(buffer, "data_from_host1=%d\r\n",data_from_host);
    			// send_through_uart(buffer);
    
    
    			data_from_host = 0;
    			parse_the_incoming_data_from_host(host_data);
    		}
    		if (max_response_wait_time_from_host == 100)
    		{
    			break;
    		}
    	}
    }
    
    void send_ack_to_the_sensor_for_the_last_packet()
    {
    
    	
    	ack_string[0] = 0xAB;
    	ack_string[1] = (last_packet_number_received & 0xFF000000) >> 24;
    	ack_string[2] = (last_packet_number_received & 0x00FF0000) >> 16;
    	ack_string[3] = (last_packet_number_received & 0x0000FF00) >> 8;
    	ack_string[4] = (last_packet_number_received & 0x000000FF);
    
    	// bt_nus_client_send(&nus_client, ack_string, strlen(ack_string));
    
    	bt_nus_client_send(&nus_client, ack_string, 5);
    	// k_msleep(100);
    }
    
    
    void stop_scannig_and_restart(void)
    {
    	scan_init();
    	scan_start();
    }
    
    void stop_the_scanning(void)
    {
    	bt_le_scan_stop();
    }
    
    void send_the_current_time_to_sensor(void)
    {
    	// if (latest_config.is_time_set)
    	{
    		time_string[0] = 0xAA;
    		time_string[1] = (global_time & 0xFF000000) >> 24;
    		time_string[2] = (global_time & 0x00FF0000) >> 16;
    		time_string[3] = (global_time & 0x0000FF00) >> 8;
    		time_string[4] = (global_time & 0x000000FF);
    		time_string[5] = 0;	 //(latest_config.commission[sensor_device_index].upload_interval & 0xFF00) >> 8;
    		time_string[6] = 60; // latest_config.commission[sensor_device_index].upload_interval & 0x00FF;
    		time_string[7] = 0;	 // latest_config.commission[sensor_device_index].index;
    
    		bt_nus_client_send(&nus_client, time_string, 8);
    		// k_msleep(100);
    	}
    }
    
    void main(void)
    {
    
    	leds_init();
    
    	timers_init();
    
    	led_blink(3);
    	bluetooth_init();
    
    	uart_init();
    	scan_init();
    	nus_client_init();
    
    	nrf_fstorage_init();
    
    	send_through_uart("GND Scanner Application Started\r\n");
    
    	wait_for_time_from_host();
    	
    	scan_start();
    	
    	for (;;)
    	{
    		
    		if(data_from_host)
    		{
    			data_from_host = 0;
    			parse_the_incoming_data_from_host(host_data);
    		}
    
    		if(data_received)
    		{
    			data_received = 0;
    			parse_the_incoming_data_from_sensors(data_received_over_connection);
    	    }
    
    		if (recd_packet)
    		{
    			recd_packet = 0;
    			ack_received_from_host = 0;
    			send_sensor_data_to_host_controller();
    
    			wait_for_ack_from_host_controller();
    			// TODO: remove the below lines
    
    			// k_msleep(500);
    			// if(data_from_host)
    			// {
    			// 	data_from_host = 0;
    			// 	parse_the_incoming_data_from_host(host_data);
    			// }
    			// TODO: remove the below line
    			// ack_received_from_host = 1;
    			// sprintf(buffer, "data_from_host2=%d\r\n",data_from_host);
    			// send_through_uart(buffer);
    
    			if (ack_received_from_host)
    			{
    				send_ack_to_the_sensor_for_the_last_packet();
    			}
    			else
    			{
    				send_through_uart("else\r\n");
    			}
    			
    		}
    
    		if (time_received_from_host)
    		{
    			global_time = utc_seconds_received;
    			start_timer();
    			time_received_from_host = 0;
    			latest_config.is_time_set = 1;
    		}
    
    		k_sleep(K_MSEC(100));
    	}
    }
    

    please note that we are using uart to send data from nrf52833 soc to controller and vice versa.

    when receive a data from controller UART_RX_RDY callback will trigger and i will copy the data there.

    the problem what i am getting (UART_RX_RDY is not triggering) is not consistent it will trigger normally but like once in a 5 or 10 minutes its not getting triggered.

  • HI Susheel,

    I have given you a source code any update regarding.

  • Hello,

    Thank you so much for you significant patience with this.

    I took over this case for when Susheel went out of office, but I have not seen the same issue as you do.

    Are you still seeing the same issue? If you do, I will try again and update you with my progress.

    Best regards,

    Maria

Reply Children
  • Hi Maria thanks for replying,

    Yes, I am seeing the same issue

  • Hi Theja,

    The code you give in the opening post and in your later comment are different in a key part

    Which is the correct one?

    There is also no handling of the fifo_uart_rx_data.

    As mentioned, we cannot reproduce the issue on our end with the Central UART sample. Meanwhile, your code contains multiple references to code not available to us, so we cannot effectively test it.

    Let's attempt to move forward based on more information. Could you please also give some details about the communication between the nRF52833 and this "controller" device?

    How often are packets sent from the controller?
    How many bytes are there in a packet?
    How, in details, is the callback not triggered?

    Alternatively, please see if you can create a minimally modified copy of Central UART sample where the issue can be reproduced, along with the steps to reproduce it.

    Best regards,

    Hieu

  • Hi Hieu,

    Sorry for that bumble, Uncommented one is the right one.

    So I'm using NUS example, I didn't write 'fifo_uart_rx_data'  and whatever data I receive over UART I will copy from "evt->data.rx.buf[buf->len]" buffer and process it later.

    This problem occurs in the central device, whatever data I receive through bluetooth, I will process and send it to main controller through UART and I will receive the ACK for the same over UART. While receiving ACK "UART_RX_RDY" callback will trigger. This is not triggering once in a while that is problem I believe you have understood.

    Central device is receiving packet once in a minute which is of 25byte size.

    After processing the packet received over Bluetooth the same will be sent over UART and the size of the data sent over UART will be 97 bytes and wait for ACK for 1 sec.

    I am sure that ACK is coming within 1sec from main controller because, I'm monitoring it through serial terminal even after receiving ACK through UART that "UART_RX_RDY" callback is not triggering once in a while. 

  • Hi Theja,

    Then I think that the issue is likely in the copying of data to the buffer for post processing that you are using here.

    	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 ((evt->data.rx.buf[buf->len - 1] == '\n') || (evt->data.rx.buf[buf->len - 1] == '\r'))
    		{
    			disable_req = true;
    			uart_rx_disable(uart);
    			
    			data_from_host = 1;
    
    			memset(host_data, '\0', sizeof(host_data));
    
    			memcpy(host_data, evt->data.rx.buf, (strlen(evt->data.rx.buf) - 2));
    		}
    
    		break;

    I think this code is generally not a correct handling of the Zephyr UART driver events. Please read the driver documentation here: https://developer.nordicsemi.com/nRF_Connect_SDK/doc/2.4.0/zephyr/hardware/peripherals/uart.html#c.uart_event_type.

    These are some hypothetical bad scenarios/problems with your code:

    • Buffer is empty, buffer size is 20, all null. Receiving two packages, "ABC\n" and "DEF\n"
      • Upon receiving "ABC\n" your code will pass "AB" to post processing (the length passed is buffer length -2 in your code)
      • Upon receiving "DEF\n" your code will pass "ABC\nDE" to post processing
    • Receiving more data than the buffer can store. There will be three events consecutively.
      • UART_RX_RDY when the buffer is full
      • UART_RX_BUF_RELEASED right after
      • UART_RX_RDY when RX timeout
      • If timeout is short enough, your post processing might not have processed the first UART_RX_RDY event, and the data is lost. Furthermore, the first event will be without the '\n' and '\r' terminator. This message is effectively corrupted.
    • strlen is not used safely. strlen rely on the array of bytes is null terminated. However, you cannot know whether the data is always null terminated or not. See that the buffer is dynamically allocated with k_malloc(). This introduces risks of getting an invalid large length.

    I am a little surprised you didn't have more frequent issues other than just "missing some events."

    Please focus into monitoring when the issue happens. I think you will see that LOG_DBG("UART_RX_RDY") will still happen, and likely the current or next data received would be corrupted. 

    If you wish for a quick solution, I recommend leaving the UART_RX_** event in the Central UART sample as is. You can then process the data by extracting data from fifo_uart_rx_data, as done in the sample:

    		/* 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);
    		}

    The Peripheral UART actually does it even better, as it handles the FIFO in a dedicated thread: 

    void ble_write_thread(void)
    {
    	/* Don't go any further until BLE is initialized */
    	k_sem_take(&ble_init_ok, K_FOREVER);
    
    	for (;;) {
    		/* Wait indefinitely for data to be sent over bluetooth */
    		struct uart_data_t *buf = k_fifo_get(&fifo_uart_rx_data,
    						     K_FOREVER);
    
    		if (bt_nus_send(NULL, buf->data, buf->len)) {
    			LOG_WRN("Failed to send data over BLE connection");
    		}
    
    		k_free(buf);
    	}
    }
    
    K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL,
    		NULL, PRIORITY, 0, 0);

Related