Proprietary IEEE 802.15.4 protocol with nRF5340

Hi,

I am new to Nordic products and Zephyr RTOS in general.

I want to implement a proprietary IEEE 802.15.4 protocol using a uBlox NORA-B126 module that incorporates a nRF5340.

As I can see in the Thread/ZigBee examples and the "Working with nRF53" section, I need to build "nRF IEEE 802.15.4: Serialization RPMsg" as child image.

But instead of using an OpenThread or ZigBee library, I want to access the lower layers to implement a proprietary protocol.
Looking at its API, the nRF 802.15.4 Radio Driver seems to fit. But it's running in the network core, so there is serialization in between which probably complicates things a little.

Since I am new to Zephyr and nRF Connect, I don't really know where to start.
It's recommended to start with an example, but with what example should I start with and how do I know what Kconfig (+ Devicetree?) options to set?
How do I know what the Kconfig options do (e.g. add files to compilation), preferraby in VS Code to investigate the samples?

Thank you in advance for your help.

Parents
  • Hi,

    Since I am new to Zephyr and nRF Connect, I don't really know where to start.

    Depending on how new you are, I recommend checking out our nRF Connect SDK Fundamentals course, to learn more about the SDK itself.

    Running the 802.15.4 driver directly on the nRF5340 is a bit more work due to the network core, but it is possible.

    We do not have any 802.15.4 samples for you to start with, so it might be easiest to simply start with the 'Hello World' sample.

    On the nRF5340 you need to enable serialization of the nRF IEEE 802.15.4 driver if you want to use it on the application core. This is done by setting CONFIG_NRF_802154_SER_HOST in prj.conf. You also need to enable some other configurations for the 802.15.4 driver and networking. All in all, you need this in prj.conf for the application core firmware:

    CONFIG_NRF_802154_SER_HOST=y
    CONFIG_IEEE802154_NRF5=y
    CONFIG_NETWORKING=y
    CONFIG_IEEE802154=y
    CONFIG_NET_L2_IEEE802154=y
    
    CONFIG_PARTITION_MANAGER_ENABLED=y

    How do I know what the Kconfig options do (e.g. add files to compilation), preferraby in VS Code to investigate the samples?

    You can use the Kconfig menu to find the different configuration options and information about them. For example:

    Another option is to use the Kconfig reference in our documentation, for example CONFIG_NRF_802154_SER_HOST.

    I need to build "nRF IEEE 802.15.4: Serialization RPMsg" as child image.

    The child image should be added by default with the configurations above enabled, but if not you need to make sure to add 802154_rpmsg as child image. You can see whether the child image has been included or not by looking at the output when you build, where you will have the following if it is included:

    === child image 802154_rpmsg - CPUNET begin ===

    The API for the 802.15.4 driver can be found here: nRF 802.15.4 Radio Driver - API. Make sure to include the header file nrf_802154.h, and to initialize the radio with nrf_802154_init().

    Best regards,
    Marte

  • Hi Marte,

    thank you very much for your helpful reply.

    I have already completed the fundamentals course, which was very helpful to start with.

    Anyway, before testing your reply I managed to send out a few packets but in a different way (probably not the correct one). By using the Kconfig menu, investigating examples and some trial and error I ended up with these options in my prj.conf:

    CONFIG_NETWORKING=y
    CONFIG_IEEE802154=y
    CONFIG_IEEE802154_RAW_MODE=y

    I could then send a packet using

    static const struct device *const radio_dev =
    	DEVICE_DT_GET(DT_CHOSEN(zephyr_ieee802154));
    static struct ieee802154_radio_api *radio_api;
    
    int main(void)
    {
    	if (!device_is_ready(radio_dev))
    	{
    		return -1;
    	}
    
    	radio_api = (struct ieee802154_radio_api *)radio_dev->api;
    	if (!radio_api)
    	{
    		return -1;
    	}
    	radio_api->set_channel(radio_dev, 11);
    
    	while (1)
    	{
    		struct net_pkt pkt;
    		struct net_buf frag;
    
    		int retval = radio_api->tx(radio_dev, IEEE802154_TX_MODE_DIRECT, &pkt, &frag);
    		printk("Sent frame, retval = %i\n\r", retval);
    		k_sleep(K_MSEC(500));
    	}
    
    	return 0;
    }

    Using your options it seems that I can use the nRF 802.15.4 directly (what I intended to do), while what I did was using some kind of wrapper. Where is the difference and why would I choose this API?

    Furthermore, VSCode tells me the option CONFIG_NRF_802154_SER_HOST stays n in the build, if i leave it out it still builds and the resulting image seems to be the same. Do I really need that option in the application core? Here are the dependencies from the Kconig menu:

    !NRF_802154_RADIO_DRIVER (=y) && !HAS_HW_NRF_RADIO_IEEE802154 (=y) && HAS_NORDIC_DRIVERS (=y)
    || !NRF_802154_RADIO_DRIVER (=y) && !HAS_HW_NRF_RADIO_IEEE802154 (=y) && HAS_NORDIC_DRIVERS (=y) && 0

    Best regards,

    Lars

  • Hi Lars,

    colar said:
    Where is the difference and why would I choose this API?

    What you were using is Zephyr's implementation and networking API. The nRF 802.15.4 radio driver is made by us, and made specifically for nRF52 and nRF53, so it is better suited for working with our SoCs. It also implements features that are not in the Zephyr implementation, such as serialization for the nRF5340 and the nRF 802.15.4 service layer. You can see a full list of functionalities here in nRF 802.15.4 Radio Driver, and more information about the different features in nRF 802.15.4 Radio Driver - Driver features.

    colar said:
    Furthermore, VSCode tells me the option CONFIG_NRF_802154_SER_HOST stays n in the build, if i leave it out it still builds and the resulting image seems to be the same. Do I really need that option in the application core? Here are the dependencies from the Kconig menu:

    Yes, you need CONFIG_NRF_802154_SER_HOST on the application core if you want to use the nRF 802.15.4 driver. The option is set to n due to missing dependencies. You also need to enable the following:

    CONFIG_IEEE802154_NRF5=y
    CONFIG_NET_L2_IEEE802154=y

    This is needed for the 802154_rpmsg child image:

    CONFIG_PARTITION_MANAGER_ENABLED=y

    Best regards,
    Marte

