
###########################################################
an02044: Using XMOS TCP/IP Library for UDP-based Networking
###########################################################

|newpage|

************
Introduction
************

*Transmission Control Protocol/Internet Protocol* (TCP/IP) is an
internetworking protocol that allows cross-platform or heterogeneous
networking. It manages the flow of data in packets with headers giving
the source and destination information. It provides a reliable stream
delivery using sequenced acknowledgment and error detection
technique. TCP/IP offers the *User Datagram Protocol* (UDP), a minimal
transport protocol, wherein the packet headers contain just enough
information to forward the datagrams and their error checking. UDP
does not support flow control and acknowledgment.


XMOS TCP/IP
===========

The XMOS TCP/IP component ``lib_xtcp`` provides a IP/UDP/TCP stack that connects to
the XMOS ethernet component ``lib_ethernet``. It enables several clients to connect to
it and send and receive on multiple TCP or UDP connections. The stack
has been designed for a low memory embedded programming environment
and despite its low memory footprint provides a complete stack
including ARP, IPv4, UDP, TCP, DHCP, ICMP and IGMP
protocols. The library provides a TCP/IP stack (LwIP) with modifications
to compile for the XCORE architecture and communicate between tasks using interfaces.

Block diagram
=============

The application firmware organization is shown in :numref:`networking_xmos_section`.

.. figure:: images/lib_xtcp_ethernet_device.png
   :alt: Networking with an XMOS device
   :scale: 75%
   :align: center
   :name: networking_xmos_section
   
   Networking with an XMOS device

|newpage|

********************************
TCP/IP Application Configuration
********************************

This section describes the configuration of the application
and the TCP/IP stack used in this example.

Project Configuration
=====================

The example uses the TCP/IP implementation in the ``lib_xtcp`` library.
It depends on ``lib_board_support`` for the PHY configuration on the
`XK-ETH-316-DUAL` board. It depends on ``lib_logging`` for
lightweight debugging using `debug_printf()`.

These dependencies are specified in ``APP_DEPENDENT_MODULES`` in the application's `CMakeLists.txt`:

.. literalinclude:: ../../app_an02044/CMakeLists.txt
  :language: cmake
  :start-at: set(APP_DEPENDENT_MODULES
  :end-at: ")

All functions and types can be found in the ``xtcp.h`` header file:

.. code-block:: C

  #include <xtcp.h>

Allocating hardware resources
=============================

The TCP/IP stack connects to the RMII task from the Ethernet library
which requires several ports to communicate with the
Ethernet PHY. These ports are declared in the main program file
(``main.xc``). In this demo the ports are set up for the Ethernet
PHY connected to the `XK-ETH-316-DUAL` which uses a collection of ports to
connect to the PHY defined in `xk-eth-xu316-dual.xn`:

.. literalinclude:: ../../app_an02044/src/main.xc
  :language: C
  :start-at: port p_phy_rxd
  :end-at: port p_phy_clk

The MDIO Serial Management Interface (SMI) is used to transfer
management information between MAC and PHY. This interface consists of
two signals which are connected to two ports:

.. literalinclude:: ../../app_an02044/src/main.xc
  :language: C
  :start-at: port p_smi_mdio
  :end-at: port p_smi_mdc

.. _ip_configuration_section:

IP configuration
================

The IP is configured via a structure passed to the ``xtcp`` task
to suit the network where the XMOS device is used.

To assign a static IP address initialize with an address valid for the network
the device will be connected to:

.. literalinclude:: ../../app_an02044/src/main.xc
  :language: C
  :start-at: static xtcp_ipconfig_t
  :end-at: };

Alternatively it can be initialized to all zeros to enable DHCP, this
will attempt to dynamically assign an IP address:

.. code-block:: C

  xtcp_ipconfig_t ipconfig = {
      { 0, 0, 0, 0 }, /* ip address */
      { 0, 0, 0, 0 }, /* netmask */
      { 0, 0, 0, 0 }  /* gateway */
  };

UDP reflector
=============

The final part of the application is setup in ``udp_reflect.xc`` is a set of 
defines that assigns the port number for the incoming port. The size of data buffer is also set. These 
defines are used by the application.

.. literalinclude:: ../../app_an02044/src/udp_reflect.xc
  :language: C
  :start-at: // Defines
  :end-at: #define INIT_VAL

|newpage|

********************************
Application Detailed Description
********************************

The application main() function
===============================

For the UDP-based application example, the system comprises four tasks running
on the multicore microcontroller.

The tasks perform the following operations.

- The RMII task ``rmii_ethernet_rt_mac()`` which handles RMII/Ethernet traffic. 
- The SMI task ``smi()`` which handles the Serial Management Interface (SMI) for
  the Ethernet PHY. This is used to configure the Ethernet PHY via the 
  ``dual_ethernet_phy_driver()`` task which manages the configuration of the PHY and
  communicates with the ``lib_xtcp`` stack.
- The XTCP server which handles the TCP/IP stack and provides the
  interface to the application protocol ``xtcp_lwip``.
- The UDP reflector application ``udp_reflect()`` running in a single thread.

These tasks communicate via the use of xC channels and interface
connections which allow data to be passed between
application code running on separate logical threads.

Below is the source code for the main function of this application,
which is taken from the source file ``main.xc``

.. literalinclude:: ../../app_an02044/src/main.xc
  :language: C
  :start-at: int main

