265 lines
6.7 KiB
ReStructuredText
265 lines
6.7 KiB
ReStructuredText
.. include:: ../../../README.rst
|
|
|
|
Connecting external signals to multi-bit ports
|
|
----------------------------------------------
|
|
|
|
Multi-bit ports can be connected to independent signals in either an
|
|
all output configuration (see :ref:`lib_gpio_n_bit_output`) or an all
|
|
input configuration (see :ref:`lib_gpio_n_bit_input`). This implies
|
|
two important restrictions:
|
|
|
|
* **Bi-directional signals cannot use this library**
|
|
* **The signals on the same port must go in the same direction**
|
|
|
|
To use bi-directional signals, a dedicated 1-bit hardware port needs
|
|
to be used.
|
|
|
|
.. _lib_gpio_n_bit_input:
|
|
|
|
.. figure:: images/n_bit_input.*
|
|
|
|
Input configuration
|
|
|
|
.. _lib_gpio_n_bit_output:
|
|
|
|
.. figure:: images/n_bit_output.*
|
|
|
|
Output configuration
|
|
|
|
Performance restrictions
|
|
........................
|
|
|
|
This library allows independent access to the pins of mulit-bit ports
|
|
by multiplexing the port output or input in software. This means that
|
|
there are some performance implications, namely:
|
|
|
|
* The internal buffering, serializing and de-serializing features of
|
|
the xCORE port are not available.
|
|
* The software locking and multiplexing between individual bits of
|
|
the port limits performance. As such, toggling
|
|
pins at speed above 1Mhz, for example, is not achievable (on a
|
|
62.5Mhz logical core). The limit may be lower depending on the other
|
|
code is running on the core and how the other pins of the port are being
|
|
driven.
|
|
|
|
As such, sharing multi-bit ports is most suitable for slow I/O such as
|
|
LEDs, buttons and reset lines.
|
|
|
|
Usage
|
|
-----
|
|
|
|
Output GPIO usage
|
|
.................
|
|
|
|
Output GPIO components are instantiated as parallel tasks that run in a
|
|
``par`` statement. These components connect to the hardware ports of
|
|
the xCORE device. The application
|
|
can connect via an interface connection using an array of the ``output_gpio_if``
|
|
interface type:
|
|
|
|
.. figure:: images/output_gpio_task_diag.*
|
|
|
|
Output GPIO task diagram
|
|
|
|
For example, the following code instantiates an output GPIO component
|
|
for the first 3 pins of a port and connects to it::
|
|
|
|
port p = XS1_PORT_4C;
|
|
|
|
int main(void) {
|
|
output_gpio_if i_gpio[3];
|
|
par {
|
|
output_gpio(i_gpio, 3, p, null);
|
|
task1(i_gpio[0], i_gpio[1]);
|
|
task2(i_gpio[2]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Note that the connection is an array of interfaces, so several tasks
|
|
can connect to the same component instance, each controlling
|
|
different pins of the port.
|
|
|
|
The application can use the client end of the interface connection to
|
|
perform GPIO operations e.g.::
|
|
|
|
void task1(client output_gpio_if gpio1, client output_gpio_if gpio2)
|
|
{
|
|
...
|
|
gpio1.output(1);
|
|
gpio2.output(0);
|
|
delay_milliseconds(200);
|
|
gpio1.output(0);
|
|
gpio2.output(1);
|
|
...
|
|
}
|
|
|
|
More information on interfaces and tasks can be be found in
|
|
the :ref:`XMOS Programming Guide<programming_guide>`. By default the
|
|
output GPIO component does not use any logical cores of its
|
|
own. It is a *distributed* task which means it will perform its
|
|
function on the logical core of the application task connected to
|
|
it (provided the application task is on the same tile).
|
|
|
|
Input GPIO usage
|
|
................
|
|
|
|
There are two types of input GPIO component: those that support events
|
|
and those that do not support events. In both cases,
|
|
input GPIO components are instantiated as parallel tasks that run in a
|
|
``par`` statement. These components connect to the hardware ports of
|
|
the xCORE device. The application
|
|
can connect via an interface connection using an array of the ``input_gpio_if``
|
|
interface type:
|
|
|
|
.. figure:: images/input_gpio_task_diag.*
|
|
|
|
Input GPIO task diagram
|
|
|
|
For example, the following code instantiates an input GPIO component
|
|
for the first 3 pins of a port and connects to it::
|
|
|
|
port p = XS1_PORT_4C;
|
|
|
|
int main(void) {
|
|
input_gpio_if i_gpio[3];
|
|
par {
|
|
input_gpio(i_gpio, 3, p, null);
|
|
task1(i_gpio[0], i_gpio[1]);
|
|
task2(i_gpio[2]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
Note that the connection is an array of interfaces, so several tasks
|
|
can connect to the same component instance, each controlling
|
|
different pins of the port.
|
|
|
|
|newpage|
|
|
|
|
The application can use the client end of the interface connection to
|
|
perform GPIO operations e.g.::
|
|
|
|
void task1(client input_gpio_if gpio1, client input_gpio_if gpio2)
|
|
{
|
|
...
|
|
val1 = gpio1.input();
|
|
val2 = gpio2.input();
|
|
...
|
|
...
|
|
val1 = gpio1.input();
|
|
val2 = gpio2.input();
|
|
...
|
|
}
|
|
|
|
More information on interfaces and tasks can be be found in
|
|
the :ref:`XMOS Programming Guide<programming_guide>`. By default the
|
|
output GPIO component does not use any logical cores of its
|
|
own. It is a *distributed* task which means it will perform its
|
|
function on the logical core of the application task connected to
|
|
it (provided the application task is on the same tile).
|
|
|
|
Using events
|
|
............
|
|
|
|
The :c:func:`input_gpio_with_events` and
|
|
:c:func:`input_gpio_1bit_with_events` functions support the event
|
|
based functions of the input GPIO interface::
|
|
|
|
port p = XS1_PORT_4C;
|
|
|
|
int main(void) {
|
|
input_gpio_if i_gpio[3];
|
|
par {
|
|
input_gpio_with_events(i_gpio, 3, p, null);
|
|
task1(i_gpio[0], i_gpio[1]);
|
|
task2(i_gpio[2]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
In this case the application can request an event on a pin change and
|
|
then select on the event happening e.g.::
|
|
|
|
gpio.event_when_pins_eq(1);
|
|
select {
|
|
case gpio.event():
|
|
// This event was caused by the pin value being 1
|
|
...
|
|
break;
|
|
}
|
|
|
|
|newpage|
|
|
|
|
Pin maps
|
|
........
|
|
|
|
The GPIO tasks all take a ``pin_map`` argument. If this is ``null``
|
|
then the elements of the inteface array will correspond with the a bit
|
|
of the port based on the array element index. So the first element of
|
|
the array will control bit 0, the second with control bit 1 and so on.
|
|
|
|
Alternatively an array can be provided mapping array elements to
|
|
pins. For example, the following will map the array indices to pins 3,
|
|
2 and 7 of the port::
|
|
|
|
char pin_map[3] = {3, 2, 7};
|
|
|
|
int main() {
|
|
...
|
|
par {
|
|
output_gpio(i_gpio, 3, p, pin_map);
|
|
...
|
|
|
|
Output GPIO API
|
|
---------------
|
|
|
|
All GPIO functions can be accessed via the ``gpio.h`` header::
|
|
|
|
#include <gpio.h>
|
|
|
|
You will also have to add ``lib_gpio`` to the
|
|
``USED_MODULES`` field of your application Makefile.
|
|
|
|
Output GPIO components
|
|
......................
|
|
|
|
.. doxygenfunction:: output_gpio
|
|
|
|
|newpage|
|
|
|
|
Output GPIO interface
|
|
.....................
|
|
|
|
.. doxygeninterface:: output_gpio_if
|
|
|
|
Input GPIO API
|
|
--------------
|
|
|
|
Input GPIO components
|
|
......................
|
|
|
|
.. doxygenfunction:: input_gpio
|
|
.. doxygenfunction:: input_gpio_with_events
|
|
|
|
|newpage|
|
|
|
|
.. doxygenfunction:: input_gpio_1bit_with_events
|
|
|
|
|newpage|
|
|
|
|
Input GPIO interface
|
|
....................
|
|
|
|
.. doxygeninterface:: input_gpio_if
|
|
|
|
|
|
|appendix|
|
|
|
|
Known Issues
|
|
------------
|
|
|
|
No known issues.
|
|
|
|
.. include:: ../../../CHANGELOG.rst
|