[nRF52832] how to fix k_sys_fatal_error_handler()

I made my custom board using nrf52832.

Since this will be used for peripheral, I created a new project using custom board wizard in VSCode (nRF Connect SDK) and peripheral_uart sample code.

One issue I am struggling is that my firmware keeps throwing fatal exception after bt_le_adv_start() called. (Not right after but inside for loop).

>> err code = 0 (very interesting)

k_sys_fatal_error_handler executed with reason=3

I can't find the device in the connect app. (It's things are right, it should be found)

Here's the current main.c and myboard_defconfig file.

main.c

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

/** @file
 *  @brief Nordic UART Bridge Service (NUS) sample
 */
#include "uart_async_adapter.h"

#include <zephyr/types.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/usb/usb_device.h>

#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <soc.h>

#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/hci.h>

#include <bluetooth/services/nus.h>

#include <dk_buttons_and_leds.h>

#include <zephyr/settings/settings.h>

#include <stdio.h>

#include <zephyr/logging/log.h>

#define LOG_MODULE_NAME peripheral_uart
LOG_MODULE_REGISTER(LOG_MODULE_NAME);

#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
#define PRIORITY 7

#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)

#define RUN_STATUS_LED DK_LED1
#define RUN_LED_BLINK_INTERVAL 1000

#define CON_STATUS_LED DK_LED2

#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
#define KEY_PASSKEY_REJECT DK_BTN2_MSK

#define UART_BUF_SIZE CONFIG_BT_NUS_UART_BUFFER_SIZE
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
#define UART_WAIT_FOR_RX CONFIG_BT_NUS_UART_RX_WAIT_TIME

static K_SEM_DEFINE(ble_init_ok, 0, 1);

static struct bt_conn *current_conn;
static struct bt_conn *auth_conn;

static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
static struct k_work_delayable uart_work;

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 const struct bt_data ad[] = {
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
	BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};

static const struct bt_data sd[] = {
	BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
};

#if CONFIG_BT_NUS_UART_ASYNC_ADAPTER
UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
#else
static const struct device *const async_adapter;
#endif

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

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

static bool uart_test_async_api(const struct device *dev)
{
	const struct uart_driver_api *api =
		(const struct uart_driver_api *)dev->api;

	return (api->callback_set != NULL);
}

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

	if (!device_is_ready(uart))
	{
		return -ENODEV;
	}

	if (IS_ENABLED(CONFIG_USB_DEVICE_STACK))
	{
		err = usb_enable(NULL);
		if (err && (err != -EALREADY))
		{
			LOG_ERR("Failed to enable USB");
			return err;
		}
	}

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

	k_work_init_delayable(&uart_work, uart_work_handler);

	if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !uart_test_async_api(uart))
	{
		/* Implement API adapter */
		uart_async_adapter_init(async_adapter, uart);
		uart = async_adapter;
	}

	err = uart_callback_set(uart, uart_cb, NULL);
	if (err)
	{
		k_free(rx);
		LOG_ERR("Cannot initialize UART callback");
		return err;
	}

	if (IS_ENABLED(CONFIG_UART_LINE_CTRL))
	{
		LOG_INF("Wait for DTR");
		while (true)
		{
			uint32_t dtr = 0;

			uart_line_ctrl_get(uart, UART_LINE_CTRL_DTR, &dtr);
			if (dtr)
			{
				break;
			}
			/* Give CPU resources to low priority threads. */
			k_sleep(K_MSEC(100));
		}
		LOG_INF("DTR set");
		err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DCD, 1);
		if (err)
		{
			LOG_WRN("Failed to set DCD, ret code %d", err);
		}
		err = uart_line_ctrl_set(uart, UART_LINE_CTRL_DSR, 1);
		if (err)
		{
			LOG_WRN("Failed to set DSR, ret code %d", err);
		}
	}

	tx = k_malloc(sizeof(*tx));

	if (tx)
	{
		pos = snprintf(tx->data, sizeof(tx->data),
					   "Starting Nordic UART service example\r\n");

		if ((pos < 0) || (pos >= sizeof(tx->data)))
		{
			k_free(rx);
			k_free(tx);
			LOG_ERR("snprintf returned %d", pos);
			return -ENOMEM;
		}

		tx->len = pos;
	}
	else
	{
		k_free(rx);
		return -ENOMEM;
	}

	err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
	if (err)
	{
		k_free(rx);
		k_free(tx);
		LOG_ERR("Cannot display welcome message (err: %d)", err);
		return err;
	}

	err = uart_rx_enable(uart, rx->data, sizeof(rx->data), 50);
	if (err)
	{
		LOG_ERR("Cannot enable uart reception (err: %d)", err);
		/* Free the rx buffer only because the tx buffer will be handled in the callback */
		k_free(rx);
	}

	return err;
}

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

	if (err)
	{
		LOG_ERR("Connection failed (err %u)", err);
		return;
	}

	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
	LOG_INF("Connected %s", addr);

	current_conn = bt_conn_ref(conn);

	dk_set_led_on(CON_STATUS_LED);
}

