openthread MTD offline in long time stability testing

NCS ver: 2.0.1

chip: nrf52840

node: MTD not SED

network: one OTBR as leader and one MTD as child

After about 4~10 hours, MTD will offline. Sometimes it can reconnect to the network but sometimes it can never reconnect until I reboot it.

MTD output log like this:

[00:01:00.778,533] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.783,966] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.786,773] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.788,757] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.792,388] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.800,567] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.807,189] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.811,737] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.818,847] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.822,906] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.827,209] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.833,465] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.839,324] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.844,360] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.850,769] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.855,041] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.858,673] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.860,656] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.864,471] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:00.872,711] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:01.216,033] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:01.223,693] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:02.768,676] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered
[00:01:02.782,257] <dbg> net_openthread: [D] Mac-----------: Frame rx failed, error:DestinationAddressFiltered

Parents
  • Hi Kelly,

    I have the following suggestions for the issue:

    1) Can you provide more information about your MED device? Is it modified form Thread: CoAP Client ? Did it do something after connecting with OTBR formed thread network? I want to repeat the same test on my side to understand the issue.

    2) Are you able to test with the latest NCS2.2.0? Try to also use the latest OTBR suggested(0895ad5).

    Best regards,

    Charlie

  • Hi Charlie,

    1. The firmware I test now is define by our product hardware(some gpio and sensor). It will report some data every half hours by coap udp.

    I also test the openthread/cli project and add some code as follow. I think you can use nrf52840DK board to test.

    /*
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    
    #if defined(CONFIG_BT)
    #include "ble.h"
    #endif
    
    #include <drivers/gpio.h>
    #include <devicetree.h>
    #include <device.h>
    #include <dk_buttons_and_leds.h>
    
    
    #include <zephyr/drivers/uart.h>
    #include <zephyr/usb/usb_device.h>
    
    #include <net/openthread.h>
    #include <openthread/thread.h>
    
    
    #define LED1 0
    #define LED2 1
    
    #define LED_ON 1
    #define LED_OFF 0
    
    
    LOG_MODULE_REGISTER(cli_sample, CONFIG_OT_COMMAND_LINE_INTERFACE_LOG_LEVEL);
    
    #define WELLCOME_TEXT \
    	"\n\r"\
    	"\n\r"\
    	"OpenThread Command Line Interface is now running.\n\r" \
    	"Use the 'ot' keyword to invoke OpenThread commands e.g. " \
    	"'ot thread start.'\n\r" \
    	"For the full commands list refer to the OpenThread CLI " \
    	"documentation at:\n\r" \
    	"https://github.com/openthread/openthread/blob/master/src/cli/README.md\n\r"
    
    
    
    static struct k_timer led1_timer;
    static struct k_timer led2_timer;
    static bool led1_timer_start;
    static bool led2_timer_start;
    
    static void on_led1_timer_expiry(struct k_timer *timer_id)
    {
    	static uint32_t val = 1;
    
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED1, val);
    	val = !val;
    }
    
    static void on_led1_timer_stop(struct k_timer *timer_id)
    {
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED1, (uint32_t)LED_OFF);
    }
    
    static void on_led2_timer_expiry(struct k_timer *timer_id)
    {
    	static uint32_t val = 1;
    
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED2, val);
    	val = !val;
    }
    
    static void on_led2_timer_stop(struct k_timer *timer_id)
    {
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED2, (uint32_t)LED_OFF);
    }
    
    void led_toggle_start(int led_node, int ms)
    {
    	if(led_node == LED1)
    	{
    		k_timer_stop(&led1_timer);
    
    		led1_timer_start = true;
    
    		k_timer_init(&led1_timer, on_led1_timer_expiry, on_led1_timer_stop);
    		k_timer_start(&led1_timer, K_MSEC(100), K_MSEC(ms));
    	}else if(led_node == LED2) {
    		k_timer_stop(&led2_timer);
    
    		led2_timer_start = true;
    
    		k_timer_init(&led2_timer, on_led2_timer_expiry, on_led2_timer_stop);
    		k_timer_start(&led2_timer, K_MSEC(100), K_MSEC(ms));
    	}
    }
    
    void led_toggle_stop(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		k_timer_stop(&led1_timer);
    
    		led1_timer_start = false;
    
    	}else if(led_idx == LED2){
    		k_timer_stop(&led2_timer);
    
    		led2_timer_start = false;
    	}
    }
    
    void led_on(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		if (led1_timer_start)
    			led_toggle_stop(LED1);
    	}else if(led_idx == LED2) {
    		if (led2_timer_start)
    			led_toggle_stop(LED2);
    	}
    
    	dk_set_led_on(led_idx);
    }
    
    void led_off(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		if (led1_timer_start)
    			led_toggle_stop(LED1);
    	}else if(led_idx == LED2) {
    		if (led2_timer_start)
    			led_toggle_stop(LED2);
    	}
    
    	dk_set_led_off(led_idx);
    }
    
    static bool is_joined = false;
    
    static void on_thread_state_changed(uint32_t flags, void *context)
    {
    	struct openthread_context *ot_context = context;
    
    	if (flags & OT_CHANGED_THREAD_ROLE) {
    		printk("otThreadGetDeviceRole: %d\n", otThreadGetDeviceRole(ot_context->instance));
    		switch (otThreadGetDeviceRole(ot_context->instance)) {
    		case OT_DEVICE_ROLE_CHILD:
    		case OT_DEVICE_ROLE_ROUTER:
    		case OT_DEVICE_ROLE_LEADER:
    			led_on(LED2);
    			break;
    
    		case OT_DEVICE_ROLE_DISABLED:
    		case OT_DEVICE_ROLE_DETACHED:
    			led_toggle_start(LED2, 300);
    			break;
    		default:
    			break;
    		}
    	}
    
    	if (flags & OT_CHANGED_JOINER_STATE) {
    		int state = otJoinerGetState(ot_context->instance);
    		switch (state) {
    		case OT_JOINER_STATE_DISCOVER:
    		case OT_JOINER_STATE_CONNECT:
    			led_toggle_start(LED1, 300);
    			break;
    
    		case OT_JOINER_STATE_IDLE:
    			led_off(LED1);
    			// if(!is_joined)
    			break;
    		case OT_JOINER_STATE_JOINED:
    			led_on(LED1);
    			// is_joined = true;
    			break;
    		default:
    			break;
    		}
    	}
    }
    
    
    void main(void)
    {
    #if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_shell_uart), zephyr_cdc_acm_uart)
    	int ret;
    	const struct device *dev;
    	uint32_t dtr = 0U;
    
    	ret = usb_enable(NULL);
    	if (ret != 0) {
    		LOG_ERR("Failed to enable USB");
    		return;
    	}
    
    	dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart));
    	if (dev == NULL) {
    		LOG_ERR("Failed to find specific UART device");
    		return;
    	}
    
    	LOG_INF("Waiting for host to be ready to communicate");
    
    	/* Data Terminal Ready - check if host is ready to communicate */
    	while (!dtr) {
    		ret = uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
    		if (ret) {
    			LOG_ERR("Failed to get Data Terminal Ready line state: %d",
    				ret);
    			continue;
    		}
    		k_msleep(100);
    	}
    
    	/* Data Carrier Detect Modem - mark connection as established */
    	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DCD, 1);
    	/* Data Set Ready - the NCP SoC is ready to communicate */
    	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DSR, 1);
    #endif
    
    	LOG_INF(WELLCOME_TEXT);
    
    	dk_leds_init();
    	
    	openthread_set_state_changed_cb(on_thread_state_changed);
    
    	struct openthread_context *context = openthread_get_default_context();
    	otLinkSetPanId(context->instance, 0xffff);
    	otPlatRadioSetTransmitPower(context->instance, 8);
    
    	openthread_start(context);
    
    #if CONFIG_BT
    	ble_enable();
    #endif
    
    }
    

    prj.conf add this:

    CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=2048
    CONFIG_NET_BUF_LOG=y
    CONFIG_OPENTHREAD_FULL_LOGS=y
    CONFIG_OPENTHREAD_JOINER_AUTOSTART=y
    CONFIG_OPENTHREAD_JOINER_PSKD="AAAAAA"
    CONFIG_NET_LOG=y
    CONFIG_OPENTHREAD_DEBUG=y
    CONFIG_OPENTHREAD_LOG_LEVEL_INFO=y
    CONFIG_OPENTHREAD_L2_DEBUG=y
    CONFIG_OPENTHREAD_L2_DEBUG_DUMP_15_4=y
    CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6=y
    CONFIG_OPENTHREAD_THREAD_PREEMPTIVE=y
    CONFIG_OPENTHREAD_MTD=y
    CONFIG_DK_LIBRARY=y

    2. I will update my ncs version and test again next week 

