Hide navigation sidebar
Hide table of contents sidebar
Skip to content
Back to top
Toggle table of contents sidebar

# Advanced usage

Advanced usage is termed to mean the implementation of multiple endpoints in a single task as well as the addition of real-time processing to an endpoint task.

The functions documented in Basic usage such as `XUD_SetBuffer()` and `XUD_GetBuffer()` are synchronous in nature - they block until data has either been successfully sent or received to or from the host. For this reason it is not generally possible to handle multiple endpoints in a single thread efficiently (or at all, depending on the protocols involved).

To solve this `lib_xud` provides an API that is asynchronous in nature with functions that allow the separation of requesting to send/receive a packet and the notification of a successful transfer. This API utilises xcore events by using the XC `select` statement language feature.

General operation is as follows:

> - A `XUD_SetReady_` function is called to mark an endpoint as ready to send or receive data

> - A``select`` statement is used, along with a `select handler` to wait for, and capture, send/receive notifications from the `XUD_Main` task

## Function details

The available `XUD_SetReady_` functions for the asynchronous API are listed below.

### `XUD_SetReady_Out()`

int XUD_SetReady_Out(XUD_ep ep, unsigned char buffer[])

  Marks an OUT endpoint as ready to receive data.

  Parameters:

    - ep – The OUT endpoint identifier (created by `XUD_InitEp`).

    - buffer – The buffer in which to store data received from the host. The buffer is assumed to be word aligned.

  Returns:

    XUD_RES_OKAY on success, for errors see `Status Reporting`.

### `XUD_SetReady_In()`

XUD_Result_t XUD_SetReady_In(XUD_ep ep, unsigned char buffer[], int len)

  Marks an IN endpoint as ready to transmit data.

  Parameters:

    - ep – The IN endpoint identifier (created by `XUD_InitEp`).

    - buffer – The buffer to transmit to the host. The buffer is assumed be word aligned.

    - len – The length of the data to transmit.

  Returns:

    XUD_RES_OKAY on success, for errors see `Status Reporting`.

The following functions are also provided to ease integration with more complex buffering schemes than a single packet buffer. A example might be a circular-buffer for an audio stream.

### `XUD_SetReady_OutPtr()`

XUD_Result_t XUD_SetReady_OutPtr(XUD_ep ep, unsigned addr)

  Marks an OUT endpoint as ready to receive data.

  Parameters:

    - ep – The OUT endpoint identifier (created by `XUD_InitEp`).

    - addr – The address of the buffer in which to store data received from the host. The buffer is assumed to be word aligned.

  Returns:

    XUD_RES_OKAY on success, for errors see `Status Reporting`.

### `XUD_SetReady_InPtr()`

XUD_Result_t XUD_SetReady_InPtr(XUD_ep ep, unsigned addr, int len)

  Marks an IN endpoint as ready to transmit data.

  Parameters:

    - ep – The IN endpoint identifier (created by `XUD_InitEp`).

    - addr – The address of the buffer to transmit to the host. The buffer is assumed be word aligned.

    - len – The length of the data to transmit.

  Returns:

    XUD_RES_OKAY on success, for errors see `Status Reporting`.

Once an endpoint has been marked ready to send/receive by calling one of the above `XUD_SetReady_` functions, an XC `select` statement can be used to handle notifications of a packet being sent/received from `XUD_Main()`. These notifications are communicated via channels.

For convenience, `select handler` functions are provided to handle events in the `select` statement. These are documented below.

### `XUD_GetData_Select()`

void XUD_GetData_Select(

  chanend c,
  XUD_ep ep,
  REFERENCE_PARAM(unsigned, length),
  REFERENCE_PARAM(XUD_Result_t, result),

)

  Select handler function for receiving OUT endpoint data in a select.

  Parameters:

    - c – The chanend related to the endpoint

    - ep – The OUT endpoint identifier (created by `XUD_InitEp`).

    - length – Passed by reference. The number of bytes written to the buffer (that was passed into XUD_SetReady_Out())

    - result – XUD_Result_t passed by reference. XUD_RES_OKAY on success, for errors see `Status Reporting`.

### `XUD_SetData_Select()`

void XUD_SetData_Select(

  chanend c,
  XUD_ep ep,
  REFERENCE_PARAM(XUD_Result_t, result),

)

  Select handler function for transmitting IN endpoint data in a select.

  Parameters:

    - c – The chanend related to the endpoint

    - ep – The IN endpoint identifier (created by `XUD_InitEp`).

    - result – Passed by reference. XUD_RES_OKAY on success, for errors see `Status Reporting`.

Warning

It is currently not possible to share control endpoint (i.e. endpoint 0) functionalty with other endpoints/tasks. This is because a control endpoint must remain responsive to the host.

## Example

A simple example of the functionality described in this section is shown below:

    void ExampleEndpoint(chanend c_ep_out, chanend c_ep_in)
    {
        unsigned char rxBuffer[1024];
        unsigned char txBuffer[] = {0, 1, 2, 3, 4};
        int length, returnVal;

        XUD_ep ep_out = XUD_InitEp(c_ep_out);
        XUD_ep ep_in = XUD_InitEp(c_ep_in);

        /* Mark OUT endpoint as ready to receive */
        XUD_SetReady_Out(ep_out, rxBuffer);
        XUD_SetReady_In(ep_in, txBuffer, 5);

        while(1)
        {
            select
            {
                case XUD_GetData_Select(c_ep_out, ep_out, length):

                    /* Packet from host received */

                    for(int i = 0; i< length; i++)
                    {
                        /* Process packet... */
                    }

                    /* Mark EP as ready again */
                    XUD_SetReady_Out(ep_out, rxBuffer);
                    break;

                case XUD_SetData_Select(c_ep_in, ep_in, returnVal):

                    /* Packet successfully sent to host */

                    /* Create new buffer */
                    for(int i = 0; i < 5; i++)
                    {
                        txBuffer[i]++;
                    }

                    /* Mark EP as ready again */
                    XUD_SetReady_In(ep_in, txBuffer, 5);
                    break;

            }
        }
    }