i.MX Processors Knowledge Base

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

i.MX Processors Knowledge Base

Discussions

Sort by:
The solution works when I use mx53_loco bsp. Modify u-boot and kernel, keep the same. Then you may find you can't login into the system regardless of whatever you input after freescale login: It confused me for a long time. If you  also met this problem,try to check the iomux-mx53.h(linux/arch/arm/plat-mxc/include/mach/). #define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX   IOMUX_PAD(the fourth argument 0x878 should be changed to 0x0) I think this is a small bug in header files. Haifeng
View full article
Attached is the Kernel image needed to construct the Linux Image i.MX 6Dual/6Quad Power Consumption Measurement Linux Image
View full article
This guide is a continuation from our latest Debian 12 Installation Guide for iMX8MM, iMX8MP, iMX8MN and iMX93. Here we will describe the process to install the multimedia and hardware acceleration packages, specifically GPU, VPU and Gstreamer on i.MX8M Mini, i.MX8M Plus and i.MX8M Nano. The guide is based on the one provided by our colleague Build Ubuntu For i.MX8 Series Platform - NXP Community, which requires to previously build an image using Yocto Project with the following distro and image name. Distro name - fsl-imx-wayland Image name – imx-image-multimedia For more information please check our BSP documentation i.MX Yocto Project User’s Guide.   Hardware Requirements Linux Host Computer (Ubuntu 20.04 or later) USB Card reader or Micro SD to SD adapter SD Card Evaluation Kit Board for the i.MX8M Nano, i.MX8M Mini, i.MX8M Plus   Software Requirements Linux Ubuntu (20.04 tested) or Debian for Host Computer BSP version 6.1.55 built with Yocto Project   After built the image we can start the installation by following the steps below:   GPU Installation The GPU Installation consists of copy the files from packages imx-gpu-g2d, imx-gpu-viv, libdrm to the Debian system. As our latest installation guide, we will continue naming “mountpoint” to the directory where Debian system is mounted on our host machine. Regarding the path provided on each step, we put labels <build-path> and <machine> that you will need to change based on your environment. These are the paths that Yocto Project uses to save the packages. However, this could change on your environment and you can find the work directory from each package using the following command: bitbake -e <package-name> | grep ^WORKDIR= This command will show you the absolute path of the package work directory. 1. Install GPU Packages $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/imx-gpu-g2d/6.4.11.p2.2-r0/image/* mountpoint $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/imx-gpu-viv/1_6.4.11.p2.2-aarch64-r0/image/* mountpoint $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/libdrm/2.4.115.imx-r0/image/* mountpoint   2. Install Linux IMX Headers and IMX Parser $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/linux-imx-headers/6.1-r0/image/* mountpoint $ sudo cp -Pra <build-path>/tmp/work/armv8a-poky-linux/imx-parser/4.8.2-r0/image/* mountpoint   3. Use chroot $ sudo LANG=C.UTF-8 chroot mountpoint/ qemu-aarch64-static /bin/bash   4. Install Dependencies $ apt install libudev-dev libinput-dev libxkbcommon-dev libpam0g-dev libx11-xcb-dev libxcb-xfixes0-dev libxcb-composite0-dev libxcursor-dev libxcb-shape0-dev libdbus-1-dev libdbus-glib-1-dev libsystemd-dev libpixman-1-dev libcairo2-dev libffi-dev libxml2-dev kbd libexpat1-dev autoconf automake libtool meson cmake ssh net-tools network-manager iputils-ping rsyslog bash-completion htop resolvconf dialog vim udhcpc udhcpd git v4l-utils alsa-utils git gcc less autoconf autopoint libtool bison flex gtk-doc-tools libglib2.0-dev libpango1.0-dev libatk1.0-dev kmod pciutils libjpeg-dev   5. Create a folder for Multimedia Installation. Here we will clone all the multimedia repositories.  $ mkdir multimedia_packages $ cd multimedia_packages   6. Build Wayland $ git clone https://gitlab.freedesktop.org/wayland/wayland.git $ cd wayland $ git checkout 1.22.0 $ meson setup build --prefix=/usr -Ddocumentation=false -Ddtd_validation=true $ cd build $ ninja install   7. Build Wayland Protocols IMX $ git clone https://github.com/nxp-imx/wayland-protocols-imx.git $ cd wayland-protocols-imx $ git checkout wayland-protocols-imx-1.32 $ meson setup build --prefix=/usr -Dtests=false $ cd build $ ninja install   8. Build Weston $ git clone https://github.com/nxp-imx/weston-imx.git $ cd weston-imx $ git checkout weston-imx-11.0.3 $ meson setup build --prefix=/usr -Dpipewire=false -Dsimple-clients=all -Ddemo-clients=true -Ddeprecated-color-management-colord=false -Drenderer-gl=true -Dbackend-headless=false -Dimage-jpeg=true -Drenderer-g2d=true -Dbackend-drm=true -Dlauncher-libseat=false -Dcolor-management-lcms=false -Dbackend-rdp=false -Dremoting=false -Dscreenshare=true -Dshell-desktop=true -Dshell-fullscreen=true -Dshell-ivi=true -Dshell-kiosk=true -Dsystemd=true -Dlauncher-logind=true -Dbackend-drm-screencast-vaapi=false -Dbackend-wayland=false -Dimage-webp=false -Dbackend-x11=false -Dxwayland=false $ cd build $ ninja install   VPU Installation To install VPU and Gstreamer please follow the steps below: 1. Install firmware-imx $ sudo cp -Pra <build-path>/tmp/work/all-poky-linux/firmware-imx/1_8.22-r0/image/lib/* mountpoint/lib/   2. Install VPU Driver $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/imx-vpu-hantro/1.31.0-r0/image/* mountpoint $ sudo cp -Pra <build-path>/tmp/work/armv8a-<machine>-poky-linux/imx-vpuwrap/git-r0/image/* mountpoint   3. Use chroot $ sudo LANG=C.UTF-8 chroot mountpoint/ qemu-aarch64-static /bin/bash   4. Install dependencies for Gstreamer Plugins $ apt install libgirepository1.0-dev gettext liborc-0.4-dev libasound2-dev libogg-dev libtheora-dev libvorbis-dev libbz2-dev libflac-dev libgdk-pixbuf-2.0-dev libmp3lame-dev libmpg123-dev libpulse-dev libspeex-dev libtag1-dev libbluetooth-dev libusb-1.0-0-dev libcurl4-openssl-dev libssl-dev librsvg2-dev libsbc-dev libsndfile1-dev   5. Change directory to multimedia packages. $ cd multimedia-packages   6. Build gstreamer $ git clone https://github.com/nxp-imx/gstreamer -b lf-6.1.55-2.2.0 $ cd gstreamer $ meson setup build --prefix=/usr -Dintrospection=enabled -Ddoc=disabled -Dexamples=disabled -Ddbghelp=disabled -Dnls=enabled -Dbash-completion=disabled -Dcheck=enabled -Dcoretracers=disabled -Dgst_debug=true -Dlibdw=disabled -Dtests=enabled -Dtools=enabled -Dtracer_hooks=true -Dlibunwind=disabled -Dc_args=-I/usr/include/imx $ cd build $ ninja install   7. Build gst-plugins-base $ git clone https://github.com/nxp-imx/gst-plugins-base -b lf-6.1.55-2.2.0 $ cd gst-plugins-base $ meson setup build --prefix=/usr -Dalsa=enabled -Dcdparanoia=disabled -Dgl-graphene=disabled -Dgl-jpeg=disabled -Dopus=disabled -Dogg=enabled -Dorc=enabled -Dpango=enabled -Dgl-png=enabled -Dqt5=disabled -Dtheora=enabled -Dtremor=disabled -Dvorbis=enabled -Dlibvisual=disabled -Dx11=disabled -Dxvideo=disabled -Dxshm=disabled -Dc_args=-I/usr/include/imx $ cd build $ ninja install   8. Build gst-plugins-good $ git clone https://github.com/nxp-imx/gst-plugins-good -b lf-6.1.55-2.2.0 $ cd gst-plugins-good $ meson setup build --prefix=/usr -Dexamples=disabled -Dnls=enabled -Ddoc=disabled -Daalib=disabled -Ddirectsound=disabled -Ddv=disabled -Dlibcaca=disabled -Doss=enabled -Doss4=disabled -Dosxaudio=disabled -Dosxvideo=disabled -Dshout2=disabled -Dtwolame=disabled -Dwaveform=disabled -Dasm=disabled -Dbz2=enabled -Dcairo=enabled -Ddv1394=disabled -Dflac=enabled -Dgdk-pixbuf=enabled -Dgtk3=disabled -Dv4l2-gudev=enabled -Djack=disabled -Djpeg=enabled -Dlame=enabled -Dpng=enabled -Dv4l2-libv4l2=disabled -Dmpg123=enabled -Dorc=enabled -Dpulse=enabled -Dqt5=disabled -Drpicamsrc=disabled -Dsoup=enabled -Dspeex=enabled -Dtaglib=enabled -Dv4l2=enabled -Dv4l2-probe=true -Dvpx=disabled -Dwavpack=disabled -Dximagesrc=disabled -Dximagesrc-xshm=disabled -Dximagesrc-xfixes=disabled -Dximagesrc-xdamage=disabled -Dc_args=-I/usr/include/imx $ cd build $ ninja install   9. Build gst-plugins-bad $ git clone https://github.com/nxp-imx/gst-plugins-bad -b lf-6.1.55-2.2.0 $ cd gst-plugins-bad $ meson setup build --prefix=/usr -Dintrospection=enabled -Dexamples=disabled -Dnls=enabled -Dgpl=disabled -Ddoc=disabled -Daes=enabled -Dcodecalpha=enabled -Ddecklink=enabled -Ddvb=enabled -Dfbdev=enabled -Dipcpipeline=enabled -Dshm=enabled -Dtranscode=enabled -Dandroidmedia=disabled -Dapplemedia=disabled -Dasio=disabled -Dbs2b=disabled -Dchromaprint=disabled -Dd3dvideosink=disabled -Dd3d11=disabled -Ddirectsound=disabled -Ddts=disabled -Dfdkaac=disabled -Dflite=disabled -Dgme=disabled -Dgs=disabled -Dgsm=disabled -Diqa=disabled -Dkate=disabled -Dladspa=disabled -Dldac=disabled -Dlv2=disabled -Dmagicleap=disabled -Dmediafoundation=disabled -Dmicrodns=disabled -Dmpeg2enc=disabled -Dmplex=disabled -Dmusepack=disabled -Dnvcodec=disabled -Dopenexr=disabled -Dopenni2=disabled -Dopenaptx=disabled -Dopensles=disabled -Donnx=disabled -Dqroverlay=disabled -Dsoundtouch=disabled -Dspandsp=disabled -Dsvthevcenc=disabled -Dteletext=disabled -Dwasapi=disabled -Dwasapi2=disabled -Dwildmidi=disabled -Dwinks=disabled -Dwinscreencap=disabled -Dwpe=disabled -Dzxing=disabled -Daom=disabled -Dassrender=disabled -Davtp=disabled -Dbluez=enabled -Dbz2=enabled -Dclosedcaption=enabled -Dcurl=enabled -Ddash=enabled -Ddc1394=disabled -Ddirectfb=disabled -Ddtls=disabled -Dfaac=disabled -Dfaad=disabled -Dfluidsynth=disabled -Dgl=enabled -Dhls=enabled -Dkms=enabled -Dcolormanagement=disabled -Dlibde265=disabled -Dcurl-ssh2=disabled -Dmodplug=disabled -Dmsdk=disabled -Dneon=disabled -Dopenal=disabled -Dopencv=disabled -Dopenh264=disabled -Dopenjpeg=disabled -Dopenmpt=disabled -Dhls-crypto=openssl -Dopus=disabled -Dorc=enabled -Dresindvd=disabled -Drsvg=enabled -Drtmp=disabled -Dsbc=enabled -Dsctp=disabled -Dsmoothstreaming=enabled -Dsndfile=enabled -Dsrt=disabled -Dsrtp=disabled -Dtinyalsa=disabled -Dtinycompress=enabled -Dttml=enabled -Duvch264=enabled -Dv4l2codecs=disabled -Dva=disabled -Dvoaacenc=disabled -Dvoamrwbenc=disabled -Dvulkan=disabled -Dwayland=enabled -Dwebp=enabled -Dwebrtc=disabled -Dwebrtcdsp=disabled -Dx11=disabled -Dx265=disabled -Dzbar=disabled -Dc_args=-I/usr/include/imx $ cd build $ ninja install   10. Build imx-gst1.0-plugin $ git clone https://github.com/nxp-imx/imx-gst1.0-plugin -b lf-6.1.55-2.2.0 $ cd imx-gst1.0-plugin $ meson setup build --prefix=/usr -Dplatform=MX8 -Dc_args=-I/usr/include/imx $ cd build $ ninja install   11. Exit chroot $ exit   Verify Installation For verification process, boot your target from the SD Card. (Review your specific target documentation) 1. Verify Weston For this verification you will need to be root user. # export XDG_RUNTIME_DIR=/run/user/0 # weston   2. Verify VPU and Gstreamer Use the following Gstreamer pipeline for Hardware Accelerated VPU Encode. # gst-launch-1.0 videotestsrc ! video/x-raw, format=I420, width=640, height=480 ! vpuenc_h264 ! filesink location=test.mp4   Then you can reproduce the file with this command: # gplay-1.0 test.mp4   Finally, you have installed and verified the GPU, VPU and Multimedia packages. Now, you can start testing audio and video applications.
View full article
This document is about to build an image by Yocto , and it will disable a function that normal user can’t use command line of “ su ”.
View full article
P3T1755DP is a ±0.5°C accurate temperature-to-digital converter with a -40 °C to +125 °C range. It uses an on-chip band gap temperature sensor and an A-to-D conversion technique with overtemperature detection. The temperature register always stores a 12-bit two's complement data, giving a temperature resolution of 0.0625 °C P3T1755DP which can be configured for different operation conditions: continuous conversion, one-shot mode, or shutdown mode.   The device has very good features but, unfortunately, is not supported by Linux yet!   The P31755 works very similarly to LM75, pct2075, and other compatibles.   We can add support to P3T1755 in the LM75.c program due to the process to communicate with the device is the same as LM75 and equivalents.   https://github.com/nxp-imx/linux-imx/blob/lf-6.1.55-2.2.0/drivers/hwmon/lm75.c route: drivers/hwmon/lm75.c   The modifications that we have to do are the next:    1. We have to add the configurations to the kernel on the imx_v8_defconfig file CONFIG_SENSORS_ARM_SCMI=y CONFIG_SENSORS_ARM_SCPI=y CONFIG_SENSORS_FP9931=y +CONFIG_SENSORS_LM75=m +CONFIG_HWMON=y +CONFIG_I2C=y +CONFIG_REGMAP_I2C=y CONFIG_SENSORS_LM90=m CONFIG_SENSORS_PWM_FAN=m CONFIG_SENSORS_SL28CPLD=m    2. Add the part on the list of parts compatible with the driver LM75.c enum lm75_type { /* keep sorted in alphabetical order */ max6626, max31725, mcp980x, + p3t1755, pct2075, stds75, stlm75,   3. Add the configuration in the structure lm75_params device_params[]. .default_resolution = 9, .default_sample_time = MSEC_PER_SEC / 18, }, + [p3t1755] = { + .default_resolution = 12, + .default_sample_time = MSEC_PER_SEC / 10, + }, [pct2075] = { .default_resolution = 11, .default_sample_time = MSEC_PER_SEC / 10,   Notes: You can change the configuration of the device using .set_mask and .clear_mask, see more details on LM75.c lines 57 to 78   4. Add the ID to the list in the structure i2c_device_id lm75_ids and of_device_id __maybe_unused lm75_of_match    { "max31725", max31725, }, { "max31726", max31725, }, { "mcp980x", mcp980x, }, + { "p3t1755", p3t1755, }, { "pct2075", pct2075, }, { "stds75", stds75, }, { "stlm75", stlm75, },   + { + .compatible = "nxp,p3t1755", + .data = (void *)p3t1755 + },   5. In addition to all modifications, I modify the device tree of my iMX8MP-EVK to connect the Sensor in I2C3 of the board.  https://github.com/nxp-imx/linux-imx/blob/lf-6.1.55-2.2.0/arch/arm64/boot/dts/freescale/imx8mp-evk.dts   }; }; + + p3t1755: p3t1755@48 { + compatible = "nxp,p3t1755"; + reg = <0x48>; + }; + };   Connections: We will use the expansion connector of the iMX8MP-EVK and J9 of the P3T1755DP-ARD board.   P3T1755DP-ARD board   iMX8MP-EVK   P3T1755DP-ARD ----> iMX8MP-EVK J9              ---------->            J21 +3v3 (Pin 9) ---> +3v3 (Pin 1) GND(Pin 7) ---> GND (PIN 9) SCL (Pin 4) ---> SCL (Pin 5) SDA (Pin 3) ---> SDA (Pin 3)     Reading the Sensor We can read the sensor using the next commands:   Read Temperature: $ cat /sys/class/hwmon/hwmon1/temp1_input Reading maximum temperature: $ cat /sys/class/hwmon/hwmon1/temp1_max Reading hysteresis: $ cat /sys/class/hwmon/hwmon1/temp1_max_hyst   https://www.nxp.com/design/design-center/development-boards-and-designs/analog-toolbox/arduino-shields-solutions/p3t1755dp-arduino-shield-evaluation-board:P3T1755DP-ARD    
View full article
Sometime need standalone compile device tree. Only Linux headers and device tree directory are needed.         
View full article
  Some customer need to config different I2C bus for their PMIC in DDR test period. There is a simple method can complete this, that is NXP DDR Config Tool. The tool download link is below: https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/config-tools-for-i-mx-applications-processors:CONFIG-TOOLS-IMX I'm going to use the i.MX 93 EVK board here as a demonstration. On i.MX 93 EVK board, the default PMIC I2C Bus is I2C2, I will show you how to change I2C2 to I2C1, the other i2c bus is same.  Step 1 : Rework the board and make sure the PMIC is connected to I2C1. Remove R714 R715, connnect I2C1_SCL(C20) to U701 pin 41  and I2C1_SDA(C21) tp U701 pin 42. Step 2 : Setup I2C1 PinMux: Config Tool UI:   Advance -> IOMUX config   Command:           Address                Size               Value memory   set     0x443c0170            32                   0x10 memory   set     0x443c0174            32                   0x10 memory   set     0x443c0320            32                   0x40000b9e memory   set     0x443c0324            32                   0x40000b9e Step 3 : Set PMIC VDDQ as 1.1 V Config Tool UI:   Advance -> Custom PMIC initialization enabled   #  PMIC commands        Value 0         pmic_cfg             0x0025       /*I2C bus 1,  PMIC address 0x25 */ (0 for I2C1, 1 for I2C2, 2 for I2C3, 3 for I2c4 …) 1         pmic_set             0x0C29       /* BUCKxOUT_DVS0/1, preset_buck1=0.8V, preset_buck2=0.7V, preset_buck3=0.8V PCA9451_BUCK123_DVS, 0x29 */ 2         pmic_set             0x1118      /*  BUCK1OUT_DVS0=0.9V   PCA9451_BUCK1OUT_DVS0, 0x18 */ 3         pmic_set             0x1718      /*  BUCK3OUT_DVS0=0.9V   PCA9451_BUCK3OUT_DVS0, 0x18 */ 4         pmic_set             0x1428      /*  Set VDDQ to 1.1V  PCA9451_BUCK2OUT_DVS0, 0x28  */ PS : About pmic register, The first two bytes are the register address and the next two bytes are the register setting. Step 4 : Run the DDR "Firmware init test" and see the test result. The success log is as follows: DEBUG memtool.comm.serial_channel ==================hardware_init======================= DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel Power up ddr... DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel DDRMIX power on done... DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel DDRPHY coldreset... DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel ********Found PMIC PCA945X********** DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel Set VDDQ to 1.1V for LPDDR4 DEBUG memtool.comm.serial_channel DEBUG memtool.comm.serial_channel ==================hardware_init exit==================    
View full article
Attached is a chunk of the filesystem for the Linux Image https://community.freescale.com/docs/DOC-93887
View full article
One chunk of the file system for the Linux Image i.MX 6Dual/6Quad Power Consumption Measurement Linux Image
View full article
Attached is a chunk of the filesystem for the Linux Image https://community.freescale.com/docs/DOC-93887
View full article
Attached is a chunk of the filesystem for the Linux Image https://community.freescale.com/docs/DOC-93887
View full article
  Some customers want to expose their i3c device on the /dev, In order to develop their i3c APP or operation the i3c device like I2C. But in our default BSP code, we do not support this feature for I3C device, This article will introduce how to make the i3c device expose to the user space. Board : i.MX 93 EVK BSP Version : lf-6.1.55-2.2.0 I3C device : LSM6DSOXTR Step 1 : Rework the i.MX93 EVK Board, Install the R1010.      Step 2 : Apply the add_i3c_device_to_dev.patch file to the linux kernel code              Command : git apply add_i3c_device_to_dev.patch Step 3 : Re-compile the kernel Image file.              Command : make imx_v8_defconfig                                  make Step 4 : Boot your board with "imx93-11x11-evk-i3c.dtb" file and see if you can see the I3C device on the /dev directory. Result : We can see the i3c device is appeared in /dev directory, The i2c-8 is an i2c device mounted to the i3c bus. The i3c is backward compatible with i2c device. It will simulate the I2C signal loading i2c device.                 PS : You can also use the i2ctool detect i2c-8 device. As shown in the following picture:   Note : If you need the patch file, Please contact me any time for free.
View full article
-- DTS for gpio wakeup   // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /*  * Copyright 2022 NXP  */   #include "imx93-11x11-evk.dts"   / {         gpio-keys {                 compatible = "gpio-keys";                 pinctrl-names = "default";                 pinctrl-0 = <&pinctrl_gpio_keys>;                   power {                   label = "GPIO Key Power";                   linux,code = <KEY_POWER>;                   gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;                   wakeup-source;                   debounce-interval = <20>;                   interrupt-parent = <&gpio2>;                   interrupts = <7 IRQ_TYPE_LEVEL_LOW>;                 };         }; };   &iomuxc {         pinctrl_gpio_keys: gpio_keys_grp {                 fsl,pins = <                         MX93_PAD_GPIO_IO07__GPIO2_IO07  0x31e                 >;         }; }; -- testing the switch GPIO  First check if your gpio dts configuration to make it act as a switch works or not After executing the command - 'evtest /dev/input/event1' Trigger an interrupt by connecting GPIO2 7 to GND, as soon as you do that, you will receive Event logs such as below:- This shows that your dts configuration for GPIO works.     -- Verify the interrupt         -- Go to sleep and then connect the GPIO to GND to trigger a wakeup, in the logs we see that kernel exits the suspend mode    
View full article
Introduction Time Synchronization stands for the alignment of time within distributed nodes, pretty critical for real-time applications, control and measurement systems as voice and video networks; all of them being embedded applications. It needs the synchronization of frequency, phase and time between all the nodes and offers action coordination, high precision triggers and event reference or timestamping. [1] A Time Synchronization resource it's the ethernet standard for time PTP or IEEE 1588 standard, its study begin with the physical representation of time information: PPS; Pulse Per Second. An squared wave timed by the capable MACs, in i.MX families we have two MACs of which. Background Customers are interested in this signal, we have an i.MX 8M Plus kernel 5 resource but there is a new processor family using the next major kernel version; 6. [2] We will go through demonstrating PPS on i.MX 93 EVK in both MACs; FEC and EQOS. HW setup i.MX 93 EVK boot over eMMC. Connect power and debug receptacles. Hands-on for FEC or eth0 MAC uSDHC2 pin group conflicts with the pps output pin and you are ought to remove the uSDHC2 nodes and assign the event0 out pin to the FEC pin group as shown below. --- imx93-11x11-evk.dts 2024-08-23 18:19:56.344798901 +0200 +++ imx93-11x11-evk-pps.dts 2024-09-02 21:31:46.569477421 +0200 @@ -100,18 +100,6 @@ regulator-max-microvolt = <1800000>; }; - reg_usdhc2_vmmc: regulator-usdhc2 { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; - regulator-name = "VSD_3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; - off-on-delay-us = <12000>; - enable-active-high; - }; - reg_vdd_12v: regulator-vdd-12v { compatible = "regulator-fixed"; regulator-name = "reg_vdd_12v"; @@ -770,21 +766,6 @@ status = "okay"; }; -&usdhc2 { - pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; - pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; - pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>; - cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; - fsl,cd-gpio-wakeup-disable; - vmmc-supply = <&reg_usdhc2_vmmc>; - bus-width = <4>; - status = "okay"; - no-sdio; - no-mmc; -}; - &usdhc3 { pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>; @@ -860,14 +842,15 @@ MX93_PAD_ENET2_RD1__ENET1_RGMII_RD1 0x57e MX93_PAD_ENET2_RD2__ENET1_RGMII_RD2 0x57e MX93_PAD_ENET2_RD3__ENET1_RGMII_RD3 0x57e MX93_PAD_ENET2_RXC__ENET1_RGMII_RXC 0x58e MX93_PAD_ENET2_RX_CTL__ENET1_RGMII_RX_CTL 0x57e MX93_PAD_ENET2_TD0__ENET1_RGMII_TD0 0x57e MX93_PAD_ENET2_TD1__ENET1_RGMII_TD1 0x57e MX93_PAD_ENET2_TD2__ENET1_RGMII_TD2 0x57e MX93_PAD_ENET2_TD3__ENET1_RGMII_TD3 0x57e MX93_PAD_ENET2_TXC__ENET1_RGMII_TXC 0x58e MX93_PAD_ENET2_TX_CTL__ENET1_RGMII_TX_CTL 0x57e + MX93_PAD_SD2_DATA0__ENET1_1588_EVENT0_OUT 0x31e >; }; @@ -887,6 +870,7 @@ MX93_PAD_ENET2_TD3__GPIO4_IO16 0x51e MX93_PAD_ENET2_TXC__GPIO4_IO21 0x51e MX93_PAD_ENET2_TX_CTL__GPIO4_IO20 0x51e + MX93_PAD_SD2_DATA0__GPIO3_IO03 0x31e >; }; @@ -998,75 +982,6 @@ >; }; - pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { - fsl,pins = < - MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e - >; - }; - - pinctrl_usdhc2_gpio: usdhc2gpiogrp { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e - >; - }; - - pinctrl_usdhc2_gpio_sleep: usdhc2gpiogrpsleep { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 - MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe - MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - pinctrl_usdhc2_sleep: usdhc2grpsleep { - fsl,pins = < - MX93_PAD_SD2_CLK__GPIO3_IO01 0x51e - MX93_PAD_SD2_CMD__GPIO3_IO02 0x51e - MX93_PAD_SD2_DATA0__GPIO3_IO03 0x51e - MX93_PAD_SD2_DATA1__GPIO3_IO04 0x51e - MX93_PAD_SD2_DATA2__GPIO3_IO05 0x51e - MX93_PAD_SD2_DATA3__GPIO3_IO06 0x51e - MX93_PAD_SD2_VSELECT__GPIO3_IO19 0x51e - >; - }; - /* need to config the SION for data and cmd pad, refer to ERR052021 */ pinctrl_usdhc3: usdhc3grp { fsl,pins = < The driver also needs the following rework. --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -184,7 +184,8 @@ static int fec_ptp_enable_pps(struct fec_enet_private *fep, uint enable) val |= (1 << FEC_T_TF_OFFSET | 1 << FEC_T_TIE_OFFSET); val &= ~(1 << FEC_T_TDRE_OFFSET); val &= ~(FEC_T_TMODE_MASK); - val |= (FEC_HIGH_PULSE << FEC_T_TMODE_OFFSET); + // val |= (FEC_HIGH_PULSE << FEC_T_TMODE_OFFSET); + val |= (FEC_TMODE_TOGGLE << FEC_T_TMODE_OFFSET); writel(val, fep->hwp + FEC_TCSR(fep->pps_channel)); /* Write the second compare event timestamp and calculate After booting the board, run these commands: $ ptp4l -A -4 -H -m -i eth0 & $ echo 1 > /sys/class/ptp/ptp0/pps_enable These will get the SD2_DATA0 or TP1009 running a square wave at 0.5 Hz through setting the ptp0 port with: -A    Select the delay mechanism automatically. Start with E2E and switch to P2P when a peer delay request is received. -4    Select the UDP IPv4 network transport. This is the default transport. -H    Select the hardware time stamping. -m    Print messages to the standard output. Run the next command to set the pps (1 Hz signal): $ echo "0 $(date +%s) 100000000 1 0" > /sys/class/ptp/ptp0/period The last because the current driver needs the actual date and a future start; in this case the signal will start within 100 ms, in order to work. You can try with different start times until the optimal value is found. [3]   Hands-on for EQOS or eth1 MAC This is reduced to the proper devicetree changes, and it does not have driver rework nor pps_enable control file. It uses SD2_CLK or TP1008, so DTS need this adjustment: --- imx93-11x11-evk.dts 2024-08-23 18:19:56.344798901 +0200 +++ imx93-11x11-evk-pps.dts 2024-09-02 21:31:46.569477421 +0200 @@ -100,18 +100,6 @@ regulator-max-microvolt = <1800000>; }; - reg_usdhc2_vmmc: regulator-usdhc2 { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>; - regulator-name = "VSD_3V3"; - regulator-min-microvolt = <3300000>; - regulator-max-microvolt = <3300000>; - gpio = <&gpio3 7 GPIO_ACTIVE_HIGH>; - off-on-delay-us = <12000>; - enable-active-high; - }; - reg_vdd_12v: regulator-vdd-12v { compatible = "regulator-fixed"; regulator-name = "reg_vdd_12v"; @@ -770,21 +766,6 @@ status = "okay"; }; -&usdhc2 { - pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; - pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; - pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; - pinctrl-3 = <&pinctrl_usdhc2_sleep>, <&pinctrl_usdhc2_gpio_sleep>; - cd-gpios = <&gpio3 00 GPIO_ACTIVE_LOW>; - fsl,cd-gpio-wakeup-disable; - vmmc-supply = <&reg_usdhc2_vmmc>; - bus-width = <4>; - status = "okay"; - no-sdio; - no-mmc; -}; - &usdhc3 { pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep"; pinctrl-0 = <&pinctrl_usdhc3>, <&pinctrl_usdhc3_wlan>; @@ -822,14 +802,15 @@ MX93_PAD_ENET1_RD1__ENET_QOS_RGMII_RD1 0x57e MX93_PAD_ENET1_RD2__ENET_QOS_RGMII_RD2 0x57e MX93_PAD_ENET1_RD3__ENET_QOS_RGMII_RD3 0x57e MX93_PAD_ENET1_RXC__CCM_ENET_QOS_CLOCK_GENERATE_RX_CLK 0x58e MX93_PAD_ENET1_RX_CTL__ENET_QOS_RGMII_RX_CTL 0x57e MX93_PAD_ENET1_TD0__ENET_QOS_RGMII_TD0 0x57e MX93_PAD_ENET1_TD1__ENET_QOS_RGMII_TD1 0x57e MX93_PAD_ENET1_TD2__ENET_QOS_RGMII_TD2 0x57e MX93_PAD_ENET1_TD3__ENET_QOS_RGMII_TD3 0x57e MX93_PAD_ENET1_TXC__CCM_ENET_QOS_CLOCK_GENERATE_TX_CLK 0x58e MX93_PAD_ENET1_TX_CTL__ENET_QOS_RGMII_TX_CTL 0x57e + MX93_PAD_SD2_CLK__ENET_QOS_1588_EVENT0_OUT 0x31e >; }; @@ -849,6 +830,7 @@ MX93_PAD_ENET1_TD3__GPIO4_IO02 0x31e MX93_PAD_ENET1_TXC__GPIO4_IO07 0x31e MX93_PAD_ENET1_TX_CTL__GPIO4_IO06 0x31e + MX93_PAD_SD2_CLK__GPIO3_IO01 0x31e >; }; @@ -998,75 +982,6 @@ >; }; - pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp { - fsl,pins = < - MX93_PAD_SD2_RESET_B__GPIO3_IO07 0x31e - >; - }; - - pinctrl_usdhc2_gpio: usdhc2gpiogrp { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x31e - >; - }; - - pinctrl_usdhc2_gpio_sleep: usdhc2gpiogrpsleep { - fsl,pins = < - MX93_PAD_SD2_CD_B__GPIO3_IO00 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2: usdhc2grp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x1582 - MX93_PAD_SD2_CMD__USDHC2_CMD 0x40001382 - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x40001382 - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x40001382 - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x40001382 - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x40001382 - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x158e - MX93_PAD_SD2_CMD__USDHC2_CMD 0x4000138e - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x4000138e - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x4000138e - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x4000138e - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x4000138e - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - /* need to config the SION for data and cmd pad, refer to ERR052021 */ - pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp { - fsl,pins = < - MX93_PAD_SD2_CLK__USDHC2_CLK 0x15fe - MX93_PAD_SD2_CMD__USDHC2_CMD 0x400013fe - MX93_PAD_SD2_DATA0__USDHC2_DATA0 0x400013fe - MX93_PAD_SD2_DATA1__USDHC2_DATA1 0x400013fe - MX93_PAD_SD2_DATA2__USDHC2_DATA2 0x400013fe - MX93_PAD_SD2_DATA3__USDHC2_DATA3 0x400013fe - MX93_PAD_SD2_VSELECT__USDHC2_VSELECT 0x51e - >; - }; - - pinctrl_usdhc2_sleep: usdhc2grpsleep { - fsl,pins = < - MX93_PAD_SD2_CLK__GPIO3_IO01 0x51e - MX93_PAD_SD2_CMD__GPIO3_IO02 0x51e - MX93_PAD_SD2_DATA0__GPIO3_IO03 0x51e - MX93_PAD_SD2_DATA1__GPIO3_IO04 0x51e - MX93_PAD_SD2_DATA2__GPIO3_IO05 0x51e - MX93_PAD_SD2_DATA3__GPIO3_IO06 0x51e - MX93_PAD_SD2_VSELECT__GPIO3_IO19 0x51e - >; - }; - /* need to config the SION for data and cmd pad, refer to ERR052021 */ pinctrl_usdhc3: usdhc3grp { fsl,pins = < After boot, issue these commands: $ ptp4l -A -4 -H -m -i eth1 & $ echo "0 $(date +%s) 1000000000 1 0" > /sys/class/ptp/ptp1/period You will have an squared wave of 1 Hz running within 1 s with the same settings as the FEC setup.   Conclusion Both PPS can run in the same image changes and DTS changes, proven in imx-linux-nanbield branch, with the manifest imx-6.6.3-1.0.0.xml. And it's the start of testing IEEE 1588 and syncing capabilities of this i.MX 9 series processors. Sources [1] http://events17.linuxfoundation.org/sites/events/files/slides/elc_insop_2015.pdf [2] https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8-serials-IEEE1588-1pps-test-procedure/ta-p/1490634 [3] https://github.com/nxp-imx/linux-imx/blob/b586a521770e508d1d440ccb085c7696b9d6d387/Documentation/ABI/testing/sysfs-ptp#L2
View full article
Ftrace is powerful tracing utility embedded in Linux kernel. It provides a very good method for kernel developer to get insights of the kernel behavior. While official kernel doc for ftrace is somehow long and complex, this document provides a quicker and simpler way to get start with ftrace.
View full article
Hello, here Jorge. On this post I will explain how to enable MQS1 on i.MX8ULP. As background about how to setup the environment to build the image using Yocto, please take a look on our i.MX Yocto Project User's Guide: Requirements: i.MX 8ULP EVK. Serial console emulator (Tera Term, Putty, etc.). USB Type-C cable. Micro USB cable. Headphones/speakers. Linux PC. Build done in Linux 6.6.23_2.0.0. i.MX8ULP audio subsystem. i.MX 8ULP extends audio capabilities on i.MX 7ULP by adding dedicated DSP cores for voice trigger and audio processing, enabling lower latency and power efficiency to support variety of audio applications. Some of hardware blocks implemented on 8ULP to support audio use cases are the next: Cadence Fusion F1 DSP processor. Cadence HiFi4 DSP processor. PowerQuad hardware accelerator with fixed and floating + FFT. Digital Microphone interface with support of up-to 8 PDM channels. Up-to 8 independent SAI instances. Up-to 2 Medium Quality Sound (MQS). Sony/Philips Digital interface (SPDIF). As is described before, MQS0 and MQS1 are part of real time domain and application domain respectively. I’m going to focus this post on how to enable MQS1 on application domain. Medium Quality Sound (MQS)  This module is basically generates a PWM from PCM audio data. For the major part of typical audio applications will require an external CODEC to deliver the audio quality but, sometimes where the application does not demand this quality, MQS can provide a medium quality audio via GPIO pin that can directly drive the audio output to a speaker or headphone via inexpensive external amplifier/buffer instead of CODEC. The design of the MQS can be described as follows: Input the PCM audio data (from SAI) into a 16-bit register. Up-sample data to match PWM switching frequency. Perform a simple 2nd order Sigma-Delta smooth on the current data versus previous data. Convert the PCM register into a 6-bit PWM width register and output through a GPIO pin.   How to enable it? By default, our BSP does not enable clock for MQS1. This clock is controlled on CGC1 (AD), specifically on MQS1CLK (Multiplexer to select the audio clock connected to the MQS clock input). So, it is needed to modify imx8ulp-clock.h and clk-imx8ulp.c. Please take a look on patch attached at the end of this post to see the modification in drivers easily. These drivers have the definition/configuration for MQS1_SEL in CGC1 and needs to be added as follows: MQS1_SEL definition needs to bed added in imx8ulp-clock.h: #define IMX8ULP_CLK_MQS1_SEL 56 #define IMX8ULP_CLK_CGC1_END 57 MQS1_SEL configuration needs to be added in imx8ulp_clk_cgc1_init of clk-imx8ulp.c: clks[IMX8ULP_CLK_MQS1_SEL] = imx_clk_hw_mux2("mqs1_sel", base + 0x90c, 0, 2, sai45_sels, ARRAY_SIZE(sai45_sels)); Also, it is necessary to configure MQS1 on device tree of i.MX8ULP. Add this in soc: soc@0 of imx8ulp.dtsi: mqs1: mqs@0x29290064 { reg = <0x29290064 0x4>; compatible = "fsl,imx8qm-mqs"; assigned-clocks = <&cgc1 IMX8ULP_CLK_MQS1_SEL>; assigned-clock-parents = <&cgc1 IMX8ULP_CLK_SPLL3_PFD1_DIV1>; clocks = <&cgc1 IMX8ULP_CLK_MQS1_SEL>, <&cgc1 IMX8ULP_CLK_MQS1_SEL>; clock-names = "core", "mclk"; status = "disabled"; }; And create a new device tree, in this case is going to be named imx8ulp-evk-mqs.dts and is as follows: #include "imx8ulp-evk.dts" / { sound-simple-mqs { compatible = "simple-audio-card"; simple-audio-card,name = "imx-simple-mqs"; simple-audio-card,frame-master = <&sndcpu>; simple-audio-card,bitclock-master = <&sndcpu>; simple-audio-card,dai-link@0 { format = "left_j"; sndcpu: cpu { sound-dai = <&sai4>; }; codec { sound-dai = <&mqs1>; }; }; }; }; &cgc1 { assigned-clock-rates = <24576000>; }; &iomuxc1 { pinctrl_mqs1: mqs1grp { fsl,pins = < MX8ULP_PAD_PTF7__MQS1_LEFT 0x43 >; }; }; &mqs1 { #sound-dai-cells = <0>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mqs1>; status = "okay"; }; &sai4 { #sound-dai-cells = <0>; assigned-clocks = <&cgc1 IMX8ULP_CLK_SAI4_SEL>; assigned-clock-parents = <&cgc1 IMX8ULP_CLK_SPLL3_PFD1_DIV1>; status = "okay"; }; Let’s apply these changes on our BSP, in my case I’m going to create a new layer in Yocto to add these modifications with a patch that can be found at the end on this post, here the steps: Install essential Yocto Project host packages: $ sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 python3-subunit zstd liblz4-tool file locales libacl1 Install the “repo” utility: $ mkdir ~/bin $ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo $ chmod a+x ~/bin/repo $ export PATH=~/bin:$PATH Set up Git: $ git config --global user.name "Your Name" $ git config --global user.email "Your Email" $ git config –list Download the i.MX Yocto Project Community BSP recipe layers and create build folder: $ mkdir imx-yocto-bsp $ cd imx-yocto-bsp $ repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-scarthgap -m imx-6.6.23-2.0.0.xml $ repo sync $ DISTRO=fsl-imx-wayland MACHINE=imx8ulp-lpddr4-evk source imx-setup-release.sh -b 8ulp_build Create the new layer: $ cd ~/imx-yocto-bsp/sources $ bibake-layers create-layer meta-mqs $ cd meta-mqs conf/layer.conf should be as follows: BBPATH .= ":${LAYERDIR}" BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend" BBFILE_COLLECTIONS += "meta-mqs" BBFILE_PATTERN_meta-mqs = "^${LAYERDIR}/" BBFILE_PRIORITY_meta-mqs = "6" LAYERSERIES_COMPAT_meta-mqs = "nanbield" Let’s change the recipe: $ sudo rm -r recipes-example $ mkdir -p recipes-kernel/linux/files 0001-8ULP-MQS-Enable.patch should be copied to ~/imx-yocto-bsp/sources/meta-mqs/recipes-kernel/linux/files Add an append (on this case is called “linux-imx_%.bbappend”)to change the recipe with next content: FILESEXTRAPATHS:prepend := "${THISDIR}/files:" SRC_URI += "file:// 0001-8ULP-MQS-Enable.patch " addtask copy_dts after do_unpack before do_prepare_recipe_sysroot do_copy_dts () { if [ -n "${DTS_FILE}" ]; then if [ -f ${DTS_FILE} ]; then echo "do_copy_dts: copying ${DTS_FILE} in ${S}/arch/arm64/boot/dts/freescale" cp ${DTS_FILE} ${S}/arch/arm64/boot/dts/freescale/ fi fi } The next step is add the layer and build the image: $ cd ~/imx-yocto-bsp/8ulp_build $ bitbake-layers add-layer ~/imx-yocto-bsp/sources/meta-mqs Confirm that the layer has been added: $ bitbake-layers show-layers Build the image: $ bitbake imx-image-multimedia i.MX8ULP EVK limitations The i.MX8ULP has the next MQS1 pins available: But, in the EVK board, the mayor part of these pins are used for other functions such as: - Push button: - MIPI DSI:  - Etc… So, take the output signal of MQS1 pins of EVK board is difficult, in this article, I’m going to configure PTF7 only (MQS1_left) for practicality. If you are working with this board and you need to use these pins for MQS function you will need to manipulate the traces and take the required signals. If you are designing a custom board, planning is essential to avoid this issue. Flash the board. One the build has been finished, we will have the necessary files to flash the board and test it. If you are not too familiarized with this process I suggest you take a look on this post. First, put the board in serial download mode changing the boot configuration switches on the board:   The next step is connecting the power cable, micro-USB cable on the debug port and USB-C type cable to USB0 connector on the board. Then, turn-on the board and run the next command in terminal of build directory: uuu -b emmc_all imx-boot-imx8ulpevk-sd.bin-flash_singleboot_m33 imx-image-multimedia-imx8ulpevk.wic Now, power-off the board, change the boot mode to single boot-eMMC and power it on to test it. Test MQS1 in i.MX8ULP. To test MQS1 it is needed to change the device tree we created, we can do it with the next commands in U-boot: u-boot=> setenv fdtfile imx8ulp-evk-mqs.dtb u-boot=> saveenv u-boot=> boot Now we can test MQS1 on i.MX8ULP EVK, let's confirm that the clock is active in MQS module with the next command: $ cat /sys/kernel/debug/clk/clk_summary -n As you can see mqs1_sel is active and running at 24576000 Hz: And the card appears if we run the next command: $ aplay -l To play audio through MQS we can do it as any sound card: $ speaker-test -D sysdefault:CARD=imxsimplemqs -c 2 -f 48000 -F S16_LE -t pink -P 3 The signal should look like this in the pin output: And like this after a filter, for example the filter used in i.MX93 EVK.   With this post we have been able check the general operation of MQS, configure and compile the image with the required changes to enable MQS1 on EVK board and measure the output on the board. There is a considerable limitation on EVK board since we cannot test left and right outputs without intervene the base board, but this can be helpful as a reference to who would like to use this audio output on i.MX8ULP processor. Best regards. References. Yocto Project customization guide - NXP Community How to add a new layer and a new recipe in Yocto - NXP Community Flashing Linux BSP using UUU - NXP.  i.MX8ULP reference manual. Embedded Linux Projects Using Yocto Project Cookbook.
View full article
Hello, on this post I will explain how to record separated audio channels using an 8MIC-RPI-MX8 Board. As background about how to setup the board to record and play audio using i.MX boards, I suggest you take a look on the next post: How to configure, record and play audio using an 8MIC-RPI-MX8 Board. Requirements: I.MX 8M Mini EVK. Linux Binary Demo Files - i.MX 8MMini EVK. 8MIC-RPI-MX8 Board. Serial console emulator (Tera Term, Putty, etc.). Headphones/speakers. Waveform Audio Format WAV, known for WAVE (Waveform Audio File Format), is a subset of Microsoft’s Resource Interchange File Format (RIFF) specification for storing digital audio files. This format does not apply compression to the information and stores the audio with different sampling rates and bitrates. WAV files are larger in size compared to other formats such as MP3 which uses compression to reduce the file size while maintaining a good audio quality but, there is always some lose on quality since audio information is too random to be compressed with conventional methods, the main advantage of this format is provide an audio file without losses that is also widely used on studio. This files starts with a file header with data chunks. A WAV file consists of two sub-chunks: fmt chunk: data format. data chunk: sample data. So, is structured by a metadata that is called WAV file header and the actual audio information. The header of a WAV (RIFF) file is 44 bytes long and has the following format: How to separate the channels? To separate each audio channel from the recording we need to use the next command that will record raw data of each channel. arecord -D plughw:<audio device> -c<number of chanels> -f <format> -r <sample rate> -d <duration of the recording> --separate-channels <output file name>.wav arecord -D plughw:2,0 -c8 -f s16_le -r 48000 -d 10 --separate-channels sample.wav This command will output raw data of recorded channels as is showed below. This raw data cannot be used as a “normal” .wav file because the header information is missing. It is possible to confirm it if import raw data to a DAW and play recorded samples: So, to use this information we need to create the header for each file using WAVE library on python. Here the script that I used: import wave import os name = input("Enter the name of the audio file: ") os.system("arecord -D plughw:2,0 -c8 -f s16_le -r 48000 -d 10 --separate-channels " + name + ".wav") for i in range (0,8): with open(name + ".wav." + str(i), "rb") as in_file: data = in_file.read() with wave.open(name + "_channel_" + str(i) +".wav", "wb") as out_file: out_file.setnchannels(1) out_file.setsampwidth(2) out_file.setframerate(48000) out_file.writeframesraw(data) os.system("mkdir output_files") os.system("mv " + name + "_channel_" + "* " + "output_files") os.system("rm " + name + ".wav.*") If we run the script, will generate a directory with the eight audio channels in .wav format. Now, we will be able to play each channel individually using an audio player. References IBM, Microsoft Corporation. (1991). Multimedia Programming Interface and Data Specifications 1.0. Microsoft Corporation. (1994). New Multimedia Data Types and Data Techniques. Standford University. (2024, January 30). Retrieved from WAVE PCM sound file format: http://hummer.stanford.edu/sig/doc/classes/SoundHeader/WaveFormat/
View full article
P3T1755 Demo   In this space I want to show you the things that you can create usign our products.   In  this demo I demostrate a use case creating a GUI for a Temperature Sensor.   We can create modern GUIs and more with LVGL combined with our powerful processors.               CPU USAGE As we can see  the CPU usage for this demo is around 2%   Pictures         This demo is based on the previous publused articles.   References: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/Adding-support-to-P3T1755-on-Linux/ta-p/1855874 https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/How-to-run-LGVL-on-iMX-using-framebuffer/ta-p/1853768  
View full article
The Gui-guilder doesn't provide remote debug function in IDE and we still need use Yocto to build project or copy binary to board rootfs. This knowledge base will provide a solution about how to use VSCode to remote debug LVGL project on i.MX93 EVK board.    Yocto toolchain: L6.6.x GUI GUILDER: v1.8.0   Need to open GUI GUILDER project in VSCode.   1.Scripts in VScode   1.1 build.sh Modify build.sh in <LVGL project>/ports/linux     #!/bin/sh toolchain=$1 if [ -z "$toolchain" ];then toolchain=/opt/fsl-imx-xwayland/6.1-mickledore/sysroots/x86_64-pokysdk-linux/usr/share/cmake/armv8a-poky-linux-toolchain.cmake if [ ! -r $toolchain ];then toolchain=/opt/fsl-imx-xwayland/6.1-langdale/sysroots/x86_64-pokysdk-linux/usr/share/cmake/armv8a-poky-linux-toolchain.cmake fi fi toolchain_path=$(echo $toolchain |sed -E 's,^(.*)/sysroots/.*,\1,') toolchain_arch=armv8a-poky-linux if [ ! -r $toolchain -o ! -r "$toolchain_path/environment-setup-$toolchain_arch" ];then echo "ERROR: Yocto Toolchain not installed?" exit 1 fi if [ -n "$BASH_SOURCE" ]; then ROOTDIR="`readlink -f $BASH_SOURCE | xargs dirname`" elif [ -n "$ZSH_NAME" ]; then ROOTDIR="`readlink -f $0 | xargs dirname`" else ROOTDIR="`readlink -f $PWD | xargs dirname`" fi BUILDDIR=$ROOTDIR/../build rm -fr $BUILDDIR mkdir $BUILDDIR . "$toolchain_path/environment-setup-$toolchain_arch" echo "start build..." cd $ROOTDIR/linux/lv_drivers/wayland/ cmake . make cd $BUILDDIR toolchain_path=/opt/fsl-imx-wayland/6.6-scarthgap/sysroots/x86_64-pokysdk-linux/usr/share/cmake/armv8a-poky-linux-toolchain.cmake cmake -G 'Ninja' .. -DCMAKE_TOOLCHAIN_FILE=$toolchain_path -Wno-dev -DLV_CONF_BUILD_DISABLE_EXAMPLES=1 -DLV_CONF_BUILD_DISABLE_DEMOS=1 -DCMAKE_CXX_FLAGS="-ggd3 -O0" -DCMAKE_BUILD_TYPE=Debug ninja if [ -e gui_guider ];then echo "Binary locates at $(readlink -f gui_guider)" ls -lh gui_guider fi # Copy binary to board scp $BUILDDIR/gui_guider root@192.168.31.243:/opt     1.2 tasks.json     { "version": "2.0.0", "tasks": [ { "label": "Build", "type": "shell", "command": "./build.sh /opt/fsl-imx-wayland/6.6-scarthgap", "options": { "cwd": "${workspaceFolder}/ports/linux" }, "problemMatcher": [ "$gcc" ], } ] }       1.3 launch.json   miDebuggerServerAddress is board ip address.     { "version": "0.2.0", "configurations": [ { "name": "(gdb) Launch", "preLaunchTask": "Build", "type": "cppdbg", "request": "launch", "program": "${workspaceFolder}/build/gui_guider", "args": [], "stopAtEntry": false, "cwd": "${workspaceFolder}/", "environment": [], "externalConsole": false, "MIMode": "gdb", "logging": { "engineLogging": true, "trace": true, "traceResponse": true }, "debugStdLib":true, "miDebuggerPath":"/usr/bin/gdb-multiarch", //DO NOT USE GDB IN SDK!!!! "miDebuggerServerAddress": "192.168.31.243:12345", "setupCommands": [ { "description": "Enable pretty-printing for gdb", "text": "-enable-pretty-printing", "ignoreFailures": true, "text": "set remotetimeout 100", } ] }] }       2. Launch gdbserver on board     export SHELL=/opt/gui_guider gdbserver 192.168.31.243:12345 /opt/gui_guider       3. Debug in VSCode   Click (gdb)launch, the source code will be compiled. Then you will see the breakpoint in program. Enjoy your debug~    
View full article
  This guide assumes that the developer has knowledge of the V4L2 API and has worked or is familiar with sensor drivers and their operation within the Linux kernel. This guide does not focus on the details of the sensor driver development that you want to port. It is assumed that you already have an existing driver for your sensor, before making the port. The version of the ISP's was 6.6.36 Linux BSP. If a different version is used, it is the developer's responsibility to review the API documentation for the corresponding version, since there may be changes that affect what is indicated in this guide. To port the camera sensor, the following steps must be taken as described in the following sections: Define sensor attributes and create instances. ISS Driver and ISP Media Server. Sensor Calibration Files. VVCAM Driver Creation. Device Tree Modifications. Define Sensor Attributes and Create Instances The following three steps are already implemented in CamDevice and are included for reference only. Step 1: Define the sensor attributes in the IsiSensor_s data structure. Step 2: Define the IsiSensorInstanceConfig_t configuration structure that will be used to create a new sensor instance. Step 3: Call the IsiCreateSensorIss() function to create a new sensor instance. ISS Driver and ISP Media Server Step 0 - Use a driver template as base code: Drivers can be found in $ISP_SOURCES_TOP/units/isi/drv/. For example, the ISP sources, come with the OV4656 and OS08a20 drivers. $ISP_SOURCES_TOP indicates the path of your working directory, where the respective sources are located. Step 1 - Add your <SENSOR> ISS Driver: Create the driver entry for your sensor in the path $ISP_SOURCES_TOP/units/isi/drv/<SENSOR>/source/<SENSOR>.c. Change all occurrences of the respective sensor name within the code, for instance, OV4656 -> <SENSOR>, respecting capital letters where applicable. Step 2 - Check the information on the IsiCamDrvConfig_s data structure: Data members defined in this data structure include the sensor ID (CameraDriverID) and the function pointer to the IsiSensor data structure. By using the address of the IsiCamDrvConfig_s structure, the driver can then access the sensor API attached to the function pointer. The following is an example of the structure: /***************************************************************************** * Each sensor driver needs to declare this struct for ISI load *****************************************************************************/ IsiCamDrvConfig_t IsiCamDrvConfig = {     .CameraDriverID = 0x0000,     .pIsiHalQuerySensor = <SENSOR>_IsiHalQuerySensorIss,     .pfIsiGetSensorIss = <SENSOR>_IsiGetSensorIss, };   Important Note: Modify the CameraDriverID according to the chip ID of your sensor. Apply this change to any Chip ID occurrence within the code. Step 3 - Check sensor macro definitions: In case there is any macro definition in the ISS Driver code, which involves specific properties of the sensor, you should modify it according to your requirements. For example: #define <SENSOR>_MIN_GAIN_STEP         (1.0f/16.0f)   Step 4 - Modify ISP Media Server build tools: Changes required in this step include: Add a CMakeLists.txt file in $ISP_SOURCES_TOP/units/isi/drv/<SENSOR>/ that builds your sensor module. Modify the CMakeLists.txt located at $ISP_SOURCES_TOP/units/isi/drv/CMakeLists.txt to include and reference your sensor directory. Modify the $ISP_SOURCES_TOP/appshell/ and $ISP_SOURCES_TOP/mediacontrol/ build tools, since by default they refer to the construction of a particular sensor, for example, the OV4656, so it is necessary to change the name of the corresponding sensor. Modify the $ISP_SOURCES_TOP/build-all-isp.sh script to reference the sensor modules and generate the corresponding binaries when building the ISP media server instance.   Step 5 - ISP Media Server run script: You need to add the operation modes defined for your sensor in the script. Each operating mode is associated with an order (mode 0, mode 1 ... mode N), a name used to execute the command in the terminal (e.g <sensor>_custom_mode_1), a resolution, and a specific calibration file for the sensor. The script is located at $ISP_SOURCES_TOP/imx/run.sh .   Step 6 - Sensor<X> config: At $ISP_SOURCES_TOP/units/isi/drv/ you can find the files to configure each sensor entry to the ISP, called Sensor0_Entry.cfg and Sensor1_Entry.cfg. There, the associated calibration files are indicated for each sensor operating mode, including the calibration files in XML format and the Dewarp Unit configuration files in JSON format. In addition, the .drv file generated for your sensor is referenced, creating the association between the respective /dev/video<X> node and the sensor driver module outputted from the ISP Media Server. In case you are using only one ISP channel, just modify Sensor0_Entry.cfg. In case you require both instances of the ISP, you will need to modify both files. Sensor Calibration Files It is a requirement for using the ISP, to have a calibration file in XML format, specific to the sensor you are using and according to the resolution and working mode. To obtain the calibration files in XML format, there are 3 options: Use the NXP ISP tuning tool for this you will need to ask for access or sign a NDA document. Pay NXP professional services to do the tune. Pay a third-party vendor to do the tune   VVCAM Driver Creation The changes indicated below are based on the assumption that there is a functional sensor driver in its base form, and that it is compatible with the V4L2 API. From now on we focus on applying the changes suggested in the NXP documentation, specifically to establish the communication of the VVCAM Driver (kernel side) and the ISI Layer. Step 0 - Create the sensor driver entry: Developers must add the driver code to the file located at $ISP_SOURCES_TOP/vvcam/v4l2/sensor/<sensor>/<sensor>_xxxx.c, along with a Makefile for the sensor driver module. In the same way, as indicated in the ISS Driver section, you can refer to one of the sample drivers that are included as part of the ISP sources, to review details about the implementation of the driver and the structure of the required Makefile.   Step 1 - Add the VVCAM mode info data structure array: This array stores all the supported modes information for your sensor. The ISI layer can get all the modes with the VVSENSORIOC_QUERY command. The following is an example of the structure, please fill in the information using the attributes of your sensor and the modes it supports. #include "vvsensor.h" . . .   static struct vvcam_mode_info_s <sensor>_mode_info[] = {         {         .index = 0,         .width = ... ,         .height = ... ,         .hdr_mode = ... ,         .bit_width = ... ,         .data_compress.enable = ... ,         .bayer_pattern = ... ,         .ae_info = {                        .                        .                        .                        },         .mipi_info = {                        .mipi_lane = ... ,                        },         },         {         .index = 1,         .         .         .         }, }; Step 2 - Define sensor client to i2c : Define the client_to_sensor macro (in case you don't have any already) and check the segments of the driver code that require this macro. #define client_to_<sensor>(client)\         container_of(i2c_get_clientdata(client), struct <sensor>, subdev)   Step 3 - Define the V4L2-subdev IOCTL function: Define and implement the <sensor>_priv_ioctl, which is used to receive the commands and parameters passed down by the user space through ioctl() and control the sensor. long <sensor>_priv_ioctl(struct v4l2_subdev *subdev, unsigned int cmd, void *arg) {         struct i2c_client *client = v4l2_get_subdevdata(subdev);         struct <sensor> *sensor = client_to_<sensor>(client);         struct vvcam_sccb_data_s reg;         uint32_t value = 0;         long ret = 0;           if(!sensor){                return -EINVAL;         }           switch (cmd) {         case VVSENSORIOC_G_CLK: {                ret = custom_implementation();                break;         }         case VIDIOC_QUERYCAP: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_QUERY: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_G_CHIP_ID: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_G_RESERVE_ID: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_G_SENSOR_MODE:{                ret = custom_implementation();                break;         }         case VVSENSORIOC_S_SENSOR_MODE: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_S_STREAM: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_WRITE_REG: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_READ_REG: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_S_EXP: {                ret = custom_implementation();                break;         }         case VVSENSORIOC_S_POWER:         case VVSENSORIOC_S_CLK:         case VVSENSORIOC_RESET:         case VVSENSORIOC_S_FPS:         case VVSENSORIOC_G_FPS:         case VVSENSORIOC_S_LONG_GAIN:         case VVSENSORIOC_S_GAIN:         case VVSENSORIOC_S_VSGAIN:         case VVSENSORIOC_S_LONG_EXP:         case VVSENSORIOC_S_VSEXP:          case VVSENSORIOC_S_WB:         case VVSENSORIOC_S_BLC:         case VVSENSORIOC_G_EXPAND_CURVE:                break;         default:                break;         }           return ret; }   As you can see in the example, some cases are implemented but others are not. Developers are free to implement the features they consider necessary, as long as a minimum base of operation of the driver is guaranteed (query commands, read and write registers, among others). It is the developer's responsibility to implement each custom function, for each case or scenario that may arise when interacting with the sensor. In addition to what was shown previously, a link must be created to make the ioctl connection with the driver in question. Link your priv_ioctl function on the v4l2_subdev_core_ops struct, as in the example below: static const struct v4l2_subdev_core_ops <sensor>_core_ops = {         .s_power       = v4l2_s_power,         .subscribe_event = v4l2_ctrl_subdev_subscribe_event,         .unsubscribe_event = v4l2_event_subdev_unsubscribe,      // IOCTL link         .ioctl = <sensor>_priv_ioctl, };   Step 4 - Verify your sensor's private data structure: After performing the modifications suggested, it would be a good practice to double-check your sensor's private data structure properties, in case there is one missing, and also check that the properties are initialized correctly on the driver's probe.   Step 5 - Modify VVCAM V4L2 sensor Makefile : At $ISP_SOURCES_TOP/vvcam/v4l2/sensor/Makefile, include your sensor object as follows: ... obj-m += <sensor>/ ... Important Note: There is a very common issue that appears when working with camera sensor drivers in i.MX8MP platforms. The kernel log message shows something similar to the following: mxc-mipi-csi2.<X>: is_entity_link_setup, No remote pad found! The link setup callback is required by the Media Controller when performing the linking process of the media entities involved in the capture process of the camera. Normally, this callback is triggered by the imx8-media-dev driver included as part of the Kernel sources. To make sure that the problem is not related to your sensor driver, verify the link setup callback is already created in the code, and if is not, you can add the following template: /* Function needed by i.MX8MP */ static int <sensor>_camera_link_setup(struct media_entity *entity,                                    const struct media_pad *local,                                    const struct media_pad *remote, u32 flags) {     /* Return always zero */         return 0; }   /* Add the link setup callback to the media entity operations struct */ static const struct media_entity_operations <sensor>_camera_subdev_media_ops = {         .link_setup = <sensor>_camera_link_setup, };     /* Verify the initialization process of the media entity ops in the sensor driver's probe function*/ static int <sensor>_probe(struct i2c_client *client, ...) {         /* Initialize subdev */         sd = &<sensor>->subdev;         sd->dev = &client->dev;         <sensor>->subdev.internal_ops = ...         <sensor>->subdev.flags |= ...         <sensor->subdev.entity.function = ...     /* Entity ops initialization */         <sensor->subdev.entity.ops = &<sensor>_camera_subdev_media_ops; } In most cases, adding the link setup function will solve the media controller issue, or at least it discards problems on the driver side. Device Tree Modifications On the Device Tree side, it is necessary to enable the ISP channels that will be used. Likewise, it is necessary to disable the ISI channels, which are normally the ones that connect to the MIPI_CSI2 ports to extract raw data from the sensor (in case the ISP is not used). A MIPI_CSI2 port can be mapped to either an ISI channel or an ISP channel, but not both simultaneously. In this guide, we focus on using the ISP, so any other custom configuration that you want to implement may vary from what is shown. In the code below, ISP channel 0 is enabled, and the connection is made to the port where the sensor is connected (mipi_csi_0). &mipi_csi_0 {         status = "okay";         port@0 {         // Example endpoint to <sensor>_ep                mipi0_sensor_ep: endpoint@1 {                        remote-endpoint = <&<sensor>_ep>;                };         }; };   &cameradev {         status = "okay"; };   &isi_0 {         status = "disabled"; };   &isi_1 {         status = "disabled"; };   &isp_0 {         status = "okay"; };   &isp_1 {         status = "disabled"; };   &dewarp {         status = "okay"; }; What is shown above does not represent a complete device tree file, is only a general skeleton of the points you should pay attention to when working with ISP channels. For simplicity, we omitted all the attributes that are normally defined when working with camera sensor drivers and their respective configurations in the i2c port of the hardware.   Note: Due to hardware restrictions when using ISP channels, it is recommended to use the isp_0 channel, when working with only one sensor. In case you need to use two sensors, you can enable both channels, taking into account the limitations regarding the output resolutions and the clock frequency when both channels are working simultaneously. What is not recommended is to use the isp_1 channel when working with a single sensor.   References ISP Independent Sensor Interface (ISI) API reference, I.MX8M Plus Camera Sensor Porting User guide: https://www.nxp.com/webapp/Download?colCode=IMX8MPCSPUG Sensor Calibration tool: https://www.nxp.com/webapp/Download?colCode=AN13565 i.MX8M Plus reference manual: https://www.nxp.com/webapp/Download?colCode=IMX8MPRM  
View full article