5. Special considerations

This section is dedicated to device specific requirements that require extra attention and consideration when programming.

5.1 Ethernet, setting a static IP-address

There are several ways of setting the IP address of a device. The default method is DHCP, but a static IP address can also be used. This can be done through the network interfaces configuration file.

5.1.1 File method for IP address configuration in systemd-networkd

If you are using CC Linux version below 3.4, system-networkd is used for the networking configuration. This method requires knowledge about the interfaces file format, but a sample is given below.

$ sudo nano /etc/systemd/network/eth0.network

Sample of network file setting dynamic IP address:

[Match]
Name=eth0

[Network]
DHCP=ipv4

Sample of network file setting static IP address:

[Match]
Name=eth0
[Network]
Address=192.168.1.20/24
Gateway=192.168.1.1
DNS=192.168.1.1

Once the file has been edited, it is recommended to either reboot the device, or to bring the network interfaces down and up again, for the IP address configuration to take effect:

$ sudo systemctl restart systemd-networkd

5.1.2 File method for IP address configuration in NetworkManager

CC Linux version 3.4 and above use NetworkManager for network configuration. This method requires knowledge about the interfaces and the basic usage of NetworkManager daemon. You can see the active connections by using the command below.

$ sudo nmcli con show --active

To set a static IP address to the connection, you can use the command below. Please note that the connection name will be different than the interface name. (e.g ‘Wired connection 1’ for eth0):

$ sudo nmcli con mod ‘{Connection Name}’ ipv4.method manual ipv4.address {Static IP}/24

To set it back as a dynamic IP interface, you can use the command below:

$ sudo nmcli con mod ‘{Connection Name}’ ipv4.method auto ipv4.address “”

Once the file has been edited, it is recommended to either reboot the device, or to bring the network interfaces down and up again, for the IP address configuration to take effect:

$ sudo nmcli con up ‘{Connection Name}’

5.2 CAN

In Linux, CAN is interfaced using SocketCAN which is a standard used in the Linux kernel.

Usage of SocketCAN requires knowledge of some system specific settings and details described herein. For additional SocketCAN information see the official SocketCAN documentation.

CAN bit timings are set by default for settings considered robust for most applications. The default bit timings are set as follows for V700, V510/V710/V705 and V1000/V1200 (note that all devices do not have all buses and that V1000/1200 two CAN version has CAN0 and CAN3 only):

ip link set can0 type can bitrate 50000 sjw 5
ip link set can1 type can bitrate 50000 sjw 5
ip link set can2 type can bitrate 50000 sjw 5
ip link set can3 type can bitrate 50000 sjw 10
ip link set dev canX txqueuelen 1000

The default settings can be modified in file /etc/udev/rules.d/16-cc-can-config.rules

Refer to https://www.kernel.org/doc/Documentation/networking/can.txt for details.

5.2.1 Changing interface names with udev

In some cases, it may be beneficial to change interface names to arbitrary values. An example of this are the interfaces on the V1000 and V1200-devices where one of the can channels is interfaced over SPI to enable powerup on CAN.

In practice, legacy software naming prevents renaming the can channels many times.

To mitigate the order, an example script for udev could be:

SUBSYSTEM=="net", KERNELS=="5a8d0000.can", ACTION=="add", NAME="canfd0"
SUBSYSTEM=="net", KERNELS=="spi0.0", ACTION=="add", NAME="canfd1"
SUBSYSTEM=="net", KERNELS=="5a8e0000.can", ACTION=="add", NAME="canfd2"
SUBSYSTEM=="net", KERNELS=="5a8f0000.can", ACTION=="add", NAME="canfd3"

Warning: do not swap the kernel assigned can (can0-n) names for different interfaces, as this will end up in a race condition with indeterministic channel names.

5.2.2 Configuration of the device interface

The device node files for the CAN interfaces are can0 … canX for a device with (X+1) CAN interfaces. The interfaces should be shown when listing all network interfaces with the ifconfig command.

The CAN bus itself is not initialized during start-up. Before any communications can be executed, the user must set correct bus speed (as an example 250kbps) by first writing the value into the bitrate parameter:

$ sudo ip link set can0 type can bitrate 250000

To work properly with external CAN devices, the sample point of baud rate timings and sjw might need to be configured:

