Difference between revisions of "Using the EMAC GPIO Class"
Kyoungmeyer (talk | contribs) (Change status) |
Kyoungmeyer (talk | contribs) (begin porting remainder) |
||
Line 18: | Line 18: | ||
The <code>data</code> member is allocated as a 32-bit unsigned integer regardless of implementation. Many devices use only the least significant byte or the least significant bit. | The <code>data</code> member is allocated as a 32-bit unsigned integer regardless of implementation. Many devices use only the least significant byte or the least significant bit. | ||
− | + | <!-- | |
Data Code Example: | Data Code Example: | ||
<syntaxhighlight lang=C> | <syntaxhighlight lang=C> | ||
Line 49: | Line 49: | ||
⋮ | ⋮ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | --> | |
===DDR=== | ===DDR=== | ||
Line 55: | Line 55: | ||
For example, an EMAC GPIO Class device porta is a one-byte bit-configurable bidirectional GPIO device. Each bit in the <code>data</code> register corresponds to the digital status of the corresponding line porta[0-7]. On reset, the <code>ddr</code> member is read at <code>0x00</code>, indicating that the device is configured with all lines as inputs. If the <code>ddr</code> member is set to <code>0xAA</code> (binary 1010 1010) bits 0, 2, 4, and 6 will remain configured as inputs while the rest of the bits will be configured as outputs. Reading and setting the value in the <code>data</code> member will react according to the configuration set in the <code>ddr</code>. The <code>ddr</code> is allocated as a 32-bit unsigned integer regardless of implementation. | For example, an EMAC GPIO Class device porta is a one-byte bit-configurable bidirectional GPIO device. Each bit in the <code>data</code> register corresponds to the digital status of the corresponding line porta[0-7]. On reset, the <code>ddr</code> member is read at <code>0x00</code>, indicating that the device is configured with all lines as inputs. If the <code>ddr</code> member is set to <code>0xAA</code> (binary 1010 1010) bits 0, 2, 4, and 6 will remain configured as inputs while the rest of the bits will be configured as outputs. Reading and setting the value in the <code>data</code> member will react according to the configuration set in the <code>ddr</code>. The <code>ddr</code> is allocated as a 32-bit unsigned integer regardless of implementation. | ||
− | + | <!-- | |
DDR Code Example: | DDR Code Example: | ||
<syntaxhighlight lang=C> | <syntaxhighlight lang=C> | ||
Line 87: | Line 87: | ||
⋮ | ⋮ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | --> | |
===Index=== | ===Index=== | ||
Line 95: | Line 95: | ||
Indexed GPIO devices should check the applicable range for the <code>index</code> when the user attempts to set the device. For example, an 8-channel A/D device implemented as an EMAC GPIO Class device would have a valid range for the <code>index</code> member of 0-7. Attempting to set the <code>index</code> to anything greater than 7 would cause the <code>index</code> to be set to the maximum allowed value of 7. | Indexed GPIO devices should check the applicable range for the <code>index</code> when the user attempts to set the device. For example, an 8-channel A/D device implemented as an EMAC GPIO Class device would have a valid range for the <code>index</code> member of 0-7. Attempting to set the <code>index</code> to anything greater than 7 would cause the <code>index</code> to be set to the maximum allowed value of 7. | ||
− | + | <!-- | |
Index Code Example: | Index Code Example: | ||
<syntaxhighlight lang=C> | <syntaxhighlight lang=C> | ||
Line 129: | Line 129: | ||
⋮ | ⋮ | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | --> | ||
+ | ===Lock=== | ||
+ | {{imbox | type = notice | text = '''Note:''' Locking support is currently not available on all EMAC boards. This feature was introduced in the later versions of the 2.6.28 kernel for the AT91-based boards. It will be implemented in other kernel trees in the future.}} | ||
+ | Many GPIO devices may be accessed by multiple processes simultaneously, which leads to the possibility of race conditions. The EMAC GPIO Class includes a locking mechanism to prevent these cases when used correctly. Without the locking mechanism, synchronization needs to be performed in userspace. | ||
+ | |||
+ | The lock is implemented as a <code>struct mutex</code> in the GPIO Class device structure. The lock is obtained by the GPIO driver interface through a call to <code>mutex_lock()</code> and freed using <code>mutex_unlock()</code>. This means that any attempts to lock an already locked device will cause the caller to sleep until the lock is freed by the process holding the lock. A nonblocking method using <code>mutex_trylock()</code> may be implemented in the future. | ||
+ | |||
+ | All access to a device must be synchronized using the lock. Further details on this implementation are described in later sections. | ||
+ | |||
+ | ==User Interfaces== | ||
+ | |||
+ | This section describes the two user interfaces available for the GPIO class. The sysfs layer is very handy for scripting and testing. For higher performance and more flexible access, the character driver interface is used, generally from a C application. This provides a simple <code>ioctl()</code> interface. | ||
+ | |||
+ | === Sysfs === | ||
+ | The <code>sysfs</code> filesystem is a virtual filesystem provided by the Linux kernel that allows for a file-based interface to kernel driver parameters. The EMAC GPIO Class utilizes <code>sysfs</code> to provide a simple read/write interface to the GPIO Class device. This interface is easily accessible from the Linux shell and through shell scripting. | ||
+ | |||
+ | The GPIO Class driver registers a directory at <code>/sys/class/gpio</code> assuming that sysfs has been mounted on the system. Under this directory, every GPIO Class device registered with the system will have a directory (i.e. <code>/sys/class/gpio/porta</code>). Within this directory, there will be some files that are a part of the sysfs heirarchy as well as the GPIO Class interface files <code>data</code>, <code>ddr</code>, and <code>index</code>. Depending on the type of device and its implementation, the <code>ddr</code> and <code>index</code> files may or may not exist; <code>data</code> should always be present. | ||
+ | |||
+ | |||
+ | {{imbox | text = '''Note:''' The <code>/sys/class/gpio</code> directory is used by the new I/O driver code in the standard Linux kernel tree. This location will be changed by EMAC in the near future to avoid conflict.}} | ||
+ | |||
+ | ==== Reading ==== | ||
+ | |||
+ | Reading the current value of a device's settings is as simple as reading the respective file. The ''cat'' command is typically used for this. The output is formatted as ASCII hexadecimal characters. For example, to read the value of the data member of the ''porta'' device, run the command: <code>emac-oe$ cat /sys/class/gpio/porta/data</code>The implementation of the read function for the ''data'', ''ddr'', and ''index'' members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The actual value returned depends on the device implementation. | ||
+ | |||
+ | ==== Writing ==== | ||
+ | |||
+ | Writing a new setting to a member of the GPIO device through the sysfs interface is accomplished by writing a new value to the respective file. The ''echo'' command is typically used along with file redirection to set the new value directly, although the output of any command could be used as long as it is formatted correctly. For example, to set the ''porta'' device to ''0xFF'' (all on) the user would first set all bits to output using the ''ddr'' register and then write ''0xFF'' to the data register as shown below: <code>emac-oe$ echo 0xff > /sys/class/gpio/porta/ddremac-oe$ echo 0xff > /sys/class/gpio/porta/data</code> | ||
+ | |||
+ | The implementation of the write function for the ''data'', ''ddr'', and ''index'' members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The low-level effects of the write function depends on the device implementation. | ||
+ | |||
+ | === Character Driver === | ||
+ | |||
+ | The character driver interface is the preferred method for accessing EMAC GPIO Class devices from programmed applications. This interface is significantly more efficient than the sysfs layer and easier to program. In kernels that support the GPIO Class locking mechanism, the character driver interface offers user control over the lock that is not available using the sysfs interface. The character driver interface uses the ''ioctl()'' system call. Newer kernels also support an ''fasync'' method for signal-based event notification from the driver to the user application. | ||
+ | |||
+ | ==== Available IOCTLs ==== | ||
+ | |||
+ | Several different ''ioctl'' command are available for use. The user must know the supported features of the device before using an ''ioctl'' command. For example, many devices do not support the ''ddr'' or ''index'' functionality. All ioctl commands will return a negative error code on failure. | ||
− | |||
<!--[[Category:Custom Development]]--> | <!--[[Category:Custom Development]]--> |
Revision as of 14:53, 14 January 2014
The EMAC GPIO Class is a generic programming interface for General Purpose Input Output (GPIO) devices in the Linux Kernel. The GPIO class driver has two main interfaces under standard Linux: Linux sysfs and character device. The GPIO class is extremely flexible and uses a set of function pointers at the kernel level to allow for specialized read/write functions for each device. EMAC utilizes the GPIO class to create devices that use the same simple interface, such as GPIO registers, simple configuration variables, hardware registers, and Analog-to-Digital converter drivers where the user needs to retrieve a single value from the device.
Contents
Supported Devices
Most of EMAC's ARM based SOM-Carrier combinations and some of EMAC's x86 boards support the EMAC GPIO Class. For a list of GPIOs on each device, please see the EMAC website at emacinc.com/products/system_on_module.
Components
An EMAC GPIO Class Device has three main components. A clear understanding of these components is important for proper use and implementation.
NOTE: The code listings on this page are simple examples of how the EMAC GPIO Class may be used; they are not intended to be compiled or run in their listed state. |
Data
The data
member of a GPIO device is the primary component. In the most simple devices, this is the only component accessible from userspace. The data
member is read and/or written to access or set the current value of the GPIO device. The actual function of the data
member is implementation specific. For a GPIO device in its purest form, such as the GPIO ports present in many of EMAC's CPLD designs, the data
member is a register value with each of the 8 least significant bits representing the digital state of a single line in the GPIO port. In contrast, A/D devices implemented with the EMAC GPIO Class will typically provide the analog value of the currently selected channel in the data
member.
The data
member is allocated as a 32-bit unsigned integer regardless of implementation. Many devices use only the least significant byte or the least significant bit.
DDR
The ddr
or Data Direction Register is a member of the EMAC GPIO Class that is used primarily for direction-configurable GPIO devices. Many devices do not register this aspect of the interface. The ddr
member is used to determine if a particular device should act as an input or output. Depending on the implementation, many devices are bit-configurable GPIO devices, meaning that each bit/line in the GPIO device can be configured as an input or output by its respective value in the ddr
. Typically, a '1' value in the ddr
configures the device as an output and a '0' value in the ddr configures the device as an input. Bidirectional GPIO devices are generally configured as inputs by default until explicitly configured as an output to prevent hardware contention.
For example, an EMAC GPIO Class device porta is a one-byte bit-configurable bidirectional GPIO device. Each bit in the data
register corresponds to the digital status of the corresponding line porta[0-7]. On reset, the ddr
member is read at 0x00
, indicating that the device is configured with all lines as inputs. If the ddr
member is set to 0xAA
(binary 1010 1010) bits 0, 2, 4, and 6 will remain configured as inputs while the rest of the bits will be configured as outputs. Reading and setting the value in the data
member will react according to the configuration set in the ddr
. The ddr
is allocated as a 32-bit unsigned integer regardless of implementation.
Index
Many EMAC GPIO Class devices are implemented as indexed GPIO Devices. These devices utilize a member named index
which impacts the device according to the implementation. The index
member is typically used to specify a memory offset from some base for the data
member or some type of channel setting or controller selection. Many devices ignore the index
value or do not register this member at all.
An example of an indexed GPIO Class device is the indexed_atod
device (and other A/D devices) found on many EMAC boards. In this case, the index
member is used to set the current channel of the A/D to read from the data
member. When the index
is set to 0, channel 0 will be accessed. When the index is set to 3, the data
register will reflect the current value on channel 3 of the device. Another example would be two identical counter registers in a device where setting the index would control which counter was accessed when reading the data
register. This would be an alternative to registering a separate device for each counter.
Indexed GPIO devices should check the applicable range for the index
when the user attempts to set the device. For example, an 8-channel A/D device implemented as an EMAC GPIO Class device would have a valid range for the index
member of 0-7. Attempting to set the index
to anything greater than 7 would cause the index
to be set to the maximum allowed value of 7.
Lock
Note: Locking support is currently not available on all EMAC boards. This feature was introduced in the later versions of the 2.6.28 kernel for the AT91-based boards. It will be implemented in other kernel trees in the future. |
Many GPIO devices may be accessed by multiple processes simultaneously, which leads to the possibility of race conditions. The EMAC GPIO Class includes a locking mechanism to prevent these cases when used correctly. Without the locking mechanism, synchronization needs to be performed in userspace.
The lock is implemented as a struct mutex
in the GPIO Class device structure. The lock is obtained by the GPIO driver interface through a call to mutex_lock()
and freed using mutex_unlock()
. This means that any attempts to lock an already locked device will cause the caller to sleep until the lock is freed by the process holding the lock. A nonblocking method using mutex_trylock()
may be implemented in the future.
All access to a device must be synchronized using the lock. Further details on this implementation are described in later sections.
User Interfaces
This section describes the two user interfaces available for the GPIO class. The sysfs layer is very handy for scripting and testing. For higher performance and more flexible access, the character driver interface is used, generally from a C application. This provides a simple ioctl()
interface.
Sysfs
The sysfs
filesystem is a virtual filesystem provided by the Linux kernel that allows for a file-based interface to kernel driver parameters. The EMAC GPIO Class utilizes sysfs
to provide a simple read/write interface to the GPIO Class device. This interface is easily accessible from the Linux shell and through shell scripting.
The GPIO Class driver registers a directory at /sys/class/gpio
assuming that sysfs has been mounted on the system. Under this directory, every GPIO Class device registered with the system will have a directory (i.e. /sys/class/gpio/porta
). Within this directory, there will be some files that are a part of the sysfs heirarchy as well as the GPIO Class interface files data
, ddr
, and index
. Depending on the type of device and its implementation, the ddr
and index
files may or may not exist; data
should always be present.
Note: The /sys/class/gpio directory is used by the new I/O driver code in the standard Linux kernel tree. This location will be changed by EMAC in the near future to avoid conflict. |
Reading
Reading the current value of a device's settings is as simple as reading the respective file. The cat command is typically used for this. The output is formatted as ASCII hexadecimal characters. For example, to read the value of the data member of the porta device, run the command: emac-oe$ cat /sys/class/gpio/porta/data
The implementation of the read function for the data, ddr, and index members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The actual value returned depends on the device implementation.
Writing
Writing a new setting to a member of the GPIO device through the sysfs interface is accomplished by writing a new value to the respective file. The echo command is typically used along with file redirection to set the new value directly, although the output of any command could be used as long as it is formatted correctly. For example, to set the porta device to 0xFF (all on) the user would first set all bits to output using the ddr register and then write 0xFF to the data register as shown below: emac-oe$ echo 0xff > /sys/class/gpio/porta/ddremac-oe$ echo 0xff > /sys/class/gpio/porta/data
The implementation of the write function for the data, ddr, and index members using the sysfs interface automatically acquires and frees the lock on the respective GPIO device. The low-level effects of the write function depends on the device implementation.
Character Driver
The character driver interface is the preferred method for accessing EMAC GPIO Class devices from programmed applications. This interface is significantly more efficient than the sysfs layer and easier to program. In kernels that support the GPIO Class locking mechanism, the character driver interface offers user control over the lock that is not available using the sysfs interface. The character driver interface uses the ioctl() system call. Newer kernels also support an fasync method for signal-based event notification from the driver to the user application.
Available IOCTLs
Several different ioctl command are available for use. The user must know the supported features of the device before using an ioctl command. For example, many devices do not support the ddr or index functionality. All ioctl commands will return a negative error code on failure.