This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

GATT TIMEOUT ERROR when moving away quickly from the device

Hello everyone,

I am having an odd problem. I am using an SoC based on the nRF52832 (the ISP1507-AX). I am using ncs v1.7.0 for development. I am trying out a few things and right now, I have a sensor that needs to advertise every 50ms. I've noticed a strange bug however. When connected to the device and moving away quickly from it, a GATT TIMEOUT ERROR (0x08) happens. The sensor/device seems to reboot completely.

  I have no idea where it comes from, I did change the peripheral preferred max/min connection interval to be around half of 50ms but this error still happens. 

Would anyone have any idea about what is going on ?

Attached you'll find all files.timeout_range_pblm.zip

Here is the main.c:

/* Standard and Zephyr libraries */
#include <zephyr.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <soc.h>
#include <sys/byteorder.h>
#include <sys/util.h>
#include <device.h>
#include <devicetree.h>
#include <drivers/sensor.h>

/* Bluetooth Stack Libraries */
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/conn.h>
#include <bluetooth/uuid.h>
#include <bluetooth/gatt.h>
#include <bluetooth/services/bas.h>
#include <bluetooth/services/dis.h>
#include <bluetooth/services/hrs.h>

/* Settings librairy for DIS */
#include <settings/settings.h>

/* Logging module */
#include <logging/log.h>
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);

/**************************************************************************
 * DECLARATIONS
 *************************************************************************/

void sensor_stop(void);
void sensor_start(void);

/**************************************************************************
 * BLUETOOTH FUNCTIONS
 *************************************************************************/

/** Device Name as defined in the prj.conf */
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
/** device name length */
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

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_UUID16_ALL,
		      BT_UUID_16_ENCODE(BT_UUID_HRS_VAL),
		      BT_UUID_16_ENCODE(BT_UUID_BAS_VAL),
		      BT_UUID_16_ENCODE(BT_UUID_DIS_VAL))
};

static void connected(struct bt_conn *conn, uint8_t err)
{
	if (err) {
		LOG_ERR("Connection failed (err 0x%02x)", err);
	} else {
		LOG_INF("Connected\n");
        sensor_start();
	}
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	LOG_INF("Disconnected (reason 0x%02x)", reason);
    sensor_stop();
}

static struct bt_conn_cb conn_callbacks = {
	.connected = connected,
	.disconnected = disconnected,
};

static void bt_ready(void)
{
	int err;

	LOG_INF("Bluetooth initialized");

	err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
	if (err) {
		LOG_ERR("Advertising failed to start (err %d)", err);
		return;
	}

	LOG_INF("Advertising successfully started");
}

static void bas_notify(void)
{
	uint8_t battery_level = bt_bas_get_battery_level();

	battery_level--;

	if (!battery_level) {
		battery_level = 100U;
	}

	bt_bas_set_battery_level(battery_level);
}

static void hrs_notify(uint8_t heartrate)
{
	bt_hrs_notify(heartrate);
}

static void ble_init(void)
{
    int err;

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

	bt_ready();

	bt_conn_cb_register(&conn_callbacks);
}

/**************************************************************************
 * UPDATE VALUES FUNCTIONS
 *************************************************************************/

#define START_DELAY_MS              5000
#define SENSOR_SAMPLING_TIME_MS     50

static K_SEM_DEFINE(sensor_ok, 0, 1);
static K_SEM_DEFINE(sensor_init_ok, 0, 1);

static void sensor_timer_handler(struct k_timer *dummy)
{
    k_sem_give(&sensor_ok);
}

K_TIMER_DEFINE(sensor_timer, sensor_timer_handler, NULL);

int sensor_init(void)
{
    int status = 0;

    /* Indicate to the processing thread that initialization is finished */
    k_sem_give(&sensor_init_ok);

    return status;
}

void sensor_stop(void)
{
    k_timer_stop(&sensor_timer);
    LOG_INF("Sensor stopped.\n");
}

void sensor_start(void)
{
    /* start periodic timer that expires once every "samplingTime" */
    k_timer_start(&sensor_timer, K_MSEC(START_DELAY_MS),
                  K_MSEC(SENSOR_SAMPLING_TIME_MS));
    LOG_INF("Sensor started.\n");
}

