i.MX Processors Knowledge Base

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

i.MX Processors Knowledge Base

Discussions

Sort by:
www.nxp.com公网资源 .............................................. 2 1.1 www.nxp.com Documentation ................................ 3 1.2 www.nxp.com Tools&Software ............................... 7 2 nxp share point资源(仅对有访问权限客户开放) ....... 14 2.1 i.MX 8X Family Board, Software POR and How to Purchase ...................................................................... 14 2.2 Development Platforms ........................................ 14 2.3 Device Dcoumentation ......................................... 15 2.4 Security Reference Manual .................................. 16 2.5 Software Documentation ...................................... 16 3 nxp 社区资源 ........................................................... 16
View full article
i.MX6X_内核驱动代码与定制_V2-20150518.doc: 3.0.35
View full article
Freescale's PF0100 PMIC should have VDDIO power tied to the same supply as the associated I2C supply on MX6. There is a momentary on-chip sneak path on power-up if VDDIO is wired per the i.MX6 SABRE-AI automotive development platform. As a result, I2C power rail P3V3_DELAYED rises prematurely due to backfeed from P3V3 through the I2C port. Note that on SABRE-AI, P3V3 powers up before P3V3_DELAYED. Existing SABRE-AI design: PF0100 VDDIO is wired to P3V3. Corrective action for mass production: Wire PF0100 VDDIO to P3V3_DELAYED; same supply as the associated I2C supplies on MX6 (NVCC_EIM0 and NVCC_GPIO). Laboratory results attached.
View full article
This tool is also for emmc user partition mirror. Just give this tool the emmc files. The typical use case is for emmc mass production by emmc offline programming. Ver 0.4.0 2/14/2017 Support Android 7 Nougat. AndroidSDCARDMirrorCreator_Version_0.4.0_02142017.tgz Ver 0.3.2: 6/13/2016 Using static link simg2img AndroidSDCARDMirrorCreator_Version_0.3.2_06132016.tgz Ver 0.3.1: 5/31/2016 Remove some redundent code   AndroidSDCARDMirrorCreator_Version_0.3.1_05312016.tgz Ver 0.3: 5/25/2016 Add Marshmallow partition layout AndroidSDCARDMirrorCreator_Version_0.3_05252016.tgz Ver 0.2: Add Lollipop partition layout 1. Directory AndroidSDCARDMirrorCreator |-- AndroidSDCARDMirrorCreator.sh        --- main script |-- CFG.INC                              --- configuration file |-- KitKat_LAYOUT.INC                    --- KitKat partition layout |-- LAYOUT.INC -> Lollipop_LAYOUT.INC    --- symbol link to partition layout |-- Lollipop_LAYOUT.INC                  --- Lollipop partition layout `-- readme.txt                           --- this file 2. Need "root" run or "sudo" to run 3. parted and kpartx must be installed    sudo apt-get instal parted kpartx 4. test pass under the debian 8.2 and ubuntu 12.04 5. The AndroidSDCARDMirrorCreator.sh will look for LAYOUT.INC.    please make symbol link to the correct partition layout.    The default symbol link has created for Lollipop_LAYOUT.INC (LAYOUT.INC -> Lollipop_LAYOUT.INC) 6. Command    AndroidSDCARDMirrorCreator.sh -c    AndroidSDCARDMirrorCreator.sh -p 7. Example:    Suppose    The AndroidSDCARDMirrorCreator directory is in    ~/AndroidSDCARDMirrorCreator       The Android Images are in    ~/SD and ~/eMMC       Sdcdard Mirror:    cd ~/SD    ~/AndroidSDCARDMirrorCreator/AndroidSDCARDMirrorCreator.sh -c    eMMC Mirror:    cd ~/eMMC    ~/AndroidSDCARDMirrorCreator/AndroidSDCARDMirrorCreator.sh -c    8. Once the Mirror has been created. Can be reused. Just use kpartx.
View full article
Basic Linear Algebra Subprograms (BLAS) is a specification that prescribes a set of low-level routines for performing common linear algebra operations such as vector addition, scalar multiplication, dot products, linear combinations, and matrix multiplication. OpenBLAS is an optimized BLAS library which is uesd for deep learning accelerator in Caffe/Caffe2. I enable it in Yocto (Rocko) by adding bb file. And I build on i.MX6QP, i.MX7ULP and i.MX8MQ and also run its test example successfully. You can find test example(openblas_utest) under folder image/opt/openblas/bin of OpenBLAS work directory. Currently, version 0.3.0 is supported in the bb file. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ update to v 0.3.6 and enable mutli-thread by set USE_OPENMP=1 and USE_THREAD=4 when compiling this library.
View full article
Preface With i.MX android, it is often infeasible to directly build an OTA package with a newer android version and apply that OTA package to a device running old version of Android. For example, the OTA package buit with i.MX android-13.0.0_2.0.0 release for evk_8mm cannot be direclty applied on the evk_8mm board running the image built with i.MX android-11.0.0_1.0.0. In this article, the reason why directly cross-version OTA is infeasible in i.mx android is firstly explained. Then what should be takein into consideration and done before cross-version OTA are described.   The way Google update the system for its device Once Google first time releases a device, it is called a "launch device". it has: codename. Take pixel 3a xl as an example, the codename is bonito Android version. For pixel 3a xl, it's Android 9.0 kernel version. For pixel 3a xl, it's 4.9 PRODUCT_SHIPPING_API_LEVEL. For pixel 3a xl, it is set to be 28, the same as the SDK version of that Android version. FCM target level. For pixel 3a xl, it's 3 After the system code is updated to a new version, an OTA package can be built with the lunch target aosp_bonito-user or aosp_bonito-userdebug for pixel 3a xl, let's call the updated device "retrofit device" codename is not changed. its device configuration still can be found in "device/google/bonito/" Android version. it is the version the OTA updated to. Four android versions are supported, here they are android 9, 10, 11, 12, which means pixel 3a xl can at most upgraded to android12. "device/google/bonito/" is introduced in android9, and removed in android13. kernel version. not changed after OTA PRODUCT_SHIPPING_API_LEVEL. Not changed in OTA, so after the OTA, the value of property "ro.product.first_api_level" is different from the SDK version. FCM target level. not changed after OTA. The FCM target level is in the device manifest.xml, corresponds to a specific version of system compatibility.matrix.xml, so HALs provided by this device does not need to have much changes if the FCM target level is not changed. This is the way Google maintains the system for their devices. This is not the way i.MX Android devices are maintained. The way i.MX Android update the system to a new version for maintained device when the code is upaded to a new version for maintained imx devices, all the device are taken as "launch device", so compaired to the previous version, in the new system for the device: the kernel version is changed PRODUCT_SHIPPING_API_LEVEL is changed FCM target level is changed. Physical partitions may also be changed The FCM target level change means there may be some big changes in the HALs provided by this device. The PRODUCT_SHIPPING_API_LEVEL change means quite many code logic based on the property "ro.product.first_api_level" execute in different flow. Fro the partition changes, the OTA package directly build with this updated code often cannot be applied, for example, a new image for the new partition cannot be applied on the board running old system, as it does not have the partition for the image. Things cannot be changed during OTA To make things more clear that why direct cross-version OTA is infeasible, it is necessary to know that there are things cannot be changed during OTA. 1. physical partitions cannot be changed during OTA. related features are: * dynamic partition * gki * boot header version 2. user data on theuserdata partition should not be changed, or data loss may occur during OTA. the related features are: * encryption options encryption options should not be changed, to make new version of android can recognize the data encrypted by the old version of android. For some  fs_mgr encrypt options, the product_shipping_api_level impacts on the final encryption parameters passed to the kernel. take a look at the following code, even with the same fs_mgr encryption option, if the first_api_level is different, the final encryption parameter is different in different android version. android10 system/extras/libfscrypt/fscrypt.cpp if (filenames_encryption_mode == FS_ENCRYPTION_MODE_AES_256_CTS) { // Use legacy padding with our original filenames encryption mode. return FS_POLICY_FLAGS_PAD_4; } else if (filenames_encryption_mode == FS_ENCRYPTION_MODE_ADIANTUM) { // ...snip... return (FS_POLICY_FLAGS_PAD_16 | FS_POLICY_FLAG_DIRECT_KEY); } // ...snip... return FS_POLICY_FLAGS_PAD_16; android11 system/extras/libfscrypt/fscrypt.cpp if (!is_gki && options->version == 1 && options->filenames_mode == FSCRYPT_MODE_AES_256_CTS) { options->flags |= FSCRYPT_POLICY_FLAGS_PAD_4; } else { options->flags |= FSCRYPT_POLICY_FLAGS_PAD_16; } android12 system/extras/libfscrypt/fscrypt.cpp if (first_api_level <= __ANDROID_API_Q__ && options->version == 1 && options->filenames_mode == FSCRYPT_MODE_AES_256_CTS) { options->flags |= FSCRYPT_POLICY_FLAGS_PAD_4; } else { options->flags |= FSCRYPT_POLICY_FLAGS_PAD_16; }  The fscrypt version will also impact the result. If not sepcified, the default "version" would be "v1" if the "product_shipping_api_level <= 29" or the default "version" would be "v2". Some fscrypt functions like "casefold" and "project id" will depend on fscrypt "v2", these functions are enabled by including the "$(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk)" in "device/nxp". The "emulated_storage.mk" must not be included if fscrypt "v1" is used.  * the userdata partition filesystem type ext4 (used before i.mx android 13.0.0) f2fs (used from i.mx android 13.0.0) * The filesystem for the emulated storage on the userdata partition sdcardfs fuse 3. The boot control info in misc partition should be able to be recognized before and after OTA related feature is: * bootcontrol HAL 4. The bootargs passed by u-boot to kernel cannot be changed if the bootloader is not updated The related feature is: * bootconfig is used to pass boot args from android12.0.0_1.0.0. used with vendor boot header v4.   it should be known that if dual bootloader of postinstall is used, bootloader can be updated.   For these related features. Google does not implement or change them for a "retrofit device", just imlement for change the features for a "launch device", makes direct cross-version OTA feasible for them, because things cannot be changed during OTA are the same between different android versions. For i.mx android, to implement new features for all maintaied devices, things can be changed during OTA are often changed when update to a new version of android. which makes direct cross-version OTA infeasible.    For the ease of reference, list some feature change history here: * physical partition change history   P9.0.0_2.3.0 10.0.0_1.0.0 10.0.0_2.0.0 11.0.0_1.0.0 12.0.0_1.0.0 12.1.0_1.0.0 13.0.0_1.0.0 14.0.0_1.0.0 bootloader_a/b 4MB 4MB 4MB 4MB 4MB 16MB 16MB 16MB dtbo_a/b 4MB 4MB 4MB 4MB 4MB 4MB 4MB 4MB boot_a/b 48MB 48MB 64MB 64MB 64MB 64MB 64MB 64MB init_boot_a/b - -   -   - 8MB 8MB vendor_boot_a/b - -   64MB 64MB 64MB 64MB 64MB misc 4MB 4MB 4MB 4MB 4MB 4MB 4MB 4MB metadata 2MB 2MB 2MB 2MB 16MB 16MB 64MB 64MB presistdata 1MB 1MB 1MB 1MB 1MB 1MB 1MB 1MB super - - 7168MB 3584MB 4096MB 4096MB 4096MB 4096MB fbmisc 1MB 1MB 1MB 1MB 1MB 1MB 1MB 1MB vbmeta_a/b 1MB 1MB 1mb 1MB 1MB 1MB 1MB 1MB system_a/b 2560MB 1536MB - -   - - - vendor_a/b 256MB 512MB - -   - - - product_a/b - 1792MB - -   - - -   boot_a/b: 48MB → 64MB, Image becames bigger ater enabling some debug options vendor_boot_a/b: boot header v3. Vendor boot and boot header v3 are MUST to enable GKI feature.  init_boot_a/b: The init binary in ramdisk is moved from boot.img to init_boot.img. flash gki image from Google does not impact on the vendor modifications on init.   for the metadata partition: 2MB → 16MB, requirement of vts "-m vts_gsi_boot_test -t MetadataPartition#MinimumSize" 16MB → 64MB, to make the partition be formated as f2fs, 32MB is not enough, 64MB is used. metadata partition was firstly mounted in android11, when enable the user data checkpoint feature * gki feature history Firstly introduced in android11. Some codes are built into modules, put the modules in vendor_boot_a/b partition. vendor_boot_a/b partitions are also firstly introduced in android11 GKI prebuilt binary was integrated from android12   The way to handle cross-version OTA for i.mx android Here are the steps align the partitions within the OTA base code and the OTA target code if the product may be in the development stage, and the OTA base  code can be modified: reserve partitions in OTA base code. for example, OTA from 10 to 11, reserver the vendor_boot partition in android10 partitiont able although there is not vendor_boot.img. change the selinux rules to have update_engine to be able to update this partition. enlarge some partitions in the OTA base code as in the OTA target code. for examples, the bootloader partitions is 16MB in android13. if OTA from android12 to android13 and the android 12 code can be modified, enlarge the bootloader partition to 16MB. as data in userdata and metadata partition is not touched during OTA, modify the mount options of userdata and metadata partitions in OTA target code to be the same as the one in OTA base code. if the product partitions are already shipped, only the OTA target code can be modified:  as data in userdata and metadata partition is not touched during OTA, modify the mount options of userdata and metadata partitions in OTA target code to be the same as the one in the OTA base code. change the partition size to align with the OTA base code partitions like vendor_boot and/or init_boot may need to be removed. remove/change the features related to the removed or changed partitions if dual bootloader is not used: recently in android version update, vendor_boot and init_boot partitions are added, this is related to boot image header version, the images in these partitions are loaded and verified by uboot, so if dual bootloader is not used, uboot code related to these things need to be changed. check the code related to "struct boot_img_hdr" in uboot. the a/b slot metadata format may be changed between the OTA base code and the OTA target code , this a/b slot metadata is accessed by both Android bootctrl HAL and uboot, as dual bootloader is not used, uboot is not upaded, the updated Android bootctrl HAL should also use the same format to access the file. a postinstall mechanism can be used to update the uboot images, but as there is no fallback for the update failure, the risks need to be evaluated. check whether the OTA package can be applied and whether the updated system can boot up an failure example: OTA from android10 to android12, the system fail to boot up because of the PRODUCT_SHIPPING_API_LEVEL/"ro.product.first_api_level" value difference, different encryption options are used for userdata partitions. so the PRODUCT_SHIPPING_API_LEVEL value need to be changed to be the same as the one in the OTA base code. as PRODUCT_SHIPPING_API_LEVEL is changed, the FCM target version and related HALs may also need to be changed, including changes in device manifest.xml and compatibility_matrix.xml. need to check the commit history about what is changed together with the FCM target version change.   For dynamic partitions, there are something to be noticed: OTA from the image without dynamic partitions to use dynamic partitions: Refer to the code in android10.0.0_2.0.0, there is a demonstration to update 10.0.0_1.0.0 to 10.0.0_2.0.0. In 0.0.0_1.0.0, dynamic partition is not enabled. check the variable "TARGET_USE_RETROFIT_DYNAMIC_PARTITION" and related configurations. OTA from dynamic partitions to virtual A/B, for example, OTA from android10 to android11 inherit the file "build/make/target/product/virtual_ab_ota_retrofit.mk" the first time when update from android10 to android11 with OTA, inherit the "build/make/target/product/virtual_ab_ota_retrofit.mk", the BOARD_NXP_DYNAMIC_PARTITIONS_SIZE is set as dynamic paritition is used. the second time, the device is runing android11 with retrofit virtual A/B feature, this time OTA again, but not cross version, inherit "build/make/target/product/virtual_ab_ota.mk" instead, and the BOARD_NXP_DYNAMIC_PARTITIONS_SIZE  can be set as virtual A/B feature is used. Devices that were upgraded to dynamic partitions can’t retrofit virtual A/B. if there are new dynamic partitions in OTA target code, like vendor_dlkm, no additional changes need to be made for it. Then the customers need to do full xTS test to guarantee the quality.  
View full article
Device: i.MX93 A1. ELE FW version: 0.0.10 Some new test scripts are added to secure enclave library, please refer to attached files. Please note: the scripts attached are for internal test/debug purpose only. The summary is from our test results and understanding, it's preliminary and may have changes later.    1. All current and all GA Sentinel FWs do not use lifecycle for key derivation of HSM keystore. Keystore created in OEM_OPEN lifecycle can be directly used in OEM_CLOSED lifecycle.  A-> Different from previous SECO devices 2. Key has lifecycle attribute. This attribute defines in which device lifecycle the key is usable. This attribute is set at key creation operation (generate key, import key, key exchange …). Before executing a key depending cryptographic or data storage (export option) operation the key lifecycle is compared with the current device lifecycle. Operation is executed only if the key lifecycle includes the current device lifecycle. When mentioned in the API command message description, the key lifecycle could be set to the current device lifecycle if the value is set to 0x0. Lifecycle values are encoded as bitfield. Multiple values could be set. The key could be used in several lifecycles.   Tested cases:   The key lifecycle attribute is verified during the key usage, not when the key is created. If the key operation doesn’t match device lifecycle, it will report 0xe29 - The key is not usable in the current lifecycle.  Please see attached hsm_generate_key.c / hsm_generate_key_signature.c  for reference.   3. SYNC operation and MC increase are separate flag. The previous STRICT operation is used to store persistent key, during which the monotonic counter will increase if the device is closed. For ELE device, two flags are used: SYNC flag and MC flag. The ELE SYNC pushes persistent key(s) in the NVM. Without executing this operation, even if the key attribute is set as persistent at the key creation the key will not be stored in the NVM. This operation is set through a flag in key management operations arguments. SYNC is applicable only for persistent key/permanent key. MC flag is new on ELE device. When used in conjunction with SYNC, the request is completed only when the monotonic counter has been updated. MC flag can be used both in OPEN and CLOSED lifecycle and increase the monotonic counter value. -> different from previous SECO device. Note: MC flag is not defined in 0.0.10 secure enclave library, but user can test it by directly setting the corresponding bit of the flag.   4. If the generated key store is deleted accidently and the monotonic counter is not 0, reprovisioning function is needed.  This is applied to both OPEN and CLOSED device. We cannot directly create a keystore again. Reprovisioning method is not supported yet.   5. One keystore can store 100 key groups at most. 100 groups are available per key store. It must be a value in the range [0; 99]. The key group ID should be 0~99, or it will report 0x429- MU sanity check failed / Invalid parameters. To push persistent keys in the NVM, a flag (SYNC) needs to be set during key management operations (generate, import, manage, …). Pushing a key to the NVM will also push all the key group data. When in use, a key group is loaded from the NVM to the internal secure RAM. The number of key group present is limited (depends on the device). A key group present in internal memory and not used, can be swapped out and replaced by a new key group containing the key to be used when there is no more free space. Note that only key 2 groups per key store can be stored in the internal secure RAM. Note that volatile keys cannot be in the same key group than persistent keys.   One assumption based on tests: It looks that each key group has its own SW counter, which may record update time of this key group. This is the test on i.MX93: If we delete the key group #2 file 0000abcd00020004 only from NVM manually, then we cannot create key of group #2 again, but we can create key of group #1. The process might be: Try to create key in group #2 -> checked the counter value is not 0 -> try to import the chunk from NVM -> fail because the chunk is deleted. Each key group has its own counter, so key group #1 is not affected.   6. Key size in one keystore One key group can store 16 ECC(p256) keys, or 1 RSA 2k key, or 1 RSA 4k key. Size of key group on i.MX93 = 8448 bits (size defined to allow 4k modulus+ 4k private exponent + header). Storage file in NVM will have additional overhead, the 8448 size is purely related to key data storage. For ECC keys, only private keys are stored (public key can be derived from private key), so P256 key only needs 256 bits of key storage + 256 bits header = 512 bits. 16 * 512 = 8192 => fits within 8448.    7. Delete key To delete the key from the NVM, an SYNC operation (in “Flags” field) must be done. To delete a key, user need to provide the key identifier which is generated when creating this key. There is also “MC” flag which should can be used for anti-rollback protection. Deleting key will not decrease the size of key group file directly, but the space in the key group will be covered by new key generated later.  Please see attached hsm_delete_key.c for reference.   8. Generic API Generic API is not supported on i.MX93 A0 due to a lack of RAM, it is supported on i.MX93 A1. In lf-6.1.22_2.0.0 ELE library, the generic feature is set as none supported, need to change the src/plat/ele/sab_msg.def file as below to test it on i.MX93 A1 chip. -MT_SAB_GC_AKEY_GEN := ${NOT_SUPPORTED} -MT_SAB_GC_ACRYPTO := ${NOT_SUPPORTED} +MT_SAB_GC_AKEY_GEN := ${FMW} +MT_SAB_GC_ACRYPTO := ${FMW} Generic cryptographic APIs can be used to perform cryptographic operation without using the FW key store. The key buffer, in plaintext, is an input parameter of the API. No need to open hsm keystore before using generic APIs. Because it will not save the key to key store, so NVM thread is also not necessary. Please see attached hsm_generic_api.c for reference. Asymmetric key generate: Only RSA is supported on S401 for now. It will return the address of output RSA key modulus /output RSA private exponent /input RSA public exponent Asymmetric crypto User can choose different operation mode for Encryption / Decryption / Signature generation / Signature verification.    9. How to get chip MC value? Command “Get device information” can be used to get generic information regarding the user, the chip and the EdgeLock Enclave FW. It can return Chip UUID/lifecycle/monotonic counter etc. User can run this API before and after some MC operation to check if the counter value is increased. Please see the attached hsm_get_info.c for reference.   Best Regards, Tia
View full article
BSP: L5.15.5_1.0.0   Platform: i.MX8MPlus EVK   1. Parameter preparation For more parameter calculation, please refer to: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/iMX-8M- Mini-Register-Programming-Aid-DRAM-PLL-setting/ta-p/111209  For 1866MHz LPDDR4, we need a DRAM PLL size of 933MHz. The PLL dividing parameters are: m=622,p=16,s=0, k=0.   2. Calibration and stress test with DDR Tool 2.1 Creating a test script for 1866MHz Here we copy the script from another file (e.g. 2000MHz) and modify the contents of the script.   2.2 Modify the script to adapt to 1866MHz 2.3 Download the test script After selecting the ddr script we created, click on the download button   2.4 Calibrating the stress test Set the core clock of the chip's cpu to 1.2GHz, then click the Calibration button to calibrate, then click Gen Code to generate the lpddr4_timing.c file. Set the start frequency to 1866MHz for the stress test.   2.5 Modify lpddr4_timing.c We need to modify the generated lpddr4_timing.c file to change the maximum speed to 3732MTS.   3. SPL patch After getting the correct lpddr4_timing.c file, the SPL code also needs to be modified to add support for the 933MHz DRAM PLL. diff --git a/arch/arm/mach-imx/imx8m/clock_imx8mm.c b/arch/arm/mach-imx/imx8m/clock_imx8mm.c index e39f238fdf...5622a6334e 100644 --- a/arch/arm/mach-imx/imx8m/clock_imx8mm.c +++ b/arch/arm/mach-imx/imx8m/clock_imx8mm.c @@ -55,6 +55,7 @@ static struct imx_int_pll_rate_table imx8mm_fracpll_tbl[] = { PLL_1443X_RATE(650000000U, 325, 3, 2, 0), PLL_1443X_RATE(600000000U, 300, 3, 2, 0), PLL_1443X_RATE(594000000U, 99, 1, 2, 0), + PLL_1443X_RATE(933000000U, 622, 16, 0, 0), PLL_1443X_RATE(400000000U, 400, 3, 3, 0), PLL_1443X_RATE(2660000U, 266, 3, 3, 0), PLL_1443X_RATE(167000000U, 334, 3, 4, 0), diff --git a/drivers/ddr/imx/imx8m/ddrphy_utils.c b/drivers/ddr/imx/imx8m/ddrphy_utils.c index 326b92d784..ebd005bc2b 100644 --- a/drivers/ddr/imx/imx8m/ddrphy_utils.c +++ b/drivers/ddr/imx/imx8m/ddrphy_utils.c @@ -117,6 +117,10 @@ void ddrphy_init_set_dfi_clk(unsigned int drate) dram_pll_init(MHZ(1000)); dram_disable_bypass(); break; + case 3732: + dram_pll_init(MHZ(933)); + dram_disable_bypass(); + break; case 3200: dram_pll_init(MHZ(800)); dram_disable_bypass();   4. Test results   Reference blog. DDR Tool: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8M-Family-DDR-Tool-Release/ta-p/1104467  RPA: https://community.nxp.com/t5/i-MX-Processors-Knowledge-Base/i-MX-8MPlus-m865S-DDR-Register-Programming-Aids-RPA/ta-p/1235352 
View full article
Overview The purpose of this docuement is to collect general information about USB certification on i.MX 7Dual/Solo SabreSD board. Reference The test procedure and instructions of USB certification is similar with i.MX6 platform. You can refer to I.MX6 series USB Certification Guides for the test details.  Software Configuration "How to do usb compliance test for 4.x kernel_mx7_v1.0.pdf" in attachment is genernal software guideline for USB compliance test based on L4.x Kernel version on i.MX 7Dual/Solo SabreSD board. Test Report Please refer to attachment "Freescale Semiconductor_MCIMX7D_Pass_Test_Report_20160627_formal.pdf" for i.MX 7Dual/Solo USB OTG certification report. This report is based on: Software Image: L4.1.15_1.2.0_ga internal candidate image Hardware: i.MX 7Dual SabreSD board
View full article
This document simply introduce how to change uboot for porting new PHY on imx7D customized board   Background: Current imx7D Sabresd board uses BCM54220B0KFBG PHY, the customized board wants to use KSZ9031 as PHY on the yocto 4.9.88 version, the customized board uses only one ethernet port on ENET2 port according to the imx7D Sabresd board   Requirement: Refer to the yocto user guide of 4.9.88 version, built your own image, for simple, you can built core-image-minimal, and download the 4.9.88 mfgtool to program        The document of 4.9.88: https://www.nxp.com/webapp/Download?colCode=L4.9.88_2.0.0_LINUX_DOCS        mfgtool for downloading: https://www.nxp.com/webapp/sps/download/license.jsp?colCode=IMX6_L4.9.88_2.0.0_MFG_TOOL&appType=file2&location=null&DOWNLOAD_ID=null&lang_cd=en        Design files: https://www.nxp.com/webapp/sps/download/license.jsp?colCode=iMX7D-SABRE-DESIGNFILES&appType=file1&DOWNLOAD_ID=null&lang_cd=en     adding customized code in u-boot head file: refer to the customized board schematic as below:     This board use eth2 as ethernet port, the code mx7dsabresd.h(path: yocto-L4.9.88_2.0/build-x11/tmp/work/imx7dsabresd-poky-linux-gnueabi/u-boot-imx/2017.03-r0/git/include/configs) /* Network */ #ifdef CONFIG_DM_ETH #define CONFIG_FEC_MXC #define CONFIG_MII #define CONFIG_FEC_XCV_TYPE             RGMII #define CONFIG_FEC_ENET_DEV       0   #define CONFIG_PHYLIB #define CONFIG_PHY_BROADCOM /* ENET1 */ #if (CONFIG_FEC_ENET_DEV == 0) #define IMX_FEC_BASE              ENET_IPS_BASE_ADDR #define CONFIG_FEC_MXC_PHYADDR          0x0 #ifdef CONFIG_DM_ETH #define CONFIG_ETHPRIME                 "eth0" #else #define CONFIG_ETHPRIME                 "FEC0" #endif #elif (CONFIG_FEC_ENET_DEV == 1) #define IMX_FEC_BASE              ENET2_IPS_BASE_ADDR #define CONFIG_FEC_MXC_PHYADDR          0x1 #ifdef CONFIG_DM_ETH #define CONFIG_ETHPRIME                 "eth1" #else #define CONFIG_ETHPRIME                 "FEC1" #endif #endif     Change the source code as below, add two macro definition and change the PHY address according to the schematic: /* Network */ #define CONFIG_PHY_MICREL #define CONFIG_PHY_MICREL_KSZ9031   #ifdef CONFIG_DM_ETH #define CONFIG_FEC_MXC #define CONFIG_MII #define CONFIG_FEC_XCV_TYPE             RGMII   #define CONFIG_FEC_ENET_DEV       0     #define CONFIG_PHYLIB #define CONFIG_PHY_BROADCOM /* ENET1 */ #if (CONFIG_FEC_ENET_DEV == 0) #define IMX_FEC_BASE              ENET_IPS_BASE_ADDR #define CONFIG_FEC_MXC_PHYADDR          0x1 #ifdef CONFIG_DM_ETH #define CONFIG_ETHPRIME                 "eth0" #else #define CONFIG_ETHPRIME                 "FEC0" #endif #elif (CONFIG_FEC_ENET_DEV == 1) #define IMX_FEC_BASE              ENET2_IPS_BASE_ADDR #define CONFIG_FEC_MXC_PHYADDR          0x2   #ifdef CONFIG_DM_ETH #define CONFIG_ETHPRIME                 "eth1" #else #define CONFIG_ETHPRIME                 "FEC1" #endif #endif       adding customized code in u-boot source file: the source code named mx7dsabresd.c (path: yocto-L4.9.88_2.0/build-x11/tmp/work/imx7dsabresd-poky-linux-gnueabi/u-boot-imx/2017.03-r0/git/board/freescale/mx7dsabresd)         Don’t forget include the micrel.h file        Focus on the setup_fec fuction   Imx7d Sabresd board uses gpio_spi 5 as reset pin so the source code as below: ret = gpio_lookup_name("gpio_spi@0_5", NULL, NULL, &gpio)                if (ret) {               printf("GPIO: 'gpio_spi@0_5' not found\n");     The customized board uses GPIO1_IO03 as reset pin, so the source code was changed to : imx_iomux_v3_setup_pad(MX7D_PAD_GPIO1_IO03__GPIO1_IO3 | MUX_PAD_CTRL(NO_PAD_CTRL)); ret = gpio_request(IMX_GPIO_NR(1, 3), "enet_phy_rst"); gpio_direction_output(IMX_GPIO_NR(1, 3), 0);        mdelay(20);        gpio_direction_output(IMX_GPIO_NR(1, 3), 1);       udelay(100);         Focus on the function board_phy_config fuction Use this function to set the phy rx, tx data pad skew and clock pad skew, for ksz9031, can refer to the UDOO board, then change the setting source code as below: /* control data pad skew - devaddr = 0x02, register = 0x04 */        ksz9031_phy_extended_write(phydev, 0x02,                                MII_KSZ9031_EXT_RGMII_CTRL_SIG_SKEW,                                MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);        /* rx data pad skew - devaddr = 0x02, register = 0x05 */        ksz9031_phy_extended_write(phydev, 0x02,                                MII_KSZ9031_EXT_RGMII_RX_DATA_SKEW,                                MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);        /* tx data pad skew - devaddr = 0x02, register = 0x05 */        ksz9031_phy_extended_write(phydev, 0x02,                                MII_KSZ9031_EXT_RGMII_TX_DATA_SKEW,                                MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x0000);        /* gtx and rx clock pad skew - devaddr = 0x02, register = 0x08 */        ksz9031_phy_extended_write(phydev, 0x02,                                MII_KSZ9031_EXT_RGMII_CLOCK_SKEW,                                MII_KSZ9031_MOD_DATA_NO_POST_INC, 0x03FF);       Build the uboot source code then program to the customized board, the log file as below: U-Boot 2017.03-imx_v2017.03_4.9.88_2.0.0_ga+gb76bb1b (Apr 20 2019 - 17:51:51 +0800)   CPU:   Freescale i.MX7D rev1.3 996 MHz (running at 792 MHz) CPU:   Commercial temperature grade (0C to 95C) at 32C Reset cause: POR Model: Freescale i.MX7D SabreSD Board Board: i.MX7D SABRESD RevC in secure mode DRAM:  1 GiB PMIC: PFUZE3000 DEV_ID=0x30 REV_ID=0x11 MMC:   FSL_SDHC: 0, FSL_SDHC: 1 Display: TFT43AB (480x272) Video: 480x272x24 In:    serial Out:   serial Err:   serial switch to partitions #0, OK mmc1(part 0) is current device Net:   Error: ethernet@30bf0000 address not set. eth0: ethernet@30be0000 Error: ethernet@30bf0000 address not set.   Ending: Don’t worry about this error message, because you don’t set correct mac address, one has two option to set this, For one, you can add mac address in the uboot manually, like setenv ethaddr 00:11:22:33:44:55     another option is add CONFIG_NET_RANDOM_ETHADDR=y in the configure file, then you don’t need to set mac address manually, would get a random mac address   this document just simply introduce how to change the source code in the u-boot, you also need to change the kernel dts file and kernel file to support the new PHY, the kernel has the same process, the phy address, the phy settings, and the gpio pins, hope this document give you some hints to port the new PHY
View full article
Debugging with JTAG JTAG was created to test populated circuit boards after manufacture. Nowadays, JTAG is primarilly used to access sub-blocks of integrated circuits and useful mechanism for debugging embedded systems. When used as a debugging tool, an in-circuit emulator - which in turn uses JTAG as the transport mechanism - enables a programmer to access an on-chip debug module which is integrated into the CPU, via the JTAG interface. The debug module enables the programmer to debug the software of an embedded system. Besides debugging, the second purpose of the JTAG interface is allowing device programmer hardware to transfer data into internal non-volatile device memory. Some device programmers serve a double purpose for programming as well as debugging the device. [Source: http://en.wikipedia.org] All Boards Hardware Software i.MX27 ADS Board Installing OpenOCD and GDB All Boards Debugging Android All Boards How To Understand JTAG BSDL
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 guide provides step-by-step instructions for setting up and applying necessary patches to the Linux kernel for the FRDM-IMX93 development board. The process involves cloning the required repositories, applying patches, and preparing the kernel for customization and compilation.   Prerequisites Required Software: A Linux-based operating system (Ubuntu/Debian recommended). Git installed (sudo apt install git). Yocto dependencies: $ sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential chrpath socat cpio python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping python3-git python3-jinja2 python3-subunit zstd liblz4-tool file locales libacl1 ​   Hardware: FRDM-IMX93 Board Sufficient storage space   1. Downloading the Repository Start by downloading the necessary tools and repository. If the ~/bin folder does not already exist, create it: $ mkdir ~/bin (this step may not be needed if the bin folder already exists) $ curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo $ chmod a+x ~/bin/repo $ export PATH=~/bin:$PATH   2. Compile the Yocto SDK: $: mkdir Yocto_SDK $: cd Yocto_SDK $: repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-scarthgap -m imx-6.6.36-2.1.0.xml $: repo sync $: MACHINE=imx93evk DISTRO=fsl-imx-xwayland source ./imx-setup-release.sh -b bld-xwayland $: bitbake imx-image-full -c populate_sdk   Run the generated .sh file to install the SDK: sudo ./fsl-imx-xwayland-glibc-x86_64-imx-image-full-armv8a-imx93evk-toolchain-6.6-scarthgap.sh   The final .sh file is located in: bld-xwayland/tmp/deploy/sdk/   3. Creating the Working Directory First, create a dedicated directory for the kernel setup and navigate into it: $ mkdir FRDM-IMX93-Kernel $ cd FRDM-IMX93-Kernel   4. Cloning the Kernel patches Retrieve the necessary kernel patches from the NXP repository: $ git clone https://github.com/nxp-imx-support/meta-imx-frdm.git -b lf-6.6.36-2.1.0   5. Cloning the Kernel Repository (linux-imx repository) Clone the kernel source of Yocto SDK that you built earlier: $ git clone https://github.com/nxp-imx/linux-imx.git -b lf-6.6.36-2.1.0 6. Applying Kernel Patches Apply the necessary patches to the kernel: $ cd linux-imx/ $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0001-gpio-pca953x-fix-pca953x_irq_bus_sync_unlock-race.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0002-arm64-dts-add-i.MX93-11x11-FRDM-basic-support.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0003-arm64-dts-add-imx93-11x11-frdm-mt9m114-dts.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0004-Add-DSI-Panel-for-imx93.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0005-Add-CTP-support-for-waveshare-panel.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0006-arm64-dts-add-imx93-11x11-frdm-tianma-wvga-panel-dts.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0007-arm64-dts-add-imx93-11x11-frdm-aud-hat-dts.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0008-arm64-dts-add-button-support.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0009-arm64-dts-add-imx93-11x11-frdm-ov5640-dts.patch $ cd linux-imx/ $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0010-arm64-dts-add-imx93-11x11-frdm-ld.dts-for-lpm.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0011-arm64-dts-add-pwm-function-of-the-LED.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0012-arm64-dts-add-imx93-11x11-frdm-8mic.dts.patch $ git apply ../meta-imx-frdm/meta-imx-bsp/recipes-kernel/linux/linux-imx/0013-arm64-dts-add-imx93-11x11-frdm-lpuart.dts.patch   7. Customizing the Device Tree Device trees can be modified or created based on your hardware setup.   Device Tree Locations: arch/arm64/boot/dts/freescale/   If you create a new device tree, add it to the respective Makefile: arch/arm64/boot/dts/freescale/Makefile   8. Setting Up the Cross-Compilation Environment To prepare for kernel compilation, source the environment setup script. Assuming the Yocto SDK is installed in /opt, run:   EXAMPLE: $ source /opt/fsl-imx-xwayland/6.6-scarthgap/environment-setup-armv8a-poky-linux   9. Configuring the Kernel Make configuration adjustments as needed in the file: arch/arm64/configs/imx_v8_defconfig Use the appropriate configuration command: $: make imx_v8_defconfig   10. Compiling Device Trees Only To compile only the device tree files, run: $: make dtbs   11. Compiling the Kernel Finally, compile the kernel image using: $ make -j $(nproc)   The resulting kernel image will be located in: arch/arm64/boot/   References: IMX YOCTO PROJECT USERS GUIDE IMX LINUX USERS GUIDE  IMX REFERENCE MANUAL 
View full article
Hello everyone, this post is intended to add support to one of the most popular NFC chips on the market (PN532).  On this example I will use the I.MX93 EVK as reference board and focused in I2C communication for the PN532 Chip.    Details:   I.MX93 EVK  PN532 Module (I2C, SPI, UART)  BSP Linux 6.6.36_2.1.0 (Yocto)      STEP 1 (IMAGE COMPILATION).    At first, we need to compile our image for our board (in my case I.MX93 EVK) to add the NFC layer (Details on Yocto User's Guide😞😞 $ mkdir yocto-bsp $cd yocto-bsp $ repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-scarthgap -m imx-6.6.36-2.1.0.xml $ repo sync $DISTRO=fsl-imx-wayland MACHINE=imx93evk source imx-setup-release.sh -b imx93evk-build   Then, add the support for NFC in our local.conf file:  $ nano conf/local.conf   We will add the below lines: CORE_IMAGE_EXTRA_INSTALL += "libnfc" CORE_IMAGE_EXTRA_INSTALL += "libnfc-dev"   Then, we can compile the image with:  $ bitbake imx-image-full   NOTE:  libnfc is a complete coverage of low-level PN53x chipset commands written in pure and plain C for portability and speed.  libnfc-dev are the development files and headers to use in our low-level applications.    By default, the NXP BSP support the NFC pn532 driver with a tool called nfctool, but this one is very limited compared with the libnfc.      STEP 2 (DEVICE TREE MODIFICATION).    We need to add the below lines to the Device tree:  &lpi2c5 { #address-cells = <1>; #size-cells = <0>; clock-frequency = <400000>; pinctrl-names = "default", "sleep"; pinctrl-0 = <&pinctrl_lpi2c5>; pinctrl-1 = <&pinctrl_lpi2c5>; status = "okay"; nfc@24 { compatible = "nxp,nxpnfc"; //we can set the "nxp,pn533" driver but it will just work for the nfctool mentioned before reg = <0x24>; clock-frequency = <400000>; interrupt-parent = <&gpio2>; interrupts = <18 IRQ_TYPE_EDGE_FALLING>; }; };    And to the iomux section(same in device tree):  pinctrl_lpi2c5: lpi2c5grp { fsl,pins = < MX93_PAD_GPIO_IO22__LPI2C5_SDA 0x40000b9e MX93_PAD_GPIO_IO23__LPI2C5_SCL 0x40000b9e MX93_PAD_GPIO_IO18__GPIO2_IO18 0x31e >; };     STEP 3 (Connection with PN532 MODULE).     For this example, we must connect the Module with the I.MX93 RP Header as follows:    I.MX93 SIDE  PN532 SIDE  GND  GND  VCC  VCC  GPIO_IO22  SDA  GPIO_IO23  SCL  GPIO_IO18  IRQ    STEP 4 (BOOT BOARD AND CREATE libnfc.conf FILE).    Once when we have booted our board and selected our modified Device Tree, we should see our i2c-4 under /dev of our Linux OS: root@imx93evk:~# ls /dev | grep i2c i2c-0 i2c-1 i2c-2 i2c-4   And see our specific device (0x24) with the i2cdetect tool:   root@imx93evk:~# i2cdetect -y 4 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- 24 -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --     Now, we need to create a file called libnfc.conf under /etc/nfc/ (You can create that directory if does not exist).  This file must contain information about how the libnfc layer will communicate with the i2c device:    # Allow device auto-detection (default: true) # Note: if this auto-detection is disabled, user has to set manually a device # configuration using file or environment variable allow_autoscan = false # Allow intrusive auto-detection (default: false) # Warning: intrusive auto-detection can seriously disturb other devices # This option is not recommended, user should prefer to add manually his device. allow_intrusive_scan = true # Set log level (default: error) # Valid log levels are (in order of verbosity): 0 (none), 1 (error), 2 (info), 3 (debug) # Note: if you compiled with --enable-debug option, the default log level is "debug" log_level = 2 # Manually set default device (no default) # To set a default device, you must set both name and connstring for your device # Note: if autoscan is enabled, default device will be the first device available in device list. #device.name = "_PN532_SPI" #device.connstring = "pn532_spi:/dev/spidev0.0:500000" device.name = "_PN532_I2c" device.connstring = "pn532_i2c:/dev/i2c-4"   As you can see, the most important line to modify is the device.connstring, that is the charged of interaction and connection between the PN53x Module and the libnfc layer. In my case is pn532_i2c:/dev/i2c-4.    Now we can use the NFC module:  root@imx93evk:~# nfc-list nfc-list uses libnfc 1.8.0 NFC device: _PN532_I2c opened root@imx93evk:~#   And read UID of TAGs:  root@imx93evk:~# nfc-poll nfc-poll uses libnfc 1.8.0 NFC reader: _PN532_I2c opened NFC device will poll during 36000 ms (20 pollings of 300 ms for 6 modulations) ISO/IEC 14443A (106 kbps) target: ATQA (SENS_RES): 00 44 UID (NFCID1): 04 17 b5 d2 a2 11 90 SAK (SEL_RES): 00 Waiting for card removing...nfc_initiator_target_is_present: Target Released done. root@imx93evk:~#   Also, attached is a little application using the NFC headers installed with libnfc-dev. Tha application will do a poll with a 10 seconds time out. If Tag is not detected in 10 seconds, the app will close. If a tag is detected before the timeout, the app will print the UID of the NFC TAG:   OUTPUT of timeout: root@imx93evk:~# ./nfc-app NFC reader: _PN532_I2c opened Waiting for an NFC tag (timeout: 10 seconds)... No NFC tag detected within the timeout period. root@imx93evk:~#   OUTPUT when tag is detected: root@imx93evk:~# ./nfc-app NFC reader: _PN532_I2c opened Waiting for an NFC tag (timeout: 10 seconds)... Tag detected - UID: 04:16:BC:D2:A2:11:90 root@imx93evk:~#   To compile the app just copy the attached nfc-app.c file to the i.MX93 EVK and compile using this command: root@imx93evk:~# gcc nfc-app.c -o nfc-app -lnfc     I hope this thread can be helpful!   Best regards, Salas.  
View full article
1.Compile full aosp or only kernel Build full aosp: source build/envsetup.sh lunch evk_8mm-userdebug ./imx-make.sh -j8  Only build kernel: ./imx-make.sh kernel -j8 2.Build GKI locally Download GKI outside of android_build. mkdir gki && cd gki (Make sure folder gki is not inside of ${MY_ANDROID}) repo init -u https://android.googlesource.com/kernel/manifest -b commonandroid13-5.15 repo sync Build GKI locally. BUILD_CONFIG=common/build.config.gki.aarch64 build/build.sh 3. Export symbols After building GKI locally, you can copy linux-imx from /vendor/nxp-opensource/kernel_imx into common. cd common rm -r ./* cp ${MY_ANDROID}/vendor/nxp-opensource/kernel_imx/* ./ ln -s ${MY_ANDROID}/vendor/nxp-opensource/verisilicon_sw_isp_vvcam verisilicon_sw_isp_vvcam ln -s ${MY_ANDROID}/vendor/nxp-opensource/nxp-mwifiex nxp-mwifiex  Build GKI about i.MX: BUILD_FOR_GKI=yes BUILD_CONFIG=common/build.config.imx EXT_MODULES_MAKEFILE="verisilicon_sw_isp_vvcam/vvcam/v4l2/Kbuild" EXT_MODULES="nxp-mwifiex/mxm_wifiex/wlan_src" build/build_abi.sh --update-symbol-list -j8 Then the  common/android/abi_gki_aarch64_imx will be generated. cd gki cp common/android/abi_gki_aarch64_imx /tmp/abi_gki_aarch64_imx   Update GKI kernel rm -r common/* # delete imx kernel repo sync # recover aosp kernel cp /tmp/abi_gki_aarch64_imx android/abi_gki_aarch64_imx cd .. BUILD_CONFIG=common/build.config.gki.aarch64 build/build_abi.sh LTO=thin --update -j8  Then, common/android/abi_gki_aarch64.xml is updated.  
View full article
i.MX8DXL DDR3L EVK board, nor flash using is MT25QU512ABB8ESF-0SIT. This doc will show reference of FlexSPI configuration parameters to make booting from MT25Q flash, with QUAD pad and DDR mode. HW: i.MX8DXL DDR3L EVK board SW: Linux 5.4.70 BSP From RM 5.9.3.2 FlexSPI serial flash BOOT operation, the FlexSPI boot flow as :   FlexSPI configuration parameters,  could be think as two kind group: parameter for FlexSPI controller,  parameter related to the operation on nor flash.   Full parameter table check check i.MX8DXL RM Table 5-20. FlexSPI Configuration block. Let us check MT25Q data sheet for its feature, note our target is DDR mode(80MHZ) and QUAD pad:     Now let us change the FlexSPI configuration parameters: 1>readSampleClkSrc , set as 2 , that is loop back from SCK pad; this filed default set as 0, as found default value booting will met failure in this use case, so change to 2. 2>deviceModeCfgEnable set 1, deviceModeSeq.seqNum set 1 , deviceModeSeq. seqId set to 4; deviceModeArg set 0x5f. i.MX8DXL will send some cmd to flash to make MT25Q enter DDR mode and QUAD mode, so deviceModeCfgEnable =1. For seqNum=1, seqId =4; means index 4 of LUT table will store this sequence, and cost one LUT entry. We will explain how to change LUT entry later. For deviceModeArg=0x5f, check MT25Q data sheet, its enhanced volatile register could be write to configure the flash working mode:  3>controllerMiscOption as 0x40, this parameter only for FlexSPI controller itself, means as” External device works using DDR commands”. 4>deviceType=1(Serial Nor),  sflashPadType=4 (QUAD pad),  serialClkFreq=4(80MHZ CLK), these parameter also only for FlexSPI controller. 5>sflashA1Size fill actual size, in terms of bytes 6>LUT entry changes, check 8DXL RM Table 5-21: So LUT entry 0 is sequence for Read command, entry 1 is for Read Status sequence, entry 3 is for Write Enable sequence,  entry 15 is for Dummy command sequence. Other index LUT entry(for example 2,4,6,7,8,10,12,13,14) is could be used for store your sequence for some cmd your flash device neede. We store sequence of writing MT25Q enhance volatile register as LUT entry 4. Check 8DXL RM,  Figure 15-6. LUT and sequence structure:   Each LUT entry (sequence) will using 16 byte,  one sequence consists of up to 8 instructions, each instruction will using 16bit. Each instruction  format as opcode—num_pads—operand. Check RM 15.2.4.8 Programmable Sequence Engine, for supported instructions:   Actually the Write enable sequence is run first before the other sequence, as we will write Mt25Q volatile register, before that need issue Write enable sequence. Check MT25Q data sheet: For this sequence only need one instruction, that is 0x0406, at this time still using is SDR and one pad mode:  Opcode (CMD_SDR),  one pad (0), operand (6).   LUT entry 1, Read status sequence, it is READ STATUS REGISTER (05h) of MT25Q , check data sheet: It use two instructions: 0x0405: opcode(CMD_SDR), pad (one pad), operand (0x5, READ STATUS REGISTER) 0x2404: opcode(READ_SDR), pad (one pad), operand (0x4 , byte number)   LUT entry 4, that is for make MT25Q enter DDR mode and quad pad: From MT25Q data sheet: It will use two instructions, that is 0x0461: opcode (CMD_SDR),  one pad (0), operand (0x61 WRITE ENHANCED VOLATILE CONFIGURATION REGISTER) 0x2001: opcode (WRITE_SDR 08), one pad(0), operand (1 byte data size) The 0x5f will be send out as data.   Next check LUT entry read , at this time MT25Q had enter QUAD pad and DDR mode: LUT entry 0, Read sequence, it is fast read data from MT25Q, from data sheet: will use four instructions , that is : 86ED, opcode (CMD_DDR ), pad ( four pad), operand (0xEDh fast read) 8a18, opcode (RADDR_DDR), pad (four pad), operand (0x18 , three byte address) B210, opcode(DUMMY_ADDR), pad (four pad), operand(0x10, dummy cycle) A604, opcode (READ_DDR), pad (four pad) , operand (0x4, data byte)   Reference: 1.i.MX8DXL Reference Manual 2.MT25Q data sheet              
View full article
gst-inspect is a tool to to get documentation about GStreamer elements. Pipeline Check installed GST elements gst-inspect | tail -1 Check installed FSL GST elements gst-inspect | grep imx Element documentation gst-inspect <gst element>
View full article
The following are a couple of recommendations for setting up a Host machine for building the Android Nougat 7.1.1_1.0.0 BSP. Some of these recommendations are not exclusive of the Nougat release and may help in other scenarios. These also apply to using Virtual Machines as Host. Installing Open JDK 8 on Ubuntu 14.04 As mentioned on the Android guide for Establishing a Build Environment (http://source.android.com/source/initializing.html) there are no available supported OpenJDK 8 packages for Ubuntu 14.04, which is the version recommended and tested on the Nougat Android BSP. An alternative is downloading the Ubuntu 15.04 Open JDK 8 packages and installing them manually, which can be done by following this procedure: Download the .deb packages for 64-bit architecture from archive.ubuntu.com: openjdk-8-jre-headless_8u45-b14-1_amd64.deb with SHA256 0f5aba8db39088283b51e00054813063173a4d8809f70033976f83e214ab56c0 http://archive.ubuntu.com/ubuntu/pool/universe/o/openjdk-8/openjdk-8-jre-headless_8u45-b14-1_amd64.deb  openjdk-8-jre_8u45-b14-1_amd64.deb with SHA256 9ef76c4562d39432b69baf6c18f199707c5c56a5b4566847df908b7d74e15849 http://archive.ubuntu.com/ubuntu/pool/universe/o/openjdk-8/openjdk-8-jre_8u45-b14-1_amd64.deb  openjdk-8-jdk_8u45-b14-1_amd64.deb with SHA256 6e47215cf6205aa829e6a0a64985075bd29d1f428a4006a80c9db371c2fc3c4c http://archive.ubuntu.com/ubuntu/pool/universe/o/openjdk-8/openjdk-8-jdk_8u45-b14-1_amd64.deb  Once you have downloaded these three packages and checked the checksum for them install the packages (optional) install them by running: $ sudo apt-get update $ sudo dpkg -i openjdk-8-jre-headless_8u45-b14-1_amd64.deb $ sudo dpkg -i openjdk-8-jre_8u45-b14-1_amd64.deb $ sudo dpkg -i openjdk-8-jdk_8u45-b14-1_amd64.deb‍‍‍‍   Increasing SWAP to compensate for the lack of RAM Having insufficient RAM especially on the linking part of the image build may cause a number of issues that are difficult to troubleshoot. In these cases it’s good to take a look at the resource monitor to see if indeed the RAM was depleted. One way to make up for the limited RAM is using a bigger swap. Google recommends at least 16GB of RAM/swap so it’s not uncommon to create a 10GB swap when working in VM, to do this please use the following commands.    $ sudo fallocate -l 10g /mnt/10GB.swap $ sudo chmod 600 /mnt/10GB.swap $ sudo mkswap /mnt/10GB.swap $ sudo swapon /mnt/10GB.swap‍‍‍‍   Increasing heap size to avoid out of memory errors It is possible to encounter an out of memory error with the recommendation “try increasing heap size witj java option ‘-Xmx<size>’. If you encounter this error or would like to proactively avoid it you may run the following commands that will increase heap size to four gigabytes and then reset the Jack Server by killing it and starting it again. With the android environment initialized: $ cd my android $ export JACK_SERVER_VM_ARGUMENTS="-Dfile.encoding=UTF-8 -XX:+TieredCompilation -Xmx4g" $ jack-admin kill-server && jack-admin start-server‍‍‍‍‍‍  Fixing Jack Servers errors due to multiple users on the Host Android Nougat uses Jack Server as mono-user by default. If this is not the case for your host you would need to choose different port numbers for each user and adjust SERVER_NB_COMPILE accordingly. You can also disable the Jack server by setting SERVER=false in your $HOME/.jack. Alternatively, you may also use the patch available on the following link to myandroid/prebuilts/sdk. It will help to fix the mono-user build restriction. When installing the jack-server, it will detect if Jack server is running in the same build machine and then generate a random ports for my build instead of using the default one. https://groups.google.com/forum/#!topic/android-building/UWhJrXH8Vig
View full article
This doc show: on i.MX6Q SabreSD board, configure ov5640 sensor(parallel or MIPI) output 5MP(2592x1944) RAW(Bayer) data at 15fps,and i.MX6Q IPU capture RAW RGB data, and i.MX6Q GPU debayer RAW data then display image. HW: i.MX6Q-SabreSD board, ov5640 sensor. SW: Linux 4.14.98_2.0.0 BSP, and patches in this doc. Configure at camera sensor side A Bayer filter is a color filter array (CFA) for arranging RGB color filters on a square grid of photosensors. The filter pattern is 50% green, 25% red and 25% blue, hence is also called BGGR, RGBG ,GRGB, or RGGB. The ov5640 has an image array capable of operating at up to 15 fps in 5 megapixel (2592x1944) resolution. OV5640 support output formats: RAW(Bayer), RGB565/555/444,CCIR656, YUV422/420, YCbCr422, and compression. To make ov5640 output 5MP RAW data at 15fps, check my patch imx6_ov5640_dvp_mipi_raw_capture_driver-4.14.98_2.0.0.diff which apply on i.MX Linux 4.14.98_2.0.0 BSP kernel code: Parallel interface ov5640, use ov5640_raw_setting[] array of drivers/media/platform/mxc/capture/ov5640.c. This register setting is come from ov5640 software application note and data sheet. MIPI interface ov5640, use ov5640_mipi_raw_setting[] array of drivers/media/platform/mxc/capture/ov5640_mipi.c. This register setting is combine setting of original code (remove ISP register setting), plus PLL register setting for MIPI interface, plus some data format register setting. Configure at i.MX6Q side The i.MX6Q IPU camera port(CSI-2 module) support data format include Raw(Bayer), RGB, YUV 4:4:4, YUV 4:2:2 and grayscale, up to 16 bits per value. Below is camera data routing for i.MX6Q:    Below is i.MX6Q IPU block daigram: The CSI-2 of IPU which is responsible for synchronizing and packing the video (or generic data) and sending it to other blocks. The video data received by CSI-2, could be sent to three other blocks: SMFC, VDI, IC. For RAW (Bayer) data capture, should go through path like this: CSI-2-->SMFC-->IDMAC-->DDR memory It means RAW data is received as generic data, see IPU_PIX_FMT_GENERIC in my patch, and IPU cannot process this kind data, it is just received to DDR memory. For MIPI interface camera, need note is i.MX6 side MIPI D-PHY clock must be calibrated to the actual clock range of the camera sensor’s D-PHY clock and the calibrated value must be equal to or greater than the camera sensor clock, detail see  AN5305. Take MIPI ov5640 as example: Pixel clock = 2592x1944x15fpsx(1/2 cycle/pixel)x1.35 blank interval = 51MHZ MIPI data rate = 51MHZ x 16 bit = 816Mb/s so 816/2/2*2 is 408MHZ is i.MX6 side D-PHY clock. Here due to one bayer pixel is 8bit, and i.MX6 MIPI data bus is 16 bit, so above use 1/2 cycle/pixel. And check ov5640_mipi_raw_setting[], you will got the sensor side D-PHY clock is about 672/2 = 336MHZ. And check AN5305, register MIPI_CSI2_PHY_TST_CTRL1 of i.MX6 need set as 0xC, but here i still keep it as default BSP value 0x14.   3.Capture test code I changed unit test mxc_v4l2_capture.c to capture the RAW data and save it to file. Check my patch imx6_ov5640_raw_captupre_test_4.14.98_2.0.0_ga.diff which apply on i.MX  Linux 4.14.98_2.0.0 BSP unit test code. Note the usage is: ./cap.out -c 1 -i 1 -fr 15 -m 6 -iw 2592 -ih 1944 -ow 2592 -oh 1944 -f BA81 -d /dev/video1 savefile.dmp parameter -i 1 means use CSI to MEM mode /dev/video1 is MIPI ov5640, /dev/video0 is parallel ov5640   4.Display RAW data The RAW data cannot be displayed directly, debayer process is needed to get complete red, green, blue color for each pixel. The debayer process if run on CPU, will cost much CPU time. To save CPU time, debayer could done by GPU. The method is, captured RAW data upload to GPU as texture , then GPU will do the debayer, then full color of each pixel will be got, then display it. To upload RAW camera data to GPU with zero memory copy, i will use i.MX6Q GPU extension GL_VIV_direct_texture. It create a texture with direct access support. API glTexDirectVIVMap,  which support mapping a user space memory or a physical address into the texture surface. The API glTexDirectVIVMap need logic and physical address of data buffer, so i will allocate data buffer from /dev/mxc_ipu, it is dma-buffer also get logic/physical address of buffer, then queue it as USERPTR to ipu v4l2 capture driver, after dequeue got RAW camera data, pass it to GPU for debayer. GPU side, I will use OpenGL shader code from "Efficient, High-Quality Bayer Demosaic Filtering on GPUs". Check my patch imx6-5640-debayer-testcode-gpusdk-5.2.0.diff which apply on i.MX GPU SDK 5.2.0 code. Note, here i only do is debayer, no extra process.   Known issue One thing is ov5640 output 5MP at 15fps, compare with output 5MP at 5fps, there are more noise of camera data at 15fps case. My debug found is , this noise seems come from ov5640 itself.   Reference: a>https://www.nxp.com/webapp/Download?colCode=IMX6DQRM b>https://www.nxp.com/webapp/Download?colCode=L4.14.98_2.0.0_MX6QDLSOLOX&appType=license c>https://github.com/NXPmicro/gtec-demo-framework d>https://www.nxp.com/docs/en/application-note/AN5305.pdf e>ov5640 data sheet f>ov5640 software application note g>Efficient, High-Quality Bayer Demosaic Filtering on GPUs https://www.semanticscholar.org/paper/Efficient%2C-High-Quality-Bayer-Demosaic-Filtering-on-McGuire/088a2f47b7ab99c78d41623bdfaf4acdb02358fb
View full article
i.MX8/8X/8XL在汽车中的应用 • 娱乐导航 • 虚拟仪表 • 电子座舱 • 360环视与ADAS • C-V2X Tbox
View full article