Reply
  • Hi Lars,

    colar said:
    Where is the difference and why would I choose this API?

    What you were using is Zephyr's implementation and networking API. The nRF 802.15.4 radio driver is made by us, and made specifically for nRF52 and nRF53, so it is better suited for working with our SoCs. It also implements features that are not in the Zephyr implementation, such as serialization for the nRF5340 and the nRF 802.15.4 service layer. You can see a full list of functionalities here in nRF 802.15.4 Radio Driver, and more information about the different features in nRF 802.15.4 Radio Driver - Driver features.

    colar said:
    Furthermore, VSCode tells me the option CONFIG_NRF_802154_SER_HOST stays n in the build, if i leave it out it still builds and the resulting image seems to be the same. Do I really need that option in the application core? Here are the dependencies from the Kconig menu:

    Yes, you need CONFIG_NRF_802154_SER_HOST on the application core if you want to use the nRF 802.15.4 driver. The option is set to n due to missing dependencies. You also need to enable the following:

    CONFIG_IEEE802154_NRF5=y
    CONFIG_NET_L2_IEEE802154=y

    This is needed for the 802154_rpmsg child image:

    CONFIG_PARTITION_MANAGER_ENABLED=y

    Best regards,
    Marte

Children
  • Hi Marte,

    after restarting VS Code and doing a prisitne build it did not say anymore CONFIG_NRF_802154_SER_HOST would have missing dependencies. I had the other options set as you suggested and haven't changed anything. So it kinda fixed itself.

    As I can see, constructing the MAC Header (destination address, frame control field etc.) is not part of the driver while there seems to be a support for frame security and filtering (which should depend on the MAC Header). What is the recommended way to construct the MAC Header, are there some structs/functions to support me?

    Furthermore, I cannot override weak functions like nrf_802154_transmit_failed(). Looking at the objdump from build/zephyr/drivers/ieee802154/libdrivers__ieee802154.a, it seems that the function does not have the weak symbol. Are there compiler options I should check? I followed the getting stated guide for setting up the toolchain and IDE.

    Best regards,
    Lars

    Edit: The multiple definition came from ieee802154_nrf5.c and not nrf_802154.c where I initially saw the weak symbol. This is why there are multiple definitions since both don't have a weak symbol - but isn't this file from the Zephyr implementation and shouldn't the Zephyr implementation be excluded from the build? E.g. like this in prj.conf:

    CONFIG_NRF_802154_SER_HOST=y
    CONFIG_IEEE802154_NRF5=y
    # CONFIG_NETWORKING=y
    # CONFIG_IEEE802154=y
    # CONFIG_NET_L2_IEEE802154=y
    
    CONFIG_PARTITION_MANAGER_ENABLED=y

Related