$ sudo ifconfig can0 type can sample-point 0.78 sjw 5

and then setting interface up with ifconfig:

$ sudo ifconfig can0 up

After this, ifconfig should show can0 as a network interface:

$ ifconfig
can0      Link encap:UNSPEC  HWaddr 00-00-00-00-00-00
      UP RUNNING NOARP  MTU:16  Metric:1
      RX packets:0 errors:0 dropped:0 overruns:0 frame:0
      TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:10
      RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
      Interrupt:31

For V1000/V1200 tcan4550.ko is used for the CAN controller connected on SPI. Startup scripts handle the loading of the kernel modules upon start-up. The loaded modules can be checked via terminal access using the lsmod command:

$ lsmod | grep can
flexcan         10092           0
can_dev         8641            1 flexcan,xilinx

Since the drivers are compiled as modules, unnecessary protocols may be removed or new modules inserted, according to user needs.

5.2.3 CAN-FD

Some devices support CAN with flexible data rate (FD), see the Technical Manual of your device for more details. The nominal and data baud rates are setup using socketCAN in a similar fashion as standard CAN (example 500 kbps nominal, 2 Mbps data):

$ sudo ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on

In order to work properly with external CAN-FD devices the sample point of baud rate timings and sjw might need to be adjusted:

$ sudo ip link set can0 type can sample-point 0.78 dsample-point 0.8 dsjw 5

5.2.4 Configuring the CAN socket transmission buffer

By default, the CAN driver is configured with a transmission buffer that can hold up to 10 CAN frames. As each frame is sent over the bus, the buffer is cleared. However, it is possible to write frames to the socket faster than the frames are sent. If your application needs to send more than 10 CAN frames in a burst, it might be a good idea to increase the size of the transmission buffer:

$ ifconfig can0 txqueuelen 100

Note: For SPI-based can interfaces (Yukon-platforms) it might be beneficial to increase the buffer length even more i.e 1000.

5.2.5 Bus off recovery options

It is possible to implement automatic bus off recovery after bus off has occurred. State changes are automatically detected, and controller is re-initialized after the specified time-out period.

Automatic bus off recovery is by default turned off. It can be turned on using the ip command, where the wanted restart period in milliseconds is set. For example, a 100 ms restart period for can0 is set from command line like this:

$ ifconfig can0 down
$ ip link set can0 type can restart-ms 100
$ ifconfig can0 up

Same commands apply for all available CAN interfaces by replacing can0 appropriately. The restart period interval is possible to set as needed by the application. Value zero turns automatic bus recovery off.

Warning: Enabling automatic bus off recovery may disturb other nodes on the bus if CAN interface is incorrectly initialized.

5.3 Analog video

For QML applications with analog video, CrossControl recommends using the QtMultimedia framework rather than CCAux API since the video performance is higher and development process quicker. For non-QML applications, CCAux API is recommended.

Qt is not part of the default image, but downloadable from the support site as a separate package. Additionally, you may contact support on how to build Qt with the SDK for the required platform.

5.3.1 Analog Video using QtMultimedia

You may download CC Linux examples such as QML application CCVideo for displaying analog video using a QtCamera instance, from the support site. This application is for test purposes only, CrossControl recommends implementing the video functionality into your application for correct behavior.

QtMultimedia uses the gstreamer backend and the application must export the correct video source:

setenv("QT_GSTREAMER_CAMERABIN_VIDEOSRC", "imxv4l2videosrc", 1);

5.3.2 Analog Video using CCAux API

There are some design constraints on the usage of analog video and CCAux API that it is important to highlight, to create a better understanding of what can be done and what is necessary to do within the applications. Below is a brief description of the video API for developers to consider when building their application.

The most important CCAux Video API functions are as follows:

Initialize (will open file handles, setup basic settings and request frame buffers), select deviceNr=1 for input channel 1:

Video_init(VIDEOHANDLE pObj, unsigned char deviceNr)

Select the active channel 1-4, corresponds to the physical port number:

Video_setActiveChannel(VIDEOHANDLE pObj, VideoChannel channel)

Note that CCpilot v700 does not have any analog video channels.

Set the area of the display where the video will be shown:

Video_setVideoArea(VIDEOHANDLE pObj, unsigned short topLeftX, unsigned short
topLeftY, unsigned short bottomRightX, unsigned short bottomRightY)

