USB RTOS Driver

This driver can be used to instantiate and control a USB device interface on xcore in an RTOS application.

Unlike most other xcore I/O interface RTOS drivers, only a single USB driver instance may be started. It also does not require an initialization step prior to starting the driver. This is due to an implementation detail in lib_xud, which is what the RTOS USB driver uses at its core.

Driver API

The following structures and functions are used to start and use a USB driver instance.

RTOS_USB_OUT_EP

This is used to index into the second dimension of many of the RTOS USB driver’s endpoint arrays.

RTOS_USB_IN_EP
enum rtos_usb_packet_type_t

Values:

enumerator rtos_usb_data_packet
enumerator rtos_usb_setup_packet
enumerator rtos_usb_sof_packet
typedef struct rtos_usb_struct rtos_usb_t

Typedef to the RTOS USB driver instance struct.

typedef void (*rtos_usb_isr_cb_t)(rtos_usb_t *ctx, void *app_data, uint32_t ep_address, size_t xfer_len, rtos_usb_packet_type_t packet_type, XUD_Result_t res)

Function pointer type for application provided RTOS USB interrupt callback function.

This callback function is called when there is a USB transfer interrupt.

Parameters
  • ctx – A pointer to the associated USB driver instance.

  • app_data – A pointer to application specific data provided by the application. Used to share data between this callback function and the application.

  • ep_address – The address of the USB endpoint that the transfer has completed on.

  • xfer_len – The length of the data transferred.

  • packet_type – The type of packet transferred. See rtos_usb_packet_type_t.

  • res – The result of the transfer. See XUD_Result_t.

int rtos_usb_endpoint_ready(rtos_usb_t *ctx, uint32_t endpoint_addr, unsigned timeout)

Checks to see if a particular endpoint is ready to use.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to check.

  • timeout – The maximum amount of time to wait for the endpoint to become ready before returning.

Returns

  • XUD_RES_OKAY – if the endpoint is ready to use.

  • XUD_RES_ERR – if the endpoint is not ready to use.

XUD_Result_t rtos_usb_all_endpoints_ready(rtos_usb_t *ctx, unsigned timeout)

Checks to see if all endpoints are ready to use.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • timeout – The maximum amount of time to wait for all endpoints to become ready before returning.

Returns

  • XUD_RES_OKAY – if all the endpoints are ready to use.

  • XUD_RES_ERR – if not all the endpoints are ready to use.

XUD_Result_t rtos_usb_endpoint_transfer_start(rtos_usb_t *ctx, uint32_t endpoint_addr, uint8_t *buffer, size_t len)

Requests a transfer on a USB endpoint. This function returns immediately. When the transfer is complete, the application’s ISR callback provided to rtos_usb_start() will be called.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to perform the transfer on.

  • buffer – A pointer to the buffer to transfer data into for OUT endpoints, or from for IN endpoints.

  • len – The maximum number of bytes to receive for OUT endpoints, or the actual number of bytes to send for IN endpoints.

Returns

  • XUD_RES_OKAY – if the transfer was requested successfully.

  • XUD_RES_RST – if the transfer was not requested and the USB bus needs to be reset. In this case, the application should reset the USB bus.

XUD_BusSpeed_t rtos_usb_endpoint_reset(rtos_usb_t *ctx, uint32_t endpoint_addr)

This function will complete a reset on an endpoint. The address of the endpoint to reset must be provided, and may be either direction (IN or OUT) endpoint. If there is an associated endpoint of the opposite direction, however, it will also be reset.

The return value should be inspected to find the new bus-speed.

Parameters

endpoint_addr – IN or OUT endpoint address to reset.

Returns

  • XUD_SPEED_HS – the host has accepted that this device can execute at high speed.

  • XUD_SPEED_FS – the device is running at full speed.

static inline XUD_Result_t rtos_usb_device_address_set(rtos_usb_t *ctx, uint32_t addr)

Sets the USB device’s bus address. This function must be called after a setDeviceAddress request is made by the host, and after the ZLP status is sent.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • addr – The device address requested by the host.

static inline void rtos_usb_endpoint_state_reset(rtos_usb_t *ctx, uint32_t endpoint_addr)

Reset a USB endpoint’s state including data PID toggle.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to reset.

static inline void rtos_usb_endpoint_stall_set(rtos_usb_t *ctx, uint32_t endpoint_addr)

Stalls a USB endpoint. The stall is cleared automatically when a setup packet is received on the endpoint. Otherwise it can be cleared manually with rtos_usb_endpoint_stall_clear().

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to stall.

static inline void rtos_usb_endpoint_stall_clear(rtos_usb_t *ctx, uint32_t endpoint_addr)

Clears the stall condition on USB endpoint.

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to clear the stall on.

void rtos_usb_start(rtos_usb_t *ctx, size_t endpoint_count, XUD_EpType endpoint_out_type[], XUD_EpType endpoint_in_type[], XUD_BusSpeed_t speed, XUD_PwrConfig power_source, unsigned interrupt_core_id, int sof_interrupt_core_id)

Starts the USB driver instance’s low level USB I/O thread and enables its interrupts on the requested core. This must only be called by the tile that owns the driver instance. It must be called after starting the RTOS from an RTOS thread.

rtos_usb_init() must be called on this USB driver instance prior to calling this.

