BSP Reference Manual - phyCORE-i.MX 8M (L-1001e.A0)
Table of Contents
Yocto Introduction
Please read the Yocto/Yocto_Reference_Manual (L-813e_x) for a better understanding of Yocto and this BSP. Furthermore, the meta-yogurt layer cannot be used for the alpha release. Look at the NXP documentation i.MX Yocto Project User's Guide for more information.
PHYTEC Documentation
PHYTEC will provide a variety of hardware and software documentation for all of our products. This includes any or all of the following:
- QS Guide: A short guide on how to set up and boot a phyCORE board along with brief information on building a BSP, the device tree, and accessing peripherals.
- Hardware Manual: A detailed description of the System on Module and accompanying carrier board.
- Yocto Guide: A comprehensive guide for the Yocto version the phyCORE uses. This guide contains an overview of Yocto; introducing, installing, and customizing the PHYTEC BSP; how to work with programs like Poky and Bitbake; and much more.
- BSP Manual: A manual specific to the BSP version of the phyCORE. Information such as how to build the BSP, booting, updating software, device tree, and accessing peripherals can be found here.
- Development Environment Guide: This guide shows how to work with the Virtual Machine (VM) Host PHYTEC has developed and prepared to run various Development Environments. There are detailed step-by-step instructions for Eclipse and Qt Creator, which are included in the VM. There are instructions for running demo projects for these progams on a phyCORE product as well. Information on how to build a Linux host PC yourself is also a part of this guide.
- Pin Muxing Table: phyCORE SOMs have an accompanying pin table (in Excel format). This table will show the complete default signal path, from processor to carrier board. The default device tree muxing option will also be included. This gives a developer all the information needed in one location to make muxing changes and design options when developing a specialized carrier board or adapting a PHYTEC phyCORE SOM to an application.
Tip
We recommend first working through the Development Environment Guide. This will give you a comprehensive overview of the features and functions of both the SOM and carrier board.
On top of these standard manuals and guides, PHYTEC will also provide Product Change Notifications, Application Notes, and Technical Notes. These will be done on a case-by-case basis. Most of the documentation can be found in the applicable download page of our products.
BSP Introduction
Supported Hardware
This BSP supports the phyBOARD-Polaris with 2GB RAM and the alpha kit with 1GB RAM. Visit our web page at:
https://www.phytec.de/produkt/system-on-modules/phycore-imx-8m-download/
or
https://www.phytec.eu/product-eu/system-on-modules/phycore-imx-8m-download/
Click the corresponding BSP release and look for the article number of your module in the column "Article Number". Finally, look for the correct machine name in the corresponding cell under "Machine Name".
Building the BSP
This section will guide you through the general build process of the i.MX 8M BSP using the phyLinux script.
If you want to use our software without phyLinux and the Repo tool managed environment, you can find all Git repositories at:
git://git.phytec.de
Usedu-bootrepository:
git://git.phytec.de/u-boot-imx
Our u-boot is based on the u-boot-imx and adds only a few patches which will be sent upstream in future releases.
Used Linux kernel repository:
git://git.phytec.de/linux-imx-dev
Our i.MX 8M kernel is based on the linux-imx kernel.
To find out which tag is used for a specific board, take a look at your BSP source folder under:
meta-phytec/recipes-bsp/u-boot/u-boot-imx_2018*.bb meta-phytec/recipes-kernel/linux/linux-imx_*.bb
Get the BSP
- Create a fresh project directory:
host$ mkdir ~/yocto
- Download and run the phyLinux script on the manifest file:
host$ cd ~/yocto host$ wget https://download.phytec.de/Software/Linux/Yocto/Tools/phyLinux host$ chmod +x phyLinux host$ ./phyLinux init
Basic Set Up
There are a few important steps which have to be done before the main build process.
- To set up the host, see Yocto Reference Manual Setting up the Host and NXP's documentation i.MX Yocto Project User's Guide "Host Setup".
- To set up the Git configuration, see Yocto Reference Manual Git Configuration.
Finding the Right Software Platform
The i.MX 8M BSP is a unified BSP, which means it supports a set different PHYTEC carrier boards (CB) with different Systems on Module (SOMs). Sometimes it is not easy to find the right software for your PHYTEC board. If you need to figure out the corresponding machine name of your board, take a look at https://www.phytec.de/produkt/system-on-modules/phycore-imx-8m/#download and click on the corresponding BSP release, or to the files in the source folder of the BSP:
meta-phytec/conf/machine/*.conf
where you can find the platform name to the corresponding product IDs. All this information is also displayed by the phyLinux script.
Example phyboard-polaris-imx8m-3 machine configuration file:
#@TYPE: Machine #@NAME: phyboard-polaris-imx8m-3 #@DESCRIPTION: PHYTEC phyBOARD-POLARIS i.MX8M Quad 2GB RAM, 8GB eMMC #@ARTICLENUMBERS: PB-02419-100I.A0
Machine phyboard-polaris-imx8m-3.conf represents the PB-02419-100I.A0 SOM.
Software Platform Selection
- To set the correct SOC, BSP version, and platform, call:
host$ ./phyLinux init
It is also possible to pass this information directly using command line parameters:
host$ ./phyLinux init -p imx8m -r PD19.1.0
Please read the Initialization section for more information.
Starting the Build Process
Refer to Yocto Reference ManualStart the build.
Build different Images
Depending of the used Distro you can build the following Images:
DISTRO ?= "fsl-imx-wayland"
- fsl-image-qt5-validation-image
DISTRO ?= "yogurt-vendor-xwayland"
- phytec-vision-image
- phytec-headless-image
BSP Images
All images generated by Bitbake are deployed to yocto/build/deploy/images/<machine>.
The following list shows, for example, all files generated for the i.MX 8M phyboard-polaris-imx8m-3machine:
- U-Boot: u-boot.bin
- imx-boot: imx-boot-phyboard-polaris-imx8m-3-sd.bin
- Kernel: Image
- Kernel configuration: Image.config
- Kernel device tree file: Image-phytec-imx8mq-phyboard-polaris-rdk-emmc.dtb
- Kernel device tree file sterling-lwb: Image-phytec-imx8mq-phyboard-polaris-rdk-emmc-sterling.dtb
- Root filesystem: phytec-vision-image-phyboard-polaris-imx8m-3.tar.gz, phytec-vision-image-phyboard-polaris-imx8m-3.manifest
- SD card image: phytec-vision-image-phyboard-polaris-imx8m-3.sdcard
System Booting
The default boot source for the i.MX 8M module phyBOARD-Polaris is the eMMC.
Booting from eMMC
To boot from eMMC, switch S1 POS1 has to be set to OFF. To update the software from eMMC, see Updating Software.
Booting from SD Card
Booting from an SD card is useful in several situations, for example, if the board does not start anymore due to a damaged bootloader. To boot from an SD card, switch S1 POS1 and POS3 has to be set to ON.
There are two ways to create a bootable SD card. You can either use:
- a single prebuild SD card image, or
- the four individual images (imx-boot, kernel, device tree, and root filesystem)
Single, Prebuild SD Card Image
The first possibility is to use the SD card image built by Bitbake, a tool integrated in Yocto. This image has the ending *.sdcard and can be found under build/deploy/images/imx8m-3/<MACHINE>/MACHINENAME>-<MACHINE>.sdcard. It contains all BSP files in correctly preformatted partitions and can be copied to the SD card easily using the single Linux command dd.
Tip
The created file phytec-vision-image-phyboard-polaris-imx8m-3.sdcard is only a link to a file likephytec-vision-image-phyboard-polaris-imx8m-3-<BUILD-TIME>.rootfs.sdcard. You should copy the link filefsl-image-qt5-validation-imx-phyboard-polaris-imx8m-3.sdcard to any folder you prefer. By copying the link file to another location, the link will be deleted and the main file (phytec-vision-image-phyboard-polaris-imx8m-3-<BUILD-TIME>.rootfs.sdcard) will be used directly under the namephytec-vision-image-phyboard-polaris-imx8m-3.sdcard. In short, by copying the link file to another location, you can use a link file and get a compressed image file as output.
Warning
To create your bootable SD card with the dd command, you must have root privileges. Because of this, you must be very careful when selecting the destination device for the dd command! All files on the selected destination device will be erased immediately without any further query! Consequently, having selected the wrong device can also erase your hard drive!
To create your bootable SD card, you must first find out the correct device name of your SD card and possible partitions. Then, unmount the partitions before you start copying the image to the SD card.
- In order to get the correct device name, first remove your SD card and execute ls /dev.
- Now insert your SD card and execute ls /dev again.
- Compare the two outputs to find the new device name(s) listed in the second output. These are the device names of the SD card (device and partitions if the SD card is formatted).
- In order to verify the device names found, execute the command dmesg. Within the last lines of its output, you should also find the device names, for example sde (depending on your system).
Now that you have the device name /dev/<your_device> (e.g. /dev/sde), you can see the partitions which must be unmounted if the SD card is formatted. In this case, you will also find /dev/<your_device> with an appended number (e.g. /dev/sde1) in the output. These represent the partition(s) that need to be unmounted.
- Unmount all partitions with:
host$ umount /dev/<your_device><number>
- After having unmounted all devices with an appended number (<your_device><number>), you can create your bootable SD card with:
host$ sudo dd if=<IMAGENAME>-<MACHINE>.sdcard of=/dev/<your_device> bs=1M conv=fsync see status=progress
- If you use the image file created by Bitbake instead:
host$ sudo dd if=<IMAGENAME>-<MACHINE>-<BUILD-TIME>.rootfs.sdcard of=/dev/<your_device> bs=1M conv=fsync status=progress
Use the device name (<your_device>) without appended number (e.g. sde) which stands for the whole device. The parameter conv=fsync forces a sync operation on the device before dd returns. This ensures that all blocks are written to the SD card and are not still in memory. The parameter status=progress will print out information on how much data is and still has to be copied until it is finished.
<BUILD-TIME> has the format: YYYYMMDDHHMMSS
example: Date = 22.06.2018 Time = 11:06:36 <BUILD-TIME> = 20180622110636
Four Individual Images (imx-boot, kernel image, device tree image, root filesystem)
Option two usesimx-boot and a image (a kernel or device tree image together with the root filesystem) to create a bootable SD card manually.
For this method, a new card must be set up with 2 partitions and 8 MB of free space at the beginning of the card. Use the following procedure with fdisk under Linux:
- Create a new FAT partition with partition id C. When creating the new partition, you must leave 8 MB of free space at the beginning of the card. When you go through the process of creating a new partition, fdisk lets you specify where the first sector starts. During this process, fdisk will tell you where the first sector on the disk begins. For example, if the first sector begins at 1000 and each sector is 512 bytes, then 8 MB / 512 bytes = 16384 sectors. This means your first sector should begin at 17384 to leave 8 MB of free space. The size of the FAT partition needs only be big enough to hold the zImage, which is only a few megabytes. To be safe, we recommend a size of 64 MB.
- Create a new Linux partition with partition id 83. Make sure you start this partition after the last sector of partition 1! By default, fdisk will try to use the first partition available on the disk, which in this example is 1000. However, this is our reserved space! You must use the remaining portion of the card for this partition.
- Write the new partition to the SD card and exit fdisk.
Example:
- Type:
host$ sudo fdisk -l /dev/sdc
- You will receive:
Disk /dev/sdc: 4025 MB, 4025483264 bytes 4 heads, 32 sectors/track, 61424 cylinders, total 7862272 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x26edf128 Device Boot Start End Blocks Id System /dev/sdc1 8192 24575 8192 c W95 FAT32 (LBA) /dev/sdc2 24576 655359 315392 83 Linux
- Remove and reinsert the card. Otherwise, Linux will not recognize the new partitions created in the previous step.
- Create a file system on the partitions with (replace sde with your device):
host$ sudo mkfs.vfat /dev/sde1 host$ sudo mkfs.ext4 -L "rootfs" /dev/sde2
Now, the images need to be copied to the SD card.
- Write the bootloader in front of the first partition (replace sde with your device):
host$ dd if=imx-boot-phyboard-polaris-imx8m-3-sd.bin of=/dev/sde bs=1k seek=33 conv=fsync
- Mount the first partition (vfat) and copy the linuximage and oftree file to it:
host$ sudo mount /dev/sd<X>1 /mnt
Warning
Make sure that the images are named exactly as previously mentioned as the bootloader expects them to be named as such.
- In case you want to boot the whole Linux from the SD card, also mount the ext4 partition.
- Then untar <IMAGENAME>-<MACHINE>tar.gz rootfs image to it:
host$ sudo mount /dev/sd<X>2 /media host$ sudo tar jxf <IMAGENAME>-<MACHINE>.tar.gz -C /media/
- Do not forget to properly unmount the SD card with:
host$ sudo umount /media
Booting the Kernel from a Network
Booting from network means loading the kernel over TFTP and the root filesystem over NFS. The bootloader itself must already be loaded from another boot device that is available.
Host Preparation Developments
On the development host, a TFTP server must be installed and configured. The following tools will be needed to boot the kernel from Ethernet:
- A TFTP server
For Ubuntu, install:
host$ sudo apt-get install tftpd-hpa xinetd
After the installation, there are two ways to configure the TFTP server.
TFTP Server Setup
- As a stand-alone daemon
- Controlled and handled by xinetd
- First, create a directory to store the TFTP files:
host$ sudo mkdir /tftpboot host$ sudo chmod -R 777 /tftpboot host$ sudo chown -R nobody /tftpboot
Then copy your BSP image files to this directory. You also need to configure a static IP address for the appropriate interface. The default IP address of the PHYTEC evaluation boards is 192.168.3.11. So setting 192.168.3.10 with netmask 255.255.255.0 as a host address is a good choice.
host$ ifconfig eth1
You will receive:
eth1 Link encap:Ethernet HWadr 00:11:6b:98:e3:47 inet addr:192.168.3.10 Bcast:192.168.3.255 Mask:255.255.255.0
TFTP as a Stand-Alone Daemon
- Create or edit /etc/default/tftpd-hpa:
# /etc/default/tftpd-hpa TFTP_USERNAME="tftp" TFTP_DIRECTORY="/tftpboot" TFTP_ADDRESS=":69" TFTP_OPTIONS="-s -c"
- Set TFTP_DIRECTORY to your TFTP server root directory
- Set TFTP_ADDRESS to the host address the server is listening to (set to 0.0.0.0:69 to listen to all local IPs)
- Set TFTP_OPTIONS, following command shows the available options:
host$ man tftpd
- Restart the services to pick-up the configuration changes:
host$ sudo service tftpd-hpa restart
- Now connect the Ethernet port of the board to your host system, configure the board to network boot, and start it.
Usually, TFTP servers are using the /tftpboot directory to fetch files. If you built your own images, please copy them from the BSP’s build directory to there.
We also need a network connection between the embedded board and the TFTP server. The server should be set to IP 192.168.3.10 and netmask 255.255.255.0.
After the installation of the TFTP server, an NFS server needs to be installed. The NFS server is not restricted to a certain file system location, so all we have to do on most distributions is modify the file /etc/exports and export our root filesystem to the embedded network. In this example file, the whole directory is exported and the "lab network" address of the development host is 192.168.3.10. The IP address has to be adapted to the local needs:
/home/<user>/<rootfspath> 192.168.3.11/255.255.255.0(rw,no_root_squash,sync,no_subtree_check)
<user> must be replaced with your home directory name.
<rootfspath> can be set to a folder that contains a rootfs tar.gz image extracted with sudo.
Embedded Board Preparations
- To find the Ethernet settings in the bootloader of the target, type:
u-boot=> printenv ipaddr serverip netmask gateway ethaddr netargs netboot
With your development host set to IP 192.168.3.10 and netmask 255.255.255.0, the target should return:
ipaddr=192.168.3.11 netmask=255.255.255.0 gateway=192.168.3.10 serverip=192.168.3.10 ethaddr=xx:xx:xx:xx:xx:xx ethprime=FEC
- If you need to change something, type:
u-boot=> setenv <parameter> <value>
- <parameter> should be one of ipaddr, netmask, gateway, or severip.
- <value> will be the actual value of the chosen parameter.
- Make your changes and hit 'Enter'.
The changes you made are temporary for now. To save these changes, use:
u-boot=> saveenv
Here you can also change the IP address to DHCP instead of using a static one.
- Configure:
u-boot=> setenv ip dhcp
- Set up paths for TFTP and NFS. A modification could look like this:
u-boot=> setenv nfsroot /home/user/nfssrc
Please note that these modifications will only affect the bootloader settings.
Booting from an Embedded Board
- To boot from network, call:
u-boot=> run netboot
Updating Software
In this chapter, we explain how to use theu-bootbootloader on target or linux on target/host to update the images in eMMC.
Updating from Network
i.MX 8M boards can be updated over a network. Be sure to set up the development host correctly. The IP needs to be set to 192.168.3.10, the netmask to 255.255.255.0, and a TFTP server needs to be available (see Booting the Kernel from a Network). From a high-level point of view, an eMMC device is like an SD card. Therefore, it is possible to flash the image <name>.sdcard from the Yocto build system directly to the eMMC. The image contains the imx-boot, kernel, device trees, and root filesystem.
Updating eMMC from Network in u-boot on Target
These steps will show how to update the eMMC via a network, but they only work if the size of the image file is less than 1GB. If the image file is larger, go to Updating eMMC from SD card in Linux on Target. Configure the boot switch to boot from SD Card (Switch S1 is ON) and put in an SD card. Power on the board and stop in u-boot.
Tip
A working network is necessary!
- Load your image via network to RAM:
u-boot=> tftp ${loadaddr} ${serverip}:small_test-image.sdcard Using ethernet@30be0000 device TFTP from server 192.168.3.10; our IP address is 192.168.3.11 Filename 'small_test-image.sdcard'. Load address: 0x43000000 Loading: ################################################################# ################################################################# ################################################################# ... ... ... ################################################################# ################################################################# ###################### 20.3 MiB/s done Bytes transferred = 524288000 (1f400000 hex)
- Write the image to the eMMC:
u-boot=> mmc dev0 switch to partitions #0, OK mmc0(part 0) is current device u-boot=> mmc write ${loadaddr} 0x0 0xFA000 MMC write: dev # 0, block # 0, count 1024000 ... 1024000 blocks written: OK
Updating eMMC via Network in Linux on Target
You can update the eMMC from your target.
Tip
A working network is necessary!
- Show your available image-files on host:
host$ ls phytec-vision-image-phyboard-polaris-imx8m-3.sdcard
- Send image with dd command combined with ssh through network to the eMMC of your device:
host$ dd if=phytec-vision-image-phyboard-polaris-imx8m-3.sdcard status=progress | ssh root@192.168.3.11 "dd of=/dev/mmcblk0"
Updating eMMC from SD Card
Even if there is no network available, you can update the eMMC. For that, you only need a ready-to-use image file (*.sdcard) located on SD card. Because the image file is quite large, you have to enlarge your SD card to use its full space (if it was not enlarged before). To enlarge your SD card, see Resizing ext4 Root Filesystem.
Updating eMMC from SD Card in u-boot on Target
Configure SD Card for Flashing
First, we create a new partition on the SD card to store the image.
- On your host, insert the SD card and see in dmesg, which one it is:
host$ dmesg | tail ... [30436.175412] sd 4:0:0:0: [sdb] 62453760 512-byte logical blocks: (32.0 GB/29.8 GiB) [30436.179846] sdb: sdb1 sdb2 ...
- Create a new partition with sudo fdisk /dev/sd<x>:
host$ sudo fdisk /dev/sdb Welcome to fdisk (util-linux 2.27.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/sdb: 29,8 GiB, 31976325120 bytes, 62453760 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xd28c31b9 Device Boot Start End Sectors Size Id Type /dev/sdb1 16384 81919 65536 32M c W95 FAT32 (LBA) /dev/sdb2 81920 3375103 3293184 1,6G 83 Linux Command (m for help): n Partition type p primary (2 primary, 0 extended, 2 free) e extended (container for logical partitions) Select (default p): p Partition number (3,4, default 3): 3 First sector (2048-62453759, default 2048): 3440640 Last sector, +sectors or +size{K,M,G,T,P} (3440640-62453759, default 62453759): Created a new partition 3 of type 'Linux' and of size 28,1 GiB. Command (m for help): t Partition number (1-3, default 3): 3 Partition type (type L to list all types): c Changed type of partition 'Linux' to 'W95 FAT32 (LBA)'. Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks.
- Give the new partition a name and mount it:
host$ sudo mkfs.vfat -n "data" /dev/sdb3 mkfs.fat 3.0.28 (2015-05-16) mkfs.fat: warning - lowercase labels might not work properly with DOS or Windows host$ sudo mount /dev/sdb3 /mnt
- Copy your image to the new partition and unmount it afterwards:
host$ sudo cp phytec-vision-image-phyboard-polaris-imx8m-3.sdcard /mnt/ ; sync
Flash eMMC from u-boot
This step only works if the size of the image file is less than 1GB. If the image file is larger, go to Updating eMMC from SD Card in Linux on Target.
- Configure the boot switch to boot from the SD Card (Switch S1 is ON) and insert the SD card.
- Power on the board and stop in u-boot.
- Flash your <YOUR_IMAGE>.sdcard image from the SD card to eMMC. This will partition the card and copy imx-boot, Image, dtb, and root filesystem to eMMC. (small_test-image.sdcard for example):
u-boot=> fatload mmc 1:3 ${loadaddr} small_test-image.sdcard reading small_test-image.sdcard 524288000 bytes read in 22334 ms (22.4 MiB/s) u-boot=> mmc dev 0 switch to partitions #0, OK mmc0(part 0) is current device u-boot=> mmc write ${loadaddr} 0x0 0xFA000 number of blocks to write. In this case 524288000 bytes / 512 = 0xFA000 MMC write: dev # 0, block # 0, count 1024000 ... 1024000 blocks written: OK
- Reset the board.
- Stop in u-boot again and check that the partition table for eMMC is as expected:
u-boot=> reset ... u-boot=> mmc dev 0 switch to partitions #0, OK mmc0(part 0) is current device u-boot=> mmc part Partition Map for MMC device 0 -- Partition Type: DOS Part Start Sector Num Sectors UUID Type 1 16384 65536 c4792a6c-01 0c 2 81920 3506176 c4792a6c-02 83
Updating eMMC from SD Card in Linux on Target
You can also update the eMMC under Linux. You only need a complete image saved on the SD card (e.q. phytec-vision-image-phyboard-polaris-imx8m-3.sdcard).
- Show your saved image files on the SD card:
target$ ls phytec-vision-image-phyboard-polaris-imx8m-3.sdcard
- Show list of available mmc devices:
target$ ls /dev | grep mmc mmcblk0 mmcblk0boot0 mmcblk0boot1 mmcblk0p1 mmcblk0p2 mmcblk0rpmb mmcblk2 mmcblk1p1 mmcblk1p2
- Write the image to the eMMC of phycore imx8 (mmc device 0 WITHOUT partition):
target$ dd if=phytec-vision-image-phyboard-polaris-imx8m-3.sdcard of=/dev/mmcblk0 conv=sync
- After a complete write, your board can boot from eMMC. Before this will work, you need to toggle switch S1 to OFF. If you don't, the board will boot from SD card again.
Device Tree (DT)
Introduction
The following text briefly describes the Device Tree and can be found in the Linux kernel (linux/Documentation/devicetree/usage-model.txt).
"The "Open Firmware Device Tree", or simply Device Tree (DT), is a data structure and language for describing hardware. More specifically, it is a description of hardware that is readable by an operating system so that the operating system doesn't need to hardcode details of the machine.
Structurally, the DT is a tree or acyclic graph with named nodes, and nodes may have an arbitrary number of named properties encapsulating arbitrary data. A mechanism also exists to create arbitrary links from one node to another outside of the natural tree structure.
Conceptually, a common set of usage conventions called 'bindings', is defined for how data should appear in the tree to describe typical hardware characteristics including data busses, interrupt lines, GPIO connections, and peripheral devices."
The kernel is a really good source for a DT introduction. An overview of the device tree data format can be found on the device tree usage page at devicetree.org:
PHYTEC i.MX 8M BSP Device Tree Concept
The following sections explain some rules we have defined on how to set up device trees in the first place for our i.MX 8M SoC-based boards.
DT Structure
The module includes file Modul .dtsi which contains all devices which are mounted on the module, such as PMIC and RAM. Devices which come from the i.MX 8M SoC but are just routed down to the carrier board are not part of the Module .dtsi. These devices are included in the Carrierboard .dtsi. The Board .dts includes the carrier board and module nodes. It also adds partition tables and enables all hardware configurable nodes of the carrier board or the module (i.e. the Board .dts shows the special characteristics of the board configuration). For example, there are phyCORE-i.MX 8M SOMs which may or may not have Wifi mounted. The Wifi is enabled (if available) in the Board .dts and not in the Module .dtsi.
Accessing Peripherals
To find out which boards and modules are supported by the release of PHYTEC’s i.MX8 BSP described herein, visit our web page at http://www.phytec.de/produkte/software/yocto/phytec-unified-yocto-bsp-releases/ and click the corresponding BSP release. here you can find all hardware supported in the columns "Hardware Article Number" and the correct machine name in the corresponding cell under "Machine Name". (BSP-Yocto_Machines)
For information about all our supported i.MX8 variants, visit our web page at:
https://www.phytec.de/produkt/system-on-modules/phycore-imx-8m/
or
https://www.phytec.eu/product-eu/system-on-modules/phycore-imx-8m/
To achieve maximum software re-use, the Linux kernel offers a sophisticated infrastructure that layers software components into board-specific parts. The BSP tries to modularize the kit features as far as possible. This means that when a customized baseboard or even a customer-specific module is developed, most of the software support can be re-used without error-prone copy-and-paste. The kernel code corresponding to the boards can be found in device trees (DT) under linux/arch/arm64/boot/dts/freescale/*.dts*.
In fact, software re-use is one of the most important features of the Linux kernel, especially of the ARM implementation which always has to fight with an insane number of possibilities of the System-on-Chip CPUs.
The whole board-specific hardware is described in DTs and is not part of the kernel image itself. The hardware description is in its own separate binary, called the Device Tree Blob (DTB) (section Device Tree (DT)).
Please read section PHYTEC i.MX 8M BSP Device Tree Concept to get an understanding of our i.MX8 BSP device tree model.
The following sections provide an overview of the supported hardware components and their operating system drivers on the i.MX8 platform.
Further changes can be ported upon customer request.
i.MX 8M Pin Muxing
The i.MX 8M SoC contains many peripheral interfaces. In order to reduce package size and lower overall system cost while maintaining maximum functionality, many of the i.MX 8M terminals can multiplex up to eight signal functions. Although there are many combinations of pin multiplexing that are possible, only a certain number of sets called IO sets, are valid due to timing limitations. These valid IO sets were carefully chosen to provide many possible application scenarios for the user.
Please refer to the NXP i.MX 8M Reference Manual for more information about the specific pins and the muxing capabilities:
https://www.nxp.com/docs/en/reference-manual/IMX8MDQLQRM.pdf
The IO set configuration, also called muxing, is done in the Device Tree. The driver pinctrl-single reads the DT's node fsl,pins and does the appropriate pin muxing. The following is an example of the pin muxing of the UART1 device in phytec-imx8mq-phyboard-polaris.dtsi:
pinctrl_uart1: uart1grp { fsl,pins = < MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 >; };
The first part of the string MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX names the pad (in this example UART1_RXD). The second part of the string (UART1_DCE_RX) is the desired muxing option for this pad. There is currently no documentation from NXP for pad setting value (hex value on the right).
Serial TTYs
The i.MX 8M SoC provides up to 4 so-called UART units. PHYTEC boards support different numbers of these UART units.
- From the command line prompt of Linux userspace you can easily check the availability of other UART interfaces with:
target$ echo "test" > /dev/ttymxc3
Be sure that the baud rate is set correctly on host and target.
In order to get the currently configured baud rate, you can use the command stty on the target. The following example shows how to copy all serial settings from ttymxc1 to ttymxc3.
- First, get the current parameters with:
target$ stty -F /dev/ttymxc1 -g
5500:5:1cb2:a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
- Now use the output from the stty command above as an argument for the next command:
target$ stty -F /dev/ttymxc3 5500:5:1cb2:a3b:3:1c:7f:15:4:0:1:0:11:13:1a:0:12:f:17:16:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
Network
A gigabit ethernet is provided by our module and board. All interfaces offer a standard Linux network port which can be programmed using the BSD socket interface. The whole network configuration is handled by the systemd-networkd daemon. The relevant configuration files can be found on the target in /lib/systemd/network/ and also in the BSP in meta-freescale/recipes-core/init-ifupdown/init-ifupdown/qoriq/interfaces.
IP addresses can be configured within *.network files. The default IP address and netmask for eth0 is:
eth0: 192.168.3.11/24
The DT Ethernet setup might be split into two files depending on your hardware configuration: the module DT, and the board-specific DT.
Module DT, arch/arm64/boot/dts/freescale/phytec-imx8mq-phycore-som.dtsi:
[…] #include <dt-bindings/net/ti-dp83867.h> […] &fec1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_fec1>; phy-mode = "rgmii-id"; phy-handle = <&phy0>; phy-reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; fsl,magic-packet; status = "okay"; mdio { #address-cells = <1>; #size-cells = <0>; ethphy0: ethernet-phy@0 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <1>; interrupt-parent = <&gpio1>; interrupts = <20 IRQ_TYPE_EDGE_FALLING>; ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>; ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>; enet-phy-lane-no-swap; }; }; }; […] &iomuxc { pcl066 { pinctrl_fec1: fec1grp { fsl,pins = < MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x90 MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x90 MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x90 MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x90 MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x90 MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x90 MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f MX8MQ_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x18 >; }; }; […] };
USB Host Controller
The USB controller of the i.MX 8M SoC provides a low-cost connectivity solution for numerous consumer portable devices by providing a mechanism for data transfer between USB devices with a line/bus speed up to 5 Gbps (SuperSpeed 'SS'). The USB subsystem has two independent USB controller cores. Both cores are On-The-Go (OTG) controller cores and capable of acting as a USB peripheral device or a USB host. Each is connected to a USB 2.0 PHY and a USB 3.0 PHY macrocell and supports USB Type-C connectors.
The unified BSP includes support for mass storage devices and keyboards. Other USB-related device drivers must be enabled in the kernel configuration on demand. Due to udev, all mass storage devices connected get unique IDs and can be found in /dev/disks/by-id. These IDs can be used in /etc/fstab to mount the different USB memory devices in different ways.
User USB1 (host) configuration is in the kernel device tree phytec-imx8mq-phyboard-polaris.dtsi
&usb3_phy1 { status = "okay"; &usb3_1 { status = "okay"; }; &usb_dwc3_1 { dr_mode = "host"; status = "okay"; };
USB OTG
USB OTG 2.0 is a Dual-Role Device controller, which supports both device and host functions and is fully compliant with OTG Supplement to USB2.0 specification, and support high-speed (480Mbps), full-speed (12Mbps), low-speed (1.5Mbps) transfer.
Most PHYTEC boards support USB OTG.
- To activate USB OTG as a device, you need to load an appropriate module with modprobe, e.g. the Ethernet gadget g_ether:
USB OTG target$ modprobe g_ether
For using USB OTG as a host, please load the module g_zero. User USB OTG configuration in the kernel device treephytec-imx8mq-phyboard-polaris.dtsi:
&usb3_phy0 { status = "okay"; &usb3_0 { status = "okay"; }; &usb_dwc3_0 { dr_mode = "otg"; status = "okay"; };
SD / MMC Card
The i.MX 8M alpha release kit supports a slot for Secure Digital Cards and Multi-Media Cards to be used as general-purpose block devices. These devices can be used in the same way as any other block device.
Warning
These kinds of devices are hot-pluggable. Nevertheless, you must ensure not to unplug the device while it is still mounted. This may result in data loss!
After inserting an MMC/SD card, the kernel will generate new device nodes in /dev. The full device can be reached via its /dev/mmcblk0 device node. MMC/SD card partitions will show up in the following way:
/dev/mmcblk0p<Y>
<Y> counts as the partition number starting from 1 to the max. count of partitions on this device. The partitions can be formatted with any kind of file system and also handled in a standard manner, e.g. the mount and umount command work as expected.
Tip
These partition device nodes will only be available if the card contains a valid partition table (”hard disk” like handling). If it does not contain one, the whole device can be used as a file system (”floppy” like handling). In this case, /dev/mmcblk0 must be used for formatting and mounting. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
The cards are always mounted as being writable.
DT configuration for the MMC (SD card slot) interface in arch/arm64/boot/dts/freescale/phytec-imx8mq-phyboard-polaris-sdcard.dtsi:
[…] &usdhc2 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; bus-width = <4>; no-1-8-v; cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; vmmc-supply = <®_vcc3v3>; status = "okay"; }; […] &iomuxc { imx8mq-polaris { […] pinctrl_usdhc2_gpio: usdhc2grpgpio { fsl,pins = < MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 >; }; pinctrl_usdhc2: usdhc2grp { fsl,pins = < MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83 MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3 MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3 MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3 MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3 MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3 MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 >; }; pinctrl_usdhc2_100mhz: usdhc2grp100mhz { fsl,pins = < MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x8d MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xcf MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xcf MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xcf MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xcf MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xcf MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 >; }; pinctrl_usdhc2_200mhz: usdhc2grp200mhz { fsl,pins = < MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x9f MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xdf MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xdf MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xdf MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xdf MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xdf MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 >; }; […] }; };
DT configuration for the MMC interface in arch/arm64/boot/dts/freescale/phytec-imx8mq-phycore-som.dtsi:
[…] &usdhc1 { pinctrl-names = "default", "state_100mhz", "state_200mhz"; pinctrl-0 = <&pinctrl_usdhc1>; pinctrl-1 = <&pinctrl_usdhc1_100mhz>; pinctrl-2 = <&pinctrl_usdhc1_200mhz>; bus-width = <8>; non-removable; status = "disabled"; }; […] &iomuxc { pcl066 { […] pinctrl_usdhc1: usdhc1grp { fsl,pins = < MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83 MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3 MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3 MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3 MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3 MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3 MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3 MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3 MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3 MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3 MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83 MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 >; }; pinctrl_usdhc1_100mhz: usdhc1grp100mhz { fsl,pins = < MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85 MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5 MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5 MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5 MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5 MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5 MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5 MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5 MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5 MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5 MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85 MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 >; }; pinctrl_usdhc1_200mhz: usdhc1grp200mhz { fsl,pins = < MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87 MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7 MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7 MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7 MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7 MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7 MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7 MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7 MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7 MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7 MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87 MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 >; }; […] }; };
eMMC Devices
PHYTEC modules like phyCORE-i.MX 8M are populated with an eMMC memory chip as main storage. eMMC devices contain raw MLC memory cells (section Enable Pseudo-SLC Mode) combined with a memory controller that handles ECC and wear leveling. They are connected via an MMC/SD interface to the i.MX 8M and are represented as block devices in the Linux kernel like SD cards, flash drives, or hard disks.
The electric and protocol specifications are provided by JEDEC (https://www.jedec.org/standards-documents/technology-focus-areas/flash-memory-ssds-ufs-emmc/e-mmc). The eMMC manufacturer's datasheet is relatively short and meant to be read together with the supported version of the JEDEC eMMC standard.
PHYTEC currently utilizes the eMMC chips:
eMMC Chip | Size | JEDEC Version |
---|---|---|
MTFC8GAKAJCN-4M IT | 8 GB | 5.0 |
Extended CSD Register
eMMC devices have an extensive amount of extra information and settings that are available via the Extended CSD registers. For a detailed list of the registers, see manufacturer datasheets and the JEDEC standard.
- In the Linux user space, you can query the registers with:
target$ mmc extcsd read /dev/mmcblk0
You will see:
============================================= Extended CSD rev 1.7 (MMC 5.0) ============================================= Card Supported Command sets [S_CMD_SET: 0x01] [...]
Enabling Background Operations (BKOPS)
In contrast to raw NAND Flash, an eMMC device contains a Flash Transfer Layer (FTL) that handles the wear leveling, block management, and ECC of the raw MLC cells. This requires some maintenance tasks (for example erasing unused blocks) that are performed regularly. These tasks are called Background Operations (BKOPS).
By default (which depends on the chip), the background operations may or may not be executed periodically which impacts the worst-case read and write latency.
The JEDEC Standard has specified a method since version v4.41 that the host can issue BKOPS manually. See the JEDEC Standard chapter Background Operations and the description of registers BKOPS_EN (Reg: 163) and BKOPS_START (Reg: 164) in the eMMC datasheet for more details.
Meaning of Register BKOPS_EN (Reg: 163) Bit MANUAL_EN (Bit 0):
- Value 0: The host does not support manual trigger of BKOPS. Device write performance suffers.
- Value 1: The host does support manual trigger of BKOPS. It will issue BKOPS from time to time when it does not need the device.
The mechanism to issue background operations has already been implemented in the Linux kernel since v3.7. You only have to enable BKOPS_EN on the eMMC device (see below for details).
The JEDEC standard v5.1 introduces a new automatic BKOPS feature. It frees the host to trigger the background operations regularly because the device starts BKOPS itself when it is idle (see the description of bit AUTO_EN in register BKOPS_EN (Reg: 163)).
eMMC chips deployed by PHYTEC do not currently support the new standard v5.1. Neither the Linux kernel nor userspace tool mmc support this feature.
- To check whether BKOPS_EN is set, execute:
target$ mmc extcsd read /dev/mmcblk0 | grep BKOPS_EN
The output will be for example:
Enable background operations handshake [BKOPS_EN]: 0x01 #OR Enable background operations handshake [BKOPS_EN]: 0x00
Where value 0x00 means BKOPS_EN is disabled and device write performance suffers. Where value 0x01 means BKOPS_EN is enabled and the host will issue background operations from time to time.
- To set the BKOPS_EN bit, execute:
target$ mmc bkops enable /dev/mmcblk0
- To ensure that the new setting is taken over and the kernel triggers BKOPS by itself, shut down the system with:
target$ poweroff
and perform a power cycle.
Tip
The BKOPS_EN bit is a one-time-programmable only. It cannot be reversed.
Enable Pseudo-SLC Mode
eMMC devices use MLC memory cells (https://en.wikipedia.org/wiki/Multi-level_cell) to store the data. Compared with SLC memory cells used in NAND Flash, MLC memory cells have lower reliability and a higher error rate at lower costs.
If you prefer reliability over storage capacity, you can enable the pseudo-SLC or SLC mode. The method used here employs the enhanced attribute, which is described in the JEDEC standard and can be set for continuous regions of the device. The JEDEC standard does not specify the implementation details and the guarantees of the enhanced attribute. This is up to the chipmaker. For the Micron chips, the enhanced attribute increases the reliability but also halves the capacity.
Warning
When enabling the enhanced attribute on the device, all data will be lost.
The following sequence shows how to enable the enhanced attribute.
- First obtain the current size of the eMMC device with:
target$ fdisk -l /dev/mmcblk0
- You will receive:
Disk /dev/mmcblk0: 7.1 GiB, 7616856064 bytes, 14876672 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xbfdf196d
As you can see, this device has 7616856064 Byte = 7438336 KiB = 7264.0 MiB = 7.1 GiB (rounded).
- To get the maximum size of the device after pseudo-SLC is enabled use:
target$ mmc extcsd read /dev/mmcblk0 | grep ENH_SIZE_MULT -A 1
- which shows for example:
Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x0001c6 i.e. 3719168 KiB -- Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x000000 i.e. 0 KiB
Here, the maximum size is 3719168 KiB = 3632 MiB.
- Now, you can set enhanced attribute for the whole device (example 3719168 KiB) by typing:
target$ mmc enh_area set -y 0 3719168 /dev/mmcblk0
- You will get:
Done setting ENH_USR area on /dev/mmcblk0 setting OTP PARTITION_SETTING_COMPLETED! Setting OTP PARTITION_SETTING_COMPLETED on /dev/mmcblk0 SUCCESS Device power cycle needed for settings to take effect. Confirm that PARTITION_SETTING_COMPLETED bit is set using 'extcsd read' after power cycle
- To ensure that the new setting is being used, shut down the system with:
target$ poweroff
- and perform a power cycle.
It is recommended that you verify the settings now.
- First, check the value of ENH_SIZE_MULT which must be 3719168 KiB:
target$ mmc extcsd read /dev/mmcblk0 | grep ENH_SIZE_MULT -A 1
- You should receive:
Max Enhanced Area Size [MAX_ENH_SIZE_MULT]: 0x0001c6 i.e. 3719168 KiB -- Enhanced User Data Area Size [ENH_SIZE_MULT]: 0x0001c6 i.e. 3719168 KiB
- Finally, check the size of the device. In this example, it should be 3808428032 Byte = 3632.0 MiB with:
target$ fdisk -l /dev/mmcblk0 Disk /dev/mmcblk0: 3.6 GiB, 3808428032 bytes, 7438336 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes
- Now you can flash your new image.
Further reference: https://www.micron.com/support/faqs/products/managed-nand/emmc (chapter "What are the enhanced technology features mentioned in JEDEC specification, and what are the benefits?")
eMMC Boot Partitions
An eMMC device contains four different hardware partitions: user, boot1, boot2,and rpmb.
The user partition is called the User Data Area in the JEDEC standard and is the main storage partition. The partitions boot1 and boot2 can be used to host the bootloader and are more reliable. Which partition the i.MX 8M uses to load the bootloader is controlled by the boot configuration of the eMMC device. The partition rpmb is a small partition and can only be accessed via trusted mechanism.
Furthermore, the user partition can be divided into four user-defined General Purpose Area Partitions. An explanation of this feature exceeds the scope of this document. For further information, see the JEDEC Standard chapter "7.2 Partition Management".
Tip
Do not confuse eMMC partitions with partitions of a DOS, MBR, or GPT partition table.
The current PHYTEC BSP does not use the extra partitioning feature of eMMC devices. Theubootis flashed at the beginning of the user partition. Theubootenvironment is placed at a fix location befor theu-boot. An MBR partition table is used to create two partitions, a FAT32 boot, and ext4 rootfs partition. They are located right after theu-boot. The FAT32 boot partition contains the kernel and device tree.
There are two ways to flash the bootloader to one of the two boot partitions and to switch the boot device, either via bootloader or via userspace commands, as shown in the following examples.
1. Via bootloader:
- First detect the eMMC if not already done:
bootloader$ mmc rescan
- Now, query some information about the eMMC device:
bootloader$ mmc list FSL_SDHC: 0 FSL_SDHC: 1 (SD)
- Select eMMC device:
bootloader$ mmc dev 0 switch to partitions #0, OK mmc0(part 0) is current device
- Now, query some information about the eMMC device:
bootloader$ mmc info
- The output will look like this:
Device: FSL_SDHC Manufacturer ID: 11 OEM: 100 Name: 008G3 Bus Speed: 52000000 Mode : MMC DDR52 (52MHz) Rd Block Len: 512 MMC version 5.1 High Capacity: Yes Capacity: 7.3 GiB Bus Width: 8-bit DDR Erase Group Size: 512 KiB HC WP Group Size: 4 MiB User Capacity: 7.3 GiB WRREL Boot Capacity: 8 MiB ENH RPMB Capacity: 4 MiB ENH
- Load the bootloader file over Ethernet:
bootloader$ tftp ${loadaddr} ${serverip}:imx-boot-phyboard-polaris-imx8m-3-sd.bin
- Write the new bootloader into the eMMC device:
bootloader$ mmc write ${loadaddr} 0x21 0x990D
- assumed bootloader file size 638910 Bytes = 0x9BFBE
- assumed block length of eMMC 512 Bytes = 0x200
-> size to write to eMMC should be <bootloader file size>/<block length> = 0x9BFBE/0x200 = 0x4E0 (rounded)
-> as wrote before, offset to write bootloader should be 33 blocks = 0x21
2. Via userspace commands:
- Flash the bootloader to the beginning of eMMC:
target$ dd if=<path to bootloader>/imx-boot-phyboard-polaris-imx8m-3-sd.bin of=/dev/mmcblk0 bs=1k seek=33
Reliable Write
There are two different Reliable Write options:
- Reliable Write option for a whole eMMC device/partition.
- Reliable Write for single write transactions.
Tip
Do not confuse eMMC partitions with partitions of a DOS, MBR, or GPT partition table (see previous section).
- The first Reliable Write option can be enabled with the mmc tool:
target$ mmc --help [...] mmc write_reliability set <-y|-n> <partition> <device>
The second Reliable Write option is the configuration bit Reliable Write Request parameter (bit 31) in command CMD23. It has been used in the kernel since v3.0 by file systems, e.g. ext4 for the journal and user space applications such as fdisk for the partition table. In the Linux kernel source code, it is handled via flag REQ_META.
Conclusion: ext4 file system with mount option data=journal should be safe against power cuts. The file system check can recover the file system after a power failure, but data that was written just before the power cut may be lost. In any case, a consistent state of the file system can be recovered. To ensure data consistency for the files of an application, the system functions fdatasync, or fsync should be used in the application.
Resizing ext4 Root Filesystem
fdisk can be used to expand the root filesystem. The example works for any block device such as eMMC, SD card, or hard disk.
- Get the current device size:
target$ fdisk -l /dev/mmcblk0
- The output looks like:
Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xbfdf196d Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 16384 81919 65536 32M c W95 FAT32 (LBA) /dev/mmcblk0p2 81920 3440639 3358720 1.6G 83 Linux
- Now use fdisk to delete and create a partition with max size of device:
target$ fdisk /dev/mmcblk0 Welcome to fdisk (util-linux 2.28.1). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xbfdf196d Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 16384 81919 65536 32M c W95 FAT32 (LBA) /dev/mmcblk0p2 81920 3440639 3358720 1.6G 83 Linux Command (m for help): d Partition number (1,2, default 2): 2 Partition 2 has been deleted. Command (m for help): p Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xbfdf196d Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 16384 81919 65536 32M c W95 FAT32 (LBA) Command (m for help): n Partition type p primary (1 primary, 0 extended, 3 free) e extended (container for logical partitions) Select (default p): p Partition number (2-4, default 2): 2 First sector (2048-15269887, default 2048): 81920 Last sector, +sectors or +size{K,M,G,T,P} (81920-15269887, default 15269887): Created a new partition 2 of type 'Linux' and of size 7.3 GiB. Command (m for help): p Disk /dev/mmcblk0: 7.3 GiB, 7818182656 bytes, 15269888 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xbfdf196d Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 16384 81919 65536 32M c W95 FAT32 (LBA) /dev/mmcblk0p2 81920 15269887 15187968 7.3G 83 Linux Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Syncing disks. target$
Increasing the file system size can be done while it is mounted. An on-line resizing operation is performed. But you can also boot the board from an SD card and then resize the file system on the eMMC partition while it is not mounted. Furthermore, the board has to be rebooted so that the new partition table will be read.
Erasing the Device
It is possible to erase the eMMC device directly rather than overwriting it with zeros. The eMMC block management algorithm will erase the underlying MLC memory cells or mark these blocks as discard. The data on the device is lost and will be read back as zeros.
- After booting from SD card execute:
target$ blkdiscard --secure /dev/mmcblk0
The option --secure ensures that the command waits until the eMMC device has erased all blocks.
Tip
dd if=/dev/zero of=/dev/mmcblk0 also destroys all information on the device, but this command is bad for wear leveling and takes much longer!
GPIOs
The phyBOARD-Polaris has a set of pins especially dedicated as user I/Os. Those pins are connected directly to i.MX 8M pins and are muxed as GPIOs. They are directly usable in Linuxuserspace. The processor has organized its GPIOs into five banks of 32 GPIOs each (GPIO1 – GPIO5) and one bank with 14 GPIOs. gpiochip0, gpiochip32, gpiochip64, gpiochip96,and gpiochip128 are the sysfs representation of these internal i.MX 8M GPIO banks GPIO1 – GPIO5.
The GPIOs are identified as GPIO<X>_<Y> (e.g. GPIO5_07). <X> identifies the GPIO bank and counts from 1 to 5, while <Y> stands for the GPIO within the bank. <Y> is counted from 0 to 31 (32 GPIOs on each bank).
By contrast, the Linux kernel uses a single integer to enumerate all available GPIOs in the system. The formula to calculate the correct number is:
Linux GPIO number: <N> = (<X> - 1) * 32 + <Y>
Accessing GPIOs from userspace is done using the sysfs path /sys/class/gpio/.
- First you have to register the GPIO that you want to use by writing its numbers into the file export:
target$ echo <N> > /sys/class/gpio/export
This will create a new subdirectory gpio<N> (for GPIO<X>_<Y> of the controller). The two files, direction and value,in the new subdirectory allow the processor to control the GPIO.
Example:
- To use the GPIO <N> as input, execute the following commands:
target$ echo out > /sys/class/gpio/gpio<N>/direction target$ cat /sys/class/gpio/gpio<N>/value
- To use the newly created GPIO 135 as output and to toggle it, execute:
target$ echo 135 > /sys/class/gpio/export target$ echo out > /sys/class/gpio/gpio135/direction target$ echo 1 > /sys/class/gpio/gpio135/value target$ echo 0 > /sys/class/gpio/gpio135/value
Warning
Some of the user IOs are used for special functions. Before using a user IO, refer to the schematic or the hardware manual of your board to ensure that it is not already in use.
Pinmuxing of some GPIO pins in the device tree phytec-imx8mq-phyboard-polaris.dtsi:
pinctrl__leds: leds1grp { fsl,pins = < MX8MQ_IOMUXC_GPIO1_IO01_GPIO1_IO1 0x16 MX8MQ_IOMUXC_I2C3_SCL_GPIO5_IO18 0x16 MX8MQ_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x16 >; };
Keys
With gpio-keys, the Linux kernel can interpret GPIO signals as virtual keyboard events. Some carrier boards have buttons, which can be used with the gpio-keys driver. Right now there are no gpio-keys defined on phyBOARD-Polaris DT. But, we have three gpio-keys at PEB-EVAL-01 expansion board defined in 'phytec-polaris-peb-eval-01.dtsi':
/{ gpio-keys { compatible = "gpio-key"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_gpio_keys>; status = "okay"; switch3 { label = "Power Button"; gpios = <&gpio5 27 GPIO_ACTIVE_LOW>; linux,code = <KEY_POWER>; gpio-key,wakeup; }; }; };
Unfortunately, only 'switch3' is working right now. To display the key events in ASCII format use evtest.
- To show the available input devices, run:
target$ evtest
- You will get for example:
No device specified, trying to scan all of /dev/input/event* Available devices: /dev/input/event0: 30370000.snvs:snvs-powerkey /dev/input/event1: gpio-keys Select the device event number [0-1]:
- Select input device event number 1 for gpio-keys:
Select the device event number [0-1]: 1 Input driver version is 1.0.1 Input device ID: bus 0x19 vendor 0x1 product 0x1 version 0x100 Input device name: "gpio-keys" Supported events: Event type 0 (EV_SYN) Event type 1 (EV_KEY) Event code 15 (KEY_TAB) Event code 57 (KEY_SPACE) Event code 69 (KEY_NUMLOCK) Properties: Testing ... (interrupt to exit)
- Now you will see every hit on switch3 (3 times pressed and released):
Event: time 1528280843.246429, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 1 Event: time 1528280843.246429, -------------- SYN_REPORT ------------ Event: time 1528280843.642365, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0 Event: time 1528280843.642365, -------------- SYN_REPORT ------------ Event: time 1528280844.050439, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 1 Event: time 1528280844.050439, -------------- SYN_REPORT ------------ Event: time 1528280844.390436, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0 Event: time 1528280844.390436, -------------- SYN_REPORT ------------ Event: time 1528280844.738429, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 1 Event: time 1528280844.738429, -------------- SYN_REPORT ------------ Event: time 1528280845.054439, type 1 (EV_KEY), code 69 (KEY_NUMLOCK), value 0 Event: time 1528280845.054439, -------------- SYN_REPORT ------------
- You can exit evtest with Ctrl+C
- Listing to the device with cat will print the raw output (3 times pressed and released):
target$ cat /dev/input/event1 ���[j�E����[j���[�� �E���[�� ���[����E����[������[�L�E���[�L���[�� �E����[�� ���[����E���[���
LEDs
If any LEDs are connected to GPIOs, you have the possibility to access them by a special LED driver interface instead of the general GPIO interface (section GPIOs). You can then access them using /sys/class/leds/ instead of /sys/class/gpio/. The maximum brightness of the LEDs can be read from the max_brightness file. The brightness file will set the brightness of the LED (taking a value from 0 up to max_brightness). Most LEDs do not have hardware brightness support and will just be turned on by all non-zero brightness settings.
Here is a simple example:
- To get all LEDs available, type:
target$ ls /sys/class/leds blue-mmc mmc0:: red-emmc user-led1 green-heartbeat mmc1:: user-led3 user-led2
Here the LEDs user_led_red, user_led_yellow, and user_led_green are on the expansion board PEB-EVAL-01 and the others are on phyBOARD-Polaris.
Warning
Unfortunately,user_led_yellowis not working at present.
- To toogle the LEDs ON, use:
target$ echo 255 > /sys/class/leds/user-led1/brightness
- To toggle OFF:
target$ echo 0 > /sys/class/leds/user-led1/brightness
User I/O configuration in device tree file arch/arm64/boot/dts/freescale/phytec-imx8mq-phyboard-polaris.dtsi:
/ { […] leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_leds>; led-red { label = "red-emmc"; gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc0"; }; led-blue { label = "blue-mmc"; gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>; linux,default-trigger = "mmc1"; }; led-green { label = "green-heartbeat"; gpios = <&gpio4 8 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; }; […] }; &iomuxc { imx8mq-polaris { […] pinctrl_leds: leds1grp { fsl,pins = < MX8MQ_IOMUXC_GPIO1_IO01_GPIO1_IO1 0x16 MX8MQ_IOMUXC_I2C3_SCL_GPIO5_IO18 0x16 MX8MQ_IOMUXC_SAI1_RXD6_GPIO4_IO8 0x16 >; }; […] }; };
User I/O configuration in device tree file arch/arm64/boot/dts/freescale/phytec-polaris-peb-eval-01.dtsi:
/ { […] user_leds: user_leds { compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_user_leds>; status = "okay"; user-led1 { gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>; linux,default-trigger = "gpio"; default-state = "on"; }; user-led3 { gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>; linux,default-trigger = "gpio"; default-state = "on"; }; }; }; &iomuxc { phytec-polaris-pebeval01 { [...] pinctrl_user_leds: user_ledsgrp { fsl,pins = < MX8MQ_IOMUXC_NAND_CE3_B_GPIO3_IO4 0x16 MX8MQ_IOMUXC_UART3_RXD_GPIO5_IO26 0x16 >; }; }; };
I2C Bus
The i.MX 8M contains two multimaster fast-mode I²C modules, I2C1 and I2C2. PHYTEC boards provide plenty of different I²C devices connected to the two I²C modules of the i.MX 8M. This chapter will describe the basic device usage and its DT representation of some of the I²C devices integrated on phyBOARD-Polaris.
General I²C1 bus configuration (e.g. phytec-imx8mq-phycore-som.dtsi):
&i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; [...] }; &iomuxc { pcl066 { pinctrl_i2c1: i2c1grp { fsl,pins = < MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f >; }; }; };
General I²C2 bus configuration (e.g. phytec-imx8mq-phyboard-polaris.dtsi):
&i2c2 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; […] }; &iomuxc { imx8mq-polaris { pinctrl_i2c2: i2c2grp { fsl,pins = < MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f >; }; }; };
EEPROM
It is possible to read and write directly to the device:
- To read and print the first 1024 bytes of the EEPROM as hex number, execute:
target$ dd if=/sys/class/i2c-dev/i2c-0/device/0-0050/eeprom bs=1 count=1024 | od -x
- To fill the whole EEPROM with zeros, use:
target$ dd if=/dev/zero of=/sys/class/i2c-dev/i2c-0/device/0-0050/eeprom bs=4096 count=1
This operation takes some time as the EEPROM is relatively slow.
DT representation, e.g. in phyCORE-i.MX 8M file phytec-imx8mq-phycore-som.dtsi:
&i2c1 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c1>; status = "okay"; […] i2c_eeprom@50 { compatible = "atmel,24c32"; reg = <0x50>; pagesize = <32>; }; }; […] &iomuxc { pcl066 { […] pinctrl_i2c1: i2c1grp { fsl,pins = < MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f >; }; […] }; };
RTC
RTCs can be accessed via /dev/rtc*. Because PHYTEC boards have often more than one RTC, there might be more than one RTC device file.
- To find the name of the RTC device, you can read its sysfs entry with:
target$ cat /sys/class/rtc/rtc*/name
You will get, for example:
rtc-rv3028 30370000.snvs:snvs-
Tip
This will list all RTCs including the non-I²C RTCs. Linux assigns RTC devices IDs based on the device tree /aliases entries if present.
''phytec-imx8mq-phycore-som.dtsi:'' aliases { rtc0 = &i2c_rtc; };
As the time is set according to the value of rtc0 during system boot, rtc0 should always be the RTC that is being backed up. Date and time can be manipulated with the hwclock tool, using the -w (systohc) and -s (hctosys) options. To set the date, first use date and then run hwclock -w -u to store the new date into the RTC. For more information about this tool, refer to the mainpage of hwclock.
DT representation for I²C RTCs: phytec-imx8mq-phycore-som.dtsi:
i2c_rtc: rtc@52 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_rtc>; compatible = "microcrystal,rv3028"; reg = <0x52>; interrupt-parent = <&gpio1>; interrupts = <5 IRQ_TYPE_LEVEL_LOW>; wakeup-source; trickle-resistor-ohms = <1000>; enable-level-switching-mode; }; […] &iomuxc { pcl066 { […] pinctrl_rtc: rtcgrp { fsl,pins = < MX8MQ_IOMUXC_GPIO1_IO05_GPIO1_IO5 0x18 >; }; […] };
PCIe
The phyCORE-i.MX 8M has one Mini-PCIe slot. In general, PCIe autodetects new devices on the bus. After connecting the device and booting up the system, you can use the command lspci to see all PCIe devices recognized.
- Type:
target$ lspci -v
- You will receive:
00:00.0 PCI bridge: Synopsys, Inc. Device abcd (rev 01) (prog-if 00 [Normal decode]) Flags: bus master, fast devsel, latency 0, IRQ 209 Memory at 20000000 (32-bit, non-prefetchable) [size=1M] Bus: primary=00, secondary=01, subordinate=01, sec-latency=0 Memory behind bridge: 20100000-201fffff [virtual] Expansion ROM at 20200000 [disabled] [size=64K] Capabilities: [40] Power Management version 3 Capabilities: [50] MSI: Enable+ Count=1/1 Maskable+ 64bit+ Capabilities: [70] Express Root Port (Slot-), MSI 00 Capabilities: [100] Advanced Error Reporting Capabilities: [148] L1 PM Substates Kernel driver in use: pcieport 01:00.0 Network controller: Intel Corporation WiFi Link 5100 Subsystem: Intel Corporation WiFi Link 5100 AGN Flags: fast devsel, IRQ 241 Memory at 20100000 (64-bit, non-prefetchable) [size=8K] Capabilities: [c8] Power Management version 3 Capabilities: [d0] MSI: Enable- Count=1/1 Maskable- 64bit+ Capabilities: [e0] Express Endpoint, MSI 00 Capabilities: [100] Advanced Error Reporting Capabilities: [140] Device Serial Number 00-24-d6-ff-ff-84-0d-1e Kernel modules: iwlwifi
In this example, the PCIe device is the Intel Corporation WiFi Link 5100.
For PCIe devices, you have to enable the correct driver in the kernel configuration. This WLAN card, for example, is manufactured by IntelKconfig. The option for the driver, which must be enabled, is named CONFIG_IWLWIFI and can be found under Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimat in the kernel configuration.
- In order to activate the driver, use:
host$ bitbake virtual/kernel -c menuconfig
For some devices, like this WLAN card, additional binary firmware blobs are needed. These firmware blobs have to be placed in /lib/firmware/ before the device can be used.
- Type:
host$ scp -r <firmware> root@192.168.3.11:/lib/firmware
- For example, if you try to bring up the network interface with:
target$ ip link set up wlp1s0
- You will get the following output on the serial console:
[ 58.682104] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled [ 58.690822] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled [ 58.696577] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0 [ 58.831022] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled [ 58.839679] iwlwifi 0000:01:00.0: L1 Disabled - LTR Disabled [ 58.845435] iwlwifi 0000:01:00.0: Radio type=0x1-0x2-0x0 [ 58.902797] IPv6: ADDRCONF(NETDEV_UP): wlp1s0: link is not ready
PCIe configuration is in the kernel device tree phytec-imx8mq-phyboard-polaris.dtsi:
&pcie1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie1>; clkreq-gpio = <&gpio4 2 GPIO_ACTIVE_LOW>; reset-gpio = <&gpio4 3 GPIO_ACTIVE_LOW>; ext_osc = <1>; status = "okay"; }; &iomuxc { imx8mq-polaris { […] pinctrl_pcie1: pcie1grp { fsl,pins = < MX8MQ_IOMUXC_SAI1_RXD0_GPIO4_IO2 0x16 MX8MQ_IOMUXC_SAI1_RXD1_GPIO4_IO3 0x16 >; }; […] }; };
Tip
Some PCIe devices, e.g. this Ethernet card, may function properly even if no firmware blob could be loaded from /lib/firmware/ and you received an error message as shown in the first line of the output above. This is because some manufacturers provide the firmware as fall-back on the card itself. In this case, the behavior and output strongly depend on the manufacturer's firmware.
Audio
The PHYTEC i.MX 8M phyBOARD-Polaris uses the TI TLV320AIC3007 audio codec. Audio support is done via the I2S interface and controlled via I2C.
- To check if your soundcard driver is loaded correctly and what the device is called, type:
target$ aplay -L
- You will get output similar toː
null Discard all samples (playback) or generate zero samples (capture) pulse PulseAudio Sound Server sysdefault:CARD=imxaudiohdmi imx-audio-hdmi, Default Audio Device sysdefault:CARD=TLV320AIC3007 TLV320AIC3007, Default Audio Device
- Use scp to copy a wav file to the board and play it through the sound interface with:
- You may have to change the audio device:
target$ aplay -vv file.wav -DsysdefaultːTLV320AIC3007
Warning
Not all wave formats are supported by the sound interface.
- Run speaker-test
- You may have to change the audio device:
target$ speaker-test -c 2 -t wav -Dsysdefault:TLV320AIC3007
- An external audio source can be connected to the input, in order to record a sound file which can then be played back:
- If the arecord command won't stop, use strg + c to interrupt it. The test.wav file will contain the recordings up to the interrupt.
target$ arecord -c 2 -d 5 -t wav test.wav -DsysdefaultːTLV320AIC3007 target$ aplay test.wav -DsysdefaultːTLV320AIC3007
- To inspect the capabilities of your soundcard, call:
target$ alsamixer
You should see a lot of options as the audio-ICs have many features you can experiment with. It might be better to open alsamixer via ssh instead of the serial console, as the console graphical effects are better. You have either mono or stereo gain controls for all mix points. "MM" means the feature is muted (both output, left & right), which can be toggled by hitting m. You can also toggle by hitting '<' for left and ''>' for right output.
For more advanced audio usage, you need to have an audio server. This is required if you want to playback from different applications at the same time. For example, you have a notification app that beeps every now and then, plus you have a browser running that plays sounds embedded in websites. The notification app has no possibility to open the sound device as long as the browser is running. The notifications will be suppressed. The standard sound server of Linux is pulseaudio. It is not, however, currently installed.
Audio Sources and Sinks
The baseboard has four jacks for microphone, headset speaker, line in, and line out. Enabling and disabling input and output channels can be done with the alsamixer program. F3 selects Screen Playback and F4 Screen Capture. With the Tabulator key, you can switch between these screens. To enable or disable switchable controls, press m (mute) or '<' for left and '>' for right.
With the cursor keys left and right, you can step through the different channels. There are many more channels then fit onto one screen, so they will scroll if your cursor reaches the right or left edge of it. If you have trouble with the display during scrolling, try using ssh instead of microcom. You can leave alsamixer by pressing the ESC key. The settings are saved automatically on shutdown and restored on boot by the systemd service alsa-restore. If you want to save the mixer settings manually, you can execute aslactl store. The settings are saved in /var/lib/alsa/asound.state.
Playback
To playback simple audio streams, you can use aplay. For example:
target$ aplay /usr/share/sounds/alsa/Front_Center.wav #OR target$ aplay /usr/share/sounds/alsa/Front_Center.wav -DsysdefaultːTLV320AIC3007
The file formats .ogg, and .flac can be played back using ogg123. Due to licensing issues, MP3 playback is currently not supported. If you are going to deliver a product including .mp3 files, please check the royalty fees.
Capture
arecord is a command-line tool for capturing audio streams that uses Line In as the default input source. To select a different audio source you can use alsamixer. For example, switch on Right PGA Mixer Mic3R and Left PGA Mixer Mic3L in order to capture the audio from the microphone input.
Tip
It is a known error that you need to choose Playback screen (F3) instead of Capture screen (F4) to access these two controls.
The following example captures the current stereo input source with a sample rate of 48000 Hz and creates an audio file in WAV format (signed 16 bit per channel, 32 bit per sample):
target$ arecord -t wav -c 2 -r 48000 -f S16_LE test.wav -DsysdefaultːTLV320AIC3007
Capturing can be stopped using CTRL-C.
Texas Instruments TLV320AIC3007
The TI chip has a lot of mixing features as you will notice when opening alsamixer. To get an idea of the possibilities, refer to the datasheet from TI. One important feature is the analog mixing capability. You can route input channels to output channels, either active or passive, without transferring data back and forth to the SOC. This is usually known as zero-latency monitoring in terms of PC Audio cards. To control this feature, open alsamixer and go to Playback section (F3). There will be one group of selectors for each output channel, e.g. Right Line Mixer. For most of the input paths, you can select between "passive through" or you can activate a programmable gain signal path. To route the line input to the line output, activate both "Right Line Mixer PGAR Bypass" and "Left Line Mixer PGAL Bypass". You should now hear the input signal at the line-out.
As an example application, we can route the audio stream through the whole system. First, we deactivate the direct loop from line-in to line-out in alsamixer and activate the ADC for the analog input mixer and the DAC for the analog output mixer. We can now close the signal path in the user space by using a pipe and the ALSA tools:
target$ arecord -c 2 -r 48000 -f S16_LE -DsysdefaultːTLV320AIC3007 | aplay -DsysdefaultːTLV320AIC3007
We created the following audio routing path:
analog in -> ADC -> i.MX8M -> kernel -> (userspace -> kernel -> )* DAC -> analog out
* actually twice for the pipe
You should now hear the input signal at the line output again. But this time, the routing through the entire system added latency of 750 ms to the signal. The line mixer on the other side will only add about 4 μs delay.
This pipe routing is a crude example of how to use audio. If you need good audio performance, you should use an audio server. There are two prominent choices available, pulseaudio and jack.
As a third option, you can route the audio from line-in to the internal ADC. But instead of taking the signal path through the complete system, you can use the internal digital mixer of the TLV to directly route the signal back to the DAC and then to the output analog mixer and line-out. This signal path is record only. You do not have the option of full-duplex playback in this mode. You can, however, use all the available DSP features of the TLV, the automatic gain, the high-pass filter, EQ, and de-emphasis filters for the record path. To activate this mode, you have to use the TI Windows tool to look up the specific I²C commands. The software can be found on the TI webpage and is called TLV320AIC3107EVM-K - GUI software. The 3107 is register compatible with all available features to the 3007. The software is used for both chips.
Configurations in Kernel Device Tree File phytec-imx8mq-phyboard-polaris.dtsi
/ { […] regulators { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <0>; reg_vcc1v8: vcc1v8 { compatible = "regulator-fixed"; regulator-name = "vcc1v8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; regulator-always-on; }; reg_vcc3v3: vcc3v3 { compatible = "regulator-fixed"; regulator-name = "vcc3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; regulator-always-on; }; }; sound { compatible = "simple-audio-card"; simple-audio-card,name = "TLV320AIC3007"; simple-audio-card,format = "i2s"; simple-audio-card,bitclock-master = <&dailink_master>; simple-audio-card,frame-master = <&dailink_master>; simple-audio-card,widgets = "Microphone", "Mic Jack", "Line", "Line In", "Line", "Line Out", "Speaker", "Speaker", "Headphone", "Headphone Jack"; simple-audio-card,routing = "Line Out", "LLOUT", "Line Out", "RLOUT", "Speaker", "SPOP", "Speaker", "SPOM", "Headphone Jack", "HPLOUT", "Headphone Jack", "HPROUT", "MIC3L", "Mic Jack", "MIC3R", "Mic Jack", "Mic Jack", "Mic Bias", "LINE1L", "Line In", "LINE1R", "Line In"; status = "okay"; dailink_master: simple-audio-card,cpu { sound-dai = <&sai2>; }; simple-audio-card,codec { sound-dai = <&tlv320aic3007>; }; }; }; &clk { assigned-clocks = <&clk IMX8MQ_AUDIO_PLL1>, <&clk IMX8MQ_AUDIO_PLL2>; assigned-clock-rates = <786432000>, <722534400>; }; &i2c2 { clock-frequency = <100000>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_i2c2>; status = "okay"; tlv320aic3007: tlv320aic3007@18 { compatible = "ti,tlv320aic3007"; #sound-dai-cells = <0>; reg = <0x18>; clocks = <&clk IMX8MQ_SYS2_PLL_50M>; AVDD-supply = <®_vcc3v3>; IOVDD-supply = <®_vcc3v3>; DRVDD-supply = <®_vcc3v3>; DVDD-supply = <®_vcc1v8>; status = "okay"; }; […] }; […] &sai2 { pinctrl-names = "default"; #sound-dai-cells = <0>; pinctrl-0 = <&pinctrl_sai2>; assigned-clocks = <&clk IMX8MQ_CLK_SAI2_SRC>, <&clk IMX8MQ_CLK_SAI2_DIV>; assigned-clock-parents = <&clk IMX8MQ_AUDIO_PLL1_OUT>; assigned-clock-rates = <0>, <24576000>; status = "okay"; }; […] &iomuxc { imx8mq-polaris { […] pinctrl_i2c2: i2c2grp { fsl,pins = < MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f >; }; […] pinctrl_sai2: sai2grp { fsl,pins = < MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6 MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6 MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6 MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6 MX8MQ_IOMUXC_SAI2_RXFS_SAI2_RX_SYNC 0xd6 MX8MQ_IOMUXC_SAI2_RXC_SAI2_RX_BCLK 0xd6 MX8MQ_IOMUXC_SAI2_RXD0_SAI2_RX_DATA0 0xd6 >; }; […] }; };
Video
Videos with Gstreamer
The video is installed by default in the BSP:
target$ gst-launch-1.0 playbin uri=file:///usr/share/phytec-qtdemo/videos/caminandes.webm #OR target$ gst-launch-1.0 -v filesrc location=<video.mp4> \ ! qtdemux ! h264parse ! queue ! vpudec ! waylandsink async=false enable-last-sample=false \ qos=false sync=false #OR target$ gplay-1.0 /usr/share/phytec-qtdemo/videos/caminandes.webm
kmssink Plugin ID Evaluation
The kmssink plugin needs a connector ID. To get the connector ID, you can use the tool modetest.
- Get the connector-id:
target$ modetest -c
The output will show something like:
trying to open device 'i915'...failed trying to open device 'amdgpu'...failed trying to open device 'radeon'...failed trying to open device 'nouveau'...failed trying to open device 'vmwgfx'...failed trying to open device 'omapdrm'...failed trying to open device 'exynos'...failed trying to open device 'tilcdc'...failed trying to open device 'msm'...failed trying to open device 'sti'...failed trying to open device 'tegra'...failed trying to open device 'imx-drm'...done Connectors: id encoder status name size (mm) modes encoders 46 0 disconnected HDMI-A-1 0x0 7 45 props: 1 EDID: flags: immutable blob blobs: value: 2 DPMS: flags: enum enums: On=0 Standby=1 Suspend=2 Off=3 value: 0 5 link-status: flags: enum enums: Good=0 Bad=1 value: 0 7 non-desktop: flags: immutable range values: 0 1 value: 0 6 HDR_SOURCE_METADATA: flags: blob blobs: value:
QT-Demo
At startup with the phytec-vision-image, there is the phytec-qtdemo running. To use Weston instead, you need to stop the qtdemo and reload Weston:
target$ systemctl stop phytec-qtdemo.service target$ systemctl restart weston
Camera
The BSP includes drivers for the MIPI CSI-2 i.MX8M camera interface and for the phyCAM-M cameras:
- VM-016-COL-M-(M12)
- VM-016-BW-M-(M12)
- VM-017-COL-M-(M12) (in progress)
- VM-017-BW-M-(M12) (in progress).
Many GStreamer examples and C++ examples are also included.
For information on camera test, read the application note "phyCAM_with_phyBOARD-Polaris-iMX8M_Getting_Started_Ax.pdf"
Display
The 10" Display is always active. If the PEB-AV-Connector is not connected, an error message may occur at boot. The standard output is HDMI.
To switch the standard Weston output to the display, you need to change one line at /etc/default/weston:
- First stop Weston:
target$ systemctl stop weston
- Change output to display at card1:
OPTARGS="--xwayland --drm-device=card1"
Tip
The standard Wayland output is at card0.
- Restart Weston:
target$ systemctl restart weston
phytec-imx8mq-phyboard-polaris-peb-av-009.dtsi:
backlight: backlight { compatible = "pwm-backlight"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_lcd>; default-brightness-level = <6>; power-supply = <®_vcc3v3>; pwms = <&pwm4 0 500000>; enable-gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; brightness-levels= <0 4 8 16 32 64 128 255>; status = "okay"; }; panel: panel { compatible = "edt,etml1010g0dka"; backlight = <&backlight>; port { panel_in: endpoint { remote-endpoint = <&bridge_out>; }; }; }; &pwm4 { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pwm4>; }; &i2c2 { i2c_sn65dsi83: sn65dsi83@2c { compatible = "ti,sn65dsi83"; reg = <0x2c>; lanes_in = <4>; status = "okay"; ports { #address-cells = <1>; #size-cells = <0>; port@0 { reg = <0>; bridge_out: endpoint { remote-endpoint = <&panel_in>; }; }; port@1 { reg = <1>; bridge_in: endpoint { remote-endpoint = <&dsi_out>; }; }; }; }; }; &lcdif { status = "okay"; max-res = <1920>, <1080>; port { lcdif_mipi_dsi: mipi-dsi-endpoint { remote-endpoint = <&mipi_dsi_in>; }; }; }; &mipi_dsi_phy { status = "okay"; }; &mipi_dsi { status = "okay"; as_bridge; sync-pol = <1>; pwr-delay = <10>; port@1 { mipi_dsi_in: endpoint { remote-endpoint = <&lcdif_mipi_dsi>; }; }; }; &mipi_dsi_bridge { status = "okay"; port@1 { dsi_out: endpoint { remote-endpoint = <&bridge_in>; }; }; }; &iomuxc { peb-av-009 { pinctrl_pwm4: pwm4grp { fsl,pins = < MX8MQ_IOMUXC_SAI3_MCLK_PWM4_OUT 0x16 >; }; pinctrl_lcd: lcd0grp { fsl,pins = < MX8MQ_IOMUXC_SAI3_TXD_GPIO5_IO1 0x16 >; }; }; };
Framebuffer
This driver gains access to displays connected to PHYTEC carrier boards by using an emulated framebuffer device /dev/fb1.
- To run a simple test of the framebuffer feature, execute:
fbtest -f /dev/fb1
This will show various test patterns on the display.
- Information about the framebuffer's resolution can be obtained with:
fbset
which will return something like:
mode "1280x800-0" # D: 0.000 MHz, H: 0.000 kHz, V: 0.000 Hz geometry 1280 800 1280 800 32 timings 0 0 0 0 0 0 0 accel true rgba 8/16,8/8,8/0,0/0 endmode
- To query the color depth of the framebuffer emulation, type:
target$ cat /sys/class/graphics/fb0/bits_per_pixel
Display Resolution
For displays with variable display resolution, the resolution can be changed by supplying the desired resolution as a cmdline argument during boot. But first, the correct interface name needs to be determined.
- To get the name of the available video interfaces, execute:
target$ ls /sys/class/drm/ -1
Possible output for the phyCORE-i.MX 8M mounted on the phyBOARD-Polaris Carrier Board:
- card0
- card0-HDMI-A-1
- card1
- card1-LVDS-1 version.
The suffixes of "card0-*" are the identifiers that must be used to configure the corresponding interface.
- For example, to set the HDMI interface to 1024 x 768 pixels and bits per pixel to 24 bpp, use the following kernel argument in the bootloader:
bootloader$ editenv mmcargs bootloader$ video=HDMI-A-1:1024x768-24 bootloader$ saveenv
- The available resolutions can be queried with:
fbset
Tip
Ensure the correct bits per pixel for your display is used, e.g. 18, 16 or 24, … . Otherwise, the colors will look very strange. Use fbtest to test them.
Backlight Control
If a display is connected to the PHYTEC board, you can control its backlight with the Linux kernel sysfs interface. All available backlight devices in the system can be found in the folder /sys/class/backlight. Reading the appropriate files and writing to them allows you to control the backlight.
- To get, for example, the maximum brightness level (max_brightness) execute:
target$ cat /sys/class/backlight/backlight/max_brightness
which will result in:
7
Valid brightness values are 0 to <max_brightness>.
- To obtain the current brightness level, type:
target$ cat /sys/class/backlight/backlight/brightness
you will get for example:
6
- Write to the file brightness to change the brightness:
target$ echo 0 > /sys/class/backlight/backlight/brightness
turns the backlight off,
target$ echo 6 > /sys/class/backlight/backlight/brightness
sets the brightness to the second highest brightness level. For documentation of all files, see https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-class-backlight.
CPU Core Frequency Scaling
The CPU in the i.MX8M is able to scale the clock frequency and the voltage. This is used to save power when the full performance of the CPU is not needed. Scaling the frequency and the voltage is referred to as 'Dynamic Voltage and Frequency Scaling' (DVFS). The i.MX8M BSP supports the DVFS feature. The Linux kernel provides a DVFS framework that allows each CPU core to have a min/max frequency and a governor that governs it. Depending on the i.MX 8 variant used, several different frequencies are supported.
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies
- In case you have, for example, i.MX 8 CPU with approximately a maximum of 1 GHz, the result will be:
1000000 1500000
- The voltages are scaled according to the setup of the frequencies. You can decrease the maximum frequency (e.g. to 1500000):
target$ echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq
- or increase the minimum frequency (e.g. to 1000000)
target$ echo 1000000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq
- To ask for the current frequency, type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq
So-called governors are automatically selecting one of these frequencies in accordance with their goals.
- List all governors available with the following command:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors
The result will be:
interactive conserative userspace powersave ondemand performance schedutil
- interactive: sets the CPU speed depending on usage, similar to ondemand and conserative, but with a different set of configurable behaviors.
- ondemand (default): switches between possible CPU core frequencies in reference to the current system load. When the system load increases above a specific limit, it increases the CPU core frequency immediately.
- conservative: is much like the ondem and governor. It differs in behavior in that it gracefully increases and decreases the CPU speed rather than jumping to max speed the moment there is any load on the CPU.
- powersave: always selects the lowest possible CPU core frequency.
- performance: always selects the highest possible CPU core frequency.
- schedutil: allows userspace to set the CPU frequency for the policy it is attached to by writing to the scaling_setspeed attribute of that policy.
- userspace: allows the user or userspace program running as root to set a specific frequency (e.g. to
1500000
).
- Type:
target$ echo 1500000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
- In order to ask for the current governor, type:
target$ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
- Switching over to another governor (e.g. userspace) is done with:
target$ echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
For more detailed information about the governors, refer to the Linux kernel documentation in: linux/Documentation/admin-guide/pm/cpufreq.rst.
CPU Core Management
The i.MX 8M SOC can have multiple processor cores on the die. The i.MX 8M Quad, for example, has 4 ARM Cores which can be turned on and off individually at runtime.
- To see all available cores in the system, execute:
target$ ls /sys/devices/system/cpu
This will show, for example:
cpu0 cpu1 cpu2 cpu3 cpufreq [...]
Here the system has four processor cores. By default, all available cores in the system are enabled to get maximum performance.
- To switch off a single-core, execute:
target$ echo 0 > /sys/devices/system/cpu/cpu3/online
- As confirmation, you will see:
[ 110.502295] CPU3: shutdown [ 110.505012] psci: CPU3 killed.
Now the core is powered down and no more processes are scheduled on this core.
- You can use htop to see a graphical overview of the cores and processes:
target$ htop
- To power up the core again, execute:
target$ echo 1 > /sys/devices/system/cpu/cpu3/online
The use of the kernel boot parameter maxcpus allows the processor to limit the number of cores the system is using at runtime. For more detailed information, refer to the Linux kernel documentation in: linux/Documentation/admin-guide/kernel-parameters.txt.
FreeRTOS
Download SDK for iMX8MQ from NXP:
https://www.nxp.com/webapp/sps/download/license.jsp?colCode=SDK_2.3_MX8MQ_Beta_LINUX&appType=file1&location=null&DOWNLOAD_ID=null&lang_cd=en
Download the Toolchain:
https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads
Install the SDK:
host$ cd Downloads host$ chmod +x SDK_2.3_MX8MQ_Beta_Linux.run host$ ./SDK_2.3_MX8MQ_Beta_Linux.run
Toolchain:
host$ cp Downloads/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2 /opt/. host$ bzip -d /opt/gcc-arm-none-eabi-7-2018-q2-update-linux.tar.bz2 host$ tar -xvf /opt/gcc-arm-none-eabi-7-2018-q2-update-linux.tar host$ export ARMGCC_DIR=/opt/gcc-arm-none-eabi-7-2018-q2-update host$ export PATH=$PATH:/opt/gcc-arm-none-eabi-7-2018-q2-update/bin
Customize and build a sample program:
host$ cd /SDK_2.3_EVK-MIMX8MQ/boards/evkmimx8mq/multicore_examples/rpmsg_lite_pingpong_rtos/linux_remote/
Change uart2 to uart3 and the base address to 0x58000000 in all files in this folder.
host$ ./build_debug.sh [100%] Linking C executable debug/rpmsg_lite_pingpong_rtos_linux_remote.elf [100%] Built target rpmsg_lite_pingpong_rtos_linux_remote.elf
Run application from sdcard:
- Copy debug/rpmsg_lite_pingpong_rtos_linux_remote_phy.bin to sdcard and execute:
target$ fatload mmc 1 0x7e0000 rpmsg_lite_pingpong_rtos_linux_remote.bin
From tftpserver:
host$ cp rpmsg_lite_pingpong_rtos_linux_remote.bin /tftpboot host$ sudo service xinetd restart bootloader$ tftpboot 0x7e0000 rpmsg_lite_pingpong_rtos_linux_remote.bin bootloader$ boot kernel$ modprobe imx_rpmsg_pingpong
Thermal Management
The Linux kernel has integrated thermal management which is capable of monitoring SOC temperatures, reducing the CPU frequency, driving fans, advising other drivers to reduce the power consumption of devices, and – worst-case – shutting down the system gracefully
(https://www.kernel.org/doc/Documentation/thermal/sysfs-api.txt).
This section describes how the thermal management kernel API is used for the i.MX 8M SOC platform. The i.MX8 has internal temperature sensors for the SOC.
- The current temperature can be read in millicelsius:
target$ cat /sys/class/thermal/thermal_zone0/temp
- You will get, for example:
49000
There are two trip points registered by the imx_thermal kernel driver:
- trip_point_0: 85 °C type: passive
- trip_point_1: 95 °C type: critical
(see kernel sysfs folder /sys/class/thermal/thermal_zone0/)
These trip points are used by the kernel thermal management to trigger events and change the cooling behavior. The following thermal policies (also named thermal governors) are available in the kernel:Step Wise, Fair Share, Bang Bang,and User space. The default policy used in the BSP is step_wise.
If the value of the SOC temperature in the sysfs file temp is above trip_point_0 (greater than 85 °C), the CPU frequency is set to the lowest CPU frequency. When the SOC temperature drops below trip_point_0 again, the throttling is released. If the SOC temperature reaches 95 °C, the thermal management of the kernel shuts down the systems. On the serial console, you can see:
[ 927.036250] thermal thermal_zone0: critical temperature reached(95 C),shutting down target$ Broadcast message from systemd-journald@phyboard-polaris-imx8m-3 (Fri 2018-06-01 14:13:54 UTC): kernel[2784]: [ 927.036250] thermal thermal_zone0: critical temperature reached(95 C),shutting down [ OK ] Stopped target Multi-User System. Stopping Periodic Command Sche� Stopping System Logging Service... Stopping Avahi mDNS/DNS-SD Stack... Stopping Save/Restore Sound Card State... Stopping Job spooling tools... [ OK ] Stopped target Timers. [ OK ] Stopped Daily Cleanup of Temporary Directories.
Watchdog
The PHYTEC i.MX 8M modules include a hardware watchdog that is able to reset the board when the system hangs. This chapter will explain how to enable the watchdog in Linux using systemd to check for system hangs and during reboot. By default, the watchdog is disabled in uboot and Linux.
Watchdog Support in systemd
Systemd has included hardware watchdog support since version 183.
- To activate watchdog support, the file system.conf in /etc/systemd/ has to be adapted by enabling the options:
RuntimeWatchdogSec=60s ShutdownWatchdogSec=10min
RuntimeWatchdogSec defines the timeout value of the watchdog, while ShutdownWatchdogSec defines the timeout when the system is rebooted. For more detailed information about hardware watchdogs under systemd refer to http://0pointer.de/blog/projects/watchdog.html.
On-Chip OTP Controller (OCOTP_CTRL) - eFuses
The i.MX 8M provides one-time programmable fuses to store information such as the MAC address, boot configuration, and other permanent settings ("On-Chip OTP Controller (OCOTP_CTRL)" in the i.MX 8M Reference Manual). The following list is an abstract from the i.MX 8M Reference Manual and includes some useful fuse registers in the OCOTP_CTRL (at base address 0x30350000):
Name | Bank | Word | Memory offset to 0x30350000 | Description |
---|---|---|---|---|
OCOTP_MAC0 | 9 | 0 | 0x640 | contains lower 32 bits of ENET0 MAC address |
OCOTP_MAC1 | 9 | 1 | 0x650 | contains upper 16 bits of ENET0 MAC address and the lower 16 bits of ENET1 MAC address |
OCOTP_MAC2 | 9 | 2 | 0x660 | contains upper 32 bits of ENET1 MAC address |
A complete list and a detailed mapping between the fuses in the OCOTP_CTRL and the boot/mac/... configuration is available in section "Fuse Map" of the i.MX 8M Reference Manual.
Reading Fuse Values in uBoot
You can read the content of a fuse using memory-mapped shadow registers. To calculate the memory address, use the fuse Bank and Word in the following formula:
OCOTP_MAC0: addr
bootloader$ fuse read 9 0
Tip
The shadow registers hold only values that were fused in. For example, it is not possible to read the current boot configuration from the shadow registers, only if it was fused before. Instead, the current boot configuration can read from the SRC_SBMR1 register
Burning MAC Address
Fuses can only be written once! You can brick your board easily by burning the wrong boot configuration. It cannot be reversed!
To burn the MAC address, you have to fill the fuse manually. The following sequence shows how to use it. Replace the <hexvalue> in the following commands with a valid MAC address from your pool of addresses.
- Check values:
bootloader$ fuse read 9 0 Reading bank 9: Word 0x00000000: 00000000 bootloader$ fuse read 9 1 Word 0x00000001: 00000000 bootloader$ fuse read 9 2 Word 0x00000002: 00000000
- Finally burn the MAC address:
bootloader$ fuse prog 9 0 <hexval of the lower 32 bits of ENET0 MAC address> Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y bootloader$ fuse prog 9 1 <hexval of the upper 16 bits of ENET0 MAC address and the lower 16 bits of ENET1 MAC address> Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y bootloader$ fuse prog 9 2 <hexval of the upper 32 bits of ENET1 MAC address> Warning: Programming fuses is an irreversible operation! This may brick your system. Use this command only if you are sure of what you are doing! Really perform this fuse programming? <y/N> y
WLAN
For WLAN and Bluetooth support, we use the Sterling-LWB module from Laird™. This module supports 2,4 GHz bandwidth and can be run in several modes, like client mode, Access Point (AP) mode using WEP, WPA, and WPA2 encryption, etc. More information about the module can be found athttps://connectivity-staging.s3.us-east-2.amazonaws.com/2019-09/CS-DS-SterlingLWB%20v7_2.pdf
Enabling WLAN
WLAN is not available with sdcard-boot. It is only usable with emmc-boot and the dip switch POS1 and POS3 to OFF. It is needed to load the devicetree for the Sterling-LWB:
bootloader$ setenv fdt_file Image-phytec-imx8mq-phyboard-polaris-rdk-emmc-sterling.dtb
Exchange the oftree with phytec-imx8mq-phyboard-polaris-rdk-emmc-sterling.dtb and save it.
bootloader$ saveenv bootloader$ boot
After enabling the WLAN module, the firmware should be loaded by the kernel and you should see an output on your console similar to the following:
brcmfmac: brcmf_fw_map_chip_to_name: using brcm/brcmfmac43430-sdio.bin for chip 0x00a9a6(43430) rev 01 brcmfmac mmc1:0001:1: Falling back to user helper brcmfmac: brcmf_c_process_clm_blob: no clm_blob available(err=-11), device maye brcmfmac: brcmf_c_preinit_dcmds: Firmware version = wl0: Oct 23 2017 03:55:53 brcmfmac: brcmf_sdio_ulp_preinit: ulp_sdioctrl iovar returned err = -23
WLAN is not present at start-up. You first have to configure the country where it will be used: (Worldwide acceptance: FCC (USA), IC (Canada), ETSI(Europe), Giteki (Japan), and RCM(AU/NZ)):
target$ vi /lib/firmware/brcm/brcmfmac43430-sdio.txt ... ccode=<country> ...
Now you are able to bring the WLAN up.
target$ ifconfig wlan0 up IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
For more information on how to set up a WLAN, go to Yocto Reference Manual Changing the wireless network configuration.
Bluetooth
Similar to the WLAN, the Bluetooth functionality is only given if the Sterling-DTB is loaded and emmc boot is active. The Bluetooth is connected with UART2 interface. More information about the module can be found at https://connectivity-staging.s3.us-east-2.amazonaws.com/2019-09/CS-DS-SterlingLWB%20v7_2.pdf. The firmware will not be selected from the Linux kernel automatically. To use Bluetooth, you have to load the firmware manually:
target$ brcm_patchram_plus -d --patchram /lib/firmware/brcm/4343w.hcd --enable_hci --no2bytes --tosleep 1000 /dev/ttymxc1 & [1] 3623 option patchram with arg /lib/firmware/brcm/4343w.hcd option enable_hci option no2bytes option tosleep with arg 1000 /dev/ttymxc1 writing 01 03 0c 00 received 7 04 0e 04 01 03 0c 00 writing 01 2e fc 00 received 7 04 0e 04 01 2e fc 00 writing 01 4c fc 46 10 18 21 00 42 52 43 4d 63 66 67 53 00 00 00 00 32 00 00 00 01 01 04 18 92 00 00 00 03 06 ac 1f 12 a1 43 43 00 01 1c 52 18 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 fe 00 00 ... received 7 04 0e 04 01 4c fc 00 writing 01 4e fc 04 ff ff ff ff received 7 04 0e 04 01 4e fc 00 writing 01 03 0c 00 received 7 04 0e 04 01 03 0c 00 Done setting line discpline target$ hciconfig hci0: Type: Primary Bus: UART BD Address: 00:25:CA:2F:39:96 ACL MTU: 1021:8 SCO MTU: 64:1 DOWN RX bytes:668 acl:0 sco:0 events:34 errors:0 TX bytes:423 acl:0 sco:0 commands:34 errors:0 target$ hciconfig hci0 up target$ hciconfig hci0: Type: Primary Bus: UART BD Address: 00:25:CA:2F:39:96 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING PSCAN RX bytes:1392 acl:0 sco:0 events:76 errors:0 TX bytes:1198 acl:0 sco:0 commands:76 errors:0 target$ hciconfig -a hci0: Type: Primary Bus: UART BD Address: 00:25:CA:2F:39:96 ACL MTU: 1021:8 SCO MTU: 64:1 UP RUNNING PSCAN RX bytes:3179 acl:8 sco:0 events:104 errors:0 TX bytes:1599 acl:8 sco:0 commands:85 errors:0 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 HV1 HV2 HV3 Link policy: RSWITCH SNIFF Link mode: SLAVE ACCEPT Name: 'phyboard-polaris-imx8m-2' Class: 0x200000 Service Classes: Audio Device Class: Miscellaneous, HCI Version: 4.1 (0x7) Revision: 0x60 LMP Version: 4.1 (0x7) Subversion: 0x2209 Manufacturer: Broadcom Corporation (15)
Now you can scan your environment for visible Bluetooth devices. Bluetooth is not visible during a default startup.
target$ hcitool scan Scanning ... XX:XX:XX:XX:XX:XX <SSID>
Visibility
To activate visibility:
target$ hciconfig hciX piscan
To disable visibility:
target$ hciconfig hciX noscan
Adapt Bluetooth Settings
Change name
target$ hciconfig hci0 name <name>
Change class
target$ hciconfig hci0 class <hexzahl>
class-of-device-bluetooth-cod-list-in-binary-and-hex
Connect
target$ bluetoothctl [bluetooth]# discoverable on Changing discoverable on succeeded [bluetooth]# pairable on Changing pairable on succeeded [bluetooth]# agent on Agent registered [bluetooth]# default-agent Default agent request successful [bluetooth]# scan on [NEW] Device XX:XX:XX:XX:XX:XX <name> [bluetooth]# connect XX:XX:XX:XX:XX:XX