Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

This chapter gives a short overview of how to access the different hardware parts and interfaces from within the Linux operating system. It is written universally in order to fit all SECO Northern Europe platforms in general.

Table of Contents
minLevel1
maxLevel7

Machine type

...

The SECO Northern Europe i.MX6 based platforms are generally very similar and run the same OS versions. If it is needed to find out the actual hardware that the software is run on, it can be read out using the command line.

Expand
titleChecking machine type

Reading detailed information in /proc/cpuinfo file provided by the kernel:

Code Block
root@santaro:/# cat proc/cpuinfo

processor       : 0
model name      : ARMv7 Processor rev 10 (v7l)
BogoMIPS        : 3.00
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x2
CPU part        : 0xc09
CPU revision    : 10

processor       : 1
model name      : ARMv7 Processor rev 10 (v7l)
BogoMIPS        : 3.00
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpd32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x2
CPU part        : 0xc09
CPU revision    : 10

Hardware        : Garz & Fricke SANTARO (i.MX6)
Revision        : 63015
Board revision  : 1.2
Serial          : 03515530

FNGBoot         : 13.0r3797

These files can also be accessed from inside other programs using the standard open() and read() functionality.

Ethernet

...

If all network devices are properly configured as described in the manual, they can be used by the POSIX socket API.

...

Panel
panelIconIdc5cdf552-0d34-430f-93b4-ece490a2e322
panelIcon:tr:
panelIconText:tr:
bgColor#DEEBFF

If you have some problem in connecting to network through ethernet. Please look into the following trouble shoot link.

Serial interfaces (RS-232 / RS-485 / MDB)

...

Most of the serial interfaces are exported as TTY devices and thus accessible via their device nodes under /dev/ttymxc<number>. Depending on your hardware platform (and maybe its assembly option), different transceivers (RS232, RS485, MDB) can be connected to these TTY devices. See the following table for the mapping between device nodes and hardware connectors on i.MX6:

...

Expand
title C code example for setting the RS485 interface to half duplex mode
Code Block
#include <linux/serial.h>   // serial_rs485
#include <unistd.h>         // close
#include <fcntl.h>          // O_RDWR, O_SYNC
#include <sys/ioctl.h>      // ioctl, TIOCSRS485

void set_rs485_half_duplex_mode()
{
    struct serial_rs485 rs485;
    int fd;
    /* Open port */
    fd = open ("/dev/ttymxc2", O_RDWR | O_SYNC);
    /* Enable RS485 half duplex mode */
    rs485.flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND;
    ioctl(fd, TIOCSRS485, &rs485);
    close(fd);
}

int main(void)
{
    set_rs485_half_duplex_mode();
    return 0;
}

For a full source code example, see the BSP folder sources/meta-guf/meta/recipes-test/ltp-guf-tests/ltp-guftests/testcases/rs485echo.

Interfaces with an MDB transceiver should not be accessed directly via their device nodes. Instead, there is a library for MDB communication in the BSP. Please see the folder sources/meta-guf/meta/recipes-guf/mdbtest for a full source code example.

Real Time Clock (RTC)

...

All SECO Northern Europe systems are equipped with a hardware real time clock. The system time is automatically set during the boot sequence by reading the RTC.

...

Expand
titleAdjust RTC

The RTC time cannot be adjusted directly in one command because only the current system time can be transferred to the RTC. Thus, the system time has to be set first, using the timedatectl command, and can then be written to the RTC:

Code Block
root@santaro:~# timedatectl set-time "2022-11-02 16:26:00"
root@santaro:~# hwclock --systohc

Keypad connector

...

The so called keypad connector is a general purpose connector. It can be used in different modes. The mode is selected using the kernel command line. See [Kernel command line] on how it can be modified.

The command line configuration of the keypad functionality is only needed and possible on the platforms SANTARO and SANTOKA. On the other platforms the available functionality is fix.

...

Expand
titleCombination and default setting

The options can be combined to use multiple functions at the same time, for example:

Code Block
keypad=gpio,i2c,spi

will enable all three functions. This leads to the following mapping:

  • pins 3-10 are used as GPIOs

  • 11 and 12 are used for I2C

  • 13-18 are used for SPI

The default setting is:

Code Block
keypad=gpio,i2c

SPI

...

There are two ways of controlling SPI bus devices from a Linux system:

  • Writing a kernel SPI device driver and accessing this driver from user space by using its interface.

  • Accessing the SPI bus via the Linux kernel’s spidev API directly.

Describing the process of writing a Linux SPI device driver is out of the scope of this manual. The AT25 SPI eeprom can serve as a good and simple example for such a driver. It is located in the kernel directory under:

  • drivers/misc/eeprom/at25.c