static void disconnected(struct bt_conn *conn, uint8_t reason)
{
	char addr[BT_ADDR_LE_STR_LEN];

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

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

	if (auth_conn)
	{
		bt_conn_unref(auth_conn);
		auth_conn = NULL;
	}

	if (current_conn)
	{
		bt_conn_unref(current_conn);
		current_conn = NULL;
		dk_set_led_off(CON_STATUS_LED);
	}
}

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
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);
	}
}
#endif

BT_CONN_CB_DEFINE(conn_callbacks) = {
	.connected = connected,
	.disconnected = disconnected,
#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
	.security_changed = security_changed,
#endif
};

#if defined(CONFIG_BT_NUS_SECURITY_ENABLED)
static void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
{
	char addr[BT_ADDR_LE_STR_LEN];

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

	LOG_INF("Passkey for %s: %06u", addr, passkey);
}

static void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
{
	char addr[BT_ADDR_LE_STR_LEN];

	auth_conn = bt_conn_ref(conn);

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

	LOG_INF("Passkey for %s: %06u", addr, passkey);
	LOG_INF("Press Button 1 to confirm, Button 2 to reject.");
}

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_INF("Pairing failed conn: %s, reason %d", addr, reason);
}

static struct bt_conn_auth_cb conn_auth_callbacks = {
	.passkey_display = auth_passkey_display,
	.passkey_confirm = auth_passkey_confirm,
	.cancel = auth_cancel,
};

static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
	.pairing_complete = pairing_complete,
	.pairing_failed = pairing_failed};
#else
static struct bt_conn_auth_cb conn_auth_callbacks;
static struct bt_conn_auth_info_cb conn_auth_info_callbacks;
#endif

static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data,
						  uint16_t len)
{
	int err;
	char addr[BT_ADDR_LE_STR_LEN] = {0};

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

	LOG_INF("Received data from: %s", addr);

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

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

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

		err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
		if (err)
		{
			k_fifo_put(&fifo_uart_tx_data, tx);
		}
	}
}

static struct bt_nus_cb nus_cb = {
	.received = bt_receive_cb,
};

void error(void)
{
	dk_set_leds_state(DK_ALL_LEDS_MSK, DK_NO_LEDS_MSK);

	while (true)
	{
		/* Spin for ever */
		k_sleep(K_MSEC(1000));
	}
}

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
static void num_comp_reply(bool accept)
{
	if (accept)
	{
		bt_conn_auth_passkey_confirm(auth_conn);
		LOG_INF("Numeric Match, conn %p", (void *)auth_conn);
	}
	else
	{
		bt_conn_auth_cancel(auth_conn);
		LOG_INF("Numeric Reject, conn %p", (void *)auth_conn);
	}

	bt_conn_unref(auth_conn);
	auth_conn = NULL;
}

void button_changed(uint32_t button_state, uint32_t has_changed)
{
	uint32_t buttons = button_state & has_changed;

	if (auth_conn)
	{
		if (buttons & KEY_PASSKEY_ACCEPT)
		{
			num_comp_reply(true);
		}

		if (buttons & KEY_PASSKEY_REJECT)
		{
			num_comp_reply(false);
		}
	}
}
#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

static void configure_gpio(void)
{
	int err;

#ifdef CONFIG_BT_NUS_SECURITY_ENABLED
	err = dk_buttons_init(button_changed);
	if (err)
	{
		LOG_ERR("Cannot init buttons (err: %d)", err);
	}
#endif /* CONFIG_BT_NUS_SECURITY_ENABLED */

	err = dk_leds_init();
	if (err)
	{
		LOG_ERR("Cannot init LEDs (err: %d)", err);
	}
}

