AN02039: Ports, Pins, and the XN file#
The XMOS XCORE processor can interface electrical signals on a package pin to logical signals in a program through a highly efficient low latency interface called a port.
In this document we describe the mechanism that links ports to pins in detail, and explain how to specify the desired pin-out of the device and how to select an appropriate device for your problem.
This document ties together the tools documentation (on the nature of XN files), the datasheets (that documents pins), and the port programming guides.
Introduction#
The two important terms to distinguish are:
- Pins
Pins are electrical connections on the XCORE package, Pins can typically be low (0V) or high (VDDIO)
- Ports
A port is a part of the XCORE that provides an abstraction of a pin. A port maps electrical signals to logical levels, and provides elements for, for example, serialising data. A 0 value in the port corresponds to a low signal on the pin.
These two terms are described in more detail below, followed by a description of the mechanism that links ports to pins, and then how to specify the desired pin-out of the device.
Pins#
Each tile on an XCORE device can support up to 64 I/O pins, so up to 128 I/O pins on a standard dual-tile device. The number of I/O pins available on a specific device depends on the package. For example, on xcore.ai devices the number of I/O pins is as follows
QF60 package - 34 I/O pins
TQ128 package - 78 I/O pins
FB265 package - 128 I/O pins
Depending on the package, these pins may have different VDDIO voltages when driven high.
The electrical characteristics of the pins are defined in the device’s datasheet, but in summary the main characteristics that can be changed under software control include:
Direction (input or output)
As Output - Drive strength (e.g. 2, 4, 8, 12 mA) - Slew rate control
As Input - Schmitt trigger enable - Pull-up enable - Pull-down enable
If a pin is not configured it operates as an input with a weak pull-down resistor enabled.
These modes are set by the software with the details described in the programming guides.
Pins are identified by a label of the form XnDmm
where n
is the tile number,
and mm
is the pin number.
For example, X0D12 is pin 12 on tile 0, and X1D24 is pin 24 on tile 1.
This numbering scheme is consistent across all devices in the product family. However, not all pins are available on all packages and the datasheet for the individual device provides a full list of the pins available along with the physical location of these pins on the package.
Ports#
A port is a logical abstraction of an I/O pin, or a group of I/O pins. Ports provide the interface between the XCORE processor logic and the outside world.
Basic operation#
At the basic level ports provide a mechanism to input or output logical values on the device pins, and they can be configured to represent a range of different types of signals.
XCORE ports can be configured to either 1, 4, 8, 16 or 32 bits wide, and can operate as inputs, outputs, or bidirectional signals.
Each port is identified by its width in bits and a letter, with the letter distinguishing between ports of the same width, as is shown in Table 1.
Port Size |
Label Example |
Description |
Available Ports |
---|---|---|---|
1-bit |
|
Single-bit digital I/O |
16 |
4-bit |
|
4-bit parallel I/O |
6 |
8-bit |
|
8-bit parallel I/O |
4 |
16-bit |
|
16-bit parallel I/O |
2 |
32-bit |
|
32-bit parallel I/O |
1 |
Within each port the individual bits are labelled from 0 to the width of the port. For example:
Port 4A has bits 0, 1, 2, 3 which are identified as 4A0, 4A1, 4A2, 4A3
Port 8B has bits 0, 1, …, 6, 7 which are identified as 8B0, 8B1, …, 8B6, 8B7
Architecturally, ports are typically referred to by a symbolic name and are labelled as XS1_PORT_xy
where xy
is the port identifier from the table above (e.g. XS1_PORT_8B for
the second 8-bit port). These names can be used anywhere in C programs and
Assembly programs provided you include xs1.h
.
Advanced Port Operations#
XCORE ports are, however, much more powerful than simple digital I/O pins. Each XCORE port can operate as a small state machine that provides deterministic, hardware timed, parallel processing of signals, ensuring that the signals are processed in real-time with low latency.
Ports can be configured to perform more complex operations such as:
Serialisation and deserialisation of data
Clocking data in and out
Reading and writing data in a single clock cycle
Strobing data
Buffering data
Triggering events when data is available
These advanced port operations can be used to implement a wide range of interface protocols, and they operate without the need for core processor resoureces.
These advanced port operations are described in more detail in the port application notes and the tools programming guide.
Linking Ports to Pins#
The reason to separate ports and pins is that multiple ports (and possibly
other signals) may map onto a single pin. For example, on
xcore.ai, pin X0D31
is connected to port 4F (bit 3), port 8C (bit 5), port 16B
(bit 5), and the LPPDR interface (DQ3). The 0
in X0D31
means that all
ports it is connected to are on Tile 0, the 31
is just a label that
makes each pin unique.
For each XMOS product family, the mapping between pins on the one hand and
ports and other functions on the other hand is the same for every member of
the family. That is, X0D31
will have the same mapping on all packages.
However, not all packages may make X0D31
available as a physically accessable pin.
The largest package brings out all pins, the smallest
package brings out only a small subset of pins.
Which Ports to Use#
We now look at how to select the appropriate port for a particular task. The design decisions of which port to use will depend on the both the nature of the signal and the application requirements.
The following guidelines can be used to help select the appropriate type of port.
Within a tile, all 1-bit ports are interchangeable, all 4-bit ports are interchangeable, all 8-bit ports are interchangeable, and both 16-bit ports are interchangeable. That means, if you need a 1-bit port you can pick any of them; there is no preference for a particular port. The choice whether to pick a 1-bit or 16-bit port depends on the signal that the port carries:
Clock Signals that you need to clock data in and out must be on a 1-bit port, and so must strobe (data-valid) signals.
Data signals of serial protocols are typically on 1-bit ports as that enables you to let the port logic to do the serialisation and deserialisation.
Data signals on an N-bit bus should be on an N-bit port, as that enables you to input and output data to the bus in one synchronised operation, and/or to serialise wider data onto a narrower bus.
Slow signals (LEDs, buttons, reset signals etc.) can be on any port. However, you need to make sure that all signals on a port are either all driven (outputs) or all sampled (inputs). Ports cannot do a bit of both.
Signal groups that belong to one interface should be using ports on the same tile.
For example, if an Ethernet MII Rx signal has a clock, 4-bit data, data-valid, and error signal then you would use one 4-bit port and three 1-bit ports; all on the same tile.
If you also need an MII Tx signal with a similar set-up, you need another 4-bit port and three more 1-bit ports all on one tile. There may be value to keep the Rx and Tx part on the same tile too - that is an application decision.
The port multiplexer#
From Table 1 we see that there are a total of 136 signals on one tile. That is too many signals since each tile has only 64 GPIO pins available. To resolve this, some of the ports are multiplexed (muxed) onto the same pin.
Each tile has its own multiplexer. For example, XnD18
is connected to bit 2 of port 4D, bit 4 of port 8B, and bit
12 of port 16A. These are visualised for the QF60A/B package in
Fig. 1 where we have drawn the multiplexers for X0D07
(tile 0) and X1D18
(tile 1).
Fig. 1 Visualisation of the multiplexer in a QF60A/B package#
The full structure of the multiplexed port signals on a single tile is shown in the table below:
Nr |
1-bit Port |
4-bit Port |
8-bit Port |
16-bit Port |
32-bit Port |
Pin Label |
---|---|---|---|---|---|---|
1 |
1A |
XnD00 |
||||
2 |
1B |
XnD01 |
||||
3 |
4A0 |
8A0 |
16A0 |
32A20 |
XnD02 |
|
4 |
4A1 |
8A1 |
16A1 |
32A21 |
XnD03 |
|
5 |
4B0 |
8A2 |
16A2 |
32A22 |
XnD04 |
|
6 |
4B1 |
8A3 |
16A3 |
32A23 |
XnD05 |
|
7 |
4B2 |
8A4 |
16A4 |
32A24 |
XnD06 |
|
8 |
4B3 |
8A5 |
16A5 |
32A25 |
XnD07 |
|
9 |
4A2 |
8A6 |
16A6 |
32A26 |
XnD08 |
|
10 |
4A3 |
8A7 |
16A7 |
32A27 |
XnD09 |
|
11 |
1C |
XnD10 |
||||
12 |
1D |
XnD11 |
||||
13 |
1E |
XnD12 |
||||
14 |
1F |
XnD13 |
||||
15 |
4C0 |
8B0 |
16A8 |
32A28 |
XnD14 |
|
16 |
4C1 |
8B1 |
16A9 |
32A29 |
XnD15 |
|
17 |
4D0 |
8B2 |
16A10 |
32A30 |
XnD16 |
|
18 |
4D1 |
8B3 |
16A11 |
32A31 |
XnD17 |
|
19 |
4D2 |
8B4 |
16A12 |
XnD18 |
||
20 |
4D3 |
8B5 |
16A13 |
XnD19 |
||
21 |
4C2 |
8B6 |
16A14 |
XnD20 |
||
22 |
4C3 |
8B7 |
16A15 |
XnD21 |
||
23 |
1G |
XnD22 |
||||
24 |
1H |
XnD23 |
||||
25 |
1I |
XnD24 |
||||
26 |
1J |
XnD25 |
||||
27 |
4E0 |
8C0 |
16B0 |
XnD26 |
||
28 |
4E1 |
8C1 |
16B1 |
XnD27 |
||
29 |
4F0 |
8C2 |
16B2 |
XnD28 |
||
30 |
4F1 |
8C3 |
16B3 |
XnD29 |
||
31 |
4F2 |
8C4 |
16B4 |
XnD30 |
||
32 |
4F3 |
8C5 |
16B5 |
XnD31 |
||
33 |
4E2 |
8C6 |
16B6 |
XnD32 |
||
34 |
4E3 |
8C7 |
16B7 |
XnD33 |
||
35 |
1K |
XnD34 |
||||
36 |
1L |
XnD35 |
||||
37 |
1M |
8D0 |
16B8 |
XnD36 |
||
38 |
1N |
8D1 |
16B9 |
XnD37 |
||
39 |
1O |
8D2 |
16B10 |
XnD38 |
||
40 |
1P |
8D3 |
16B11 |
XnD39 |
||
41 |
8D4 |
16B12 |
XnD40 |
|||
42 |
8D5 |
16B13 |
XnD41 |
|||
43 |
8D6 |
16B14 |
XnD42 |
|||
44 |
8D7 |
16B15 |
XnD43 |
|||
45 |
32A00 |
XnD49 |
||||
46 |
32A01 |
XnD50 |
||||
47 |
32A02 |
XnD51 |
||||
48 |
32A03 |
XnD52 |
||||
49 |
32A04 |
XnD53 |
||||
50 |
32A05 |
XnD54 |
||||
51 |
32A06 |
XnD55 |
||||
52 |
32A07 |
XnD56 |
||||
53 |
32A08 |
XnD57 |
||||
54 |
32A09 |
XnD58 |
||||
55 |
32A10 |
XnD61 |
||||
56 |
32A11 |
XnD62 |
||||
57 |
32A12 |
XnD63 |
||||
58 |
32A13 |
XnD64 |
||||
59 |
32A14 |
XnD65 |
||||
60 |
32A15 |
XnD66 |
||||
61 |
32A16 |
XnD67 |
||||
62 |
32A17 |
XnD68 |
||||
63 |
32A18 |
XnD69 |
||||
64 |
32A19 |
XnD70 |
The eighth line tells us that bit 3 of port 4B is multiplexed on bit 5 of
port 8A, bit 5 of port 16A, and bit 25 of port 32A; and it is called
XnD07
, where n
is 0
or 1
depending on the tile that the
ports are on.
You notice that the mux structure is designed so that the narrowest port takes precedence. That is, if you use port 8A to drive data, then pins 16A[0..7] are not driven out. If you also drive port 4D, then that will knock out pins 16A[10..13] too. If you do chose to drive a signal on 16A it will only show on pins XnD16, XnD17, XnD20, and XnD21. On inputting data, all data goes to all pins; but it will only make sense to sample them on the ports for which the data was intended.
In addition to the port multiplexer that governs GPIO pins there may be
another second multiplexer on the edge of the chip that can multiplex
XLINK signals (the communications network), LPDDR-1 (extended memory), and
the application PLL onto the GPIO pins. In the example in
Fig. 1 X1D18
has an XLINK signal multiplexed on it.
All port muxes are set automatically when a port is enabled. When you enable an XLINK, LPPDR, or the application PLL, it will automatically mux the pin to those, taking precedence over any port(s) out that may be mapped to the same pin. The precise mapping depends on the device family, and it is shown in the datasheet for the particular product.
Finally, the MIPI PHY and USB PHY are muxed in to a selection of ports. The USB PHY is hard-wired to ports 8A and 8B, and ports 1E, 1F, 1H, 1I, 1J, and 1K. If you enable the USB PHY these ports should not be used by application code. You can still use ports 4A, 4B, 4C, and 4D; despite them being multiplexed with 8A and 8B, they are bypassed for the USB PHY. So six 1-bit ports are taken over by the USB PHY when enabled. Similarly, the MIPI PHY uses ports 8A, 1E, 1I, and 1O. The muxing structures are shown in the datasheet. Note that the USB and MIPI ports are only being muxed if the USB PHY and/or MIPI PHY are enabled.
The port map#
To summarise, in order to pick the appropriate IO pins we have seen three constraints:
Pick the right port-width for the particular IO task
Pick the right tile to colocate IO pins (informed by the software stack)
Pick a port that is not muxed on a pin that is already in use
If there is a choice, you may want to pick a port that is in a convenient location on the chip. For example, you will note that the QSPI pins are all located together on the top left-hand corner of the chip.
A tool that can help in solving these constraints is the port-map. The port-map for a package is a spreadsheet that lists the pins available on that package, the multiplex structure, pins potentially occupied by USB and MIPI etc. The portmap is available from the landing page of the particular product, and are linked below:
An excerpt of the portmap of the QF60 packages is shown in Fig. 2. The left-most columns show the port multiplexer, then there is a list of internal pin functions, then the IO rail, the pin name, and the pin number on the particular package. Ports that may be unavailable are coloured green, yellow, and blue.
Fig. 2 Excerpt from QF60 portmap#
By filling in the final column on the right we can assign each IO
function a pin and port. In this case, we have assigned QSPI_CS_N
,
QSPI_CLK
, QSPI_D0
, QSPI_D1
, QSPI_D2
, and QSPI_D3
; the four
signals required for QSPI.
The XN-file#
An XMOS .xn
file is an XML-based description that is used by the XTC tools
to define system configurations, hardware setups, and interconnections between different components.
These files are essential when developing applications as they specify the configuration of the target processor,
including memory, clocks, boot mode and the port mapping. The XTC tools use the data in the .xn
file to generate the
header files required to compile and link a firmware application.
The .xn
file is the place where we can collect all the port-data. We can
assign names to ports, and the tools create a platform.h
file that we can
include in our program to use abstract port name.
For example, we can
include the following lines in our target_board.xn
file:
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<Port Location="XS1_PORT_4C" Name="PORT_LEDS"/>
<Port Location="XS1_PORT_4D" Name="PORT_BUTTONS"/>
By including platform.h
into our main program we can now write:
#include <xcore/port.h>
#include <platform.h>
port_t leds = PORT_LEDS;
port_t buttons = PORT_BUTTONS;
int main() {
while(1) {
int b = port_in(buttons);
port_out(leds, b);
}
}
And use the variable leds
to refer to PORT_LEDS
to refer to
XS1_PORT_4C
to refer to pins X0D14
, X0D15
, X0D20
and
X0D21
, to refer to balls D4, D3, F1 and G2 on the FB265 package.
This mechanism allows us to write code that is independent of the actual
pin numbers, and allows us to easily change the the target package by
changing the .xn
file without changing the code.
A full description of XN files can be found in the XTC tools documentation.