The Device Control Library handles the routing of control messages between a host and one or many controllable resources within the controlled device.
Logical view of lib_device_control
All communications are fully acknowledged and so the host will be informed whether or not the device has correctly received or provided the required control information.
The Host controls resources on an XCORE device by sending commands to it over a transport protocol. Resources are identified by an 8-bit identifier and exist in tasks that run on logical cores of the device. There can be multiple resources in a task.
Send command c to resource r
The command code is 8 bits and is a write command when bit 7 is not set or a read command when bit 7 is set.
Packet for control communications
Read and write Commands include data bytes that are optional (can have a data length of zero).
Send write command c to resource ``r`` with ``n`` bytes of data ``d``
Send read command c to resource ``r`` and get ``n`` bytes of data ``d`` back
There is a transport task in the device (e.g. I2C slave or USB endpoint 0) that dispatches all commands. All other tasks that have resources connect to this transport task over xC interfaces.
Tasks register their resources and these get bound to the tasks’ xC interface. When commands are received by the transport task they forwarded over the matching xC interface.
Mapping between resource IDs and xC interfaces
This means multiple tasks residing in different cores or even tiles on the device can be easily controlled using a single instance of the Device Control library and a single control interface to the host.
Commands have a result code to indicate success or failure. The result is propagated to host so host can indicate error to the user.
The control library supports USB (device is USB device), I2C (device is I2C slave) and xSCOPE (device is target connected via xTAG debug adapter) as physical protocols. The maximum data packet size for each of the transport types is as follows:
Transport |
Data length |
Limitation |
|---|---|---|
I2C |
253 Bytes |
Arbitrary |
USB |
64 Bytes |
USB control transfer specification |
xSCOPE |
256 Bytes |
Arbitrary |
It would be straightforward to add support for additional physical protocols such as UART, SPI or TCP/UDP over Ethernet or add additional control hosts where the hardware and operating system supports it.
lib_device_control is intended to be used with the
XCommon CMake,
the XMOS application build and dependency management system.
To use this library in an application include lib_device_control in the application’s APP_DEPENDENT_MODULES list in
CMakeLists.txt, for example:
set(APP_DEPENDENT_MODULES "lib_device_control")
Note
Dependent modules should be pinned to release versions where possible, otherwise the latest commit on the develop branch will be used. For further details on managing modules, pinning to a release version and other options, please see the page xcommon-cmake Dependency Management.
All lib_device_control functions can be accessed via the device_control.h header file, for example:
#include "device_control.h"
The transport task receives its natural unit of data, such as I2C transaction, or USB request, and calls a processing function on it from the library. At the same time it passes in the whole array of xC interfaces which connect to all of the controlled tasks.
The library’s logic happens inside the function that is called and once a command is complete, an xC interface call is made to pass the command over to the controlled resource.
The receiving task then receives a write or read command over the xC interface.
Over I2C slave, the command is split into multiple I2C transactions:
process_i2c_write_transaction(reg, val)
process_i2c_write_transaction(reg, val)
process_i2c_write_transaction(reg, val)
process_i2c_write_transaction(reg, val) ==> case i.write_command(r, c, n, d[])
Over USB requests, the command is sent over a single USB request:
process_usb_set_request(header, data, len) ==> case i.write_command(r, c, n, d[])
It is the same for xSCOPE, the XMOS debug protocol:
process_xscope_upload(data, len) ==> case i.write_command(r, c, n, d[])
When the system starts, the transport task does an init() call, which asks all other tasks to register
their resources:
init() ==> i.register_resources(r[])
To ensure compatibility, a special command is provided to query the version of control xC interface. This allows the host to query the device and check that it is running the same version, which will ensure command compatibility.
Please see the Device side and Host side sections for further details.
Resource count limits. Sets the size of the arrays used for storing the mappings
This interface is used to communicate with the control library from the application
Functions
Request from host to register controllable resources with the control library. This is called once at startup and is necessary before control can take place.
resources – Array of resource IDs of size MAX_RESOURCES_PER_INTERFACE
num_resources – Number of resources populated within the resources[] table
Request from host to write to controllable resource in the device. The command consists of a resource ID, command and a byte payload of length payload_len.
resid – Resource ID. Indicates which resource the command is intended for
cmd – Command code. Note that this will be in the range 0x80 to 0xFF because bit 7 set indicates a write command
payload – Array of bytes which constitutes the data payload
payload_len – Size of the payload in bytes
Whether the handling of the write data by the device was successful or not
Request from host to read a controllable resource in the device. The command consists of a resource ID, command and a byte payload of length payload_len.
resid – Resource ID. Indicates which resource the command is intended for
cmd – Command code. Note that this will be in the range 0x00 to 0x7F because bit 7 cleared indicates a read command
payload – Array of bytes which constitutes the data payload
payload_len – Size of the payload in bytes
Whether the handling of the read data by the device was successful or not
Initialize the control library. Clears resource table to ensure nothing is registered.
Whether the initialization was successful or not
Sends a request to the application to register controllable resources.
i – Array of interfaces used to communicate with controllable entities
n – The number of interfaces used
Whether the registration was successful or not
Inform the control library that an I2C slave write has started. Called from I2C callback API.
i – Array of interfaces used to communicate with controllable entities
Whether the write start was successful or not
Inform the control library that an I2C slave read has started. Called from I2C callback API.
i – Array of interfaces used to communicate with controllable entities
Whether the read start was successful or not
Inform the control library that an I2C slave write has occurred. Called from I2C callback API.
data – Array of byte data to be passed to the device
i – Array of interfaces used to communicate with controllable entities
Whether the write was successful or not
Inform the control library that an I2C slave read has occurred. Called from I2C callback API.
data – Reference to array of byte data to be passed back from the device
i – Array of interfaces used to communicate with controllable entities
Whether the read was successful or not
Inform the control library that an I2C transaction has stopped. Called from I2C callback API.
i – Array of interfaces used to communicate with controllable entities
Whether the stop was successful or not
Inform the control library that a USB set (write) has occurred. Called from USB EP0 handler.
windex – wIndex field from the USB Setup packet
wvalue – wValue field from the USB Setup packet
wlength – wLength field from the USB Setup packet
request_data – Array of byte data to be written to the device
i – Array of interfaces used to communicate with controllable entities
Whether the write was successful or not
Inform the control library that a USB get (read) has occurred. Called from USB EP0 handler.
windex – wIndex field from the USB Setup packet
wvalue – wValue field from the USB Setup packet
wlength – wLength field from the USB Setup packet
request_data – Reference to array of byte data to be passed back from the device
i – Array of interfaces used to communicate with controllable entities
Whether the read was successful or not
Inform the control library that an xscope transfer has occurred. Called from xscope handler. This function both reads and writes data in a single call. The data return is device (control library) initiated. Note: Data requires word alignment so we can cast to struct.
buf – Array of bytes for read and write data.
buf_size – Array size in bytes
length_in – Number of bytes to be written to device
length_out – Number of bytes returned from device to be read by host
i – Array of interfaces used to communicate with controllable entities
Whether the transfer was successful or not
Initialize the xscope host interface
host_str – String containing the name of the xscope host. Eg. “localhost”
port_str – String containing the port number of the xscope host
Whether the initialization was successful or not
Shutdown the xscope host interface
Whether the shutdown was successful or not
Initialize the I2C host (master) interface
i2c_slave_address – I2C address of the slave (controlled device)
Whether the initialization was successful or not
Shutdown the I2C host (master) interface connection
Whether the shutdown was successful or not
Initialize the USB host interface
vendor_id – Vendor ID of controlled USB device
product_id – Product ID of controlled USB device
interface_num – Deprecated parameter, no longer used
Whether the initialization was successful or not
Checks to see that the version of control library in the device is the same as the host
version – Reference to control version variable that is set on this call
Whether the checking of control library version was successful or not
Request to write to controllable resource inside the device. The command consists of a resource ID, command and a byte payload of length payload_len.
resid – Resource ID. Indicates which resource the command is intended for
cmd – Command code. Note that this will be in the range 0x80 to 0xFF because bit 7 set indicates a write command
payload – Array of bytes which constitutes the data payload
payload_len – Size of the payload in bytes
Whether the write to the device was successful or not
Request to read from controllable resource inside the device. The command consists of a resource ID, command and a byte payload of length payload_len.
resid – Resource ID. Indicates which resource the command is intended for
cmd – Command code. Note that this will be in the range 0x80 to 0xFF because bit 7 set indicates a write command
payload – Array of bytes which constitutes the data payload
payload_len – Size of the payload in bytes
Whether the read from the device was successful or not