void sensor_process_thread(void)
{
    /* Wait for the sensor to be initialized before starting the thread loop. */
    k_sem_take(&sensor_init_ok, K_FOREVER);

    static uint8_t sensor_data = 90;

    while (1)
    {
        /* Semaphore is available every sampling time */
        k_sem_take(&sensor_ok, K_FOREVER);

        /* Notify new sensor value */
	    sensor_data++;
	    if (sensor_data == 160U) {
		    sensor_data = 90U;
	    }
        hrs_notify(sensor_data);
    }
}

/* Defines the processor thread with its stacksize and priority. */
K_THREAD_DEFINE(sensor_producer_thread_id, 1024,
                sensor_process_thread, NULL, NULL,
                NULL, 5, 0, 0);

/**************************************************************************
 * MAIN
 *************************************************************************/

void main(void)
{
    sensor_init();
    ble_init();

    while(1)
    {
        bas_notify();
        k_sleep(K_MSEC(5000));
    }
}

Here is the prj.conf:

# Deactivate DEBUG/LOG for production builds
CONFIG_DEBUG=y
CONFIG_SERIAL=y
# Logging
CONFIG_LOG=y

# segger RTT console
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_UART_CONSOLE=n

# Unused Peripherals
CONFIG_SPI=n

# Activate the BLE layer, set as peripheral
CONFIG_BT=y
CONFIG_BT_DEBUG_LOG=y
CONFIG_BT_DEBUG_SERVICE=y
CONFIG_BT_SMP=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CTLR=y
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_GATT_CLIENT=y
# Set up the Services
CONFIG_BT_DIS=y
CONFIG_BT_DIS_PNP=n
CONFIG_BT_BAS=y
CONFIG_BT_HRS=y

# Decrease connection interval to accomodate 50ms Respiration sampling rate
# Min = 17.5ms, Max = 22.5ms
CONFIG_BT_PERIPHERAL_PREF_MIN_INT=14
CONFIG_BT_PERIPHERAL_PREF_MAX_INT=18

# Set up device appearance
# Appearance 833 is Heart Rate Belt
CONFIG_BT_DEVICE_APPEARANCE=833

Here is the CMakeLists.txt:

# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.13.1)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(peripheral_hr)

FILE(GLOB app_sources src/*.c)
target_sources(app PRIVATE
  ${app_sources}
  )

zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth)

Thank you very much in advance for any help.

Best regards,

Parents
  • Hi,

    I assume you get the GATT TIMEOUT ERROR on an Android device? Have you doen any debugging to see what happens on the nRF? You write that it seems to reboot completely. It would be interesting to start by looking at the log and see what that gives you?

    Without knowing more than that this happens more when distance is increasing, I would think about things that would be affected by packet loss (for instance buffer filling up if you try to notify data faster than it is actually successfully transmitted).

  • Ok, I randomly realized that it was not the phone getting away from the device that caused the bug but me/my chair.

    I did not have access to a Nordic DK until now and I could not reproduce the bug on an nrf52dk. So, I am pretty sure this is an EMC problem on my custom board. After a few tries with/without the J-link debugger plugged in, I am 99% certain this was the problem. The bug disappear when it is not plugged in and when it is, if I move quickly, with my chair, away from the device the device immediately resets (bc of EMC on the pin probably).

    I am really sorry for your time ! Thank you for your help, it got me to realize that the bug itself did not make sense software-wise.

Reply
  • Ok, I randomly realized that it was not the phone getting away from the device that caused the bug but me/my chair.

    I did not have access to a Nordic DK until now and I could not reproduce the bug on an nrf52dk. So, I am pretty sure this is an EMC problem on my custom board. After a few tries with/without the J-link debugger plugged in, I am 99% certain this was the problem. The bug disappear when it is not plugged in and when it is, if I move quickly, with my chair, away from the device the device immediately resets (bc of EMC on the pin probably).

    I am really sorry for your time ! Thank you for your help, it got me to realize that the bug itself did not make sense software-wise.

Children
No Data
Related