int main(void)
{
	int blink_status = 0;
	int err = 0;

	// configure_gpio();

	// err = uart_init();
	// if (err)
	// {
	// 	error();
	// }

	// if (IS_ENABLED(CONFIG_BT_NUS_SECURITY_ENABLED))
	// {
	// 	err = bt_conn_auth_cb_register(&conn_auth_callbacks);
	// 	if (err)
	// 	{
	// 		printk("Failed to register authorization callbacks.\n");
	// 		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)
	{
		error();
	}

	LOG_INF("Bluetooth initialized");

	k_sem_give(&ble_init_ok);

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

	// err = bt_nus_init(&nus_cb);
	// if (err)
	// {
	// 	LOG_ERR("Failed to initialize UART service (err: %d)", err);
	// 	return;
	// }

	err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd,
						  ARRAY_SIZE(sd));
	// if (err)
	// {
	// 	LOG_ERR("Advertising failed to start (err %d)", err);
	// 	return;
	// }

	for (;;)
	{
		// dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
		// k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));

		k_sleep(K_SECONDS(10)); // Sleep for 10 seconds
	}
}

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

custom_board_defconfig

# Copyright (c) 2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0

CONFIG_SOC_SERIES_NRF52X=y
CONFIG_SOC_NRF52832_QFAA=y
CONFIG_BOARD_PIE_MOCAP=y

# Enable MPU
CONFIG_ARM_MPU=y

# Enable hardware stack protection
CONFIG_HW_STACK_PROTECTION=y


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

CONFIG_GPIO=y

# Make sure printk is printing to the UART console
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y

CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_HCI=y
CONFIG_BT_CTLR=y
CONFIG_BT_LL_SW_SPLIT=y
CONFIG_BT_DEVICE_NAME="test"
CONFIG_BT_DEVICE_APPEARANCE=0
CONFIG_BT_MAX_CONN=1
CONFIG_BT_MAX_PAIRED=1
CONFIG_ASSERT=y

# CONFIG_BT_LL_SOFTDEVICE=y


# Enable the NUS service
CONFIG_BT_NUS=y

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

# Enable DK LED and Buttons library
CONFIG_DK_LIBRARY=y

# This example requires more workqueue stack
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_MAIN_STACK_SIZE=4096

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

CONFIG_ASSERT=y

# External 32kHz Crystal
# not enter into main.c
CONFIG_CLOCK_CONTROL=y
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL=y
# CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=n

# solution
# https://devzone.nordicsemi.com/f/nordic-q-a/96300/programs-never-make-it-to-main/408081
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y

# DCDC not LDO
CONFIG_BOARD_ENABLE_DCDC=y

# For custom board, it's essential
CONFIG_PINCTRL=y

# Special Note
# those two configuration should be custom_board_name_defconfig
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y


# https://devzone.nordicsemi.com/f/nordic-q-a/99097/zephyr-ble-samples-assert-in-bt_enable-with-zephyr-ble-controller-on-nrf52833-nrf52840-dev-kits
# CONFIG_BT_LL_SW_SPLIT=y

External 32MHz crystal soldered correctly.

How to overcome this issue? any suggestions? 