Enable or disable (horizontal) mirroring of the video image:

Video_setMirroring(VIDEOHANDLE pObj, CCStatus mode)

Show (or hide) video image:

Video_showVideo(VIDEOHANDLE pObj, bool show)

Further and more detailed API information can be found in the CCAux API documentation.

5.4 Graphics, Qt (without Weston)

For the best graphical performance, it is recommended to use the Qt-framework with KMS support.

With our i.MX8-devices using KMS and the proprietary driver, there is a need for special configuration to set the plugin to the correct color mode:

First define the correct mode in kms.json.

{
"device": "/dev/dri/card0",
"outputs": [
{ "name": "LVDS1", "mode": "800x480", "size": "800x480", "format":    "abgr8888" } ]
}

Then export the necessary configuration parameters:

export QT_QPA_EGLFS_KMS_CONFIG="/path-to-directory-with/kms.json"
export QT_QPA_EGLFS_INTEGRATION=eglfs_kms
export QT_QPA_EGLFS_KMS_ATOMIC=1

And finally launch your application with:

./Application -platform eglfs

There is also a native Vivante platform available, (though this usage is, at present, discouraged as the performance is not on par with EGLFS KMS). To use the EGLFS Vivante platform, export the following configuration:

export QT_QPA_EGLFS_INTEGRATION=eglfs_viv
export QT_QPA_EGLFS_FORCEVSYNC=0
export QT_QPA_EGLFS_FORCE888=1
./application -platform eglfs

5.5 Graphics, Weston

The graphics framework uses the Wayland protocol reference implementation Weston for graphic operations. Wayland is fast and efficient, and is used by most modern advanced Linux systems, giving it vast standard support in the Linux user space.

For example, Qt has a plugin that enables the Qt libraries to be built for Weston. For Qt applications the impact for that means that it simply needs to be started with a specific flag, platform wayland-egl, and built with the correct development libraries. In CC Linux, this flag has been set to the default graphics framework, hence there’s no need to pass the flag.

Weston includes a windowing system, enabling several applications to overlap while in operation.

The Wayland protocol does not, by default, allow its clients (Qt applications etc.) to have any information about where the client is positioned on the screen. Therefore, some Qt functions, like QWidget::pos(), will always give a zero return. This issue has been resolved in CC Linux by adding an extension to wayland, where the window starting coordinates can be given to the application. Please refer to the Software Guide for more information.

5.6 Serial Number Broadcast interface

The device has a Serial Number Broadcast service (SNB). The SNB does not have a programming interface at the device end, but the broadcasted data output can be handled elsewhere; including in another device if required.

The message sent is a multicast UDP datagram to address 224.0.0.27. The message contains a char array with three values separated by tabs; Serial number, Firmware version and device type. The sender’s IP address is available in datagram headers.

Example data contents (without quotes):

“PR01<tab>10.0.0<tab>0”

An example implementation of the data listener is available in the BSP: apps/snb/snb_reader.c.

5.7 Polarity of PWM outputs

The PWM outputs can be either high or low sided, which will affect the duty cycle behavior. For high sided outputs, a duty cycle of 90% will result in the output signal being 90% high and 10% low. For low sided outputs, the opposite is true - the output signal will be 10% high and 90% low.

Refer to the Technical Manual of your device in order to know if it has PWM outputs and if they are high or low sided.

5.8 Suspend

Upon suspending of the device, some peripherals are turned off. These will need to be restarted by the user application upon resume from suspend. The following peripherals are affected (available peripherals differ for different devices, see the Technical Manual for your device):
  • Buzzer/Speaker

  • PWM outputs

  • Digital outputs

  • Configurable inputs (applies to vx10)

The CCAux API function PowerMgr_hasResumed() can be called from within the user application in order to detect a resume from suspend event, see the CCAux API documentation [7].

5.9 General-purpose input/output (GPIO)

Note that this is for low-level gpio only and is not needed for control of PWM outputs or reading configurable inputs.

In the kernel version 5.15 and later the sysfs interface for GPIOs have been removed (traditionally found in /sys/class/gpio). Instead, the libgpiod utilities should be used. For instance, to set GPIO bank 3 GPIO 15 as low, issue the following command:

gpioset gpiochip3 15=0

For more information, read the libgpiod manual pages.