This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Unable to initialize USB CDC and I2C in Open Thread examples

Hello developers,

I would like to know what is wrong with open thread examples, literally tired of trying now. Firstly my two FTD sensor nodes are not able to reconnect, so i thought to again start with a demo example and build the example. Than i face this issue as mentioned in headline. I have been using nRF connect SDK from past 2 months have developed solutions using USB CDC and also using I2C. So it's not like i don't know how to interface USB CDC or I2C using NCS.

I would like to know how can i enable USB CDC in the open thread examples. Here is my normal sensor example, were i am just reading the i2c address of the sensor and printing on terminal.

Simple Code:

/*
 * Copyright (c) 2016 Intel Corporation.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <sys/printk.h>
#include <sys/util.h>
#include <string.h>
#include <usb/usb_device.h>
#include <drivers/uart.h>
#include <stdio.h>
#include <drivers/i2c.h>
#include <sys/printk.h>
#include <usb/usb_device.h>
#include <devicetree.h>
#include <drivers/gpio.h>

/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
#define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
#define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
#define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
#endif

static struct device *i2c_dev;

int i2cscanner()
{
    printk("i2c scanner\r\n");
    i2c_dev = device_get_binding("I2C_1");
    if (!i2c_dev) {
            printk("I2C: Device driver not found.\n");
            return 0;
    }
    i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)| I2C_MODE_MASTER);  
    for (uint8_t i = 4; i <= 0x77; i++) {
		struct i2c_msg msgs[1];
		uint8_t dst[2];

		/* Send the address to read from */
		msgs[0].buf = &dst[0];
		msgs[0].len = 1U;
		msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

		if (i2c_transfer(i2c_dev, &msgs[0], 1, i) == 0) {
			printk("----------------------------0x%2x FOUND\n", i);
		} 
	}
        //k_msleep(1000);
        return 1;
}
void main(void)
{
	const struct device *dev = device_get_binding(
			CONFIG_UART_CONSOLE_ON_DEV_NAME);
	uint32_t dtr = 0;

	if (usb_enable(NULL)) {
		return;
	}

	/* Poll if the DTR flag was set, optional */
	//while (!dtr) {
		uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
	//}

	if (strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME) !=
	    strlen("CDC_ACM_0") ||
	    strncmp(CONFIG_UART_CONSOLE_ON_DEV_NAME, "CDC_ACM_0",
		    strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME))) {
		printk("Error: Console device name is not USB ACM\n");

		return;
	}


const struct device *gpio_dev1;

		gpio_dev1 = device_get_binding("GPIO_1");

 gpio_pin_configure(gpio_dev1, 8, GPIO_OUTPUT_INACTIVE| FLAGS);
      gpio_pin_set(gpio_dev1, 8,1); //      1--- off
	while (1) {
		//printk("Hello World! %s\n", CONFIG_ARCH);
        printk("USB_CDC\r\n");
        i2cscanner();
		k_sleep(K_SECONDS(1));
	}
}
 

And here is my proj.conf for the same.

proj.conf

CONFIG_GPIO=y
CONFIG_SERIAL=y
CONFIG_I2C=y
CONFIG_I2C_1=y
CONFIG_NEWLIB_LIBC_FLOAT_PRINTF=y

CONFIG_USB=y
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_MANUFACTURER="DnK"
CONFIG_USB_DEVICE_PRODUCT="S_Node_test"
CONFIG_USB_UART_CONSOLE=y

CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_UART_LINE_CTRL=y
CONFIG_UART_CONSOLE_ON_DEV_NAME="CDC_ACM_0"


The above example easily runs smoothly without any error. But whenever i try to add the same example in Open thread client server examples. How can i do that ?  If i debug the program in open thread it gives me hard fault error after execution of this statement         uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);  in the below program. I am doing all the experiment on the NCS demo examples itself, haven't invented anything by myself.

Below is the code where i am trying to use USB CDC in my coap server example.

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

#include <zephyr.h>
#include <dk_buttons_and_leds.h>
#include <logging/log.h>
#include <net/openthread.h>
#include <openthread/thread.h>

#include "ot_coap_utils.h"

#include <sys/printk.h>
#include <sys/util.h>
#include <string.h>
#include <usb/usb_device.h>
#include <drivers/uart.h>
#include <stdio.h>
#include <drivers/i2c.h>
#include <devicetree.h>
#include <drivers/gpio.h>

LOG_MODULE_REGISTER(coap_server, CONFIG_COAP_SERVER_LOG_LEVEL);

#define OT_CONNECTION_LED DK_LED1
#define PROVISIONING_LED DK_LED3
#define LIGHT_LED DK_LED4

static struct device *i2c_dev;
static struct k_work provisioning_work;

static struct k_timer led_timer;
static struct k_timer provisioning_timer;



/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0)

#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
#define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
#define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
#define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
#endif

static struct device *i2c_dev;
int i2cscanner()
{
    printk("i2c scanner\r\n");
    i2c_dev = device_get_binding("I2C_1");
    if (!i2c_dev) {
            printk("I2C: Device driver not found.\n");
            return 0;
    }
    i2c_configure(i2c_dev, I2C_SPEED_SET(I2C_SPEED_STANDARD)| I2C_MODE_MASTER);  
    for (uint8_t i = 4; i <= 0x77; i++) {
		struct i2c_msg msgs[1];
		uint8_t dst[2];

		/* Send the address to read from */
		msgs[0].buf = &dst[0];
		msgs[0].len = 1U;
		msgs[0].flags = I2C_MSG_WRITE | I2C_MSG_STOP;

		if (i2c_transfer(i2c_dev, &msgs[0], 1, i) == 0) {
			printk("----------------------------0x%2x FOUND\n", i);
		} 
	}
        //k_msleep(1000);
        return 1;
}