Parents
  • Hello,

    Are you able to retreive the debug logs from the device? In that case, please post the log here. You may need to add CONFIG_RESET_ON_FATAL_ERROR=n to your build to be able to view the crashlog.

    Best regards,

    Vidar

  • Here's the Log with CONFIG_RESET_ON_FATAL_ERROR=n

    JLinkGDBServerCL: SEGGER J-Link GDB Server V7.80c Command Line Version
    JLinkGDBServerCL: 
    JLinkGDBServerCL: JLinkARM.dll V7.80c (DLL compiled Sep 27 2022 16:06:20)
    JLinkGDBServerCL: 
    JLinkGDBServerCL: -----GDB Server start settings-----
    JLinkGDBServerCL: GDBInit file:                  none
    JLinkGDBServerCL: GDB Server Listening port:     62845
    JLinkGDBServerCL: SWO raw output listening port: 2332
    JLinkGDBServerCL: Terminal I/O port:             2333
    JLinkGDBServerCL: Accept remote connection:      localhost only
    JLinkGDBServerCL: Generate logfile:              off
    JLinkGDBServerCL: Verify download:               off
    JLinkGDBServerCL: Init regs on start:            off
    JLinkGDBServerCL: Silent mode:                   on
    JLinkGDBServerCL: Single run mode:               on
    JLinkGDBServerCL: Target connection timeout:     0 ms
    JLinkGDBServerCL: ------J-Link related settings------
    JLinkGDBServerCL: J-Link Host interface:         USB
    JLinkGDBServerCL: J-Link script:                 none
    JLinkGDBServerCL: J-Link settings file:          none
    JLinkGDBServerCL: ------Target related settings------
    JLinkGDBServerCL: Target device:                 nrf52
    JLinkGDBServerCL: Target device parameters:      none
    JLinkGDBServerCL: Target interface:              SWD
    JLinkGDBServerCL: Target interface speed:        12000kHz
    JLinkGDBServerCL: Target endian:                 little
    JLinkGDBServerCL: 
    =thread-group-added,id="i1"
    =cmd-param-changed,param="pagination",value="off"
    z_arm_reset () at C:/ncs/v2.5.0/zephyr/arch/arm/core/aarch32/cortex_m\reset.S:73
    73	    movs.n r0, #0
    [New Remote target]
    [New Thread 536877656]
    [New Thread 536877472]
    [New Thread 536874096]
    [New Thread 536877840]
    [New Thread 536875368]
    [New Thread 536875584]
    [New Thread 536876776]
    [New Thread 536876592]
    [Switching to Thread 536877656]
    
    Thread 3 hit Breakpoint 1, main () at ../src/main.c:632
    632	{
    Execute debugger commands using "-exec <command>", for example "-exec info registers" will list registers in use (when GDB is the debugger)
    [New Thread 536875584]
    [New Thread 536876776]
    [New Thread 536876592]
    
    Thread 3 hit Breakpoint 2, main () at ../src/main.c:691
    691		for (;;)
    [New Remote target]
    [Switching to Remote target]
    
    Thread 14 hit Breakpoint 5, k_sys_fatal_error_handler (reason=reason@entry=3, esf=esf@entry=0x20005e38 <z_interrupt_stacks+1592>) at C:/ncs/v2.5.0/zephyr/kernel/fatal.c:41
    41	{
    

    ** As you can see, debugger pointer still survive after checking error code from bt_ld_adv_start()

  • Sorry, I meant to ask for the logs from your FW (from LOG_ERR(), printk(), etc), not the GDB log you posted. To view these logs, you need to connect RTT or to the serial port if you have logging over UART enabled.

     https://nrfconnect.github.io/vscode-nrf-connect/guides/bd_work_with_boards.html?h=rtt#how-to-connect-to-a-device 

  • Oh. Currently, I didn't soldered UART to USB converter on PCB. 

    I thought this won't affect the firmware behavior.

    How do you think

  • oh. let me give you more detailed info.

    _oops at swap_helper.s called

    >> I don't know well about the assembly but I guess it's related with fatal exception detection inside zephyr.

    >> If my guess is right, I think we need to check previous method called in callstacks. 

    lll_adc.c file exact call is " radio_isr_set(isr_abort, lll);" can you guess what's wrong?

    #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
    	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
    	uint32_t overhead;
    
    	overhead = lll_preempt_calc(ull, (TICKER_ID_ADV_BASE + ull_adv_lll_handle_get(lll)),
    				    ticks_at_event);
    	/* check if preempt to start has changed */
    	if (overhead) {
    		LL_ASSERT_OVERHEAD(overhead);
    
    		radio_isr_set(isr_abort, lll);
    		radio_disable();
    
    		return -ECANCELED;
    	}
    #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */

Reply Children
  • Please check below.

    I got to understand why you keep suggesting using RTT log.

    As soon as fatal exception triggered, RTT Log printed on the console.

    Can you guess what's wrong?

    00> [00:00:53.469,451] <dbg> bt_hci_core: send_cmd: calling net_buf_get
    00> --- 718 messages dropped ---
    00> [00:00:53.469,482] <dbg> bt_hci_core: send_cmd: calling sem_take_wait
    00> [00:00:53.469,512] <dbg> bt_hci_core: send_cmd: Sending command 0x200a (buf 0x2000adcc) to driver
    00> [00:00:53.469,543] <dbg> bt_hci_core: bt_send: buf 0x2000adcc len 4 type 0
    00> [00:00:53.469,573] <dbg> bt_ctlr_hci_driver: hci_driver_send: enter
    00> [00:00:53.469,696] <dbg> bt_ctlr_ull_filter: rpa_refresh_start: 
    00> [00:00:53.469,757] <dbg> bt_ctlr_hci_driver: cmd_handle: Replying with event of 6 bytes
    00> [00:00:53.469,787] <dbg> bt_hci_core: hci_cmd_complete: opcode 0x200a
    00> [00:00:53.469,818] <dbg> bt_hci_core: hci_cmd_done: opcode 0x200a status 0x00 buf 0x2000adcc
    00> [00:00:53.469,879] <dbg> bt_ctlr_hci_driver: hci_driver_send: exit: 0
    00> [00:00:53.469,909] <dbg> bt_hci_core: process_events: ev->state 0
    00> [00:00:53.469,940] <dbg> mpu: mpu_configure_region: Configure MPU region at index 0x2
    00> [00:00:53.470,123] <dbg> mpu: region_allocate_and_init: Program MPU region at index 0x2
    00> [00:00:53.470,153] <dbg> mpu: region_init: [2] 0x20005300 0x150b000a
    00> [00:00:53.470,184] <dbg> bt_conn: bt_conn_prepare_events: 
    00> [00:00:53.470,214] <dbg> bt_hci_core: hci_tx_thread: Calling k_poll with 2 events
    00> [00:00:53.470,275] <dbg> mpu: mpu_configure_region: Configure MPU region at index 0x2
    00> [00:00:53.470,306] <dbg> mpu: region_allocate_and_init: Program MPU region at index 0x2
    00> [00:00:53.470,336] <dbg> mpu: region_init: [2] 0x200079c0 0x150b000a
    00> [00:00:53.470,367] <dbg> bt_hci_core: bt_hci_cmd_send_sync: rsp 0x2000adcc opcode 0x200a len 1
    00> [00:00:53.470,428] <dbg> bt_conn: bt_conn_unref: handle 0 ref 2 -> 1
    00> [00:01:25.463,684] <err> os: r0/a1:  0x00000003  r1/a2:  0x0004c09d  r2/a3:  0x00000000
    00> [00:01:25.463,714] <err> os: r3/a4:  0x00002695 r12/ip:  0x00008d04 r14/lr:  0x000016bb
    00> [00:01:25.463,745] <err> os:  xpsr:  0x61000011
    00> [00:01:25.463,775] <err> os: Faulting instruction address (r15/pc): 0x000016c6
    00> [00:01:25.463,836] <err> os: >>> ZEPHYR FATAL ERROR 3: Kernel oops on CPU 0
    00> [00:01:25.463,836] <err> os: Fault during interrupt handling
    00> 
    00> [00:01:25.463,928] <err> os: Current thread: 0x20001b20 (main)
    00> [00:01:30.185,211] <err> fatal_error: Resetting system

  • Yes, this is what I was looking for. Thanks. But is this tested with or without 'CONFIG_BT_LL_SW_SPLIT' enabled? 

    Please also try to measure the ramp-up time of your 32M crystal with the code snippet posted here:  RE: MPSL ASSERT: 112, 2134 if using multiple BLE communication  

  • Let me answer step by step.

    1) CONFIG_BT_LL_SW_SPLIT enabled 

    CONFIG_BT_LL_SW_SPLIT

    2)  Can you help me for this more detail?

    also try to measure the ramp-up time of your 32M crystal with the code snippet

    [UPDATE] Hang in the while loop which checks 32MHz clock starts correctly.

    I used 32MHz Crystal "Seiko Epson Q22FA1280002500"


    32MHz 8pF ±10ppm SMD2016-4P Crystals ROHS

    I put 12pF Capacitor for each Clock Pins.

    What would be the first debugging process?

  • Please check if the XTAL bit is set in HFCLKSTAT when printing the "Starting HFCLK line...". If it's not set, then that suggests that the problem is with the crystal (soldering issue, etc).

Related