i.MX Processors Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

i.MX Processors Knowledge Base

Knowledge Base Articles

Important: If you have any questions or would like to report any issues with the DDR tools or supporting documents please create a support ticket in the i.MX community. Please note that any private messages or direct emails are not monitored and will not receive a response. i.MX 8/8X DDR Tools Overview   This page contains the latest releases for the i.MX 8/8X DDR Tools. The tools described on this page cover the following i.MX 8/8X Family SoCs with the System Controller Unit (SCU): i.MX 8QuadMax and its derivatives i.MX 8QuadPlus i.MX 8QuadXPlus and its derivatives i.MX 8DualXPlus and i.MX 8DualX  NOTE: For the i.MX 8M Family of DDR tools please refer to the :  i.MX 8M Family DDR Tool Release                            The purpose of the i.MX 8/8X DDR Tools is to enable users to generate and test a custom DRAM initialization based on their device configuration (density, number of chip selects, etc.) and board layout (data bus bit swizzling, etc.).  This process equips the user to then proceed with the bring-up of a boot loader and an OS.  Once the OS is brought up, it is recommended to run an OS-based memory test (like Linux memtester) to further verify and test the DDR memory interface.     The  i.MX 8/8X DDR Tools consist of: DDR Register Programming Aid (RPA) DDR Stress test   For more details regarding these DDR tools and their usage, refer to the MX8X_DDR_Tools_quickstart_guide.pdf attached to this page.   i.MX 8/8X DDR Register Programming Aid (RPA)   The i.MX 8/8X DDR RPA (or simply RPA) is an Excel spreadsheet tool used to develop DDR initialization for a user’s specific DDR configuration (DDR device type, density, etc.). The RPA generates the DDR initialization in two formats (in separate Excel worksheet tabs):   DDR Stress Test script: This format is used specifically with the DDR stress test by first copying the contents in this worksheet tab and then pasting it to a text file, naming the document with the “.ds” file extension. The user will select this file when executing the DDR stress test. DCD CFG file: This format is the configuration file used specifically by the SCU Firmware (SCFW). In this scenario, the user copies the contents in this worksheet tab and pastes it to a text file, naming the document with the “.cfg” file extension and placing this file in the appropriate SCFW board file directory.   i.MX 8/8X DDR Register Programming Aid (RPA): Current Versions Note: In all cases, the RPA revision is aligned to a minimum SCFW version as shown in the table below. In some cases, the BSP alignment is provided as extra detail, however, the RPA tool is specifically aligned to a minimum SCFW version and later. To obtain the latest RPAs, please refer to the following links (note, existing RPAs have been removed from this main page and moved to the SoC specific links below): i.MX8QM: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8QM-DDR-Register-Programming-Aid-RPA/ta-p/1166307 i.MX8QXP/QXP/DX: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8QXP-DXP-DX-DDR-Register-Programming-Aid-RPA/ta-p/1166302   Processor Mask Revisions Memory Supported Latest RPA Version * Notes i.MX 8QM B0 LPDDR4 Rev 22** Rev 21** Rev 20** Rev 19** Rev22: The following changes have no effect on the DDR IO interface. This updated setting basically adds a define in the DCD file for the total DDR density configured by the RPA. This defined is used by the SCFW.  Rev 21: Fixed 1 DRC operation to comment out calls to VREF training to DRC1 and added DDRC_SCHED register programming to align with latest SCFW programming (refer to RPA revision history for more details). Rev 20: use with SCFW 1.4.0 and NXP BSP GA version L5.4.3_2_0_0 later (to support SW VREF training work around command) Rev 19: use with SCFW 1.3.1 and N XP BSP GA version L5.4.3_1_0_0 i.MX 8QXP C0, B0 LPDDR4 Rev 15** Rev 14** Rev 13** Rev 15: The following changes have no effect on the DDR IO interface. This updated setting basically adds a define in the DCD file for the total DDR density configured by the RPA. This defined is used by the SCFW.  Rev 14: use with SCFW 1.4.0 and NXP BSP GA version L5.4.3_2_0_0   later  (to support SW VREF training work around command) Rev 13: use with SCFW 1.3.1 and N XP BSP GA version L5.4.3_1_0_0 i.MX 8QXP C0, B0 DDR3L Rev 21 Rev 20 Rev 21: The following changes have no effect on the DDR IO interface. This updated setting basically adds a define in the DCD file for the total DDR density configured by the RPA. This defined is used by the SCFW. -Compatible with SCFW 1.1.10 and later -Changes made to this revision do not affect the DCD CFG file output based on v19 -Issue discovered in the DDR stress test script, wherein certain commands were not being properly configured based on the ECC setting in the Register Configuration worksheet; this was resolved (cells A84, A87, A90, A93 ) -In addition, in both DCD CFG and DDR stress test script worksheets, all commands that depend on ECC config have been updated to include an "OR" with whether or not the data bus is configured for 16-bit (ECC is only supported for full 32-bit data bus width configurations) i.MX 8DualX C0, B0 LPDDR4 Rev 15* Rev 14** Rev 13** Rev 15: The following changes have no effect on the DDR IO interface. This updated setting basically adds a define in the DCD file for the total DDR density configured by the RPA. This defined is used by the SCFW.  Rev 14: use with SCFW 1.4.0 and NXP BSP GA version L5.4.3_2_0_0   later  (to support SW VREF training work around command) Rev 13: use with SCFW 1.3.1 and N XP BSP GA version L5.4.3_1_0_0 i.MX 8DualX C0, B0 DDR3L Rev 19 Rev 18 Rev 19: The following changes have no effect on the DDR IO interface. This updated setting basically adds a define in the DCD file for the total DDR density configured by the RPA. This defined is used by the SCFW.  -Compatible with SCFW 1.1.10 and later * For a history of the previous versions of an RPA, refer to the Revision History tab of the respective RPA.  ** In general, it is recommended to use the latest RPA tool even with a pre-released BSP as it ensures you are testing with the latest fixes and features. Older versions of the RPA may be provided to support existing/released versions of the BSP.  This only applies to those RPA tools that are compatible with pre-release BSPs but may not be compatible with released versions of the BSP.     i.MX 8/8X DDR Stress Test    The i.MX 8/8X  DDR stress test tool is a Windows-based software tool that is used as a mechanism to verify that the DDR initialization is operational prior to building the SCFW for use with u-boot and OS bring-up. The DDR stress test uses the .ds DDR stress test script generated from the RPA tool along with a special build of the SCFW, built with option: DDR_CON=ddr_stress_test_parser Or in the case of i.MX 8QuadMax use of one DDR Controller: DDR_CON=ddr_stress_test_parser_DRC0_only The DDR stress test offers a Target option to dictate which SoC is under test. The following are Target options to select from: MX8QM – used to test i.MX 8QuadMax and its derivates i.MX 8QuadPlus MX8QX – used to test i.MX 8QuadXPlus and its derivates i.MX 8DualXPlus/DualX   To install the DDR Stress Test, save and extract the zip file  mx8_ddr_stress_test_ERxx_installation.zip    (where 'xx' is the current version number) and follow the on-screen installation instructions. Note, when extracting the DDR Stress Test tool .zip file, it is recommended to perform an "Extract here" operation.  Some systems do not allow for the extracted installation executable to run from another folder and will only work when being executed from the same location as the original, downloaded zip file.  For more details on the DDR stress test usage, refer to the MX8_DDR_Tool_User_Guide found in the DDR Stress Test tool delivery. NOTE:  Before using the DDR tools on a new custom board, the user should properly port the SCU Firmware (SCFW) to this new board. The DDR tools will not be able to run without a properly ported and working SCFW.            i.MX 8/8X DDR Stress Test   Requirements The tool requires access to the Windows registry, hence  users must run it in administrator mode . The tool cannot run on an OEM closed device that requires images signed by the customer When users design new i.MX 8/8X boards, please make sure to follow the rules outlined in the respective Hardware Developers Guide and the  MX8_DDR_Tool_User_Guide , which can help users bring up DDR devices on their respective i.MX 8/8X boards.   i.MX 8/8X DDR Stress Test  SECO Firmware It is generally not recommended to update the SECO (ahab) firmware that comes default with the DDR Stress Test. This is not recommended because the purpose of the DDR Stress Test is to test the DDR memory interface, not the entire SCFW to SECO firmware operation even though a newer version of the SCFW may complain that the SECO firmware version is not the latest. The SECO firmware version that comes with the DDR Stress Test has been tested and proven to work by the factory before the DDR Stress Test release; updating the SECO firmware to a different version may result in unintended consequences rendering the DDR stress test inoperable. In most cases, it is allowable to update only the SCFW without updating the SECO firmware. Should the user wish to update the SECO firmware version in the DDR Stress Test, then they will need to rename this firmware without the silicon version (for example, if updating the MX8QM SECO firmware, the user will need to rename mx8qmb0-ahab-container.img to mx8qm-ahab-container.img, basically remove the “b0”). The exception is for the MX8QXP, if updating the C0 silicon version SECO firmware, then the user should maintain the C0 nomenclature. If the user finds that the updated SECO firmware causes the DDR Stress Test to become inoperable, then it is recommended to revert to the default SECO firmware version that came with the DDR Stress Test release. i.MX 8/8X DDR Stress Test  User Guide The i.MX 8/8X DDR Stress Test tool includes the document: MX8_DDR_Tool_User_Guide.pdf NOTE: Please read the  MX8_DDR_Tool_User_Guide inside the package carefully before you use this tool.   DDR Stress Test Revision History   Rev Major Changes (Features) NXP BSP Software Version ER 14 Updated to support parsing of the VREF training command in the DDR Stress Test script This version is aligned with NXP BSP GA version L5.4.3_2_0_0 and later.    Related Resources Links: i.MX 8M Family DDR Tool Release  i.MX 6/7 DDR Stress test GUI Tool i.MX 8QM RPA: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8QM-DDR-Register-Programming-Aid-RPA/ta-p/1166307 i.MX 8QXP/DXP/DX RPA: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX8QXP-DXP-DX-DDR-Register-Programming-Aid-RPA/ta-p/1166302
View full article
To enable USB 2.0 port on BB for USB OTG, you need to apply below two changes: device/fsl.git   diff --git a/imx8q/mek_8q/init.usb.rc b/imx8q/mek_8q/init.usb.rc index af4e388..0f3ab0b 100644 --- a/imx8q/mek_8q/init.usb.rc +++ b/imx8q/mek_8q/init.usb.rc @@ -44,7 +44,7 @@ on early-boot      mount functionfs mtp /dev/usb-ffs/mtp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1      mount functionfs ptp /dev/usb-ffs/ptp rmode=0770,fmode=0660,uid=1024,gid=1024,no_disconnect=1      setprop sys.usb.mtp.device_type 3 -    setprop vendor.usb.config "5b110000.usb3" +    setprop vendor.usb.config "ci_hdrc.0"      write /sys/module/libcomposite/parameters/disable_l1_for_hs "y"      symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1   vendor/nxp-opensource/kernel_imx.git           revert below patch:           commit 2f9586c120971312e61df464264993899cf34536           Author: yang.tian <yang.tian@nxp.com>           Date:   Tue Jan 7 13:30:02 2020 +0800       MA-15242 Set usb2.0 port as usb host only for mek_8q  
View full article
This document is a user guide for the GStreamer version 1.0 based accelerated solution included in all the i.MX 8 family SoCs supported by NXP BSP L5.4.24_1.1.0. Some instructions assume a host machine running a Linux distribution, such as Ubuntu, connected to i.MX 8 device. These commands were tested using Ubuntu 18.04 LTD, and while Ubuntu is not required on the host machine, other distributions have not been tested. These instructions are targeted for use with the following hardware: • i.MX 8MQ EVK • i.MX 8MN EVK • i.MX 8MN EVK • i.MX 8QXP MEK B0 • i.MX 8QM MEK B0   Release History v1.0 - Mar 2020 - Initial release. v2.0 - Sep 2020: Added the following content: - Mux/Demux Examples - Audio Examples - Image Examples - Transcode Examples - Streaming Examples - Multi-Display Examples - Scaling and Rotation Examples - Zero-copy Examples - Debug Examples Maintainers: . Marco Franchi . Pedro Jardim
View full article
GmSSL is an open source cryptographic toolbox that supports SM2 / SM3 / SM4 / SM9 and other national secret (national commercial password) algorithm, SM2 digital certificate and SM2 certificate based on SSL / TLS secure communication protocol to support the national security hardware password device , To provide in line with the national standard programming interface and command line tools, can be used to build PKI / CA, secure communication, data encryption and other standards in line with national security applications. For more information, please access GmSSL official website http://gmssl.org/english.html.   Software environments as the belows: Linux kernel: imx_4.14.98_2.0.0_ga cryptodev: 1.9 HW platform: i.MX6UL, i.MX7D/S, i.MX8M/MM, i.MX8QM/QXP. The patches include the following features: 1, Support SM2/SM9   encryption/decryption/sign/verify/ key exchange ,   RSA  encryption/decryption, DSA/ECDSA sign/verify, DH/ECDH key agreement, ECC & DLC & RSA key generation and big number  operation and   e lliptic  c urve   m ath by CAAM hardware   accelerating . 2, run "git apply 0001-Enhance-cryptodev-and-its-engine-in-GmSSL-by-CAAM-s-.patch" under folder sources/poky, and "git apply 0001-Add-public-key-cryptography-operations-in-CAAM-drive.patch"   under folder   sources/meta-fsl-bsp-release for patch these codes. 3, GmSSL Build command: $ tar zxvf GmSSL-master-iMX.tgz $  cd  GmSSL-master-iMX (For i.MX8M/MM, i.MX8QM/QXP) $  source /opt/arm-arch64/environment-setup-aarch64-poky-linux  $  ./Configure -DHAVE_CRYPTODEV -DUSE_CRYPTODEV_DIGESTS -DHW_ENDIAN_SWAP  --prefix= ~/install64   --openssldir=/etc/gmssl --libdir=/usr/lib no-saf no-sdf no-skf no-sof no-zuc -no-ssl3 shared linux-aarch64 $  make  $  make install                              /*image and config file will be installed to folder   ~ /install64   */   (For  i.MX6UL, i.MX7D/S ) $   source /opt/arm-arch32/environment-setup-cortexa7hf-neon-poky-linux-gnueabi $   ./Configure -DHAVE_CRYPTODEV -DUSE_CRYPTODEV_DIGESTS --prefix= ~ /install32   --openssldir=/etc/gmssl --libdir=/usr/lib no-saf no-sdf no-skf no-sof no-zuc -no-ssl3 shared linux-armv4 $  make  $  make install                             /*image and config file will be installed to folder   ~ /install32   */   4, How to use GmSSL: copy image gmssl to /usr/bin on i.MX board;  copy  gmssl libcrypto.so.1.1 and libssl.so.1.1 to /usr/lib  on i.MX board; copy folder etc/ gmssl to /etc/ on i.MX board. copy test examples (dhtest, dsatest, rsa_test, ecdhtest, ecdsatest, eciestest, sm3test, sms4test, sm2test, sm9test) under GmSSL-master-iMX/test  to U disk for running. You can run test examples by the following commands: #insmod /lib/modules/4.14.98-imx_4.14.98_2.0.0_ga+g5d6cbeafb80c/extra/cryptodev.ko #/run/media/sda1/dhtest #/run/media/sda1/dsatest #/run/media/sda1/rsa_test #/run/media/sda1/ecdhtest #/run/media/sda1/ecdsatest #/run/media/sda1/eciestest #/run/media/sda1/sm3test #/run/media/sda1/sms4test #/run/media/sda1/sm2test #/run/media/sda1/sm9test and speed test commands: #gmssl speed sm2 #gmssl genrsa -rand -f4 512 #gmssl speed dsa #gmssl genrsa -rand -f4 1024 #gmssl speed rsa #gmssl genrsa -rand -f4 2048 #gmssl speed ecdsa #gmssl genrsa -rand -f4 3072 #gmssl speed ecdh #gmssl genrsa -rand -f4 4096   ++++++++++++++++++++++++++++     updating at 2019-09-10    +++++++++++++++++++++++++++++++++++++++++++++ 0001-fix-the-bug-which-hash-and-cipher-key-don-t-use-DMA-.patch fix the issue which   dismatching on key buffer between crytodev and caam driver. Crytodev uses stack's buffer for key storage and caam driver use it to dma map which cause flush cache failure. The patch need to apply on cryptodev-module in Yocto build.   ++++++++++++++++++++++++++++     updating at 2019-10-14   +++++++++++++++++++++++++++++++++++++++++++++ This updating is for China C-V2X application. The package meta-cv2x_4.14.98_2.0.0_ga.tgz is Yocto layer which bases on GmSSL and Cryptodev. I add HW SM2 verification by dedicated CAAM job descriptor and enhanced SW  SM2 verification by precomputed multiples of generator and ARMv8 assembler language to accelerate point  operation.  Software environments as the belows: Linux kernel: imx_4.14.98_2.0.0_ga cryptodev: 1.9 HW platform: i.MX8M/MM/MN, i.MX8QM/QXP. How to build: 1, decompress  meta-cv2x_4.14.98_2.0.0_ga.tgz and copy meta-cv2x to folder (Yocto 4.14.98_2.0.0_ga dir)/sources/ 2, Run DISTRO=fsl-imx-wayland MACHINE=imx8qxpmek source fsl-setup-release.sh -b build-cv2x and add BBLAYERS += " ${BSPDIR}/sources/meta-cv2x " into ( Yocto 4.14.98_2.0.0_ga dir ) /build-cv2x/conf/bblayers.conf and  IMAGE_INSTALL_append += " gmssl-bin "  into local.conf 3, Run bitbake fsl-image-validation-imx. 4, You can find  cv2x-verify.c under (build dir)/tmp/work/aarch64-poky-linux/cryptodev-tests/1.9-r0/git/tests. It is example for using CAAM cryptdev interface to do C-V2X verification (includes SM2 p256, NIST p256 and brainpoolP256r1).   cv2x_benchmark.c   under ( build dir )/tmp/work/aarch64-poky-linux/gmssl/1.0-r0/gmssl-1.0/test is the benchmark test program of C-V2X verifying. It includes HW, SW and HW+SW(one CPU) verifying for  SM2 p256, NIST p256 and brainpoolP256r1. 5, Run the below command on your i.MX8QXP MEK board. modprobe cryptodev ./cv2x_benchmark Note: the udpated GmSSL also support projective coordinates and affine coordinates (CAAM only support affine  coordinates ). Affine  coordinates is used  by default. You can call EC_GROUP_set_coordinates() and EC_GROUP_restore_coordinates() to change coordinates and restore default. When you hope to use some EC APIs under expected coordinates, you need to call EC_GROUP_set_coordinates() before EC APIs and  EC_GROUP_restore_coordinates()  after them. Like the below example: orig_coordinate = EC_GROUP_set_coordinates(EC_PROJECTIVE_COORDINATES); group = EC_GROUP_new_by_curve_name(NID_sm2p256v1); EC_GROUP_restore_coordinates(orig_coordinate);
View full article
The system controller timer service is responsible for: Watchdog - The watchdog resource is managed by the SCU. The SCFW exposes a "virtual" watchdog to all CPUs. This virtual watchdog is managed by software and it is based on a low power timer, the SCU also features a physical watchdog timer that is used to ensure the correct operation of the device. Some of the features implemented by this watchdog service are: - Update of the watchdog timeout - Start/stop of the watchdog - Refresh of the watchdog - Return of the watchdog status such as maximum watchdog timeout that can be set, watchdog timeout interval, and watchdog timeout interval remaining. Since this is usually handled by the OS itself no examples are provided in this guide. Real Time Clock (RTC) - The SCFW is responsible for providing access to the RTC. The features supported by the API are: - Set/get time - Setting alarms Only the partition that owns the SC_R_SYSTEM resource is allowed to set the time, alarms and calibration values for the RTC. All other partitions are able to read the RTC time.  Here is an example on setting the RTC from the M4 side: struct time_date { uint16_t year ; uint8_t month ; uint8_t day ; uint8_t hour ; uint8_t min ; uint8_t sec ; } rtc_time ; sc_err_t sc_status ; sc_ipc_t ipc ; /* Open IPC channel */ sc_status = sc_ipc_open ( & ipc , SC_IPC_AP_CH0 ) ; if ( sc_status != SC_ERR_NONE ) printf ( "Error opening Inter Processor Channel\n" ) ; /* Initialize RTC */ /* Hard code RTC time to January 5th 2018 at 12:00 hours */ sc_status = sc_timer_set_rtc_time ( ipcHandle , 2018 , 1 , 5 , 12 , 0 , 0 ) ; if ( sc_status != SC_ERR_NONE ) printf ( "Error initializing RTC. \r\n" ) ; /* Return time */ sc_status = sc_timer_get_rtc_time ( ipcHandle , & ( rtc_time . year ) , & ( rtc_time . month ) , & ( rtc_time . day ) , & ( rtc_time . hour ) , & ( rtc_time . min ) , & ( rtc_time . sec ) ) ; printf ( "Year: %d, Month: %d, Day: %d, Hour: %d, Minutes: %d, Seconds: %d. \r\n" , rtc_time . year , rtc_time . month , rtc_time . day , rtc_time . hour , rtc_time . min , rtc_time . sec ) ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ https://community.nxp.com/docs/DOC-342654 
View full article
i.MX evaluation board can be a simple solution to program i.MX boards in a factory for instance. i.MX evaluation board are not for industrial usage, but you can find plenty of cheap i.MX insdustrial boards on the web. Here I am using an i.MX8QXP rev B0 MEK board and I will program an i.MX6Q SABRE SD board. The first step is to generate your image. Follow the documentation steps to generate the "validation" image. You will have to customize a little bit the local.conf file (in conf/local.conf) to have git, cmake, gcc and other missing package. edit local.conf and add the following lines at the end of the file: IMAGE_INSTALL_append = " git cmake htop packagegroup-core-buildessential xz p7zip rsync" ‍‍‍‍ ‍ I have added rsync package in local, it can replace cp (copy) but with the --progress option you can see the copy progression. P7zip replace unzip for our images archives avaialable on nxp.com as unzip as issues with big files. then rebake your image: bitbake - k fsl - image - validation - imx‍‍‍‍ ‍ When it is done, go in tmp/deploy/image/<your image generated> and use uuu to program your board (I use a sd card; thus I can increase the partition esily): sudo . / uuu - b sd_all imx - boot - imx8qxpmek - sd . bin - flash fsl - image - validation - imx - imx8qxpmek . sdcard . bz2 / * ‍‍‍‍ ‍ As the rootfs can be too small, use gparted under Linux for instance to increase the size of the partition. Put the SD card and start your board. Here here the dirty part... You may know archlinux|ARM websitesite (Arch Linux ARM ), you have a lots of precompiled packages. Thus on the board you can download it, and copy the file in /usr folder (you can use it to have the latest openSSL for  instance!). Plug an ethernet cable on the board and check if it is up: ifconfig - a ifconfig eth0 up‍‍‍‍‍‍‍‍ ‍ ‍ Now you should have access to the internet. On uuu webpage you can find all the packages you need (here I am using a 4.14.98_2.0.0 Linux): mkdir missinglibs cd missinglibs wget http : / / mirror . archlinuxarm . org / aarch64 / core / bzip2 -1.0 . 8 - 2 - aarch64 . pkg . tar . xz wget http : / / mirror . archlinuxarm . org / aarch64 / core / nettle -3.5 . 1 - 1 - aarch64 . pkg . tar . xz wget http : / / mirror . archlinuxarm . org / aarch64 / core / libusb -1.0 . 22 - 1 - aarch64 . pkg . tar . xz wget http : / / mirror . archlinuxarm . org / aarch64 / extra / libzip -1.5 . 2 - 2 - aarch64 . pkg . tar . xz wget http : / / mirror . archlinuxarm . org / aarch64 / core / zlib -1 : 1.2 . 11 - 3 - aarch64 . pkg . tar . xz wget http : / / mirror . archlinuxarm . org / aarch64 / extra / p7zip -16.02 - 5 - aarch64 . pkg . tar . xz cd . . ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Wait all the archives are downloaded (otherwise you'll decompress before the archive is downloaded) as wget is running in background! Now untar the archives and copy it in the rootfs (dirty): tar - xJf libzip -1.5 . 2 - 2 - aarch64 . pkg . tar . xz tar - xJf libusb -1.0 . 22 - 1 - aarch64 . pkg . tar . xz tar - xJf nettle -3.5 . 1 - 1 - aarch64 . pkg . tar . xz tar - xJf bzip2 -1.0 . 8 - 2 - aarch64 . pkg . tar . xz cp zlib -1 : 1.2 . 11 - 3 - aarch64 . pkg . tar . xz zlib tar - xJf zlib tar - xJf p7zip -16.02 - 5 - aarch64 . pkg . tar . xz cd usr sudo cp - R . / usr cd . . / . . / ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Download and compile uuu: git clone git : / / github . com / NXPmicro / mfgtools . git cd mfgtools / cmake . make‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ Download an image on nxp.com for instance. I have downloaded on the i.MX6 4.14.98_2.0.0 image and put it on a usb key. then unzip it in the uuu folder: 7z e L4 .14 . 98_2 .0 . 0_ga_images_MX6QPDLSOLOX . zip‍‍‍ ‍ As mentionned before unzip cannot hadle big files... so use 7z as me plug the i.MX6Q SABRE SD to the i.MX8X and program your i.MX6 board: . / uuu uuu . auto - imx6qsabresd‍ uuu ( Universal Update Utility ) for nxp imx chips -- libuuu_1 .3 . 74 - 0 - g64eeca1 Success 1 Failure 0 ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍
View full article
This document explains the pad implementation and its relationship with the System Controller Firmware pad configuration service. There are two components to pad configuration in the SCFW, there are the modules that generate the signals that will ultimately appear on the physical pad, let's say GPIO/Ethernet/I2C/UART etc... and then there is the part that configures the muxing of the pad (what signal is going to be outputted through the specific pad), the drive strength of the pad, pull selection, etc, this is the part that the SCFW pad service configures. Introduction‌ The i.MX8 has three types of I/Os: 1.8V only I/Os 3.3V only I/Os 1.8V / 3.3V I/Os Dual Voltage I/Os Note: USB High Speed Inter-Chip (HSIC) and Ethernet interfaces have specific integration schemes with dedicated features. They are a modified versions of the above I/O types. HSIC are a special kind of I/O modified to sustain 480Mbps data rates ENET I/Os are modified versions of Dual Voltage I/Os to support 2.5V operations All of these I/Os have "common features" and "technology specific features" which depend on the type of I/O and the chip manufacturing process (FDSOI in the i.MX8QM case) I/O common features Muxing capability of up to 4 signals Each Pad can have up to 4 signals, only one signal can be present in the pad. To select the signal that will output on the pad simply look at the Pinmux spreadsheet and use the desired alternative, for instance in the following image SCU_GPIO0_00 has 3 options, SCU_GPIO (ALT0 - GPIO controlled directly by the SCU), SCU_UART0_RX (ALT1 - SCU UART receiver) or LSIO_GPIO0_IO28 (ALT3 - Low speed I/O GPIO).   Pads without GPIO functionality (i.e. without the GPIO option in the pinmux spreadsheet) are implemented for one purpose only, these pins are connected directly to the module that drives them and they feature their own physical interface. Examples are XTAL pins, DDR pins and SCU PMIC interface (shown above). Mode of operation All GPIO types support four modes of operation: Normal mode Data is being driven directly to the pad (an internal signal of 1 shows in the pad as a 1 and vice-versa) and the pad works either as an output or as an input but not both at the same time. The output buffer while on this mode looks like this: Open drain Data is being driven through an open drain configuration, the output on the pad switches between 0 and high-z. The pad works either as an output or as an input but not both at the same time, e.g. if the Output Buffer is enabled the Input Buffer is disabled. This is how the output buffer looks like on Open drain mode: Open drain and input Output buffer acts as in open drain mode but with the input buffer enabled regardless of the output buffer state (enabled/disabled), this allows to simultaneously read the signal at the pad while driving it. Output and input Output buffer acts as in normal mode but with the input buffer enabled regardless of the output buffer state (enabled/disabled), this allows to read the signal at the pad while driving it. Wake-up capability Each I/O can be configured to wake-up the device, the following configuration options are available: OFF I/O cannot wake-up the system Low detect Generate wake-up event when the pad remains in low-level High detect Generate wake-up event when the pad remains in high-level Rising edge Generate wake-up event on rising edge detection Falling edge Generate wake-up event on falling edge detection Technology specific features Some of the available features for each pad depend on two factors: Chip manufacturing process (FDSOI or LPP) I/O type (1.8V, 3.3V or Dual Voltage) The i.MX8QM is manufactured using FDSOI technology and it features all of the three available I/O types. Drive strength Drive strength options vary within I/O types and chip manufacturing options. The available options for a FDSOI chip are: 1.8V Drive strength options 3.3V Drive strength options Dual Voltage drive strength options Drive strength of 1mA Drive strength of 2mA Low drive strength (50 ohms) Drive strength of 2mA Drive strength of 4mA High drive strength (33 ohms) Drive strength of 4mA Drive strength of 8mA Drive strength of 6mA Drive strength of 12mA Drive strength of 8mA Drive strength of 10mA Drive strength of 12mA High-speed drive strength Pull Select The pull select available options are almost the same for all I/O types (1.8V being the exception) and they also depend on chip manufacturing process. The available options for a FDSOI chip are: Pull select options for FDSOI Bus-keeper (only available for 1.8V) Pull-up Pull-down No Pull (Disabled) A bus-keeper or bus-holder is used to keep the last state on the bus. In normal operation it makes no difference, but once the bus is tri-stated it keeps the last logic level in the bus to prevent the bus from floating. Compensation The compensation feature is only available on Dual Voltage I/Os. Dual Voltage I/Os have a different implementation, they require: Voltage reference generator - which provides a voltage reference to the supply detector and compensation cell Supply detector - detects automatically whether the I/O is being supplied with 1.8V or 3.3V and broadcasts this information to compensation cell and I/O  Compensation cell - adjusts drive strength of dual voltage I/Os depending on Process Voltage and Temperature (PVT) conditions. The default configuration takes care of adjusting this parameters and no further modifications are required. Pad configuration service SCFW API Mux selection The very first function that needs to be called to configure a pad is: sc_err_t sc_pad_set_mux ( sc_ipc_t ipc , sc_pad_t pad , uint8_t mux , sc_pad_config_t config , sc_pad_iso_t iso ) ; ‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ This function takes care of configuring the muxing alternative and setting the common features, its parameters are: ipc - The Inter Processor Communication (IPC) channel that you will use to communicate with the SCU. You need to call sc_ipc_open to obtain it. pad - The pad you want to configure, the different pad definitions are in imx8qm_pads.h, this is basically the same list that is included in the scfw_api_qm.pdf document (page 27 Chapter 5 Pad List) and it also mimics the Pinmux excel sheet. mux - The mux setting that you require, basically Alt0 -> 0, Alt1 -> 1, Alt2 -> 2 and Alt3-> 3, the pinmux spreadsheet contains the required information (take a look at I/O common features above). config - Used to select the desired mode of operation ( take a look at I/O common features above), the available options are declared under sc_pad_config_t Normal mode - SC_PAD_CONFIG_NORMAL Open Drain mode - SC_PAD_CONFIG_OD Open Drain and input - SC_PAD_CONFIG_OD_IN Output and input - SC_PAD_CONFIG_OUT_IN iso - This is the low-power isolation configuration ( take a look at I/O common features above). The available options are declared under sc_pad_iso_t ISO_OFF - SC_PAD_ISO_OFF ISO_EARLY - SC_PAD_ISO_EARLY ISO_LATE - SC_PAD_ISO_LATE ISO_ON - SC_PAD_ISO_ON For instance to configure M40_I2C0_SCL with its UART alternative in normal mode with low-power isolation off, the call would look like this: sc_pad_set_mux ( ipc , SC_P_M40_I2C0_SCL , 1 , SC_PAD_CONFIG_NORMAL , SC_PAD_ISO_OFF ) ; ‍‍‍‍‍‍‍‍‍ ‍ Pad configuration To configure drive strength and pull select options the technology specific functions need to be used (FDSOI for i.MX8QM): sc_pad_set_gp is being used by our Linux team because it admits the passing of the configuration parameters as a single value and this eases the handling on the device tree, but you should aim to use the technology specific functions. sc_err_t sc_pad_set_gp_28fdsoi ( sc_ipc_t ipc , sc_pad_t pad , sc_pad_28fdsoi_dse_t dse , sc_pad_28fdsoi_ps_t ps ) ; ‍‍‍‍‍‍‍‍‍‍ ‍ This function takes care of configuring the drive strength (DSE) and pull select settings (PS) for the specified pad, here is a break down of the parameters it uses: ipc - The Inter Processor Communication (IPC) channel that you will use to communicate with the SCU. You need to call sc_ipc_open to obtain it. pad -  The pad you want to configure, the different pad definitions are in imx8qm_pads.h, this is basically the same list that is included in the scfw_api_qm.pdf document (page 27 Chapter 5 Pad List) and it also mimics the Pinmux excel sheet. dse - The desired drive strength configuration (see Technology specific features above). DSE settings depend on the I/O type being used, the available options for each I/O type are defined under sc_pad_28fdsoi_dse_t: ENET pads capable of operating at 2.5V are a subset of dual voltage I/Os, the dse options available for these pads are the same as normal dual voltage I/Os. i.e. High drive and low drive. ps - The desired pull select configuration  (see  Technology specific features above). The available options are defined under sc_pad_28fdsoi_ps_t: To determine whether a GPIO pad is 1.8V, 3.3V or Dual Voltage one can look at the pinmux spread sheet, the supply for the pad will indicate what implementation of the GPIO is used. For instance: pads under VDD_SIM_1P8_3P3 are Dual voltage I/Os pads under VDD_SCU_1P8 are 1.8V I/Os pads under VDD_ADC_3P3 are 3.3V I/Os taking the same example as above we could configure the M40_I2C0_SCL as follows: sc_pad_set_gp_28fdsoi(ipc, SC_P_M40_I2C0_SCL, SC_PAD_28FDSOI_DSE_DV_LOW, SC_PAD_28FDSOI_PS_NONE);‍‍‍‍‍‍‍‍‍‍‍‍ ‍ Configuration under Linux Linux configures pads through the device tree, the full documentation of the binding is under Documentation/devicetree/bindings/pinctrl/fsl,imx8qxp-pinctrl.txt. but here is an extract: * Freescale i.MX8QXP IOMUX Controller Required properties: - compatible: "fsl,imx8qxp-iomuxc" - fsl,pins: each entry consists of 2 integers. Its format is <pin_id pin_config>. pin_config definition: - i.MX8QXP have different pad types, please refer to below pad register definitions, the pinctrl driver will just write the pin_config into the hardware register.‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The driver uses the following API: sc_err_t sc_pad_set_gp ( sc_ipc_t ipc , sc_pad_t pad , uint32_t ctrl ) ‍‍ ‍ Instead of configuring each parameter individually as done with sc_pad_set_gp_28fdsoi it configures the pad as if writing to a register, the bitfield format is under the binding documentation but it is as follows: struct _hw_pad_iomux_bitfields0 { uint32_t GP : 19 ; /*!< [18:0] GP controls. */ uint32_t WAKEUP : 3 ; /*!< [21:19] Wakeup controls. */ uint32_t WAKEUP_ENB : 1 ; /*!< [22] Wakeup write enable. */ uint32_t LPCONFIG : 2 ; /*!< [24:23] Low-power config. */ uint32_t CONFIG : 2 ; /*!< [26:25] Config. */ uint32_t IFMUX : 3 ; /*!< [29:27] Mux. */ uint32_t GP_ENB : 1 ; /*!< [30] GP write enable. */ uint32_t IFMUX_ENB : 1 ; /*!< [31] Mux write enable. */ } B ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ All the configurations mentioned above can be configured, but they are done in a single pass, e.g. Muxing, Configuration (Norma, Open Drive, etc...), Wakeup control, and GP controls are for Pull Select Drive Strenght etc... Check the Reference Manual Chapter for IOMUXD for the register definition for each pad. References For more details refer to the sc_fw_api.pdf document: Chapter 1.3.3 Pad Configuration Service Chapter 6 Pad List Chapter 9.3 (SVC) Pad Service System Controller Firmware 101 
View full article
The i.MX 8QXP MEK does not allow the OV5640/LVDS/LCD usage only by changing the device tree anymore. It occurs because the M4 owns the i2c resources, so the A core must use rpmsg to enable virtual drivers. Due to this, if the user changes the device tree, for instance, the *ov5640.dtb, the kernel won't boot, entering in the following loop: [    8.603353] [drm] Supports vblank timestamp caching Rev 2 (21.10.2013).      [    8.610025] [drm] No driver support for vblank timestamp query.              [    8.616077] imx-drm display-subsystem: bound imx-drm-dpu-bliteng.2 (ops dpu_) [    8.624978] imx-drm display-subsystem: bound imx-dpu-crtc.0 (ops dpu_crtc_op) [    8.632526] imx-drm display-subsystem: bound imx-dpu-crtc.1 (ops dpu_crtc_op) [    8.639833] imx-drm display-subsystem: failed to bind ldb@562210e0 (ops imx_7 [    8.648428] imx-drm display-subsystem: master bind failed: -517 With the approach provided in this post, it is possible to make this change manually, only by changing the flash.bin at U-boot for a non-m4 one. In order to make the changes to the flash.bin file, it’s needed to obtain the following files: - u-boot.bin from internal u-boot provided by NXP. - scfw_tcm.bin from SCFW porting kit - bl31.bin from ARM Trusted Firmware - SECO firmware container image Disclaimer The described procedures in this document target a GNU/Linux (Ubuntu 20.04 LTS) and it’s focused on iMX8QXP B0 + BSP L4.19.35_1.1.0. Required packages 1 - Install ARM64 ToolChain: 1.1 - Install ARM64 GCC and G++ cross-compilers: # apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu 2 - Install ARM32 GCC6 ToolChain: 2.1 - Download the ARM32 6 Toolchain and install it: $ mkdir ~/gcc_toolchain $ cp ~/Downloads/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 ~/gcc_toolchain/ $ cd ~/gcc_toolchain/ $ tar xvjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 # apt-get update # apt-get install srecord 3 - Download MKimage 3.1 - Create a new directory desired to the packages: $ mkdir flash_build $ cp flash_build 3.1 - Clone the MKimage: $ git clone https://source.codeaurora.org/external/imx/imx-mkimage -b imx_4.19.35_1.1.0 4 - U-boot build 4.1 - Clone the U-boot  $ git clone https://source.codeaurora.org/external/imx/uboot-imx -b imx_v2019.04_4.19.35_1.1.0 $ cd uboot-imx 4.2 - Export the ARM64 ToolChain:  $ export ARCH=arm64 $ export CROSS_COMPILE=/usr/bin/aarch64-linux-gnu- 4.3 - Build it:  $ unset LDFLAGS $ make -j4 imx8qxp_mek_defconfig $ make 4.4 - Copy the binary files to the MKimage/iMX8QX directory:  $ cp spl/u-boot-spl.bin ../imx-mkimage/iMX8QX/ $ cp u-boot-nodtb.bin ../imx-mkimage/iMX8QX/ $ cd ..   5 - ARM Trusted Firmware 5.1 - Clone the imx-atf:  $ git clone https://source.codeaurora.org/external/imx/imx-atf -b imx_4.19.35_1.1.0 $ cd imx-atf 5.2 - Build it:  $ unset LDFLAGS $ make PLAT=imx8qx bl31 5.3 - Copy the binary files to the MKimage/iMX8QX directory:  $ cp build/imx8qx/release/bl31.bin ../imx-mkimage/iMX8QX/ $ cd ..   6 - SCFW 6.1 - Export the ARM32 GCC6 Toolchain:  $ export TOOLS=~/gcc_toolchain/ 6.2 - Download the BSP L4.19.35_1.1.0_SCFW and copy it to the flash_build directory:  $ cp ~/Downloads/imx-scfw-porting-kit-1.2.7.1.tar.gz $ tar xvzf imx-scfw-porting-kit-1.2.7.1.tar.gz $ cd packages/ $ chmod a+x imx-scfw-porting-kit-1.2.7.1.tar.gz $ ./imx-scfw-porting-kit-1.2.7.1.bin 6.3 - Build it to i.MX 8QXP MEK B0:  $ cd imx-scfw-porting-kit-1.2.7.1/src/ $ tar xvzf scfw_export_mx8qx_b0.tar.gz $ cd scfw_export_mx8qx_b0/ $ make qx R=B0 B=mek 6.4 -  Copy the binary file to the MKimage/iMX8QX directory:  $ cp build_mx8qx_b0/scfw_tcm.bin ../../../../imx-mkimage/iMX8QX/ $ cp ../../../../ 7 - SECO Firmware Container Image 7.1 - Download the SECO firmware binaries and copy it to the flash_build directory $ cp ~/Downloads/firmware-imx-7.9.bin . $ chmod a+x firmware-imx-7.9.bin 7.2 - Copy the binary files to the MKimage/iMX8QX directory:  $ cp firmware-imx-7.9/firmware/seco/mx8qx-ahab-container.img /imx-mkimage/iMX8QX/ 8 - Build flash.bin 8.1 -  In a new terminal, open the imx-mkimage directory : $ cd flash_build/imx-mkimage 8.2 - Build it:  $ make SOC=iMX8QX flash 8.3 - Deploy it to the SDCard:  $ sudo dd if=iMX8QX/flash.bin of=/dev/sdX bs=1k seek=32 && sync Now, you are able to use any non-rpmsg.dtb without kernel errors. Author: Pedro Jardim: pedro.jardim@nxp.com
View full article
The resource management service offers the possibility to divide the system into groups of resources or partitions. Resources within a partition can not access resources outside of it's partition. Partitioning a system is useful to isolate resources from one another, this gives you the ability to have for instance FreeRTOS and Linux each running simultaneously with its own set of resources. In the FreeRTOS/Linux example you could partition/divide the system into two groups/partitions where all resources/peripherals needed by FreeRTOS would be completely isolated from the resources needed by Linux, if any of the resources on the Linux partition tried to access a resource on the FreeRTOS partition the transaction would result in a bus error, as if the resource tried to access a region outside of its memory map. The partitioning mechanism is   enforced by hardware   and the configuration of the underlying hardware is completely abstracted by the SCFW API. The system partitioning can be performed in two ways: At   boot time   by modifying the function board_system_config on the board.c portion of the SCFW porting kit that corresponds to your board. This is used for software that is loaded as part of the boot process. At   run time   by calling the resource management service functions available. This is used to partition software that is launched by an operating system, e.g. an M4 used as sensor fusion and loaded/started by Linux. A partition can have: Resources (peripherals) Pads Memory regions All of the items mentioned above can be grouped within a partition. It is important to note that: At boot time all resources are grouped into a single partition. Resources can only be assigned to another partition by a resource within it's own partition.  Initial partitioning state of the system At boot time the system is initially configured in three partitions: The first partition (SCFW) contains all the resources, pads and memory required by the System Controller Unit (SCU) to execute the System Controller Firmware. The second partition (SECO) contains all the resources required by the Security Controller to execute. The third partition (Boot) contains all of the remaining resources, pads and memory available for the whole system. Once Linux and the M4 boot a typical use case is to partition the system as follows: In this case the boot partition is split into the ATF/Linux partition and the M4 partition. The ARM Trusted Firmware environment add a layer of abstraction to secure the environment and it is assigned cores and memory to execute in this privileged state, all the remaining resources, pads and memory are assigned to the Linux partition. The M4 partition contains all the resources required by the M4 to execute, as well as the resources required by the application running on the M4. Resource partitioning - Boot time configuration The SCFW porting kit provides an example on doing boot time configuration at the board.c file under platform/board/mx8q<x or m>_<your board>/board.c, board_system_config is the function in charge of partitioning the system at boot time. From the sc_fw_port.pdf (porting guide) document included in the porting kit - Boot Flags chapter: Here are a few important points to highlight: The code will only execute if the SC_BD_FLAGS_ALT_CONFIG is set under the boot flags (more details in the Usage chapter of the sc_fw_port.pdf), the flags are set while building the image with mkimage. An example is provided to build an image with partitioning enabled: flash_linux_m4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_image.bin ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ The example above can be found under your i.MX8 variant on the soc.mak file, in the example above the SC_BD_FLAGS_ALT_CONFIG flag is being set by -flags 0x00200000 and the partition for the M4 is defined as the third one by the -p3 parameter. Without the -flags 0x00200000 (setting SC_BD_FLAGS_ALT_CONFIG) parameter on mkimage NO partition happens at boot time, if the target used to build the image does not set this flag, then the SCU does not partition the system. On the board.c file the code in charge of checking for this flag is the following: /* Configure initial resource allocation (note additional allocation and assignments can be made by the SCFW clients at run-time */ if ( alt_config != SC_FALSE ) { ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ if the alt_config flag is not set, then the partitioning is skipped. The function rm_dump(pt_boot); dumps the partitioning state of the whole system, it can be called before and after the partitioning to make sure the device was partitioned as expected. Here is how a partition dump looks like: *** Partitions ********************************** Partition: 0 Parent: 0 DID: 2 Flags: Used Secure Isolated Partition: 1 Parent: 0 DID: 0 Flags: Used Isolated Partition: 2 Parent: 0 DID: 1 Flags: Used Secure Restricted Isolated *** Resources *********************************** Partition: 0 SC_PID0 SC_SEMA42 SC_TPM SC_PIT SC_UART ... Continues .... DBLOGIC DRC_0 DRC_1 Partition: 1 SC_PID1 SC_PID2 SC_PID3 SC_PID4 ... Continues .... BOARD_R5 BOARD_R6 BOARD_R7 Partition: 2 SECO CAAM_JR1 CAAM_JR1_OUT *** Memory Regions ****************************** Partition: 0 000: 0x030FE0000 - 0x03101FFFF Partition: 1 001: 0x000000000 - 0x01BFFFFFF 002: 0x034000000 - 0x037FFFFFF 003: 0x038000000 - 0x03BFFFFFF 004: 0x060000000 - 0x06FFFFFFF 005: 0x070000000 - 0x07FFFFFFF 006: 0x080000000 - 0x0FFFFFFFF 007: 0x400000000 - 0x43FFFFFFF 008: 0x880000000 - 0xFFFFFFFFF Partition: 2 *** Pads **************************************** Partition: 0 M40_I2C0_SCL M40_I2C0_SDA ... Continues .... SCU_BOOT_MODE4 SCU_BOOT_MODE5 Partition: 1 SIM0_CLK SIM0_RST SIM0_IO ... Continues .... ENET1_RGMII_RXD2 ENET1_RGMII_RXD3 COMP_CTL_GPIO_1V8_3V3_ENET_ENETA Partition: 2‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The dump contains the configuration of the partition, for instance: *** Partitions ********************************** Partition: 0 Parent: 0 DID: 2 Flags: Used Secure Isolated‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ On the example above the Partition parent is partition 0 (itself, this is the System Controller partition, all partitions spawn from this one). The Domain ID (DID) is 2, this ID is used to identify the partition by the hardware, it is used to enforce hardware isolation. It is also a secure and isolated partition, the meaning of these flags can be found below and in the sc_fw document: Secure - boolean indicating if this partition should be secure; only valid if caller is secure Isolated - boolean indicating if this partition should be HW isolated; set SC_TRUE if new DID is desired Restricted - boolean indicating if this partition should be restricted; set SC_TRUE if masters in this partition cannot create new partitions Grant - boolean indicating if this partition should always grant access and control to the parent Coherent - boolean indicating if this partition is coherent; set SC_TRUE if only this partition will contain both AP clusters and they will be coherent via the CCI The rest of the sections of the dump highlight all the resources, pads and memory regions enclosed in each partition. For more details on the definition of all the API calls please refer to the respective sc_fw_api document for each SoC variant. Resource partitioning - Run time configuration  The run time partitioning doesn't differ from the example provided on the porting kit, that example can be used as a base to create a partition at run time by calling the SCFW API.  Examples The following examples will show how to modify the default partition configuration on the evaluation boards, i.MX8QM MEK will be used as a reference. With BSP 4.14.98_2.3.0, the porting kit can be obtained from i.MX Software and Development Tools | NXP . Default configuration without partitioning First we will dump the default configuration without partition, e.g. without setting the ALT_CONFIG flag, most mkimage targets with a single image are configured this way, see the soc.mak and related files under scripts: soc.mak\iMX8QM - imx-mkimage - i.MX Mkimage Bootloader Tool  For details on how to create a bootable image see i.MX8 Boot process and creating a bootable image  We can see that the targets flash and flash_spl do not set any flags on the image, therefore no partition of the system will occur at boot time. flash: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf.bin ./$(MKIMG) -soc QM -rev B0 -append $(AHAB_IMG) -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -out flash.bin‍‍‍‍ ‍ ‍ We will build the SCFW with the Debug Monitor enabled in order to be able to dump the partitions: make qm R=B0 B=mek M=1‍‍‍ ‍ Now we copy the SCFW binary we just build (scfw_tcm.bin under build_mx8qm_b0) to the mkimage iMX8QM folder, along with the SECO FW, ATF (bl31.bin) and u-boot. On mkimage the flash target will be used to create a bootable image with the SCFW we just build: make SOC=iMX8QM flash‍‍‍‍ ‍ Flash the image to your sd card sudo dd if=iMX8QM/flash.bin of=/dev/mmcblkXX bs=1k seek=32 sync‍‍‍‍‍‍ ‍ ‍ The MEK has two serial ports, the first one (usually ttyUSB0) is used by the A cores (u-boot/Linux in this case), the second one is used by one of the M4 cores OR the SCFW, in this case it will be used by the SCFW.  Unfortunately there aren't enough serial ports on the MEK board to allow a dedicated port for SCU, M4 cores and A cores, so in order to use the Debug Monitor on the MEK the SCFW has to take over the M4_0 UART terminal. On the SCFW Debug monitor terminal type "dump rm" this will dump all the partition information, the full log is attached to this document (imx8qm_mek_no_partition.txt). On this log it can be seen that 4 partitions are created: Partition 0 --> SCFW Partition 1 --> ATF Partition 2 --> SECO Partition 3 --> U-boot/Linux/M4 cores/Rest of the system The ATF partition is created at run time by the ATF to run in its secure state, no extra partition is created at boot time, if an image without ATF where to be used only three partitions would be seen: Partition 0 --> SCFW Partition 1 --> U-boot/Linux/M4 cores/Rest of the system Partition 2 --> SECO Default configuration with partitioning enabled Now we will create an image with the SC_BD_FLAGS_ALT_CONFIG flag set, so that partitioning occurs at boot time, for demonstration purpose we will use the same target previously used but we will modify it to set the ALT_CONFIG flag, so on mkimage modify the flash target as follows: On iMX8QM/soc.mak flash: $(MKIMG) $(AHAB_IMG) scfw_tcm.bin u-boot-atf.bin ./$(MKIMG) -soc QM -rev B0 -append $(AHAB_IMG) -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -out flash.bin‍‍ ‍ ‍ After the modification build the image again make clean make SOC=iMX8QM flash‍‍ ‍ ‍ On mkimage's output you should be able to see: FLAG: 0x00200000 Note how the same SCFW is used as in the previous example, same for ATF, SECO, U-boot the only required change in this case is to enable the ALT_CONFIG flag in the image. Flash the sd card with the new image sudo dd if=iMX8QM/flash.bin of=/dev/mmcblkXX bs=1k seek=32 ‍ ‍ ‍ Dumping again the partitioning on the Debug monitor shows how the system now created additional partitions for the M4 cores and a shared partition: Partition 0 --> SCFW Partition 1 --> ATF (Created at run time by the ARM Trusted Firmware) Partition 2 --> SECO Partition 3 --> M4_0 Partition 4 --> M4_1 Partition 5 --> Shared partition Partition 6 --> U-boot/Linux/rest of the system The full log is attached as well. Modifying default configuration Now we will modify the default SCFW configuration to move some resources/pads from the M4 partition to the A cores partition (u-boot/Linux). All FlexCAN resources and pads will be moved from the M4 partition to the A core partition. From sc_fw_api_qm_b0.pdf Resource List: From sc_fw_api_qm_b0.pdf Pad List: Not all resources are available on all variants, for details on what resources/pads are available on your device please refer to its respective api document. Go back to the SCFW porting kit and open platform/board/mx8qm_mek/board.c, go to the definition of board_system_config which is the function where partitioning occurs. The code first verifies if the alt_config flag is set, and if not it skips partitioning, so all partitioning happens within the following if statement: /* Configure initial resource allocation (note additional allocation and assignments can be made by the SCFW clients at run-time */ if ( alt_config != SC_FALSE ) ‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ The following partitions and memory regions are declared within this if statement: sc_rm_pt_t pt_m4_0 ; sc_rm_pt_t pt_m4_1 ; sc_rm_mr_t mr_m4_0 , mr_m4_1 ; sc_rm_pt_t pt_sh ; sc_rm_mr_t mr_sh ; ‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ pt_m4_0 is the partition for the M4_0 core, its memory region is declared as mr_m4_0. Likewise for the M4_1 pt_m4_1 and mr_m4_1 are the partitions and memory regions assigned to the M4. pt_sh and mr_sh are the shared partition and memory region. A shared partition is created but it can only have a shared memory region. Pads and resources CANNOT BE SHARED there is no mechanism to protect the pads and resources from contention, if access to a resource is required by multiple partitions a virtual resource needs to be created, in this way the partition that requires access asks the partition that owns the resource to configure/use the resource on its behalf. See the VIRT_I2C example on the Linux BSP. The partition that hosts all remaining resources is the pt_boot partition, this can be seen as the A cores partition, all resources and memory regions not assigned to the M4 partitions will be left on the pt_boot partition where the A cores are. The code is documented well and self-explanatory, for instance the following line marks all resources within the M4_0 subsystem to be moved to the M4_0 partition: /* Mark all M4_0 subsystem resources as movable */ BRD_ERR ( rm_set_subsys_rsrc_movable ( pt_boot , SC_R_M4_0_PID0 , SC_TRUE ) ) ; BRD_ERR ( rm_set_pad_movable ( pt_boot , SC_P_M40_I2C0_SCL , SC_P_M40_GPIO0_01 , SC_TRUE ) ) ; ‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ The resource list in the sc_fw_api_qm_b0.pdf document shows what resources belong to the M4 subsystem: Next some other resources required by the M4 are assigned to its partition, such as MUs used to communicate with the other cores, timers and the IRQ steer resource. In this case we are interested on having the FlexCAN resources/pads on the A cores side, these resources/pads are being assigned to the M4_1 partition as can be seen on the previous partitions dumps and the following code: /* Move some resources not in the M4_1 subsystem */ BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_IRQSTR_M4_1 , SC_R_IRQSTR_M4_1 , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_UART_2 , SC_R_UART_2 , SC_TRUE ) ) ; BRD_ERR ( rm_set_pad_movable ( pt_boot , SC_P_UART0_CTS_B , SC_P_UART0_RTS_B , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_MU_6B , SC_R_MU_6B , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_MU_7B , SC_R_MU_7B , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_MU_9B , SC_R_MU_9B , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_GPT_3 , SC_R_GPT_3 , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_CAN_0 , SC_R_CAN_2 , SC_TRUE ) ) ; BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_FSPI_0 , SC_R_FSPI_0 , SC_TRUE ) ) ; /* Move some pads not in the M4_1 subsystem */ BRD_ERR ( rm_set_pad_movable ( pt_boot , SC_P_FLEXCAN0_RX , SC_P_FLEXCAN2_TX , SC_TRUE ) ) ; BRD_ERR ( rm_set_pad_movable ( pt_boot , SC_P_QSPI0A_DATA0 , SC_P_COMP_CTL_GPIO_1V8_3V3_QSPI0 , SC_TRUE ) ) ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Previous dump: *** Resources *********************************** Partition: 4 M4_1_PID0 UART_2 CAN_0 CAN_1 CAN_2 IRQSTR_M4_1 *** Pads **************************************** Partition: 4 M41_I2C0_SCL M41_I2C0_SDA M41_GPIO0_00 M41_GPIO0_01 UART0_RTS_B UART0_CTS_B FLEXCAN0_RX FLEXCAN0_TX FLEXCAN1_RX FLEXCAN1_TX FLEXCAN2_RX FLEXCAN2_TX So we just need to remove the following lines from the board.c: BRD_ERR ( rm_set_resource_movable ( pt_boot , SC_R_CAN_0 , SC_R_CAN_2 , SC_TRUE ) ) ; BRD_ERR ( rm_set_pad_movable ( pt_boot , SC_P_FLEXCAN0_RX , SC_P_FLEXCAN2_TX , SC_TRUE ) ) ; ‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ That way the resources/pads won't be marked to be moved to the M4_1 partition and they will be left on the pt_boot partition (A core partition). If a resource needs to be added to the M4 partition just add the calls to rm_set_resource_movable to assign it. Now we just need to rebuild the scfw and our image: make qm R=B0 B=mek M=1‍‍‍‍ ‍ Then on mkimage (with the flags set modification above): make SOC=iMX8QM flash‍‍‍ ‍ Flash the sd card with the new image: sudo dd if=iMX8QM/flash.bin of=/dev/mmcblkXX bs=1k seek=32 ‍ ‍ ‍ Now when the dump is done we can see that the FlexCAN resources and pads belong to the same partition as the A cores (partition 6). *** Resources *********************************** Partition: 6 FTM_1 CAN_0 CAN_1 CAN_2 DMA_1_CH0 *** Pads **************************************** Partition: 6 COMP_CTL_GPIO_1V8_3V3_GPIOLHT FLEXCAN0_RX FLEXCAN0_TX FLEXCAN1_RX FLEXCAN1_TX FLEXCAN2_RX FLEXCAN2_TX COMP_CTL_GPIO_1V8_3V3_GPIOTHR The device tree would still need to be modified to configure the pads and FlexCAN resources. System Controller Firmware 101 
View full article
Recently I published this i.MX Dev Blog post about the Gateworks plugin gst-variable-rtsp-server support for i.MX 6. Now, you can check how to use it on i.MX 8 SoCs as well. 1. Preparing the image In order to use gst-variable-rtsp-server plugin, prepare your machine and distro: Add the following line to conf/local.conf: IMAGE_INSTALL_append += " gstreamer1.0-rtsp-server gst-variable-rtsp-server " Download the attached patch and apply it by doing: $ cd <yocto_path>/sources/meta-fsl-bsp-release/ $ git am ~/Download/0001-Add-RTSP-support-for-i.MX-8-L4.14.78_ga1.0.0-or-olde.patch Note: This patch is not necessary for L4.14.98_ga2.0.0 BSP! Then, build the image with bitbake and deploy it to the SD card. 2. Video Test Source Example Server $ gst-variable-rtsp-server -p 9001 -u "videotestsrc ! v4l2h264enc ! rtph264pay name=pay0 pt=96" Client 2. Camera Example Server $ gst-variable-rtsp-server -p 9001 -u "v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480 ! v4l2h264enc ! rtph264pay name=pay0 pt=96" Client In order to use VLC or other application as the client, just enter the URL as shown in the image below:
View full article
When working with an evaluation kit you will be provided with a System Controller Firmware (SCFW) binary included in your BSP. This scfw binary has been tailored for that specific board and you might need to modify some board dependencies to fit your specific hardware. This document aims to provide an overview on the SCFW porting process, for detailed information please refer to the System Controller Porting guide (sc_fw_port.pdf). Setting up the system The SCFW is built on a Linux host. The steps to set-up your system are the following: Download the GNU ARM Embedded Toolchain: 6-2017-q2-update June 28, 2017 from the ARM website: Select a directory to untar the file unto, for instance: mkdir ~/gcc_toolchain cp ~/Downloads/gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2 ~/gcc_toolchain/ cd ~/gcc_toolchain/ tar xvjf gcc-arm-none-eabi-6-2017-q2-update-linux.tar.bz2‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ Set TOOLS environment variable to the directory containing the tool chain, "~/gcc_toolchain" on the example above, .bash_profile can also be modified to export this environment variable: export TOOLS=~/gcc_toolchain/ srec_cat is also necessary for the build, this is usually contained in the srecord package, on ubuntu you can do: sudo apt-get update sudo apt-get install srecord Now you can change to the porting kit directory (e.g. scfw_export_mx8qm) and build the scfw. System Controller Firmware Porting kit  The SCFW porting kit contains source files and object files that will allow you to modify the SCFW to work with your board. You can get the latest System Controller Firmware Porting kit from the   i.MX Software and development webpage : Once you obtain the porting kit untar it: tar xvzf imx-scfw-porting-kit-1.1.tar.gz ‍ You will see the following file structure: The porting kit is contained under packages, the README contains the instructions to extract the porting kit, basically: cd packages/ chmod a+x imx-scfw-porting-kit-1.1.bin ./imx-scfw-porting-kit-1.1.bin ‍ ‍ ‍ You will be prompted to accept an End User License Agreement: Once you accept the agreement the porting kit will be extracted in a new folder, the folder structure is as follows: All documentation regarding SCFW is under doc/pdf or in html format if preferred, it is recommended to go over sc_fw_port.pdf. The porting kits for different SoC variants (QM A0, QM B0 and QXP B0) are under src packaged as tar.gz, all other files are SCFW libraries for different software packages, such as Linux, QNX, FreeRTOS, U-boot, ARM Trusted Firmware, etc... If you will be working with several SoC variants (working with both QXP and QM) it is recommended to extract all porting kits into a single directory, that way you will be able to build for any variant from this directory, the command to do this is: cd imx-scfw-porting-kit-1.1/ cd src/ find scfw_export_mx8*.gz -exec tar --strip-components 1 --one-top-level=scfw_export_mx8 -xzvf {} \; ‍ ‍ ‍ A scfw_export_mx8 folder will be created, from here you will be able to build SCFW for any supported variant. Or you can just extract the package for the variant you are interested on and use that. cd scfw_export_mx8/ ‍ All the build folders contain the results of building the SCFW and platform is where the source of the SCFW is stored. All the code that is specific to a board configuration is under "platform/board/mx8<derivative>_<board_name>" where derivative is the i.MX8 silicon family such as QXP or QM, and board name is the name of the board the SCFW package is for. The first step in porting the SCFW to your board is to create a folder for your i.MX8 derivative and board, you can take one of the available board examples and rename the folder, that will provide you a project to get started with, for instance: cp -r platform/board/mx8qm_val/ platform/board/mx8qm_myBoard/‍‍‍‍‍‍‍‍‍ ‍ The board in this example will be called "myBoard" and it is for an i.MX8QM B0 device. To build a SCFW for this board simply call: make qm R=B0 B=myBoard‍‍‍‍‍‍‍‍‍‍‍ ‍ If the target is an i.MX8QXP simply take a board based on this device and change the call to "make qx". Additional information such as build options and in detailed boot information can be found in the SCFW porting guide (sc_fw_port.pdf), chapter 2 of this document is a great introduction to the porting process. Overview and useful information Configuring the PMIC overview and board.c common modifications The main file that needs to be altered (if not the only) is the "board.c" file, it is located at "platform/board/mx8X_board/". The board.c file contains most of the board related information such as SCU UART ports, PMIC initialization routines, PMIC temperature alarms settings and you can also modify it to configure LDOs voltages and communicate with the PMIC in general. All functions in the board.c file are executed by the SCU itself and this gives you access to the I2C interface that is used to communicate with the PMIC. SoC resources that are powered by an external supply (PMIC LDO for instace) such as AP cores and GPUs are powered off/on by board_set_power_mode, the mapping of the resource to an specific PMIC supply happens in board_get_pmic_info, for instance in our i.MX8QM validation board using the A53 subsystem is powered by SW2 of the third PMIC (PMIC_2_ADDR addresses start at PMIC_0) on the PF100 PMIC card and by SW5 of the first PMIC (PMIC_0_ADDR) on the PF8100 PMIC card. case SC_SUBSYS_A53 : pmic_init ( ) ; if ( pmic_card == PF100 ) { pmic_id [ 0 ] = PMIC_2_ADDR ; pmic_reg [ 0 ] = SW2 ; * num_regs = 1 ; } else { /* PF8100_dual Card */ pmic_id [ 0 ] = PMIC_0_ADDR ; pmic_reg [ 0 ] = PF8100_SW5 ; * num_regs = 1 ; } break ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The voltages of SoC resources that are powered by an external supply (AP cores, GPUs, etc...) are managed by board_set_voltage in the board.c file. The mapping of resource to power supply occurs in board_get_pmic_info as in the example above. Eight "board resources" (SC_R_BOARD_R0, ... SC_R_BOARD_R7) are available, these resources allow you to define components in your board that the SCU can manage, for instance a sensor on your board powered by one of the PMIC LDOs can be mapped to a board resource and the board.c file can be modified to power on/off the sensor as well as modifying its voltage. Modifying the voltage on a board resource can be either be done by modifying the voltage at board_trans_resource_power (see below) or if the voltage needs to change at run time the function board_set_control can be modified to change the voltage whenever a miscellaneous call (more details in the Miscellaneous Service 101) is made on that resource. For instance to change the voltage on SC_R_BOARD_R7 you would have the following case to board_set_control: case SC_R_BOARD_R7 : if ( ctrl == SC_C_VOLTAGE ) { /* Example only PMIC_X_ADDR and PMIC_SUPPLY need to match an actual device */ pmic_interface . pmic_set_voltage ( PMIC_X_ADDR , PMIC_SUPPLY , val , step ) ; } else return SC_ERR_PARM ; break ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The case above will be executed by the SCU every time the application calls the function below: sc_misc_set_control ( ipc , SC_R_BOARD_R7 , SC_C_VOLTAGE , voltage_val ) ; ‍‍‍‍‍‍‍ ‍ Powering on/off a board resource happens at board_trans_resource_power in the board.c file. For instance in NXP's validation board the PTN5150 on the board is managed through a board resource 0, and the power on/off is managed as follows: case BRD_R_BOARD_R0 : /* PTN5150 (use SC_R_BOARD_R0) */ if ( pmic_ver . device_id == PF100_DEV_ID ) { if ( to_mode > SC_PM_PW_MODE_OFF ) { pmic_interface . pmic_set_voltage ( PMIC_2_ADDR , VGEN6 , 3300 , SW_RUN_MODE ) ; pmic_interface . pmic_set_mode ( PMIC_2_ADDR , VGEN6 , VGEN_MODE_ON ) ; } else { pmic_interface . pmic_set_mode ( PMIC_2_ADDR , VGEN6 , VGEN_MODE_OFF ) ; } } else { /* PF8100_dual Card */ if ( to_mode > SC_PM_PW_MODE_OFF ) { pmic_interface . pmic_set_voltage ( PMIC_1_ADDR , PF8100_LDO1 , 3300 , REG_RUN_MODE ) ; pmic_interface . pmic_set_mode ( PMIC_1_ADDR , PF8100_LDO1 , RUN_EN_STBY_EN ) ; } else { pmic_interface . pmic_set_mode ( PMIC_1_ADDR , PF8100_LDO1 , RUN_OFF_STBY_OFF ) ; } } break ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Whenever the function below is called from the application side the SCU will execute the code above: sc_pm_set_resource_power_mode ( ipc , SC_R_BOARD_R0 , SC_PM_PW_MODE_ON / OFF ) ; ‍‍‍‍‍‍‍ ‍ board_config_sc is used to mark resources that the SCU needs, such as the I2C module and pads used to communicate with the PMIC, any resource needed by the board.c functions to work should be marked in this function as not movable, for instance to keep the SCU I2C module the following line is added: rm_set_resource_movable ( pt_sc , SC_R_SC_I2C , SC_R_SC_I2C , false ) ; ‍‍‍‍‍‍‍‍ ‍ The following pads are part of the SCU and the application will not be able to access them: - SC_P_SCU_PMIC_MEMC_ON - SC_P_SCU_WDOG_OUT - SC_P_PMIC_EARLY_WARNING - SC_P_PMIC_INT_B - SC_P_SCU_BOOT_MODE0 through SC_P_SCU_BOOT_MODE5 board_system_config is where early resource management occurs, this function is only called when the alt_config flag is set in the image, and it can create partitions and allocate resources to it. More details are found in the resource management service 101. board_get_pcie_clk_src defines the clock that the PCIe uses, it can be either BOARD_PCIE_PLL_EXTERNAL or BOARD_PCIE_PLL_INTERNAL. board_print is very useful to debug your changes the syntax is as follows: board_print ( 3 , "Debug printout %d\n" , val ) ; ‍‍‍‍‍‍ ‍ Where the first parameter is the Debug Level and from there on it works as a standard printf. The output will only be visible on the SCU debug output whenever the SCU is built with the corresponding debug level, in the case above the SCFW needs to be built as follows in order to see the output: make qm B=myBoard‍‍‍‍ DL=3 or higher (debug level goes from 0 to 5)‍‍‍‍‍‍ ‍ Usage examples The following utility shows how to make System Controller Firmware requests and provides a way to make such requests through command line interface on both QNX and Linux System Controller Firmware Command Line Utility for Linux and QNX System Controller Firmware 101  
View full article
Before reading: only a personal works and sharing, not any form of "release". I didn't find any confidential information from the packages. So, I'm publishing it here. This is only for testing purpose. Do NOT use it for building a product. Use it at your own risk!! Yocto is flexible and powerful, and also, big and slow (when building). Sometimes we only need to build uboot or kernel or some piece of testing code. It's really a waste of time to build-up the whole Yocto environment which may cost over 50GB disk space and over 3 hours of building. I've made some scripts and sum them up to form a toolset for building uboot, kernel and some testing code out of Yocto environment. It's only a simple container and expect to use with uboot and kernel source code from formal Freescale release and a SDK built from Yocto project. GitHub source repo:       https://github.com/gopise/gopbuild What’s made off (a full package, not only the container): 1.    Some scripts and configurations files. 2.    SDK built from Yocto. 3.    Uboot/kernel from specific version. 4.    A hello-world to demonstrate how to build app in this environment. 5.    A slimmed rootfs binary from specific BSP pre-built as base. Will customize base on the source under “rootfs” folder. Only a placeholder in the container-only version. How to use it: Several common used board configurations have been included in the script: 6qsabresd/6qsabreai/6qpsabreai. You can add more into the “gopbuild” script easily. The “sabresd” has been set as default.      If you want to build all for sabresd (First of all, de-compress the package): cd < de - compressed - folder > source envsetup [ It will prompt for selecting board configuration to be built . Choose one by input corresponding number or click < ENTER > for default board . ] gmk ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍      If you want to build specific module for default board, such as uboot: gmk uboot ‍‍‍‍‍‍‍ ‍ ‍      Build kernel for sabreai board instead of default device: gmk kernel sabreai ‍‍‍‍‍‍‍ ‍ ‍      Clean everything? gmk all clean ‍‍‍‍‍‍‍ ‍ ‍ After a successfully full build, you will get everything under “output” folder, including a log folder contains full build log:      “u-boot.imx/zImage/rootfs.tar.bz2/*.dtb”, can be used with MFG or uuu.      “fsl-image.sdcard”, can be burn into SD card directly. "Ready-for-building" Package: The "gopbuild" itself is a "container-only" package which doesn't contain any source or SDK. I've also made some packages based on latest BSP release for i.MX6/i.MX7/i.MX8. These packages are "ready-for-build" package which you can de-compress and build it directly. -------------------------------------------------------------------------------------------------- URL:https://pan.baidu.com/s/1Xlh1OBGsTRXez_NQw-Rjxg Password: gdc9 -------------------------------------------------------------------------------------------------- Note: 1. To build for i.MX8 (8QM/8MQ/8QXP), you need L4.14.* or above. 2. To build for i.MX8, please download the SCFW from i.MX software page       i.MX Software and Development Tools | NXP      After download, decompress corresponding package for specific chip and put it under "/platform/scfw/". Take i.MX8QXP for example:             /platform/scfw/scfw_export_mx8qx/ All material (uboot/kernel/test code and SDK) are from official Yocto release. Thanks!
View full article
The miscellaneous service is in charge of providing access to all features not handled by the other services some examples include the following features: Subsystems controls - Some subsystems have settings that can be configured through the SCFW. For instance it is possible to set thresholds for a temperature alarm and get the temperature value of the sensor in different resources. For a complete list of resources and its controls please refer to the sc_fw_api document Chapter 5 Control List. DMA configurations - The SCFW provides access to DMA grouping and priority functions. Security functions - The SCFW provides some security functions such as: Image loading and authentication Fuse writing Life cycle management. Debug features - The SCFW provides some debug functionality through its miscellaneous service, some examples include:  Output a character through the SCU UART port Obtain SCFW build information (SCFW version) Obtain device Unique ID For a complete list of functions supported by your device please refer to the (SVC) Miscellaneous Service chapter of the sc_fw_api document.  This guide will cover the most common functions,  Getting and setting a control The process to get and set a control on a resource is the same for all available controls. Refer to the Control list chapter of your SoC SCFW API document for a complete list of the available controls. The following example will be based on an i.MX8QM.  The control list looks as follows: The table lists the controls available per resource as well as the width of the data to get/set, the 'Set' column describes whether a control is 'settable' or not, for instance the temperature sensor on the A53 resource can only be read/retrieved it cannot be 'written' (set) therefore the 'Y' (yes) in this column is missing, a brief description of the control is also provided. To get a control sc_misc_get_control must be called: uint32_t val ; sc_misc_get_control ( ipc , SC_R_A53 , SC_C_TEMP , & val ) ‍ ; ‍‍‍‍ ‍ ‍ By default all calls to get_control need a pointer to a 32 bit unsigned integer, the width field on the control list table defines the span of meaningful data. In the example above the data from the temperature sensor in the A53 resource is retrieved. This call returns SC_ERR_NONE whenever it succeeds. If the parameters are invalid it returns SC_PARM and if the caller does not have access to that resource it returns SC_ERR_NOACCESS. To set a control sc_misc_set_control must be called: uint32_t val = high_alarm_temperature_value ; sc_misc_set_control ( ipc , SC_R_A53 , SC_C_TEMP_HI , val ) ; ‍‍‍‍‍‍ ‍ ‍ As in the get example sc_misc_set_control expects a 32 bit unsigned integer, it is the responsibility of the user to pass a value within the width limits defined in the control list table. In the example above the upper threshold for the A53 resource is being set/configured. The return values are the same as in sc_misc_get_control. Other functions There is a different method for getting/setting temperatures in a friendly human readable format, the method above uses a 'raw' format to interact with the temperature sensors in the resources, an easier way is to use the sc_misc_get_temp and sc_misc_set_temp functions. This functions return the temperature value in degrees Celsius as well as it's fractional part. To define whether to get/set the value for the temperature sensor itself or one of it's alarm the sc_misc_temp_t has been defined. SC_MISC_TEMP      -> Temperature sensor SC_MISC_TEMP_HIGH -> Upper threshold temperature sensor alarm SC_MISC_TEMP_LOW  -> Lower threshold temperature sensor alarm‍‍‍‍‍‍ ‍ ‍ ‍ For instance to get the temperature reading from the A53 resource the following call can be made: int16_t celsius ; int8_t tenths ; sc_misc_get_temp ( ipc , SC_R_A53 , SC_MISC_TEMP , & celsius , & tenths ) ; ‍‍‍‍‍‍ ‍ ‍ ‍ And to set the upper threshold alarm: int16_t celsius = 80 ; int8_t tenths = 0 ; /* Set High temperature alarm to 80 degrees Celsius */ sc_misc_set_temp ( ipc , SC_R_A53 , SC_MISC_TEMP_HIGH , celsius , tenths ) ; ‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ Unique ID of the chip as well as the build info of the SCFW can also be obtained through the miscellaneous service, the following example queries for this information: /* Getting SCFW version information */ uint32_t build_version ; uint32_t commit_hash ; sc_misc_build_info ( ipc , & build_version , & commit_hash ) ; ‍‍‍ /* Getting Device Unique ID */ uint32_t ID_L ; uint32_t ID_H ; /* The ID is a 64-bit number ID_L stores the lower 32-bit portion and ID_H the 32-bit upper portion */ sc_misc_unique_id ( ipc , & ID_L , & ID_H ) ; ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Refer to the sc_fw_api document for a definition of the remaining miscellaneous functions. https://community.nxp.com/docs/DOC-342654 
View full article
Platform: imx8qm mek imx-yocto-L4.14.98_2.0.0_ga Building Step: Apply the nvp6324 patches.   Symbol: IMX8_NVP6324 [=y] Type : tristate Prompt: IMX8 NVP6324 Driver Location: -> Device Drivers -> Multimedia support (MEDIA_SUPPORT [=y]) -> V4L platform devices (V4L_PLATFORM_DRIVERS [=y]) -> MX8 Video For Linux Video Capture (VIDEO_MX8_CAPTURE [=y]) (1) -> IMX8 Camera ISI/MIPI Features support ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ select nvp6324 to y in menuconfig(default is 'y') make Image -j8; make freescale/fsl-imx8qm-mek-nvp6324.dtb, to build kernel and dts, outputs are at  work/imx8qmmek-poky-linux/linux-imx/4.14.98-r0/build/arch/arm64/Image work/imx8qmmek-poky-linux/linux-imx/4.14.98-r0/build/arch/arm64/boot/dts/freescale/fsl-imx8qm-mek-nvp6324.dtb copy them to the sd  boot partition. reboot the board, you can test the first camera with command: ./mx8_v4l2_cap_drm.out -cam 1 -ow 1280 -oh 720 mx8_v4l2_cap_drm.out is at /unit_tests/V4L2/mx8_v4l2_cap_drm.out The corresponding video device should be default to /dev/video0 ~ /dev/video3.
View full article
The System Controller Unit (SCU) is in charge of controlling several features related to power management of the whole system. The user gets access to the following features through the System Controller Firmware: Powering up/down the system,resources and partitions Configuring resource clocks Reset controls Configuring wake-up sources This document will cover the more commonly used features, for details on the full capabilities of the API please refer to the API document for your device. Resource Power Control The SCU is in charge of managing power control to the resources (peripherals) in the SoC. Attempting to access a resource on the OFF state will result in a bus error or a hang All resources are organized within several subsystems, subsystems group together resources with common functionality. Subsystems are independent of each other and have their own PLLs and power domains, this allows modular control of clocks and power to the resources. The System Controller Unit has a dedicated I2C channel to interact with the PMIC, this allows dynamic control of some power sources for resources like the GPUs and Cortex-A cores. The SCU can enable/disable the LDO that supplies power to the GPU for instance and also turn on/off the internal power domains. The mapping of PMIC supplies and resources happens on the board.c (included in the SCFW Porting kit) and it is part of the porting process of the SCFW to new boards. The function board_get_pmic_info is where the mapping of resources to supplies happen, see: /*--------------------------------------------------------------------------*/ /* Get the pmic ids and switchers connected to SS. */ /*--------------------------------------------------------------------------*/ static void board_get_pmic_info ( sc_sub_t ss , pmic_id_t * pmic_id , uint32_t * pmic_reg , uint8_t * num_regs ) { /* Map SS/PD to PMIC switch */ switch ( ss ) { case SC_SUBSYS_A53 : pmic_init ( ) ; { /* PF8100_dual Card */ pmic_id [ 0 ] = PMIC_0_ADDR ; pmic_reg [ 0 ] = PF8100_SW5 ; * num_regs = 1U ; } break ; case SC_SUBSYS_A72 : pmic_init ( ) ; { /* PF8100_dual Card */ pmic_id [ 0 ] = PMIC_0_ADDR ; pmic_reg [ 0 ] = PF8100_SW3 ; pmic_id [ 1 ] = PMIC_0_ADDR ; pmic_reg [ 1 ] = PF8100_SW4 ; * num_regs = 2U ; } break ; case SC_SUBSYS_GPU_0 : pmic_init ( ) ; { /* PF8100_dual Card */ pmic_id [ 0 ] = PMIC_1_ADDR ; pmic_reg [ 0 ] = PF8100_SW1 ; pmic_id [ 1 ] = PMIC_1_ADDR ; pmic_reg [ 1 ] = PF8100_SW2 ; * num_regs = 2U ; } break ; case SC_SUBSYS_GPU_1 : pmic_init ( ) ; { /* PF8100_dual Card */ pmic_id [ 0 ] = PMIC_1_ADDR ; pmic_reg [ 0 ] = PF8100_SW3 ; pmic_id [ 1 ] = PMIC_1_ADDR ; pmic_reg [ 1 ] = PF8100_SW4 ; * num_regs = 2U ; } break ; default : ; /* Intentional empty default */ break ; } } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ Only some subsystems have their own dedicated external power supplies, in the example above A cores and GPUs are the only ones with a dedicated external power supplies. Most of the other subsystems are powered from the main power supply and power gating happens internally, each subsystem contains different power domains that can be turned on/off to manage power consumption. The SCFW API used to power on/off resources is the following: sc_err_t sc_pm_set_resource_power_mode ( sc_ipc_t ipc , sc_rsrc_t resource , sc_pm_power_mode_t mode ) ‍‍‍‍ ‍ Where: ipc - is the interprocessor communication channel used to communicate with the SCU (obtained by calling sc_ipc_open). resource - is the resource that will have the power mode change mode - is the power mode to change to The available power mode options are the following: Power mode Voltage Clocks SC_PM_PW_MODE_OFF OFF All clocks off SC_PM_PW_MODE_STBY ON All clocks off SC_PM_PW_MODE_LP ON PLLs off resource running from XTAL SC_PM_PW_MODE_ON ON PLLs on In order to be able to access a resource it must be at least on SC_PM_PW_MODE_LP mode, since that mode has the resource voltage on and the clock is supplied by the 24MHz crystal. For more details please refer to the SCFW API document. Clocks Configuration As in the power management case, clocks are also organized in a distributed manner within the device. Each subsystem has it's own PLLs and all of them are clocked by the 24MHz crystal. The number of PLLs in each subsystem varies between all subsystems. To see how many PLLs are within a subsystem please refer to the datasheet of the device you are interested on. For instance on the datasheet of the i.MX8QXP on table 16 in Chapter 4.3.1: It can be seen that the GPU subsystem contains two PLLs, the ADMA subsystem contains 4 PLLs, Display Controller 3, etc... The SCFW API used to configure a clock is the following: sc_err_t sc_pm_set_clock_rate ( sc_ipc_t ipc , sc_rsrc_t resource , sc_pm_clk_t clk , sc_pm_clock_rate_t ∗ rate ) ‍ ‍ ‍ ‍ ‍ Where: ipc - is the interprocessor communication channel used to communicate with the SCU (obtained by calling sc_ipc_open). resource - is the resource that will have the clock rate change clk - is the clock to set the rate to (each resource can have different clocks associated with it for instance the GPU resource has a clock associated for its shader and another for the GPU, this parameter is used to identify the clock) rate - this contains the desired clock rate, the SCFW will try to match the provided rate if not possible it will then set the closest possible value and return the value that was actually configured. To identify the clk that needs to be passed, please refer to the SCFW API chapter called "Clock List" That chapter contains a table with all the different clocks that are configurable by the SCFW, in the case of the GPUs for instance to select the rate for the Shader or GPU, either the SC_PM_CLK_MISC or SC_PM_CLK_PER options would have to be selected. Set=Y indicates the clock/PLL is not shared and the rate can be set via sc_pm_set_clock_rate(). Enable=Y indicates the clock is not auto gated and must be enabled via sc_pm_clock_enable(). As an example the following snippet configures the GPU_0 shader clock: sc_clock_rate_t shader_clk = 700000000 ; // 700 MHz sc_pm_set_clock_rate ( ipc , SC_R_GPU_0_PID0 , SC_PM_CLK_MISC , & shader_clk ) ; ‍ ‍ System Controller Firmware 101 
View full article
NOTE: Always de-power the target board and the aggregator when plugging or unplugging smart sensors from the aggregator. NOTE: See this link to instrument a board with a Smart Sensor. This page documents the triple-range "smart" current sensor that's part of a larger system for profiling power on application boards. The smart sensor features a Kinetis KL05Z with three current sense amplifiers. It allows measurement currents in three ranges. Four assembly options allow measurement of rail voltages 0-3.3V (two overall current ranges), 0-6.6V, and 12V. It connects to an aggregator, which powers, controls and aggregates data from a number of smart sensor boards. One of the biggest improvements over the older dual-range measurement system is that the on-sensor microcontroller allows near-simultaneous measurement of all instrumented rails on a board. The dual range profiler can only make one measurement at a time.  These are intended to be used with a microncontroller board to act as a trigger and data aggregator. This aggregator could also be used to reprogram the sensors.  The series resistance added by the smart sensor when in run mode (highest current range) is under 11 milliOhms as measured with 4-point probes and a Keysight B2902B SMU.  A "power oscilloscope" can be made by triggering measurements at regular intervals and presenting the results graphically.... Schematic: Board Layout, Top: Board Layout, Bottom: Here's a photo of two with a nickel is included to show scale. The board measures about 0.5 by 1.3 inches. Connections: The smart sensor header connections are: 5V: powers the 3.3V regulator, which in turn powers everything else on the sensor board 12V: all the gates of all the switching FETs are pulled pulled up to 12V GND: ground connection SCL/TX: I2C clock line  SDA/RX:  I2C data line  SWD_CLK:  line for triggering smart sensors to make measurements RESET_B:  line for resetting the smart sensor board SWD_IO: select line for the smart sensor Theory of operation: Three shunts and current sense amplifiers are used to measure current in three ranges. One shunt/sense amp pair has a 0.002 Ω shunt integrated into the IC package (U1, INA250). The other two sense amps (U2 and U3, INA212) require an external shunt.  FETs Q1, Q2,  and Q3 are used to switch the two lower range shunt/sense amp pairs in and out of circuit. In normal run operation (highest current range), Q1 (FDMC012N03, with Rds(on) under 1.5m Ω ) is turned on, which shorts leaves only U1 in circuit. FETs Q4, Q5 and Q6 translate the voltages to 3.3V so that GPIO on U4 (MCU KL05Z) can control them.  Rail voltage measurement is facilitated via resistors R3, R4, and R12 and Q7. Not all of these are populated in every assembly option. For measuring rail voltages 0-3.3V, R12 is populated. To measure 0-6.6V, R3, R4,and Q7 are populated. When turned on Q7 enables the voltage divider. All of the assembly option population info can be found in the schematic (attached). Regulator U5 (AP2210N) provides the 3.3V supply for all of the components on the board. This 1% tolerance regulator is used to provide a good reference for the ADC in U4.  Microcontroller U4 detects the assembly population option of the board via resistors R9, R10, and R11 so that the same application code can be used across all variations of the sensor boards. GPIO control the FETs and four ADC channels are used to measure the sense amplifier outputs and the rail voltage. Having a microcontroller on the sensor board allows the user to do extra credit things like count coulombs as well as allowing all similarly instrumented rails to measure at the same time via trigger line SWD_CLK. Data communication can be via I2C or UART, since these two pins can do both.  But if multiple sensor boards are to be used with an aggregator, communication needs to be over I2C. Application Code: The latest application code for the KL05Z on the smart sensor resides here: https://os.mbed.com/users/r14793/code/30847-SMRTSNSR-KL05Z/. The latest binary is attached below. In order to re-flash a smart sensor, the modification detailed in the aggregator page needs to be made. Once the modification is completed, leave the aggregator unpowered while pluging the SWD debugger into J5 and the smart sensor to be programmed into JP15. Very old UART-based application code for the KL05Z, built in the on-line MBED compiler (note that it requires the modified mbed library for internal oscillator). This code was used while testing the first smart sensor prototypes. It has since been abandoned. It's published here in the event that a user wants to use a single sensor plugged into JP15 with UART breakout connector J6. /****************************************************************************** * * MIT License (https://spdx.org/licenses/MIT.html) * Copyright 2017-2018 NXP * * MBED code for KL05Z-based "smart" current sensor board, basic testing * of functions via UART (connected via FRDM board and OpenSDA USB virtual * COM port). * * Eventual goal is to have each smart sensor communicate over I2C to an * aggregator board (FRDM board with a custom shield), allowing 1-10 power * supply rails to be instrumented. Extra credit effort is to support * sensors and aggregator with sigrok... * * Because there is no crystal on the board, need to edit source mbed-dev library * to use internal oscillator with pound-define: * change to "#define CLOCK_SETUP 0" in file: * mbed-dev/targets/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/device/system_MKL05Z4.c * ******************************************************************************/ #include "mbed.h" // These will be GPIO for programming I2C address... // not yet implemented, using as test pins... DigitalOut addr0 ( PTA3 ) ; DigitalOut addr1 ( PTA4 ) ; DigitalOut addr2 ( PTA5 ) ; DigitalOut addr3 ( PTA6 ) ; // configure pins for measurements... // analog inputs from sense amps and rail voltage divider... AnalogIn HIGH_ADC ( PTB10 ) ; AnalogIn VRAIL_ADC ( PTB11 ) ; AnalogIn LOW1_ADC ( PTA9 ) ; AnalogIn LOW2_ADC ( PTA8 ) ; // outputs which control switching FETs... DigitalOut VRAIL_MEAS ( PTA7 ) ; // turns on Q7, connecting voltage divider DigitalOut LOW_ENABLE ( PTB0 ) ; // turns on Q4, turning off Q1, enabling low measurement DigitalOut LOW1 ( PTB2 ) ; // turns on Q5, turning off Q2, disconnecting shunt R1 DigitalOut LOW2 ( PTB1 ) ; // turns on Q6, turning off Q3, disconnecting shunt R2 // input used for triggering measurement... // will eventually need to be set up as an interrupt so it minimizes delay before measurement InterruptIn trigger ( PTA0 ) ; // use as a trigger to make measurement... // PTB3/4 can be used as UART or I2C... // For easier development with one smart sensor, we are using UART here... Serial uart ( PTB3 , PTB4 ) ; // tx, rx long int count = 0 ; int n = 25 ; // global number of averages for each measurement int i , temp ; bool repeat = true ; // flag indicating whether measurements should repeat or not const float vref = 3.3 ; // set vref for use in calculations... float delay = 0.25 ; // default delay between measurement bool gui = false ; // flag for controlling human vs machine readable output bool statistics = false ; // flag for outputting min and max along with average (GUI mode only) void enableHighRange ( ) { LOW_ENABLE = 0 ; // short both low current shunts, close Q1 wait_us ( 5 ) ; // delay for FET to settle... (make before break) LOW1 = 0 ; LOW2 = 0 ; // connect both shunts to make lower series resistance VRAIL_MEAS = 0 ; // disconnect rail voltage divider wait_us ( 250 ) ; // wait for B2902A settling... } void enableLow1Range ( ) { LOW1 = 0 ; LOW2 = 1 ; // disconnect LOW2 shunt so LOW1 can measure wait_us ( 5 ) ; // delay for FET to settle... (make before break) LOW_ENABLE = 1 ; // unshort low current shunts, open Q1 VRAIL_MEAS = 0 ; // disconnect rail voltage divider wait_us ( 250 ) ; // wait for B2902A settling... } void enableLow2Range ( ) { LOW1 = 1 ; LOW2 = 0 ; // disconnect LOW1 shunt so LOW2 can measure wait_us ( 5 ) ; // delay for FET to settle... (make before break) LOW_ENABLE = 1 ; // unshort low current shunts, open Q1 VRAIL_MEAS = 0 ; // disconnect rail voltage divider wait_us ( 500 ) ; // wait for B2902A settling... } void enableRailV ( ) { VRAIL_MEAS = 1 ; // turn on Q7, to enable R3-R4 voltage divider wait_us ( 125 ) ; // wait for divider to settle... // Compensation cap can be used to make // voltage at ADC a "square wave" but it is // rail voltage and FET dependent. Cap will // need tuning if this wait time is to be // removed/reduced. // // So, as it turns out, this settling time and // compensation capacitance are voltage dependent // because of the depletion region changes in the // FET. Reminiscent of grad school and DLTS. // Gotta love device physics... } void disableRailV ( ) { VRAIL_MEAS = 0 ; // turn off Q7, disabling R3-R4 voltage divider } // this function measures current, autoranging as necessary // to get the best measurement... void measureAuto ( ) { Timer t ; float itemp ; float tempI = 0 ; float imin = 1.0 ; // used to keep track of the minimum... float imax = 0 ; // used to keep track of the maximum... t . start ( ) ; // use timer to see how long things take... enableHighRange ( ) ; // this should already be the case, but do it anyway... for ( i = 0 ; i < n ; i ++ ) { itemp = HIGH_ADC ; // read HIGH range sense amp output if ( statistics && itemp > imax ) imax = itemp ; // update max if necessary if ( statistics && itemp < imin ) imin = itemp ; // update min if necessary tempI + = itemp ; // add current sample to running sum } tempI = tempI / n * vref / 0.8 ; // compute average we just took... if ( gui ) uart . printf ( "=> %5.3f " , tempI ) ; if ( statistics && gui ) uart . printf ( "[%5.3f/%5.3f] " , imin * vref / 0.8 , imax * vref / 0.8 ) ; // if current is below this threshold, use LOW1 to measure... if ( tempI < 0.060 ) { if ( ! gui ) uart . printf ( "... too Low: %f A, switching to low1 ==>\r\n" , tempI ) ; tempI = 0 ; enableLow1Range ( ) ; // change FETs to enable LOW1 measurement... imin = 1.0 ; imax = 0 ; for ( i = 0 ; i < n ; i ++ ) { itemp = LOW1_ADC ; // read LOW1 sense amp output if ( statistics && itemp > imax ) imax = itemp ; // update max if necessary if ( statistics && itemp < imin ) imin = itemp ; // update min if necessary tempI + = itemp ; // add current sample to running sum } tempI = tempI / n * vref / 0.05 / 1000 ; // compute average we just took... if ( gui ) uart . printf ( "%6.4f " , tempI ) ; if ( statistics && gui ) uart . printf ( "[%6.4f/%6.4f] " , imin * vref / 0.05 / 1000 , imax * vref / 0.05 / 1000 ) ; // if current is below this threshold, use LOW2 to measure... if ( tempI < 0.0009 ) { if ( ! gui ) uart . printf ( "... too Low: %f A, switching to low2 ==>\r\n" , tempI ) ; tempI = 0 ; enableLow2Range ( ) ; // change FETs to enable LOW1 measurement... imin = 1.0 ; imax = 0 ; for ( i = 0 ; i < n ; i ++ ) { itemp = LOW2_ADC ; // read LOW2 sense amp output if ( statistics && itemp > imax ) imax = itemp ; // update max if necessary if ( statistics && itemp < imin ) imin = itemp ; // update min if necessary tempI + = itemp ; // add current sample to running sum } tempI = tempI / n * vref / 2 / 1000 ; // compute average we just took... if ( gui ) uart . printf ( "%8.6f " , tempI ) ; if ( statistics && gui ) uart . printf ( "[%8.6f/%8.6f] " , imin * vref / 2 / 1000 , imax * vref / 2 / 1000 ) ; } } t . stop ( ) ; // stop the timer to see how long it took do do this... enableHighRange ( ) ; if ( ! gui ) uart . printf ( "\r\nCurrent = %f A Current Measure Time = %f sec\r\n" , tempI , t . read ( ) ) ; } // the autoranging should really be done with functions that return values, as should the // functions below... This would make for shorter and more elegant code, but the author // is a bit of a pasta programmer... void measureHigh ( ) { float highI = 0 ; enableHighRange ( ) ; for ( i = 0 ; i < n ; i ++ ) { highI + = HIGH_ADC ; } highI = highI / n ; uart . printf ( "HIghI = %f A\r\n" , vref * highI / 0.8 ) ; } void measureLow1 ( ) { float low1I = 0 ; enableLow1Range ( ) ; for ( i = 0 ; i < n ; i ++ ) { low1I + = LOW1_ADC ; } enableHighRange ( ) ; low1I = low1I / n ; uart . printf ( "low1I = %f A\r\n" , vref * low1I / 0.05 / 1000 ) ; } void measureLow2 ( ) { float low2I = 0 ; enableLow2Range ( ) ; for ( i = 0 ; i < n ; i ++ ) { low2I + = LOW2_ADC ; } enableHighRange ( ) ; low2I = low2I / n ; uart . printf ( "low2I = %f A\r\n" , vref * low2I / 2 / 1000 ) ; } // measure the rail voltage, default being with // a divide by 2 resistor divider // It has to be switched out when not in use or it will // add to the measured current, at least in the low ranges... void measureRailV ( ) { float railv = 0 ; float mult = vref * 2 ; // since divide by 2, we can measure up to 6.6V... float vmin = 5 ; float vmax = 0 ; float vtemp ; enableRailV ( ) ; // switch FETs so divider is connected... for ( i = 0 ; i < n ; i ++ ) { vtemp = VRAIL_ADC ; // read voltage at divider output... if ( statistics && vtemp > vmax ) vmax = vtemp ; // update max if necessary if ( statistics && vtemp < vmin ) vmin = vtemp ; // update min if necessary railv + = vtemp ; // add current sample to running sum } disableRailV ( ) ; // now disconnect the voltage divider railv = railv / n ; // compute average (note this is in normalized ADC [0..1]) // Convert to voltage by multiplying by "mult" if ( ! gui ) uart . printf ( "RailV = %5.3f V " , mult * railv ) ; if ( gui ) uart . printf ( "%5.3f " , mult * railv ) ; if ( statistics && gui ) uart . printf ( "[%5.3f/%5.3f] " , mult * vmin , mult * vmax ) ; uart . printf ( "\r\n" ) ; } // not sure how useful this function is... void measureAll ( ) { measureHigh ( ) ; measureLow1 ( ) ; measureLow2 ( ) ; measureRailV ( ) ; } // test function to see if trigger pin is being hit... // intended for use later to do timed triggering of measurements... void triggerIn ( ) { uart . printf ( "You're triggering me! \r\n" ) ; measureAll ( ) ; } // main... int main ( ) { // set up basic conditions... Timer m ; uart . baud ( 115200 ) ; enableHighRange ( ) ; // default state - only HIGH sense amp in circuit, no divider // signal that we're alive... uart . printf ( "Hello World!\r\n" ) ; // configure the trigger interrupt... trigger . rise ( & triggerIn ) ; while ( true ) { count ++ ; wait ( delay ) ; if ( repeat ) { // if repeat flag is set, keep making measurements... m . reset ( ) ; // reset and start timer... m . start ( ) ; measureAuto ( ) ; // measuring current using auto-ranging... measureRailV ( ) ; // measure rail voltage... m . stop ( ) ; // stop the timer. if ( ! gui ) uart . printf ( " Total Measure Time = %f sec" , m . read ( ) ) ; if ( ! gui ) uart . printf ( "\r\n\r\n" ) ; } // see if there are any characters in the receive buffer... // this is how we change things on the fly... // Commands (single keystroke... it's easier) // t = one shot automeasure // v = measure volt // h = one shot high measure // k = one shot LOW1 measure // l = one shot LOW2 measure (letter l) // r = toggle repeat // R = turn off repeat // + = faster repeat rate // - = slower repeat rate // = = set repeat rate to 0.25 sec // g = use human readable text output // G = use compressed text format for GUI // s = turn statistics output off // S = turn statistics output on (only in GUI mode) // n = decrease number of averages for each measurement // N = increase number of averages for each measurement // // these were for testing FET switching... // 1 = LOW_ENABLE = 0 (the number 1) // 2 = LOW1 = 0 // 3 = LOW2 = 0 // 4 = VRAIL_MEAS = 0 // ! = LOW_ENABLE = 1 // @ = LOW1 = 1 // # = LOW2 = 1 // $ = VRAIL_MEAS = 1 if ( uart . readable ( ) ) { temp = uart . getc ( ) ; if ( temp == ( int ) 't' ) { if ( ! gui ) uart . printf ( "Keyboard trigger: " ) ; measureAuto ( ) ; measureRailV ( ) ; //measureAll(); } if ( temp == ( int ) 'v' ) { uart . printf ( "Keyboard trigger: " ) ; measureRailV ( ) ; } if ( temp == ( int ) 'h' ) { uart . printf ( "Keyboard trigger: " ) ; measureHigh ( ) ; } if ( temp == ( int ) 'k' ) { uart . printf ( "Keyboard trigger: " ) ; measureLow1 ( ) ; } if ( temp == ( int ) 'l' ) { uart . printf ( "Keyboard trigger: " ) ; measureLow2 ( ) ; } if ( temp == ( int ) '1' ) { LOW_ENABLE = 0 ; uart . printf ( "Keyboard trigger: LowEnable = %d\r\n" , 0 ) ; } if ( temp == ( int ) '2' ) { LOW1 = 0 ; uart . printf ( "Keyboard trigger: LOW1 = %d\r\n" , 0 ) ; } if ( temp == ( int ) '3' ) { LOW2 = 0 ; uart . printf ( "Keyboard trigger: LOW2 = %d\r\n" , 0 ) ; } if ( temp == ( int ) '4' ) { VRAIL_MEAS = 0 ; uart . printf ( "Keyboard trigger: VRAILMEAS = %d\r\n" , 0 ) ; } if ( temp == ( int ) '!' ) { LOW_ENABLE = 1 ; uart . printf ( "Keyboard trigger: LowEnable = %d\r\n" , 1 ) ; } if ( temp == ( int ) '@' ) { LOW1 = 1 ; uart . printf ( "Keyboard trigger: LOW1 = %d\r\n" , 1 ) ; } if ( temp == ( int ) '#' ) { LOW2 = 1 ; uart . printf ( "Keyboard trigger: LOW2 = %d\r\n" , 1 ) ; } if ( temp == ( int ) '$' ) { VRAIL_MEAS = 1 ; uart . printf ( "Keyboard trigger: VRAILMEAS = %d\r\n" , 1 ) ; } if ( temp == ( int ) 'r' ) { repeat = ! repeat ; uart . printf ( "Keyboard trigger: repeat toggle: %s \r\n" , repeat ? "true" : "false" ) ; } if ( temp == ( int ) 'R' ) repeat = false ; if ( temp == ( int ) '+' ) { delay - = 0.05 ; if ( delay < 0.05 ) delay = 0.05 ; } if ( temp == ( int ) '-' ) { delay + = 0.05 ; if ( delay > 1 ) delay = 1 ; } if ( temp == ( int ) '=' ) delay = 0.25 ; if ( temp == ( int ) 'g' ) gui = false ; if ( temp == ( int ) 'G' ) gui = true ; if ( temp == ( int ) 's' ) statistics = false ; if ( temp == ( int ) 'S' ) statistics = true ; if ( temp == ( int ) 'n' ) { n - = 25 ; if ( n < 25 ) n = 25 ; } if ( temp == ( int ) 'N' ) { n + = 25 ; if ( n > 1000 ) n = 1000 ; } if ( temp == ( int ) 'N' || temp == ( int ) 'n' ) uart . printf ( "/r/n/r/n Averages = %d \r\n\r\b" , n ) ; } } } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍
View full article
This document intends to provide an overview of the i.MX8 Boot process and walk you through the process of creating a bootable image. Boot process Coming out of a reset state the i.MX8 ROM (firmware that is stored in non-volatile memory of the i.MX8) reads the boot mode pins to determine the boot media/device that will be used. The i.MX8 can boot out of the following boot devices: eMMC/SD card FlexSPI Flash NAND Serial Download Protocol (USB) - This is used in manufacturing mode to bring-up a board by downloading an image to RAM and then flashing the on-board boot device. The following table indicates the available options on a i.MX8QXP, the i.MX8 reads the boot mode pads and based in the configuration selects the desired boot device. Once the boot device has been identified, ROM configures the boot media and attempts to read the image from a predefined address in the boot device, the following table shows the addresses where the image is expected to be on different boot devices. ROM loads data from the predefined addresses above (depending on the selected boot device) to the System Controller Unit (SCU) internal memory (tightly coupled memory) and parses it to find the image container. It can also boot by downloading an image through USB. The image container has all the information needed to load all the images to the system, the first images that get loaded are the System Controller Firmware (SCFW) and Security Controller Firmware (SECO). The SECO FW needs to be loaded to refresh the watchdog timer (kick the dog) in the device, if the SECO FW is not loaded before the watchdog expires the device will reset, this usually happens when the device fails to fetch a valid image from the boot media. Once the SCFW is loaded, ROM jumps to it and starts executing it. The SCFW then initializes the DDR and starts loading the images for the Cortex-M4 (optional) and the Cortex-A cores (optional). Once the images are loaded to their destination memory the SCFW boots the cores and sets them in their start address. Creating a bootable image As a recap a bootable image is comprised of as minimum the System Controller Firmware and the Security Controller Firmware, optionally it can contain images for the Cortex M4 cores (if more than one available as in the case of QM devices) and Cortex A cores. It is possible to boot an image that only contains the SCFW and SECO FW, this could be useful in the first stages of porting the SCFW to the target board. It is also possible to boot an image with only the Cortex-M4 image (baremetal, FreeRTOS, AutoSAR...), only the Cortex-A image (U-boot or any bootloader) or both Cortex-M4 and Cortex-A images. Mkimage tool The tool in charge of merging all these images and creating a bootable image for the i.MX8 is called mkimage, and can be obtained in source form in the following repository: https://source.codeaurora.org/external/imx/imx-mkimage mkimage is only supported in Linux So the first step is to clone the mkimage repository into our machine and checkout the latest branch, at the time of writing this document the latest release is 4.14.98_02: git clone https://source.codeaurora.org/external/imx/imx-mkimage cd imx-mkimage git checkout imx_4.14.98_2.0.0_ga‍‍‍‍‍‍‍‍‍‍‍‍ ‍ ‍ ‍ You should now be able to see the following folders: Getting the SCFW Now that you have the mkimage tool you need some actual images to work with, if you are using a custom board you might need to port the SCFW and DDR configuration files for it (depending on how close it follows NXP's reference board). The following is a compendium of documents on the basics of the SCFW and how to build it from scratch you can go there if you need help getting started with the porting process: https://community.nxp.com/docs/DOC-342654 If you are trying this on one of NXP's reference board you can use a pre-built SCFW binary, this can be obtained through the building process of the Yocto project or by downloading the porting kit and following these steps: Dowload SCFW binaries for release 4.14.98_02 here. chmod a+x imx-sc-firmware-1.2.bin ./imx-sc-firmware-1.2.bin‍‍‍‍‍‍‍‍ ‍ ‍ You will prompted to accept a license agreement and after that the binaries will be extracted: Getting the SECO FW The Security Controller Firmware is only distributed in binary form and can be obtained from the NXP website. Download SECO FW binaries for release 4.14.98_02 here. chmod a+x firmware-imx-8.1.bin ./firmware-imx-8.1.bin‍‍‍‍‍‍‍‍ ‍ ‍ You will prompted to accept a license agreement and after that the   binaries   will be extracted: The SECO FW is under firmware/seco mx8qm-ahab-container.img -----> SECO FW for QM devices mx8qx-ahab-container.img ------> SECO FW for QXP devices Getting an image for the Cortex-M4 The image for the Cortex-M4 can be generated using the SDK: https://mcuxpresso.nxp.com/en/select Just select the device you are working with and click Build MCUXpresso SDK, then you will prompted to select your IDE and host. Click on Download SDK and a compressed file containing the SDK will be dowloaded to your computer. Now you only need to uncompress the file and follow the steps in the getting started document to generate the image.  The getting started document includes steps to setup the toolchain and build an image for the M4. An M4 binary for the QM and QXP MEKs is also attached in this document, the example outputs a hello world message on the M4 terminal. Getting an image for the Cortex-A  The bootloader for the Cortex-A cores can be obtained through the Yocto BSP: The steps on generating the image for the 4.14.98 release can be found here: https://www.nxp.com/webapp/Download?colCode=imx-yocto-L4.14.98_2.0.0_ga  Some more details on the Yocto BSP can be found here: https://community.nxp.com/docs/DOC-94849 All the required binaries to create a bootable image for the Cortex-A cores on the MEK platforms are attached here. Building a bootable image Once all the required pieces have been built/obtained, the bootable image can be created. The SCFW, SECO FW and respective Cortex-M4/A images need to be copied to the folder for the target device, i.e. if you are building an image for an i.MX8QX variant copy the binaries for that variant to its folder:   Here is a list of the required files to build a bootable image: scfw_tcm.bin -------------------------------------------- System Controller Firmware binary for the target board mx8qm(qx)-ahab-container.image ---------------- Security Controller Firmware for the QM or QXP variants bl31.bin --------------------------------------------------- ARM Trusted Firmware binary (Required if using u-boot with ATF) Only needed to create Cortex-A image with u-boot u-boot.bin ------------------------------------------------ U-boot binary (optional) m4_image ----------------------------------------------- M4 binary image, the QM variant has 2 Cortex-M4s and in this case to M4 binaries might be required (optional) Once the required binaries have been copied to the desired variant folder (QXP or QM in this example), you are ready to start building some images. All the targets for building different images are defined on the soc.mak file contained in each folder, this file contains different examples for creating a lot of the supported bootable images. Creating a SCFW only image The target used to create a SCFW only image is flash_b0_scfw and it is defined under the soc.mak file of each variant. To invoke this target for QXP from the imx-mkimage directory: make SOC=iMX8QX flash_b0_scfw‍‍ ‍ To invoke this target   for QM from the imx-mkimage directory: make SOC=iMX8QM flash_b0_scfw‍‍ ‍ The target definition for flash_b0_scfw can be seen below. Definition for QXP: flash_scfw flash_b0_scfw: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin ./$(MKIMG) -soc QX -rev B0 -dcd skip -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -out flash.bin ‍‍‍‍‍ ‍ ‍ ‍ Definition for QM: flash_b0_scfw: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin ./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -out flash.bin‍‍‍‍ ‍ ‍ Creating a Cortex-A image only The target used to create a Cortex-A image only is called flash_b0. To invoke this target for QXP from the imx-mkimage directory: make SOC=iMX8QX flash_b0 ‍ ‍ ‍ To invoke this target for QM from the imx-mkimage directory: make SOC=iMX8QM flash_b0‍ ‍ ‍ ‍ The target definition for flash_b0 can be seen below. Definition for QXP: flash flash_b0: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -out flash.bin‍‍ ‍ ‍ Definition for QM: flash_b0: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin u-boot-atf.bin ./$(MKIMG) -soc QM -rev B0 -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -out flash.bin‍‍ ‍ ‍ Creating a Cortex-M4 image only The target used to create a Cortex-m4 image only is called flash_b0_cm4 on QXP and QM has different targets since there are two M4s available in the system. To invoke this target for QXP from the imx-mkimage directory: make SOC=iMX8QX flash_b0_cm4‍ ‍ To invoke this target for QM from the imx-mkimage directory: // For Cortex-M4_0 only make SOC=iMX8QM flash_b0‍_cm4‍_0 // For Cortex-M4_1 only make SOC=iMX8QM flash_b0‍_cm4‍_1 // For both Cortex-M4_0 and Cortex-M4_1 make SOC=iMX8QM flash_b0‍_m4‍s_tcm ‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The target definition for flash_b0_cm4 can be seen below. Definition for QXP: flash_cm4 flash_b0_cm4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin m4_image.bin ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin‍‍ ‍ ‍ Definitions for QM: flash_b0_cm4_0: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m4_image.bin ./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin flash_b0_cm4_1: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m4_image.bin ./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m4_image.bin 1 0x38FE0000 -out flash.bin flash_b0_m4s_tcm: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin m40_tcm.bin m41_tcm.bin ./$(MKIMG) -soc QM -rev B0 -dcd skip -append mx8qm-ahab-container.img -c -scfw scfw_tcm.bin -p1 -m4 m40_tcm.bin 0 0x34FE0000 -m4 m41_tcm.bin 1 0x38FE0000 -out flash.bin‍‍‍‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ The examples above are for M4 images booting from TCM, the M4 is capable of booting and executing from DDR and it is also able to XIP (execute in place) from SPI memory, for examples on this targets please look at the soc.mak for the desired variant. Creating an image with both Cortex-A and Cortex-M4 images The target used to create an image with software for all the cores is called flash_linux_m4. To invoke this target for QXP from the imx-mkimage directory: make SOC=iMX8QX flash_linux_m4 ‍ ‍ To invoke this target for QM from the imx-mkimage directory: make SOC=iMX8QM flash_linux_m4 ‍ ‍ The target definition for flash_linux_m4 can be seen below. Definition for QXP: flash_linux_m4: $(MKIMG) mx8qx-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_image.bin ./$(MKIMG) -soc QX -rev B0 -append mx8qx-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a35 0x80000000 -p3 -m4 m4_image.bin 0 0x34FE0000 -out flash.bin ‍ ‍ Definition for QM: flash_linux_m4: $(MKIMG) mx8qm-ahab-container.img scfw_tcm.bin u-boot-atf.bin m4_0_image.bin m4_1_image.bin ./$(MKIMG) -soc QM -rev B0 -append mx8qm-ahab-container.img -c -flags 0x00200000 -scfw scfw_tcm.bin -ap u-boot-atf.bin a53 0x80000000 -p3 -m4 m4_0_image.bin 0 0x34FE0000 -p4 -m4 m4_1_image.bin 1 0x38FE0000 -out flash.bin ‍ ‍ Flash image This will create a bootable image named flash.bin, to flash this image to the SD card and boot it on your MEK simply do: sudo dd if=iMX8QX/flash.bin of=/dev/mmcblkX bs=1k seek=32‍‍‍‍‍‍ ‍ If the desired target is a QM variant change if=iMX8QX... to if=iMX8QM. Then match your SD card device on "of=/dev/mmcblkX" you can see how your SD card enumerates by typing lsblk on your console before and after inserting your SD card. Remember from the information above that the i.MX8 will search for the image at 32k on the SD card, that is why we are flashing it there. For more examples please look at the soc.mak file, it includes examples for different boot media (NAND/QSPI) as well as different configurations and usage. Additional resources Reference Manual Chapter 5 System Boot SCFW API and Port document imx-mkimage README System Controller Firmware 101 
View full article
NXP i.MX 8 series of application processors support running ArmV8a 64-bit and ArmV7a 32-bit user space programs.  A Hello World program that prints the size of a long int is cross-compiled as 32-bit and as 64-bit from an Ubuntu host and then each is copied to MCIMX8MQ-EVK and run. Resources: Ubuntu 18.04 LTS Host i.MX 8M Evaluation Kit|NXP  MCIMX8MQ-EVK Linux Binary Demo Files - i.MX 8MQuad EVK L4.9.88_2.0.0_GA release Source Code: Create a file with contents below using your favorite editor, example name hello-sizeInt.c. #include <stdio.h> int main ( int argc , char * * argv ) { printf ( "Hello World, size of long int: %zd\n" , sizeof ( long int ) ) ; return 0 ; } ‍‍‍‍‍‍‍ Ubuntu host packages: $ sudo apt - get install - y gcc - arm - linux - gnueabihf $ sudo apt - get install - y gcc - aarch64 - linux - gnu‍‍ ‍ ‍ Line 1 installs the ArmV7a cross-compile tools: arm-linux-gnueabihf-gcc is used to cross compile on Ubuntu host Line 2 install the ArmV8a cross-compile tools: aarch64-linux-gnu-gcc is used to cross compile on Ubuntu host Create Linux User Space Applications Build each application and use the static option to gcc to include run time libraries. Build ArmV7a 32-bit application: $ arm - linux - gnueabihf - gcc - static hello - sizeInt . c - o hello - armv7a‍ - static ‍ ‍ Build ArmV8a 64-bit application: $ aarch64 - linux - gnu - gcc - static   hello - sizeInt . c - o hello - armv8a‍ - static ‍ ‍ Copy Hello applications from Ubuntu host and run on MCIMX8MQ-EVK Using a SDCARD written with images from L4.9.88_2.0.0 Linux release (see resources for image link), power on EVK with Ethernet connected to network and Serial Console port which was connected to a windows 10 PC. Launched a terminal client (TeraTerm) to access console port. Login credentials: root and no password needed. Since Ethernet was connected a DHCP IP address was acquired, 192.168.1.241 on the EVK.  On the Ubuntu host, secure copy the hello applications to EVK: $ scp hello - armv7a - static root@ 192.168 . 1.241 : ~ / hello - armv7a - static                           100 %   389KB   4 . 0MB / s   00 : 00     $ scp hello - armv8a - static root@ 192.168 . 1.241 : ~ / hello - armv8a - static                           100 %   605KB   4 . 7MB / s   00 : 00 ‍‍‍‍‍ ‍ ‍ ‍ ‍ ‍ Run: root @imx8mqevk : ~ # ./hello-armv8a-static Hello World , sizeof long int : 8 root @imx8mqevk : ~ # ./hello-armv7a-static Hello World , sizeof long int : 4 ‍‍‍‍ ‍ ‍ ‍ ‍
View full article
i.MX8X 板级开发包镜像结构 ...................................... 3 2 创建 i.MX8QXP Linux 5.4.24 板级开发包编译环境 ..... 3 2.1 下载板级开发包 ....................................................... 3 2.2 创建yocto编译环境: ................................................. 5 2.3 独立编译 ............................................................... 10 3 i.MX8X SC firmware ................................................. 16 3.1 SC firmware 目录结构 ........................................... 16 3.2 SC firmware 启动流程 ........................................... 18 3.3 SC firmware定制 ................................................... 18 4 i.MX8X ATF .............................................................. 30 5 FSL Uboot 定制 ........................................................ 32 5.1 FDT支持 ............................................................... 33 5.2 DM(driver model)支持 ........................................... 38 5.3 Uboot目录 结构 ..................................................... 52 5.4 Uboot编译 ............................................................. 54 5.5 Uboot初始化流程 .................................................. 55 5.6 uboot 定制 ............................................................ 66 5.7 uboot debug信息 ................................................... 82
View full article
Some customer need to know how to add support RS485 mode half duplex? Here give some recommends. About i.MX6 UART to RS485 applications 1. Using RS485 mode of UART directly. On hardware, you should use UART_CTS_B to control RX & TX. On software, The link for you reference: Does UART in RS485 mode support only 9 Bit mode for i.MX6 ?  2. Sensing IO direction Automatically via hardware, don't need to tune software. For i.MX8QXP As the linux BSP for i.MX8QXP do not support RS 485 mode, so for the RS 485 using you can use the Sensing IO direction Automatically via hardware, don't need to tune software. As the above i.MX6 design.
View full article