The reflector function
======================

The application code for receiving UDP packets of data from a network machine 
and reflecting it back to the same machine is implemented in the file 
``udp_reflect.xc``. The code performing these tasks is contained within the function 
``udp_reflect()`` which is shown in the following code segments:

.. literalinclude:: ../../app_an02044/src/udp_reflect.xc
  :language: C
  :start-at: void udp_reflect
  :end-before: while (1)

In this segment of the code you can see the following.

- The buffers for holding the transmitted and received data are declared.

- The DNS server address and hostname to lookup are defined. The DNS lookup
  is optional and can be disabled if not required, by making ``dns_lookup`` non-zero.

This is followed by the client application event handling.
  
.. literalinclude:: ../../app_an02044/src/udp_reflect.xc
  :language: C
  :start-at: while (1)
  :end-at: case XTCP_IFDOWN:
  
Other event handling follows the above code. You can see the following in the code shown above.

- The ``while`` loop waits for an XTCP event and performs the appropriate function.

- When the link goes "up", the XTCP server is instructed to listen for data on the incoming port.

|newpage|

.. _udp_example_section:

***************
The UDP example
***************

Building the Application
========================

This section assumes you have downloaded and installed the `XMOS XTC tools <https://www.xmos.com/software-tools/>`_
(see `README` for required version). Installation instructions can be found `here <https://www.xmos.com/xtc-install-guide>`_.
Be sure to pay attention to the section `Installation of required third-party tools
<https://www.xmos.com/documentation/XM-014363-PC/html/installation/install-configure/install-tools/install_prerequisites.html>`_.

The application uses the `xcommon-cmake <https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest>`_
build system as bundled with the XTC tools.

The file `CMakeLists.txt` in the `app_an02044` directory contains the application build configuration.

The ``an02044`` software ZIP package should be downloaded and extracted to a chosen working directory.

To configure the build run the following from an XTC command prompt, this should
only need to be run once:

.. code-block:: shell

  cd an02044
  cd app_an02044
  cmake -G "Unix Makefiles" -B build

All required dependencies are included in the software package. If any dependencies are missing, they will be retrieved automatically during this step.

Finally, the application binaries can be built using ``xmake``:

.. code-block:: shell

  xmake -C build

Binary artifacts (.xe files) will be generated under the appropriate subdirectories of the ``app_an02044/bin`` directory — one for each supported build configuration.

For subsequent builds, the ``cmake`` step may be omitted. If ``CMakeLists.txt`` or other build files are modified, ``cmake`` will be re-run automatically by ``xmake`` as needed.

Demo Hardware Setup
===================

#. Connect an XTAG-4 to the `XK-ETH-316-DUAL` with a ribbon cable.
#. Connect the `XK-ETH-316-DUAL` to the PC or to a network switch using an ethernet cable.
#. Connect the XTAG to the host PC using a USB cable. This allows programming of the application.
#. Connect the `XK-ETH-316-DUAL` to the host PC using a USB-C cable. This supplies power to the board.

Running the example
===================

Once the application has been built you need to download the application binary
code onto the `xcore` development kit. Here you use the tools to load the application
over JTAG onto the `xcore` multicore microcontroller.

From a XTC command prompt run the following command from the `app_an02044` directory::

  xrun --xscope ./bin/app_an02044.xe

Alternatively the binary can be programmed into the non-volatile flash memory with the command::

  xflash ./bin/app_an02044.xe

When running the program with `xrun` you will see the output shown below:

.. code-block:: console

  Starting UDP reflect client: port 15533
  Waiting for link up...
  Link up event
  IP: 192.168.200.178
  Listening on port 15533, 0

Testing data transfer
=====================

The UDP example can be tested by running the python script ``test_udp.py``.

.. code-block:: console

  python test_udp.py 192.168.200.178
  Connecting..
  Connected
  Sending message: hello, world
  Recv'd message: HELLO, WORLD
  Closed

This will connect to the XMOS device at the IP address specified and send a message to the UDP port 15533. 
The XMOS device will respond with the same message, with the characters translated to upper case.
The `xrun` console will display output similar to that shown below:

.. code-block:: console

  Got data: 13 bytes, from 192.168.200.99:52703
  Sent response: 13 bytes

test_udp.py test script
-----------------------

.. literalinclude:: ../../app_an02044/src/test_udp.py
   :language: python
   :linenos:

|newpage|

***************
Further reading
***************

* XMOS XTC Tools Installation Guide

  https://www.xmos.com/xtc-install-guide

* XMOS XTC Tools User Guide

  https://www.xmos.com/view/Tools-15-Documentation

* XMOS application build and dependency management system; xcommon-cmake

  https://www.xmos.com/file/xcommon-cmake-documentation/?version=latest


* XMOS TCP/IP Component

  https://www.xmos.com/libraries/lib_xtcp

* XMOS Layer 2 Ethernet MAC Component

  https://www.xmos.com/libraries/lib_ethernet

* XMOS logging Component

  https://www.xmos.com/libraries/lib_logging

* TCP/IP - Internet protocol suite

  https://en.wikipedia.org/wiki/Internet_protocol_suite

* IP addressing

  https://en.wikipedia.org/wiki/Internet_Protocol

* Ethernet Type

  https://en.wikipedia.org/wiki/EtherType

* UDP - User Datagram Protocol

  https://en.wikipedia.org/wiki/User_Datagram_Protocol
