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

Openthread / Nordic Connect SDK confusion

It has been said that Nordic SDK v4.1.0 for Thread is in maintenance mode. I was told that I should move new Thread development to nRF Connect SDK. I am trying to explore that.

I try to call the same OpenThread API functions that I used in the SDK for Thread such as

otDatasetIsCommissioned(openthread_get_default_instance()) 

and it crashes.

I stumbled upon OpenThread integration in the documentation. This long and complex description is of how Openthread is integrated into Zephyr OS into nRF Connect SDK. This is not at all equivalent. How is my application supposed to perform my own joining or handling of thread state changes?

On the above page, it says "From the architecture perspective, the L2 layer is using the nRF IEEE 802.15.4 radio driver, which is located underneath the L2 layer. It can also optionally use Zephyr’s IPv6 stack, which is located above it. The OpenThread API and IPv6 stack can be used directly, but by default, Zephyr’s IPv6 stack is used."

I cannot find anywhere in that huge description of how to 'disable' or 'enable' this optional feature. The openthread examples are of no help, they simply call

openthread_start(openthread_get_default_context());

which hides all the details.

I am confused about what is and is not possible / supported with the Openthread in the nRF Connect SDK.

EDIT:

Let me add... The crash I was experiencing appears to be due to stack size. The stack that was calling

otDatasetIsCommissioned() had a stack size of 1024, I needed to increase it to 2048. 


I have made further progress, but am now stuck on another issue...

(CONFIG_OPENTHREAD_MANUAL_START=y is set)

I have a task which calls the following:

  error = otIp6SetEnabled(ot_instance, true);
__ASSERT_NO_MSG(error == OT_ERROR_NONE);

  // Must reset to 0xFFFF or it only tries to join default panid
error = otLinkSetPanId(ot_instance, 0xFFFF);
__ASSERT_NO_MSG(error == OT_ERROR_NONE);

error = otJoinerStart(ot_instance, "TEST1234", NULL, "VENDOR", "MODEL", "SWVER", NULL, joiner_callback, NULL);

__ASSERT_NO_MSG(error == OT_ERROR_NONE);

...

The joiner_callback is never invoked. And on the packet sniffer, I never see a discover sent.
However, if I call 'ot joiner start TEST1234" from the CLI, it works fine!

This code flow worked under SDK for Thread v4.1.0

Parents
  • Hi,

    How is my application supposed to perform my own joining or handling of thread state changes?

    Have you tried the CoAP client and server example? They basically show how to use thread network on the application level. The examples and documents try to explain one basic concept: Take and use only OpenThread API for features that can not be handled using NCS or Zephyr API.

    how to 'disable' or 'enable' this optional feature.

     Since the document and all Thread examples follow the above principle, so there is no guidance to use OpenThread IPv6 stack. I also strongly suggest you follow the current structure shown on the drawing now. net_ipv6_input() function in RX traffic flow step 8 is Zephyr’s IPv6 stack implementation.

    what is and is not possible / supported with the Openthread in the nRF Connect SDK.

     As described in the document, you can find some clues on the RX and TX traffic drawings. It is also possible to analyze openthread_start function source codes to find how it configures and manages the Openthread connection. 

    The joiner_callback is never invoked.

    I checked the codes you shared on openthread manual joiner hangs · Issue #32343 · zephyrproject-rtos/zephyr (github.com). This is exactly what one part of the openthread_start function does, but there are some steps you lost. Below are the critical codes related to the joining process in zephyr\subsys\net\l2\openthread\opthread.c openthread_start function. I have tested it through the CoAP client and CoAP server example. I can see the printout "Join success" from ot_joiner_start_handler callback function. Please refer to the examples and using the existing functional codes in your applications if possible.

        openthread_api_mutex_lock(ot_context);
    
    	otIp6SetEnabled(ot_context->instance, true);
    
        ...
        
    	if (otDatasetIsCommissioned(ot_instance)) {
    		/* OpenThread already has dataset stored - skip the
    		 * configuration.
    		 */
    		NET_DBG("OpenThread already commissioned.");
    	} else if (IS_ENABLED(CONFIG_OPENTHREAD_JOINER_AUTOSTART)) {
    		/* No dataset - initiate network join procedure. */
    		NET_DBG("Starting OpenThread join procedure.");
    
    		error = otJoinerStart(ot_instance, OT_JOINER_PSKD, NULL,
    				      PACKAGE_NAME, OT_PLATFORM_INFO,
    				      PACKAGE_VERSION, NULL,
    				      &ot_joiner_start_handler, ot_context);
    
    		if (error != OT_ERROR_NONE) {
    			NET_ERR("Failed to start joiner [%d]", error);
    		}
    
    		goto exit;
    		
    		...
    		
    		exit:
    	    openthread_api_mutex_unlock(ot_context);

    Best regards,

    Charlie

  • Have you tried the CoAP client and server example?

    No and the reason is that when I looked at the CoAP stack code in Zephyr it is

    1) Listed as 'Unstable'

    2) Looking at the Zephyr code, it does not even support CoAP retransmissions. It leaves all that up to the application layer, moving a lot of work to the user. If I remember, the client/server code blindly sends without a care. I believe the Nordic CoAP IoT stack in SDK v4.1.0 handled this.

    3) The CoAP examples and reliance on integration with UDP seems geared towards IoT cellular modem with large MTU, not Openthread.

    Those are the reasons I am trying to use Openthread CoAP stack rather than Zephyr.

    It looks like the only thing missing from my code is that Openthread is not 'thread-safe' so all calls need to be surrounded by the openthread_api_mutex_*. I missed that important detail.

Reply
  • Have you tried the CoAP client and server example?

    No and the reason is that when I looked at the CoAP stack code in Zephyr it is

    1) Listed as 'Unstable'

    2) Looking at the Zephyr code, it does not even support CoAP retransmissions. It leaves all that up to the application layer, moving a lot of work to the user. If I remember, the client/server code blindly sends without a care. I believe the Nordic CoAP IoT stack in SDK v4.1.0 handled this.

    3) The CoAP examples and reliance on integration with UDP seems geared towards IoT cellular modem with large MTU, not Openthread.

    Those are the reasons I am trying to use Openthread CoAP stack rather than Zephyr.

    It looks like the only thing missing from my code is that Openthread is not 'thread-safe' so all calls need to be surrounded by the openthread_api_mutex_*. I missed that important detail.

Children
No Data
Related