The interface provided to the user space by such a kernel driver depends on the sort of this driver (e.g. character misc driver, input subsystem device driver, etc.). A very common usecase for an SPI driver is a touchscreen driver that uses the input event subsystem.

Accessing the SPI bus from userspace directly via spidev is described in the Linux kernel documentation and available in the kernel directory under:

  • Documentation/spi/spidev

Additionally, there is an example C program available in the same location:

  • Documentation/spi/spidev_test.c

The header for spidev is available under:

  • include/linux/spi/spidev.h

Note

If spidev is used to access the SPI bus directly, the user is responsible for keeping the interoperability consistent with all other SPI devices that are controlled by the Linux kernel.

I2C

...

There are two ways of controlling I2C bus devices from a Linux system:

  • Writing a kernel I2C device driver and accessing this driver from user space by using its interface.

  • Accessing the I2C bus via the Linux kernel’s i2c-dev API directly.

Describing the process of writing a Linux I2C device driver is out of this scope of this manual. The AT24 I2C EEPROM can serve as a good and simple example for such a driver. It is located in the kernel directory under:

  • drivers/misc/eeprom/at24.c

The interface provided to the user space by such a kernel driver depends on the sort of this driver (e.g. character misc driver, input subsystem device driver, etc.). A very common usecase for an I2C driver is a touchscreen driver that uses the input event subsystem.

Accessing the I2C bus from userspace directly via i2c-dev is described in the Linux kernel documentation and available inside the kernel directory under:

  • Documentation/i2c/dev-interface

The header for i2c-dev is available under:

  • include/linux/i2c-dev.h

Note

If i2c-dev is used to access the I2C bus directly, the user is responsible for keeping the interoperability consistent with all other I2C devices that are controlled by the Linux kernel.

CAN

...

CAN bus devices are controlled through the SocketCAN framework in the Linux kernel. As a consequence, CAN interfaces are network interfaces. Applications receive and transmit CAN messages via the BSD Socket API. CAN interfaces are configured via the netlink protocol. Refer to the hardware manual corresponding to your device to find the physical port location..

...

The structure for a CAN message is defined in the kernel header include/linux/can.h:

Code Block
struct can_frame {
  u32 can_id; /* 29 bit CAN_ID + flags */
  u8 can_dlc; /* data length code: 0 .. 8 */
  u8 data[8];
};
Expand
titleWorking with CAN messages from a C program

Initializing SocketCAN:

Code Block
int iSock;
struct sockaddr_can addr;

iSock = socket(PF_CAN, SOCK_RAW, CAN_RAW);

addr.can_family = AF_CAN;
addr.can_ifindex = if_nametoindex("can0");