static void on_light_request(uint8_t command)
{
	static uint8_t val;

	switch (command) {
	case THREAD_COAP_UTILS_LIGHT_CMD_ON:
		dk_set_led_on(LIGHT_LED);
		val = 1;
		break;

	case THREAD_COAP_UTILS_LIGHT_CMD_OFF:
		dk_set_led_off(LIGHT_LED);
		val = 0;
		break;

	case THREAD_COAP_UTILS_LIGHT_CMD_TOGGLE:
		val = !val;
		dk_set_led(LIGHT_LED, val);
		break;

	default:
		break;
	}
}

static void activate_provisioning(struct k_work *item)
{
	ARG_UNUSED(item);

	ot_coap_activate_provisioning();

	k_timer_start(&led_timer, K_MSEC(100), K_MSEC(100));
	k_timer_start(&provisioning_timer, K_SECONDS(5), K_NO_WAIT);

	LOG_INF("Provisioning activated");
}

static void deactivate_provisionig(void)
{
	k_timer_stop(&led_timer);
	k_timer_stop(&provisioning_timer);

	if (ot_coap_is_provisioning_active()) {
		ot_coap_deactivate_provisioning();
		LOG_INF("Provisioning deactivated");
	}
}

static void on_provisioning_timer_expiry(struct k_timer *timer_id)
{
	ARG_UNUSED(timer_id);

	deactivate_provisionig();
}

static void on_led_timer_expiry(struct k_timer *timer_id)
{
	static uint8_t val = 1;

	ARG_UNUSED(timer_id);

	dk_set_led(PROVISIONING_LED, val);
	val = !val;
}

static void on_led_timer_stop(struct k_timer *timer_id)
{
	ARG_UNUSED(timer_id);

	dk_set_led_off(PROVISIONING_LED);
}

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

	if (buttons & DK_BTN4_MSK) {
		k_work_submit(&provisioning_work);
	}
}

static void on_thread_state_changed(uint32_t flags, void *context)
{
	struct openthread_context *ot_context = context;

	if (flags & OT_CHANGED_THREAD_ROLE) {
		switch (otThreadGetDeviceRole(ot_context->instance)) {
		case OT_DEVICE_ROLE_CHILD:
		case OT_DEVICE_ROLE_ROUTER:
		case OT_DEVICE_ROLE_LEADER:
			dk_set_led_on(OT_CONNECTION_LED);
			break;

		case OT_DEVICE_ROLE_DISABLED:
		case OT_DEVICE_ROLE_DETACHED:
		default:
			dk_set_led_off(OT_CONNECTION_LED);
			deactivate_provisionig();
			break;
		}
	}
}

void main(void)
{
	const struct device *dev = device_get_binding(
			CONFIG_UART_CONSOLE_ON_DEV_NAME);
	uint32_t dtr = 0;

	if (usb_enable(NULL)) {
		return;
	}

	/* Poll if the DTR flag was set, optional */
	//while (!dtr) {
		uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
	//}

	if (strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME) !=
	    strlen("CDC_ACM_0") ||
	    strncmp(CONFIG_UART_CONSOLE_ON_DEV_NAME, "CDC_ACM_0",
		    strlen(CONFIG_UART_CONSOLE_ON_DEV_NAME))) {
		printk("Error: Console device name is not USB ACM\n");

		return;
	}


    const struct device *gpio_dev1;

		gpio_dev1 = device_get_binding("GPIO_1");

      gpio_pin_configure(gpio_dev1, 8, GPIO_OUTPUT_INACTIVE| FLAGS);
      gpio_pin_set(gpio_dev1, 8,1); //      1--- off
	while (1) {
		//printk("Hello World! %s\n", CONFIG_ARCH);
        printk("USB_CDC\r\n");
        i2cscanner();
		k_sleep(K_SECONDS(1));
	}


}

So can somebody please provide me the code snippet how to use this peripherals in open thread. My whole open thread development is halted thanks to this.

  • Hi McGregor,

    This is Charlie again. I will check your codes later.

    You can also try to contact our local sales team to get a fast response on your project. Find them here: Contact us - nordicsemi.com.

    Best regards,

    Charlie

  • Hi McGregor,

    Thanks for your patience. I spend some time finding the issue of USB CDC.

    Here is my configuration adding to openthread/coap_server/prj.conf:

    CONFIG_USB=y
    CONFIG_USB_DEVICE_STACK=y
    CONFIG_USB_DEVICE_PRODUCT="Zephyr USB console sample"
    CONFIG_USB_UART_CONSOLE=y
    CONFIG_LOG_BACKEND_UART=y
    
    CONFIG_UART_INTERRUPT_DRIVEN=y
    CONFIG_UART_LINE_CTRL=y
    CONFIG_UART_CONSOLE_ON_DEV_NAME="CDC_ACM_0"

    You also need to comment on the following line in openthread/common/overlay-ot-defaults.conf, because it will cover some settings in prj.conf.

    #CONFIG_NCS_SAMPLES_DEFAULTS=y

    Please also be aware that the Console subsystem does not seem to fully support the USB transport. The USB console config setting help text mentioned:

    Note that console inputs from the USB UART are not functional yet.
    It should be OK as long as you only use it for log output.
    Best regards,
    Charlie
Related