Parameters
  • ctx – A pointer to the USB driver instance to start.

  • endpoint_count

    The number of endpoints that will be used by the application. A single endpoint here includes both its IN and OUT endpoints. For example, if the application uses EP0_IN, EP0_OUT, EP1_IN, EP2_IN, EP2_OUT, EP3_OUT, then the endpoint count specified here should be 4 (endpoint 0 through endpoint 3) regardless of the lack of EP1_OUT and EP3_IN. If these two endpoints were used, the count would still be 4.

    If for whatever reason, the application needs to use a particular endpoint number, say only EP6 in addition to EP0, then the count here needs to be 7, even though endpoints 1 through 5 are unused. All unused endpoints must be marked as disabled in the two endpoint type lists

    endpoint_out_type and endpoint_in_type.

  • endpoint_out_type – A list of the endpoint types for each output endpoint. Index 0 represents the type for EP0_OUT, and so on. See XUD_EpType in lib_xud. If the endpoint is unused, it must be set to XUD_EPTYPE_DIS.

  • endpoint_in_type – A list of the endpoint types for each input endpoint. Index 0 represents the type for EP0_IN, and so on. See XUD_EpType in lib_xud. If the endpoint is unused, it must be set to XUD_EPTYPE_DIS.

  • speed – The speed at which the bus should operate. Either XUD_SPEED_FS or XUD_SPEED_HS. See XUD_BusSpeed_t in lib_xud.

  • power_source – The source of the device’s power. Either bus powered (XUD_PWR_BUS) or self powered (XUD_PWR_SELF). See XUD_PwrConfig in lib_xud.

  • interrupt_core_id – The ID of the core on which to enable the USB interrupts.

  • sof_interrupt_core_id – The ID of the core on which to enable the SOF interrupt. Set to < 0 to disable the SoF interrupt if it is not needed.

void rtos_usb_init(rtos_usb_t *ctx, uint32_t io_core_mask, rtos_usb_isr_cb_t isr_cb, void *isr_app_data)

Initializes an RTOS USB driver instance. This must only be called by the tile that owns the driver instance. It should be called prior to starting the RTOS, and must be called before any of the core USB driver functions are called with this instance.

This will create an RTOS thread that runs lib_xud’s main loop. This thread is created with the highest priority and with preemption disabled.

Note

Due to implementation details of lib_xud, it is only possible to have one USB instance per application. Functionally this is not an issue, as no xcore chips have more than one USB interface.

Note

If using the Tiny USB stack, then this function should not be called directly by the application. The xcore device port for Tiny USB takes care of calling this, as well as all other USB driver functions.

Parameters
  • ctx – A pointer to the USB driver instance to start.

  • io_core_mask – A bitmask representing the cores on which the low level USB I/O thread created by the driver is allowed to run. Bit 0 is core 0, bit 1 is core 1, etc.

  • isr_cb – The callback function for the driver to call when transfers are completed.

  • isr_app_data – A pointer to application specific data to pass to the application’s ISR callback function isr_cb.

XUD_Result_t rtos_usb_simple_transfer_complete(rtos_usb_t *ctx, uint32_t endpoint_addr, size_t *len, unsigned timeout)

This function may be called to wait for a transfer on a particular endpoint to complete. This requires that the USB instance was initialized with rtos_usb_simple_init().

Parameters
  • ctx – A pointer to the USB driver instance to use.

  • endpoint_addr – The address of the endpoint to wait for.

  • len – The actual number of bytes transferred. For IN endpoints, this will be the same as the length requested by rtos_usb_endpoint_transfer_start(). For OUT endpoints, it may be less.

  • timeout – The maximum amount of time to wait for the transfer to complete before returning.

Returns

  • XUD_RES_OKAY – if the transfer was completed successfully.

  • XUD_RES_RST – if the transfer was not able to complete and the USB bus needs to be reset. In this case, the application should reset the USB bus.

  • XUD_RES_ERR – if there was an unexpected error transferring the data.

void rtos_usb_simple_init(rtos_usb_t *ctx, uint32_t io_core_mask)

Initializes an RTOS USB driver instance. This must only be called by the tile that owns the driver instance. It should be called prior to starting the RTOS, and must be called before any of the core USB driver functions are called with this instance.

This initialization function may be used instead of rtos_usb_init() if the application is not using a USB stack. This allows application threads to wait for transfers to complete with the rtos_usb_simple_transfer_complete() function. The application cannot provide its own ISR callback when initialized with this function. This provides a similar programming interface as a traditional bare metal xcore application using lib_xud.

This will create an RTOS thread that runs lib_xud’s main loop. This thread is created with the highest priority and with preemption disabled.

Note

Due to implementation details of lib_xud, it is only possible to have one USB instance per application. Functionally this is not an issue, as no xcore chips have more than one USB interface.

Parameters
  • ctx – A pointer to the USB driver instance to start.

  • io_core_mask – A bitmask representing the cores on which the low level USB I/O thread created by the driver is allowed to run. Bit 0 is core 0, bit 1 is core 1, etc.

RTOS_USB_ENDPOINT_COUNT_MAX

The maximum number of USB endpoint numbers supported by the RTOS USB driver.

RTOS_USB_ISR_CALLBACK_ATTR

This attribute must be specified on the RTOS USB interrupt callback function provided by the application.

struct rtos_usb_ep_xfer_info_t
#include <rtos_usb.h>

Struct to hold USB transfer state data per endpoint, used as the argument to the ISR.

The members in this struct should not be accessed directly.

struct rtos_usb_struct
#include <rtos_usb.h>

Struct representing an RTOS USB driver instance.

The members in this struct should not be accessed directly.