bind(iSock, (struct sockaddr *)&addr, sizeof(addr);

Sending CAN messages:

Code Block
struct can_frame frame;

frame.can_id = 0x123;
frame.can_dlc = 1;
frame.data[0] = 0xAB;

nbytes = write(iSock, &frame, sizeof(frame));

Receiving CAN messages:

Code Block
struct can_frame frame;

nbytes = read(iSock, &frame, sizeof(frame));

if (nbytes > 0) {
  printf("ID=0x%X DLC=%d data[0]=0x%X\n",
  frame.can_id,
  frame.can_dlc,
  frame.data[0]);
}

Sending a CAN message with four bytes with the standard ID 0x20 on can1 from the Linux shell, using the cansend tool. The CAN bus has to be physically prepared properly and there has to by at least one other node that is configured to read on this message ID for this task. Furthermore, all nodes must have the same bit-timing.

Code Block
root@santaro:~# cansend can1 -i 0x20 0xca 0xbe 0xca 0xbe

Reading all CAN messages on can1 using candump tool:

Code Block
root@santaro:~# candump can1

A more detailed documentation of the CAN bus handling in the Linux kernel can be found in the documentation directory of the Linux kernel source tree.

USB

...

There are two general types of USB devices:

  • USB Host: the Linux platform device is the host and controls several devices supported by corresponding Linux drivers.

  • USB Device: the Linux platform device acts as a USB device itself by emulating a specific device type.

USB Host

For USB Host functionality, SECO Northern Europe platforms per default support the following devices:

...

The USB Host bus can also be directly accessed by using libusb. This library is installed on SECO Northern Europe platforms per default. Further information can be found here.

Note

If libusb is used to access the USB bus directly, the user is responsible to keep the interoperability consistent with all other USB devices that are controlled by the Linux kernel.

USB Device

For USB Device functionality, the following device emulations are supported per default:

...

The Serial Gadget creates a virtual serial port over USB, accessible via the device node /dev/ttyGS0.

SD cards and USB mass storage

...

SD cards and USB mass storage devices can be accessed directly by using their devices nodes. The SD card can be found under /dev/mmcblk1, its single partitions are located under /dev/mmcblk1pX with X being a positive number. The USB mass storage devices can be found under /dev/sdX with X=a..z, its single partitions under /dev/sdXY with Y being a positive number

...

Note

For security reasons, the automount of SD cards and USB storage are disabled by default. To enable this feature, delete/rename the file automount_disable_all in /etc/udev/mount.blacklist.d and reboot the system afterwards.

The mounting point for the automount of SD cards and USB storage can be found at /run/media/

Temperature Sensor

...

Most SECO Northern Europe systems are equipped with an on-board hardware temperature sensor. The sensor is a Texas Instruments LM75 connected via I2C. To measure the current temperature you can read the corresponding sysfs file in /sys/class/hwmon/hwmon0/.

Expand
titleExample

Read current temperature:

Code Block
root@santaro:~# cat /sys/class/hwmon/hwmon0/temp1_input
23500

Note that the value will be displayed in millidegree Celsius.

The sensor generates an alert when the measured temperature exceeds the maximum temperature defined in temp1_max. The alert flag will be set to 1 (active low) and an interrupt is generated. The interrupt will trigger an event on the temp1_max_alarm sysfs entry, that can be caught using the poll() function. Additionally there is a temp1_min that works similar.

Read the temperature alert flag:

Code Block
root@santaro:~# cat /sys/class/hwmon/hwmon0/temp1_max_alarm
1

Touchscreen

...

The touchscreen device is used by the window manager (a Wayland compositor) using libinput which itself accesses the touchscreen via the Linux input subsystem kernel API, i.e. its device node /dev/input/event0. Applications ( i.e. based on Qt) get the input events from the compositor.

Calibration for touchscreens, which is mandatory for resistive touchscreens but also useful for capacitive ones, is done by libinput internally.

Note

The calibration data is still based on tslib’s /etc/shared/pointercal, which is written during the production tests. This data is converted to the libinput format during the first boot and is found in /etc/udev/rules.d/libinput-touchcalibration.rules. The latter file should not be changed manually.

Expand
titleRecalibrate the touchscreen

SECO Northern Europe devices are pre-calibrated and should be shipped out in a ready-to-use fashion. However, If the touchscreen does not behave correctly, the user can perform a recalibration of the touchscreen with:

Code Block
ts_calibrate

After following the on-screen instruction, the new calibration data is written to /etc/shared/pointercal. Now execute the following command to update the libinput calibration:

Code Block
touchcal-conv to-udevrule
sync

After a reboot the touchscreen should be correctly calibrated and work normally.

Panel
panelIconIdc5cdf552-0d34-430f-93b4-ece490a2e322
panelIcon:tr:
panelIconText:tr:
bgColor#DEEBFF

If you have any touch related issues in the hardware please refer the following trouble shoot link.

Audio

...

SECO Northern Europe systems with an integrated audio codec make use of ALSA (Advanced Linux Sound Architecture) as a software interface. This project includes a user-space library (alsa-lib) and a set of tools (aplay, arecord, amixer, alsactl) for controlling and accessing the audio hardware from user applications or the console. Please refer to the official ALSA webpage for a full documentation.

Expand
titlePlay/record an audio file and adjust playback volume

Play the audio file my_audio_file.wav from the console using aplay:

Code Block
root@santaro:~# aplay my_audio_file.wav

Record the audio file my_recorded_audio_file.wav from the console using arecord:

Code Block
root@santaro:~# arecord -f cd -t wav > my_recorded_audio_file.wav

Set the playback volume to half of the maximum:

Code Block
root@santaro:~# amixer sset 'PCM' 50%

The alsamixer command can also be used for several settings regarding the audio hardware, it includes a GUI that help with the configuration of the sound device.

On devices with HDMI output, the HDMI sound device might be chosen as default. To play sound through the internal speaker, the internal sound device must be chosen with the command alsamixer (and subsequently F6).

HDMI

...

The HDMI port can be used as primary or secondary display of the device. Furthermore, an audio-enabled HDMI device can be used as secondary sound card.

...

Depends on configurations, different settings for the HDMI output can be configured by an xml file. See the chapter [Initial Device Configuration] for further instructions.

Display power

...

The display can be powered on or off by software. The value is exported as a virtual file in the sysfs under /sys/class/backlight/backlight/bl_power. It can be accessed using the standard file operations open(), read(), write() and close().

Expand
titleTurn display on or off

Value of 0 means on, 1 means off

Code Block
root@santaro:~# echo 1 > /sys/class/backlight/backlight/bl_power
root@santaro:~# echo 0 > /sys/class/backlight/backlight/bl_power

Display backlight

...

The brightness of the display backlight can be adjusted in a range from 0 to a maximum level. The value is exported as a virtual file in the sysfs under /sys/class/backlight/backlight/brightness. It can be accessed using the standard file operations open(), read(), write() and close().

...