Reply
  • Hi Charlie,

    1. The firmware I test now is define by our product hardware(some gpio and sensor). It will report some data every half hours by coap udp.

    I also test the openthread/cli project and add some code as follow. I think you can use nrf52840DK board to test.

    /*
     * Copyright (c) 2020 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    #include <zephyr/kernel.h>
    #include <zephyr/logging/log.h>
    
    #if defined(CONFIG_BT)
    #include "ble.h"
    #endif
    
    #include <drivers/gpio.h>
    #include <devicetree.h>
    #include <device.h>
    #include <dk_buttons_and_leds.h>
    
    
    #include <zephyr/drivers/uart.h>
    #include <zephyr/usb/usb_device.h>
    
    #include <net/openthread.h>
    #include <openthread/thread.h>
    
    
    #define LED1 0
    #define LED2 1
    
    #define LED_ON 1
    #define LED_OFF 0
    
    
    LOG_MODULE_REGISTER(cli_sample, CONFIG_OT_COMMAND_LINE_INTERFACE_LOG_LEVEL);
    
    #define WELLCOME_TEXT \
    	"\n\r"\
    	"\n\r"\
    	"OpenThread Command Line Interface is now running.\n\r" \
    	"Use the 'ot' keyword to invoke OpenThread commands e.g. " \
    	"'ot thread start.'\n\r" \
    	"For the full commands list refer to the OpenThread CLI " \
    	"documentation at:\n\r" \
    	"https://github.com/openthread/openthread/blob/master/src/cli/README.md\n\r"
    
    
    
    static struct k_timer led1_timer;
    static struct k_timer led2_timer;
    static bool led1_timer_start;
    static bool led2_timer_start;
    
    static void on_led1_timer_expiry(struct k_timer *timer_id)
    {
    	static uint32_t val = 1;
    
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED1, val);
    	val = !val;
    }
    
    static void on_led1_timer_stop(struct k_timer *timer_id)
    {
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED1, (uint32_t)LED_OFF);
    }
    
    static void on_led2_timer_expiry(struct k_timer *timer_id)
    {
    	static uint32_t val = 1;
    
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED2, val);
    	val = !val;
    }
    
    static void on_led2_timer_stop(struct k_timer *timer_id)
    {
    	ARG_UNUSED(timer_id);
    
    	dk_set_led((uint8_t)LED2, (uint32_t)LED_OFF);
    }
    
    void led_toggle_start(int led_node, int ms)
    {
    	if(led_node == LED1)
    	{
    		k_timer_stop(&led1_timer);
    
    		led1_timer_start = true;
    
    		k_timer_init(&led1_timer, on_led1_timer_expiry, on_led1_timer_stop);
    		k_timer_start(&led1_timer, K_MSEC(100), K_MSEC(ms));
    	}else if(led_node == LED2) {
    		k_timer_stop(&led2_timer);
    
    		led2_timer_start = true;
    
    		k_timer_init(&led2_timer, on_led2_timer_expiry, on_led2_timer_stop);
    		k_timer_start(&led2_timer, K_MSEC(100), K_MSEC(ms));
    	}
    }
    
    void led_toggle_stop(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		k_timer_stop(&led1_timer);
    
    		led1_timer_start = false;
    
    	}else if(led_idx == LED2){
    		k_timer_stop(&led2_timer);
    
    		led2_timer_start = false;
    	}
    }
    
    void led_on(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		if (led1_timer_start)
    			led_toggle_stop(LED1);
    	}else if(led_idx == LED2) {
    		if (led2_timer_start)
    			led_toggle_stop(LED2);
    	}
    
    	dk_set_led_on(led_idx);
    }
    
    void led_off(uint8_t led_idx)
    {
    	if(led_idx == LED1)
    	{
    		if (led1_timer_start)
    			led_toggle_stop(LED1);
    	}else if(led_idx == LED2) {
    		if (led2_timer_start)
    			led_toggle_stop(LED2);
    	}
    
    	dk_set_led_off(led_idx);
    }
    
    static bool is_joined = false;
    
    static void on_thread_state_changed(uint32_t flags, void *context)
    {
    	struct openthread_context *ot_context = context;
    
    	if (flags & OT_CHANGED_THREAD_ROLE) {
    		printk("otThreadGetDeviceRole: %d\n", otThreadGetDeviceRole(ot_context->instance));
    		switch (otThreadGetDeviceRole(ot_context->instance)) {
    		case OT_DEVICE_ROLE_CHILD:
    		case OT_DEVICE_ROLE_ROUTER:
    		case OT_DEVICE_ROLE_LEADER:
    			led_on(LED2);
    			break;
    
    		case OT_DEVICE_ROLE_DISABLED:
    		case OT_DEVICE_ROLE_DETACHED:
    			led_toggle_start(LED2, 300);
    			break;
    		default:
    			break;
    		}
    	}
    
    	if (flags & OT_CHANGED_JOINER_STATE) {
    		int state = otJoinerGetState(ot_context->instance);
    		switch (state) {
    		case OT_JOINER_STATE_DISCOVER:
    		case OT_JOINER_STATE_CONNECT:
    			led_toggle_start(LED1, 300);
    			break;
    
    		case OT_JOINER_STATE_IDLE:
    			led_off(LED1);
    			// if(!is_joined)
    			break;
    		case OT_JOINER_STATE_JOINED:
    			led_on(LED1);
    			// is_joined = true;
    			break;
    		default:
    			break;
    		}
    	}
    }
    
    
    void main(void)
    {
    #if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_shell_uart), zephyr_cdc_acm_uart)
    	int ret;
    	const struct device *dev;
    	uint32_t dtr = 0U;
    
    	ret = usb_enable(NULL);
    	if (ret != 0) {
    		LOG_ERR("Failed to enable USB");
    		return;
    	}
    
    	dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_shell_uart));
    	if (dev == NULL) {
    		LOG_ERR("Failed to find specific UART device");
    		return;
    	}
    
    	LOG_INF("Waiting for host to be ready to communicate");
    
    	/* Data Terminal Ready - check if host is ready to communicate */
    	while (!dtr) {
    		ret = uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
    		if (ret) {
    			LOG_ERR("Failed to get Data Terminal Ready line state: %d",
    				ret);
    			continue;
    		}
    		k_msleep(100);
    	}
    
    	/* Data Carrier Detect Modem - mark connection as established */
    	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DCD, 1);
    	/* Data Set Ready - the NCP SoC is ready to communicate */
    	(void)uart_line_ctrl_set(dev, UART_LINE_CTRL_DSR, 1);
    #endif
    
    	LOG_INF(WELLCOME_TEXT);
    
    	dk_leds_init();
    	
    	openthread_set_state_changed_cb(on_thread_state_changed);
    
    	struct openthread_context *context = openthread_get_default_context();
    	otLinkSetPanId(context->instance, 0xffff);
    	otPlatRadioSetTransmitPower(context->instance, 8);
    
    	openthread_start(context);
    
    #if CONFIG_BT
    	ble_enable();
    #endif
    
    }
    

    prj.conf add this:

    CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=2048
    CONFIG_NET_BUF_LOG=y
    CONFIG_OPENTHREAD_FULL_LOGS=y
    CONFIG_OPENTHREAD_JOINER_AUTOSTART=y
    CONFIG_OPENTHREAD_JOINER_PSKD="AAAAAA"
    CONFIG_NET_LOG=y
    CONFIG_OPENTHREAD_DEBUG=y
    CONFIG_OPENTHREAD_LOG_LEVEL_INFO=y
    CONFIG_OPENTHREAD_L2_DEBUG=y
    CONFIG_OPENTHREAD_L2_DEBUG_DUMP_15_4=y
    CONFIG_OPENTHREAD_L2_DEBUG_DUMP_IPV6=y
    CONFIG_OPENTHREAD_THREAD_PREEMPTIVE=y
    CONFIG_OPENTHREAD_MTD=y
    CONFIG_DK_LIBRARY=y

    2. I will update my ncs version and test again next week 

Children
No Data
Related