Layerscape ナレッジベース

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Layerscape Knowledge Base

ディスカッション

ソート順:
[中文翻译版] 见附件   原文链接: https://community.nxp.com/docs/DOC-343516     
記事全体を表示
Recently some customers are porting SDK 2.0 u-boot for LS1021ATWR to their custom boards. They intended to use GPIO lines to turn on/off LEDs for diagnostics and other various purposes. However GPIO driver is not supported in SDK 2.0 u-boot for LS102xa platform. The attached patch is used to add GPIO driver on LS1021ATWR platform based on SDK 2.0 u-boot code. Please use it in SDK 2.0 as the following: $ source ./fsl-setup-env -m ls1021atwr $ bitbake u-boot -c cleansstate $ bitbake u-boot -c patch Go to the folder build_ls1021atwr/tmp/work/ls1021atwr-fsl-linux-gnueabi/u-boot-qoriq/2016.01+fslgit-r0/git, apply the attached patch $ patch -p1<0001-ls1021xa-gpio.patch Go back to build_ls1021atwr folder to rebuild u-boot $ bitbake u-boot
記事全体を表示
LS1043ARDB version updated because we replaced the Nand Flash with different page size one as the old one is obsolete. Version update information FA version Nand flash program by CodeWarrior Nand Flash firmware bring up files Boot Mode setting
記事全体を表示
When customer’s ethernet PCS could not link up, this article will give a guide how to debug it step by step based on the T1024. Many ethernet is configured by the SerDes, so how to confirm the link error is caused by the SerDes or the PCS itself. This article will give some clues. Serdes Lane&pins First check which SerDes lane the you are using, please confirm the SerDes land in the QorIQ T1024 Reference Manual. Such as configuration below, the user case set the SRDS_PRCTL_S1=0x05B in the RCW[128:136], the application will utilize the SGMII.m1 and SGMII.m2. This article will consider SGMII.m1 as an user case, now the SGMII will in the Frame Manager, MAC1. Check the SerDes Lane Assignments to confirm the Lane of the SerDes, for the SGMII.m1, the specific lane pins name would be SD1_TX3P/N and SD1_RX3P/N. it could be recognized as Lane 3. MAC number is not related to the Serdes lane number, should confirm the specific table to get the pins. Any hardware test with this ethernet should related the pins, see the component pin number below. You could test the eye diagram of RX pins of this Lane to confirm if the frequency is correct. if you set this Lane to SGMII 1.25G, you could confirm the speed is set correctly by the eye diagram. Eye diagram above, just show the speed of the SerDes. That is very important when loopback correctly, but could to connect to other device. How to confirm the SerDes link up Please find the Lane register in the QorIQ T1024 Reference Manual. In this user case it’s Lane 3, so should read out the Lane 3 registers to confirm if the SerDes Lane 3 work well. Such as below: # Lane 3 md.l 0xFFE0EA8C0 1 - aa611080 # LN3GCR0 md.l 0xFFE0EA8C4 1 - 101c4019 # LN3GCR1 md.l 0xFFE0EA8CC 1 - 00002800 # LN3SSCR0 md.l 0xFFE0EA8D0 1 - 0f0fc01f # LN3RECR0 md.l 0xFFE0EA8D4 1 - 0f0f0fa8 # LN3RECR1 md.l 0xFFE0EA8D8 1 - 00003006 # LN3TECR0 md.l 0xFFE0EA8E0 1 - 39000400 # LN3TTLCR0 md.l 0xFFE0EA8E4 1 - 00000000 # LN3TTLCR1 md.l 0xFFE0EA8F4 1 - 00000000 # LN3TCSR1 md.l 0xFFE0EA8FC 1 - 04000000 # LN3TCSR3   SerDes_LNnTCSR3 is an important debug test register, the CDR_LCK is to check if the CDR locked or not. CDR_LCK=0 means a valid bit stream is not detected. As a test, you could put the lane in loopback mode LN2TCSR3[LPBK_EN]=01. The CDR should lock in digital loopback mode (internal loopback). If not, there could be an issue with the device itself. So, if you could set the LPBK-EN to “01” Loopback Mode, it will set the SerDes’s own TX and RX signals in Loopback Mode to exclude external signals, then check the CDR_LCK again, if it’s 1, then SerDes itself works well. Anyway, CDR_LCK should always be set. In the “md.l 0xFFE0EA8FC 1 - 04000000 # LN3TCSR3”, the CDR_LCK=0, suspect the SerDes level issue. The normal status should be: => md fe0ea8fc 1 fe0ea8fc: 08000000 How to confirm the PCS link up The MAC and PHY registers should get the details from the T1024DPAArm, QorIQ T1024 Data Path Acceleration Architecture (DPAA) Reference Manual Find the offset address in the DPAARM. For the SGMII MAC address should be offset+0x1000. Follow the 6.5.4 MDIO Ethernet Management Interface usage in the T1024DPAARM to read the MDIO registers. In this application, SGMII1, MAC1, you could find the MAC1 address would be FM1_mEMAC1: 4E_0000, so FM1_mEMAC1 MDIO registers would be 4E_1000h. In the user case, the protocol is SGMII, should follow the 6.5.4.3 Clause 22 Read Flow in the T1024DPAARM. 6.5.4.3 Clause 22 Read Flow 1) Wait for MDIO_CFG[BSY] = 0. 2) Write MDIO_CTL with proper PHY_ADDR and REGISTER_ADDR and with bit 16 set. 3) Wait for MDIO_CFG[BSY] = 0. 4) If the addressed PHY did not respond then MDIO_CFG[MDIO_RD_ER] is set. Otherwise read MDIO_DATA value. In this user case, should read the MDIO_SGMII_SR, you could find the register definition in the QorIQ T1024 Reference Manual, 30.5.5 1000Base-KX PCS MDIO Memory Map/Register Definition The key bits would below: Here the user case result: When you read MDIO_SGMII_SR, please use manual input that can meet the delay time requirement. If you could not input manually, please follow the flow, " Wait for MDIO_CFG[BSY] = 0" before read MDIO_DATA value. Read SGMII1 MDIO Registers === Serdes Test 1 === 0xFFE0EA8FC value: 0x08000000 Dump PCS0 Registers 0xFFE4E1030-0xFFE4E103C: 0x40001408 0x00000000 0x00001340 0x00001340 Select 0x8002 ,devmem 0xFFE4E1034 32 0x8002 Read: 0x00000083 Select 0x8003 ,devmem 0xFFE4E1034 32 0x8003 Read: 0x0000E400 Select 0x8001 ,devmem 0xFFE4E1034 32 0x8001 Serdes0 Status: 0x00000029 Select 0x8001 devmem 0xFFE4E1034 32 0x8001 Serdes0 Status: 0x0000002D Select 0x8001, devmem 0xFFE4E1034 32 0x8001 Serdes0 Status: 0x0000002D The first time, it’s not link, LINK_STAT is 0(0x00000029), and then it’s turn to 1(0x0000002D). Now the PCS link up and the HW loopback checking is completely.
記事全体を表示
Issue description. The CodeWarrior ®  TAP enables target system debugging via a standard debug port (usually JTAG) while connected to a developer's workstation via Ethernet or USB. This the hardware debug tool(JTAG debug tool) to debug the DN MPU. You could find the tool from below link https://www.nxp.com/design/design-center/development-boards-and-designs/CW_TAP To debug the Layerscape MPU, should select CWH-CTP-BASE-HE and CWH-CTP-CTX10-YE In fact, the CWH-CTP-CTX10-YE will adapt the different signal definition, one connector will be insert to the CWH-CTP-BASE-HE, and another one(totally 10 pins) will be used to debug the Layerscape MPU. You could find the definition of the JTAG connector(CWH-CTP-CTX10-YE, 10pins) on the Layerscape board. Pin 10 (SRST)is the signal of this documents to should add workaround.     In the CodeWarrior TAP Probe User Guide, the SRST(SRST_B) is Open-drain. So the voltage of this signal should be decided by the pull-up voltage connect to it. See the schematics part below, pin 10 (JTAG_RST_B) should be 1.8V, but in fact it’s not.   The test signal will be exceed 1.8V to about 2.6V.   If you connect this pin directly to the Layerscape MPU, it will violate the SPEC of the VIN. Workaround. Workaround for the user would be to use an external circuit (level shifter/limiter) for the affected signal(s). level-shifter/limiter CWTAP <=> probe tip <=> (level-shifter/limiter) <=> target Please refer to FRWYLS1046A-PA,  use the AND gate 74AUP1G11GW similar components which the Overvoltage tolerant inputs to 3.6 V.     Logic Device Customer could also refer to LS1046ARDB CPLD LCMXO1200C-3FTN256C and LX2160ARDB CPLD EPM2210F256C5N, even the CPLD IO Voltage is 1.8V, no issue with 2.6V input on 1.8V IO ports.    
記事全体を表示
Follow these steps to update DPAA2 MC firmware and DPC images in QSPI flash, if you are booting LS1088ARDB from the QSPI flash memory.  qixis_reset boots the board from QSPI flash0 (aka bank0) and qixis_reset altbank boots the board from QSPI flash1 (aka bank4). “sf probe 0:1” means that the alternate bank will be written to. So if you boot from flash0, then enter sf probe 0:1, the commands that follow will program flash1. Prerequisites Linux machine. It is recommended to install Ubuntu 18.04 on the Linux machine. Obtaining MC firmware Download the prebuilt MC firmware image from the git repository: https://github.com/NXP/qoriq-mc-binary/tree/integration/ls1088a Obtaining DPC image Clone mc-utils repository and compile the DPC image. git clone https://source.codeaurora.org/external/qoriq/qoriq-components/mc-utils cd mc-utils/ git checkout LSDK-18.09 make -C config/ The compiled dpc.0x1D-0x0D.dtb is available at /mc-utils/config/ls1088a/RDB/. Flash MC firmware image on LS1088ARDB QSPI flash In U-Boot, boot from flash0, program flash1:  
記事全体を表示
The u-boot in SDK2.0 has a bug on SGMII2.5 support. Need to add the patch.
記事全体を表示
The document explains how to use the variable  APTGET_EXTRA_PACKAGES in Yocto-based LLDP builds (ls-image-main.bb recipe) to install Ubuntu packages via apt-get instead of BitBake recipes.  
記事全体を表示
Introduction The qDMA controller transfers blocks of data between one source and one destination. The blocks of data transferred can be represented in memory as contiguous or noncontiguous using scatter/gather table(s). Channel virtualization is supported through enqueuing of DMA jobs to, or dequeuing DMA jobs from, different work queues. QDMA can support LX2160A with DPAA2. The attached patch is used for QDMA data transfer between PCIe Endpoint and DDR memory on LX2160A Platform. Apply the patch and rebuild Kernel image in LSDK 21.08 Go to LSDK 21.08 Linux Kernel source folder components/linux/linux/   Apply the attached patch. $ patch -p1 < 0001-QDMA-Performance-test.patch   $ flex-builder -c linux:custom -a arm64 Enable CONFIG_FSL_DPAA2_QDMA=y   $ Rebuild Linux Kernel. $ flex-builder -c linux -a arm64   Transfer data from Memory to Memory root@localhost:~# restool dpdmai create --num-queues=8 --priorities=2,5 dpdmai.0 is created under dprc.1 root@localhost:~# restool dprc assign dprc.1 --object=dpdmai.0 --plugged=1 root@localhost:~# echo "dpdmai.0" > /sys/module/dmatest/parameters/device root@localhost:~# echo '7       4       1       7' > /proc/sys/kernel/printk root@localhost:~# echo 1 > /sys/module/dmatest/parameters/dmatest_option root@localhost:~# echo 10 > /sys/module/dmatest/parameters/iterations root@localhost:~# echo 4096 > /sys/module/dmatest/parameters/test_buf_size root@localhost:~# echo 1 > /sys/module/dmatest/parameters/threads_per_chan root@localhost:~# echo 1 > /sys/module/dmatest/parameters/run [  177.903819] dmatest: current_mask 1 root@localhost:~# [  177.907636] dmatest: len 11         save_mask ffff  tmp_mask 2 [  178.927396] dmatest: qdma-test-task: summary 10 tests, 0 failures 303030 iops 1212121 KB/s 1241212121 B/s (0) [  178.937308] dmatest: total_len 40960  len 4096 [  178.941870] dmatest: runtime 33 [  178.941870]   root@localhost:~# echo 8 > /sys/module/dmatest/parameters/threads_per_chan root@localhost:~# echo 1 > /sys/module/dmatest/parameters/run [  273.731698] dmatest: current_mask 1 root@localhost:~# [  273.735625] dmatest: len 11         save_mask ffff  tmp_mask 2 [  274.767409] dmatest: qdma-test-task: summary 10 tests, 0 failures 357142 iops 1428571 KB/s 1462857142 B/s (0) [  274.777315] dmatest: total_len 40960  len 4096 [  274.781875] dmatest: runtime 28 [  274.781875]   Transfer data from Memory to PCIe  root@lx2160ardb-rev2:~# restool dpdmai create --num-queues=8 --priorities=2,5 dpdmai.0 is created under dprc.1 root@lx2160ardb-rev2:~# restool dprc assign dprc.1 --object=dpdmai.0 --plugged=1 root@lx2160ardb-rev2:~# echo "dpdmai.0" > /sys/module/dmatest/parameters/device root@lx2160ardb-rev2:~# echo '7       4       1       7' > /proc/sys/kernel/printk root@lx2160ardb-rev2:~# echo 4096 > /sys/module/dmatest/parameters/test_buf_size root@lx2160ardb-rev2:~#  echo 10 > /sys/module/dmatest/parameters/iterations root@lx2160ardb-rev2:~# echo 2 > /sys/module/dmatest/parameters/dmatest_option root@lx2160ardb-rev2:~# echo 0x9040000000 > /sys/module/dmatest/parameters/pci_phys_addr root@lx2160ardb-rev2:~# echo 1 > /sys/module/dmatest/parameters/produ_task_number root@lx2160ardb-rev2:~# echo 1 > /sys/module/dmatest/parameters/run [  214.319248] dmatest: current_mask 1 root@lx2160ardb-rev2:~# [  214.322864] dmatest: len 11   save_mask ffff  tmp_mask 2 [  214.330187] dmatest: pcie_phy_base : 9040000000       pcie_virt_base : 0000000014415a49 [  215.355448] dmatest: qdma-test-task: summary 10 tests, 0 failures 26737 iops 106951 KB/s 109518716 B/s (0) [  215.365093] dmatest: total_len 40960  len 4096 [  215.369529] dmatest: runtime 374 [  215.369529]  
記事全体を表示
  ARM Cortex A57 and A53 L1/L2 cache error reporting    The attached patch adds error detection for A53 and A57 cores. Hardware error injection is supported on A53. Software error injection is supported on both. For hardware error injection on A53 to work, proper access to L2ACTLR_EL1, CPUACTLR_EL1 needs to be granted by EL3 firmware. This is done by making an SMC call in the driver. Failure to enable access disables hardware error injection. For error interrupt to work, another SMC call enables access to L2ECTLR_EL1. Failure to enable access disables interrupt for error reporting. CPU Memory Error Syndrome and L2 Memory Error Syndrome registers can be used for checking L1 and L2 memory errors. However, only A53 supports double-bit error injection to L1 and L2 memory. This driver uses the hardware error injection when available, but also provides a way to inject errors by software. Both A53 and A57 supports interrupt when multi-bit errors happen. To use hardware error injection and the interrupt, proper access needs to be granted in ACTLR_EL3 (and/or ACTLR_EL2) register by EL3 firmware SMC call. Correctable errors do not trigger such interrupt. This driver uses dynamic polling internal to check for errors. The more errors detected, the more frequently it polls. Combining with interrupt, this driver can detect correctable and uncorrectable errors. However, if the uncorrectable errors cause system abort exception, this driver is not able to report errors in time.    Build ATF and Kernel image with EDAC L1 and L2 cache error detection enabled in LSDK In LLDPUG_RevL6.1.22_2.0.0 Yocto build environment, please rebuild ATF as the following. $ source build_ls1043ardb/SOURCE_THIS $ bitbake qoriq-atf -c cleansstate $ bitbake qoriq-atf -c patch Please go to atf source code folder build_ls1043ardb/tmp/work/ls1043ardb-fsl-linux/qoriq-atf/2.8+AUTOINC+atf-r0/git/, please apply patch 0001-Porting-helper-functions-for-EDAC-support-based-on-L.patch. $ patch -p1 < 0001-Porting-helper-functions-for-EDAC-support-based-on-L.patch And rebuild atf image. $ bitbake qoriq-atf Please rebuild Linux Kernel with the following commands. $ source build_ls1043ardb/SOURCE_THIS $ bitbake virtual/kernel -c cleansstate $ bitbake virtual/kernel -c patch Please go to Linux Kernel source code folder build_ls1043ardb/tmp/work/ls1043ardb-fsl-linux/linux-qoriq/6.1.y+gitAUTOINC+66e442bc7f-r0/git/ to apply patch 0001-drivers-edac-Add-L1-and-L2-error-detection-for-A53-a.patch. $ patch -p1 < 0001-drivers-edac-Add-L1-and-L2-error-detection-for-A53-a.patch   $ bitbake virtual/kernel -c menuconfig   $ bitbake virtual/kernel   L1/L2 cache error detection and correction EDAC feature verification root@localhost:~# dmesg | grep edac [ 3.478641] EDAC DEVICE0: Giving out device to module edac-a53 controller cortex_edac_l1_l2: DEV edac-a53 (POLLED) root@localhost:~# echo 1 > /sys/devices/system/edac/cpu_cache/l1_ue_sw_inject root@localhost:~# [ 74.784912] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L1 count: 1 'Fatal error(s) on CPU 0 [ 74.784912] ' root@localhost:~# echo 1 > /sys/devices/system/edac/cpu_cache/l1_ue_hw_inject [ 83.429371] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L1 count: 1 'Fatal error(s) on CPU 3 [ 83.429371] ' root@localhost:~# echo 1 > /sys/devices/system/edac/cpu_cache/l2_ue_sw_inject root@localhost:~# echo 1 > /sys/devices/system/edac/cpu_cache/l2_ue_hw_inject [ 106.985393] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 0 [ 106.985393] ' [ 106.997164] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 1 [ 106.997164] ' root@localhost:~# [ 115.232986] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 0 [ 115.232986] ' root@localhost:~# dmesg | grep EDAC [ 1.638675] EDAC MC: Ver: 3.0.0 [ 3.478641] EDAC DEVICE0: Giving out device to module edac-a53 controller cortex_edac_l1_l2: DEV edac-a53 (POLLED) [ 74.784840] EDAC cortex_edac_l1_l2: CPU 0 L1-I Tag RAM error(s) detected [ 74.784869] EDAC cortex_edac_l1_l2: CPU 0 L1 fatal error(s) detected (0x8000000080000000) [ 74.784912] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L1 count: 1 'Fatal error(s) on CPU 0 [ 83.429298] EDAC cortex_edac_l1_l2: CPU 3 L1-D Data RAM error(s) detected [ 83.429329] EDAC cortex_edac_l1_l2: CPU 3 L1 fatal error(s) detected (0x8000000089100010) [ 83.429371] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L1 count: 1 'Fatal error(s) on CPU 3 [ 106.985331] EDAC cortex_edac_l1_l2: CPU 0 L2 fatal error(s) detected (0x80000000910dc138) [ 106.985349] EDAC cortex_edac_l1_l2: CPU 1 L2 fatal error(s) detected (0x8000000080000000) [ 106.985393] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 0 [ 106.997164] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 1 [ 115.232936] EDAC cortex_edac_l1_l2: CPU 0 L2 fatal error(s) detected (0x80000000910c0598) [ 115.232986] EDAC DEVICE0: UE: cortex_edac_l1_l2 instance: cpu_cache0 block: L2 count: 1 'Fatal error(s) on CPU 0  
記事全体を表示
 Introduction In this article, we will explain in this article which steps you have to take to transform and quantize your model with different TensorFlow versions. We are only looking into post training quantization. We are using the MX8MPlus EVK run our model that have a dedicated neural network accelerator IP from VeriSilicon (Vivante VIP8000). Press enter or click to view image in full size     i.mx8MPlus block diagram from NXP Is the neural processing unit (NPU) from NXP need a fully int8 quantized model we have to look into full int8 quantization of a TensorFlow lite or PyTorch model. Both libraries are supported with the eIQ library from NXP. Here we will only look into the TensorFlow variant. The general overview on how to do post training quantization can be found on the TensorFlow website.  The operations for floating point are more complex than for integer (arithmetic’s, avoiding overflow). This results in the ability to use only the much simpler and smaller arithmetic units instead of the larger floating-point units. ​ ​The physical space needed for float32 operation much larger than for int8. This results in:​ Lower power consumption, ​ Less heat development, ​ The ability to join more calculation units decreasing inference time. Prerequisite To create the code on your PC first, we recommend using Anaconda with a virtual environment running Python 3.6, TensorFlow 2.x, numpy, opencv-python and pandas. Post training quantization with TensorFlow Version 2.x If you created and trained a model via tf.keras there are three similar ways of quantizing the model. First Method — Quantizing a Trained Model Directly The trained TensorFlow model has to be converted into a TFlite model and can be directly quantize as described in the following code block. For the trained model we exemplary use the updated tf,keras_vggface model based on the work of rcmalli . The transformation starts at line 28. from keras_vggface_TF.utils import preprocess_input from keras_vggface_TF.vggfaceTF import VGGFace converter.inference_output_type = tf.int8   import tensorflow as tf import numpy as np tfVersion=tf.version.VERSION.replace(".", "") # can be used as savename print(tf.version.VERSION) # TRAIN A MODEL pretrained_model = VGGFace(model='resnet50', include_top=False, input_shape=(224, 224, 3), pooling='avg') # pooling: None, avg or max #Create a generator for representative Dataset folderpath='./All_croped_images/' def prepare(img):          img = np.expand_dims(img,0).astype(np.float32)          img = preprocess_input(img, version=2) return img repDatagen=tf.keras.preprocessing.image.ImageDataGenerator(preprocessing_function=prepare) datagen=repDatagen.flow_from_directory(folderpath,target_size=(224,224),batch_size=1) def representative_dataset_gen():       for _ in range(10):       Img = datagen.next()       yield [img[0]]   #CONVERT YOUR MODEL TO TFLITE AND QUANTIZE TO INT8 converter = tf.lite.TFLiteConverter.from_keras_model(pretrained_model) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset_gen converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.experimental_new_converter = True converter.target_spec.supported_types = [tf.int8] converter.inference_input_type = tf.int8 quantized_tflite_model = converter.convert() #SAVE THE QUANTIZED MODEL AS TFLITE FILE open('quant_model.tflite' , "wb").write(quantized_tflite_model) After loading/training your model you first have to create a representative data set. The representative data set is used by the converter to get the max and min values to be able to estimate the scaling factor. This limits the error introduced by the quantization from float32 to intX. The error comes from the different number-space of float and int. Converting from float to int8 limits the number-space to integer values between -128 to 127. Calibrating the model on the dynamic range of the input limits this error. Here you can just loop through your images or create a generator as in our example. We used the tf.keras.preprocessing.image.ImageDataGenerator() to yield images and do the necessary prepossessing on the images. As a generator you can of course also use the tf.data.Dataset.from_tensors() or … from.tensor_slices(). Just keep in mind to do the same pre-processing on your data here as you did on the data you trained your network with (normalization, resizing, de-noising, …). This can all be packed into the preprocessing_function call of the generator (line 19). The conversion starts at line 28. A simple TensorFlow lite conversion would look like this: converter = tf.lite.TFLiteConverter.from_keras_model(pretrained_model) tflite_model = converter.convert() open('model.tflite' , "wb").write(tflite_model) The quantization part is in-between: converter = tf.lite.TFLiteConverter.from_keras_model(pretrained_model) converter.optimizations = [tf.lite.Optimize.DEFAULT] converter.representative_dataset = representative_dataset_gen converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8] converter.experimental_new_converter = True converter.target_spec.supported_types = [tf.int8] converter.inference_input_type = tf.int8 converter.inteference_output_type=tf.int8 quantized_tflite_model = converter.convert() open('quant_model.tflite' , "wb").write(quantized_tflite_model)   Line 3 : optimizations other than default are deprecated. No other options are available at the moment (Year 2020). Line 4 : Here we set the representative data set. Line 5 : Here we make sure that we have a full conversion to int8. Without this option, only the weights and biases would be converted but not the activations. This is used when we only want to reduce the model size. However, our NPU needs full int8 quantization. Having the activations still in floating point would result in overall floating-point and could not run on the NPU. Line 6: Enables MLIR-based conversion instead of TOCO conversion, which enables RNN support, easier error tracking. Line 7: Sets the internal constant value to int8. The target_spec corresponds with the TFLITE_BUILTINS from line 5. Line 9 and 10: Set also the input to int8. This is fully available from TF 2.3 Now if we convert the model using TF2.3 with experimental_new_converter=True inference_input_type=tf.int8 inference_output_type=tf.int8 we receive the following model:     However if we do not set the inference_input_type and inference_output_type we receive following model:     So the effect is that you can determine which input data type the model accepts and returns. This can be important if you work with an embedded camera, as included with the MX8MPEVK. The mipi camera returns 8bit values, so if you want to spare a conversion to float32 int8 input can be handy. But be aware, if you use a model without prediction layers to gain e.g., embeddings, an int8 output will result in very poor performance. Here an output of float32 is recommended. This shows that each problem needs a specific solution. Second and Third Method — Quantize a Saved Model from *.h5 or *.pb Files If you already have your model, you most likely have it saved somewhere either as an Keras h5 file or a TensorFlow protocol buffer pb. We will quickly save our model using TF2.3: import tensorflow as tf f rom keras_vggface_TF.vggfaceTF import VGGFace pretrained_model = VGGFace(model='resnet50', include_top=False, input_shape=(224, 224, 3), pooling='avg') # pooling: None, avg or max # Saving as a protocol buffer !mkdir -p saved_model pretrained_model.save('saved_model/my_model') #saving as a h5 file (if your Tensorflow Version is < 2.0 use this) !mkdir -p keras_model pretrained_model.save('keras_model/my_model.h5')   Following the conversion and quantization is very similar as in Method One. The only difference is how we load the model in with the converter. Either load the model and continue as in Method One. #Load the h5 model pretrained_model = tf.keras.models.load_model('my_model.h5') #Then use the converter as before converter = tf.lite.TFLiteConverter.from_keras_model(pretrained_model) Or load the h5 model directly. When using TensorFlow version 2 and above you have to use a compatible converter: # Or load the h5 model from file # TensorFlow version >2.x converter = tf.compat.v1.lite.TFLiteConverter.from_keras_model_file(saved_model_dir + h5_modelname) #works now also with TF2.x # TensorFlowversion < 2.0 converter = tf.lite.TFLiteConverter.from_keras_model_file(saved_model_dir + h5_modelname) If you load from a TensorFlow pb file use: # Or load the pb file from the modelfolder # TensorFlow version >2.x converter = tf.lite.TFLiteConverter.from_saved_model(saved_model_dir) # the folder contains the pb file and a assets and variables folder   Converting with TensorFlow Versions below 2.0 If you want to convert a model written in TensorFlow version < 1.15.3 using Keras, not all options are available for TFlite conversion and quantization. The best way is to save the model with the TensorFlow version it was created in (e.g., rcmalli keras-vggface was trained in TF 1.13.2). I would suggest not using the “saving and freeze graph” method to create a pb file as the pb files differ between TF1 and TF2. The TFLiteConverter.from_saved_model does not work, creating quite a hassle to achieve quantization. I would suggest using the above mentioned method using Keras: import keras …. pretrained_model.save('my_model.h5') Then convert and quantize your model with a TensorFlow version from 1.15.3 onward. From this version on a lot of functions where added in preparation for TF2. I suggest using the latest version.    Regards      
記事全体を表示
How to use the GPU of the NXP Layerscape LS1028A with Yocto    Yocto Project Configuration The most modern and NXP-recommended method for developing with the LS1028A is the Layerscape Linux Distribution POC (LLDP) based on Yocto. Unlike the LSDK (which uses Flexbuild), LLDP uses Yocto/Bitbake and is the long-term supported path. 1 Host Requirements Requirement Details Operating System Ubuntu 20.04 LTS (Focal) — official recommendation RAM Minimum 8 GB (16 GB+ recommended) Disk Space Minimum 100 GB free CPU Minimum 4 cores (more cores = faster builds) Tools git, repo, python3, wget, curl, build-essential Install dependencies on Ubuntu: sudo apt-get update && sudo apt-get install -y  gawk wget git diffstat unzip texinfo gcc-multilib \   build-essential chrpath socat cpio python3 python3-pip  python3-pexpect xz-utils debianutils iputils-ping \   python3-git python3-jinja2 libegl1-mesa libsdl1.2-dev  pylint xterm rsync curl locales zstd liblz4-tool \   repo ca-certificates   # Configure git (required by repo) git config --global user.name "Your Name" git config --global user.email "[email protected]"   2 Download the LLDP Repository (Yocto for LS1028A) # Create working directory mkdir ~/lldp-ls1028a && cd ~/lldp-ls1028a   # Initialize repo with the LLDP manifest (Kirkstone, kernel 5.15) repo init -u https://github.com/nxp-qoriq/yocto-sdk.git \           -b kirkstone \           -m ls-5.15.71-2.2.0_distro.xml   # Sync all repositories (may tak             e 30-60 minutes) repo sync Note: For the latest version (LLDP L6.1.1, kernel 6.1), check the updated manifest at: https://github.com/nxp-qoriq/yocto-sdk   3 Set Up the Build Environment for LS1028A # Initialize Yocto environment for the LS1028A # (run from the lldp-ls1028a/ directory) DISTRO=fsl-qoriq-distro MACHINE=ls1028ardb source distro-setup-env   # This automatically creates and enters the build directory # You are now in: ~/lldp-ls1028a/build_ls1028ardb/   4 local.conf File — GPU Configuration The conf/local.conf file inside the build directory controls compilation options. For the LS1028A with GPU, verify or add: # Edit the configuration file nano conf/local.conf Key parameters for GPU and desktop: # Target machine MACHINE = "ls1028ardb"   # Distribution with GPU and Wayland support DISTRO = "fsl-qoriq-distro"   # Enable display and GPU features DISTRO_FEATURES:append = " wayland opengl"   # GPU driver: use Etnaviv (open-source) for LS1028A # DO NOT use imx-gpu-viv (i.MX only, requires ARCH_MXC) PREFERRED_PROVIDER_virtual/libgl = "mesa" PREFERRED_PROVIDER_virtual/libgles1 = "mesa" PREFERRED_PROVIDER_virtual/libgles2 = "mesa" PREFERRED_PROVIDER_virtual/egl = "mesa"   # Enable OpenCL support via Vivante GPU IMAGE_INSTALL:append = " clinfo"   # Accept NXP proprietary licenses (required for GPU firmware) LICENSE_FLAGS_ACCEPTED = "nxp-proprietary"   # Parallel build threads (adjust to your host PC) BB_NUMBER_THREADS = "8" PARALLEL_MAKE = "-j 8"   # (Optional) Use ccache to speed up recompilations INHERIT += "ccache"   5 Required Yocto Layers (bblayers.conf) Verify that conf/bblayers.conf includes these layers: cat conf/bblayers.conf It must contain at least: BBLAYERS ?= " \   ${BSPDIR}/sources/poky/meta \   ${BSPDIR}/sources/poky/meta-poky \   ${BSPDIR}/sources/meta-openembedded/meta-oe \   ${BSPDIR}/sources/meta-openembedded/meta-multimedia \   ${BSPDIR}/sources/meta-openembedded/meta-python \   ${BSPDIR}/sources/meta-openembedded/meta-networking \   ${BSPDIR}/sources/meta-freescale \   ${BSPDIR}/sources/meta-qoriq \   ${BSPDIR}/sources/meta-nxp-desktop \ " The meta-nxp-desktop layer is what provides GPU support for the LS1028A with the ls-image-desktop image.   6 Build the Image with GPU Support # Recommended: Desktop image with full GPU support (LS1028A only) # Includes: GNOME desktop, Weston/Wayland, Vivante GPU drivers, OpenCL bitbake ls-image-desktop   # Alternative: download all packages first before building # (useful for catching network errors before the long build) bitbake ls-image-desktop --runall fetch bitbake ls-image-desktop   # Minimal: main image without desktop (no GPU by default) bitbake ls-image-main   # Lite: minimal image bitbake ls-image-lite Estimated build time: Between 4 and 8 hours on the first build (depending on host hardware). Incremental builds are much faster.   7 Install the Image to the SD Card After compilation, output files are located in: tmp/deploy/images/ls1028ardb/ # Identify the SD card (verify with lsblk) lsblk   # Install image using flex-installer (included in the SDK) flex-installer \   -b tmp/deploy/images/ls1028ardb/boot_ls1028ardb.tgz \   -f tmp/deploy/images/ls1028ardb/firmware_ls1028ardb_sdboot.img \   -r tmp/deploy/images/ls1028ardb/ls-image-desktop-ls1028ardb.tar.zst \   -d /dev/sdX    # replace with your SD device   Practical Example: OpenCL Application on LS1028A This example shows how to compile and run a program that uses the GC7000UL GPU to add two vectors with OpenCL.   8.1 Source Code: vector_add.cl (OpenCL Kernel) Create the kernel file on the LS1028A board: # On the LS1028A (via serial or SSH) cat > /home/root/vector_add.cl << 'EOF' __kernel void vector_add(     __global const float* a,     __global const float* b,     __global float* c,     const int n) {     int gid = get_global_id(0);     if (gid < n) {         c[gid] = a[gid] + b[gid];     } }   8.2 Source Code: vector_add.c (OpenCL Host) cat > /home/root/vector_add.c << 'EOF' #include <stdio.h> #include <stdlib.h> #include <string.h> #include <CL/cl.h>   #define VECTOR_SIZE 1024   int main() {     cl_platform_id   platform;     cl_device_id     device;     cl_context       context;     cl_command_queue queue;     cl_program       program;     cl_kernel        kernel;     cl_mem           buf_a, buf_b, buf_c;     cl_int           err;       // 1. Get Vivante GPU platform and device     err = clGetPlatformIDs(1, &platform, NULL);     err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);       // Print device name     char device_name[128];     clGetDeviceInfo(device, CL_DEVICE_NAME, sizeof(device_name), device_name, NULL);     printf("GPU detected: %s\n", device_name);       // 2. Create context and command queue     context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);     queue   = clCreateCommandQueue(context, device, 0, &err);       // 3. Read kernel source from file     FILE* f = fopen("vector_add.cl", "r");     fseek(f, 0, SEEK_END);     size_t src_size = ftell(f);     rewind(f);     char* src=(char*)malloc(src_size + 1);     fread(src, 1, src_size, f);     src[src_size] = '\0';     fclose(f);       // 4. Compile OpenCL program     program = clCreateProgramWithSource(context, 1, (const char**)&src, &src_size, &err);     err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);     if (err != CL_SUCCESS) {         char log[2048];         clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,                               sizeof(log), log, NULL);         printf("Compilation error:\n%s\n", log);         return 1;     }     kernel = clCreateKernel(program, "vector_add", &err);       // 5. Prepare input data     float* h_a = (float*)malloc(VECTOR_SIZE * sizeof(float));     float* h_b = (float*)malloc(VECTOR_SIZE * sizeof(float));     float* h_c = (float*)malloc(VECTOR_SIZE * sizeof(float));     for (int i = 0; i < VECTOR_SIZE; i++) {         h_a[i] = (float)i;         h_b[i] = (float)(VECTOR_SIZE - i);     }       // 6. Create GPU buffers     buf_a = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,                            VECTOR_SIZE * sizeof(float), h_a, &err);     buf_b = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,                            VECTOR_SIZE * sizeof(float), h_b, &err);     buf_c = clCreateBuffer(context, CL_MEM_WRITE_ONLY,                            VECTOR_SIZE * sizeof(float), NULL, &err);       // 7. Set kernel arguments and execute on GPU     int n = VECTOR_SIZE;     clSetKernelArg(kernel, 0, sizeof(cl_mem), &buf_a);     clSetKernelArg(kernel, 1, sizeof(cl_mem), &buf_b);     clSetKernelArg(kernel, 2, sizeof(cl_mem), &buf_c);     clSetKernelArg(kernel, 3, sizeof(int), &n);       size_t global_size = VECTOR_SIZE;     err = clEnqueueNDRangeKernel(queue, kernel, 1, NULL,                                   &global_size, NULL, 0, NULL, NULL);     clFinish(queue);       // 8. Read result     clEnqueueReadBuffer(queue, buf_c, CL_TRUE, 0,                         VECTOR_SIZE * sizeof(float), h_c, 0, NULL, NULL);       // 9. Verify result (each element should equal VECTOR_SIZE = 1024)     int ok = 1;     for (int i = 0; i < VECTOR_SIZE; i++) {         if (h_c[i] != (float)VECTOR_SIZE) { ok = 0; break; }     }     printf("Result: %s\n", ok ? "CORRECT - GPU works!" : "CALCULATION ERROR");     printf("Example: a[0]=%.0f + b[0]=%.0f = c[0]=%.0f\n",            h_a[0], h_b[0], h_c[0]);       // Free resources     clReleaseMemObject(buf_a); clReleaseMemObject(buf_b); clReleaseMemObject(buf_c);     clReleaseKernel(kernel); clReleaseProgram(program);     clReleaseCommandQueue(queue); clReleaseContext(context);     free(h_a); free(h_b); free(h_c); free(src);     return 0; }   8.3 Compile and Run on the LS1028A On the LS1028A board (connected via serial or SSH): # Install build tools and OpenCL headers apt-get install -y gcc clinfo ocl-icd-libopencl1 opencl-headers   # Compile gcc -o vector_add vector_add.c -lOpenCL -I/usr/include   # Run ./vector_add Expected output: GPU detected: Vivante OpenCL Device GC7000UL.6202.0000 Result: CORRECT - GPU works! Example: a[0]=0 + b[0]=1024 = c[0]=1024 12.4 Yocto Recipe to Include the Example in the Image To include the example directly in the Yocto image, create a recipe in your custom layer: mkdir -p ~/lldp-ls1028a/sources/meta-my-layer/recipes-examples/opencl-vector/files cp vector_add.c vector_add.cl \    ~/lldp-ls1028a/sources/meta-my-layer/recipes-examples/opencl-vector/files/ Recipe file opencl-vector_1.0.bb: SUMMARY = "OpenCL vector addition example for LS1028A GPU" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"   SRC_URI = "file://vector_add.c \            file://vector_add.cl"   DEPENDS = "virtual/opencl-icd opencl-headers"   S = "${WORKDIR}"   do_compile() {     ${CC} ${CFLAGS} -o vector_add vector_add.c -lOpenCL ${LDFLAGS} }   do_install() {     install -d ${D}${bindir}     install -m 0755 vector_add ${D}${bindir}/     install -d ${D}/home/root     install -m 0644 vector_add.cl ${D}/home/root/ }   FILES:${PN} += "/home/root/vector_add.cl" Add to local.conf and rebuild: IMAGE_INSTALL:append = " opencl-vector" bitbake ls-image-desktop   Practical Example: OpenGL ES Rendering with Wayland/Weston This example shows how to render an animated triangle using OpenGL ES 2.0 with EGL on the Weston (Wayland) compositor — the standard "Hello World" of embedded graphics on the GC7000UL GPU. 9.1 Graphics Stack Diagram C Application      ↓ OpenGL ES 2.0  (libGLESv2.so — Vivante GC7000UL)      ↓ EGL 1.4        (libEGL.so — interface between GLES and Wayland)      ↓ Wayland Client (libwayland-client, libwayland-egl)      ↓ Weston Compositor (DRM/KMS + Mali-DP500)      ↓ DisplayPort → 4K Monitor   9.2 Install Dependencies On the LS1028A (with ls-image-desktop): apt-get install -y libgles2-mesa-dev libegl1-mesa-dev libwayland-dev libwayland-egl-backend-dev gcc pkg-config   9.3 Source Code: triangle_gles.c cat > /home/root/triangle_gles.c << 'EOF' /**  * OpenGL ES 2.0 + EGL + Wayland example  * Renders a colored spinning triangle on the Vivante GC7000UL GPU of the LS1028A  * Compile: gcc -o triangle_gles triangle_gles.c -lwayland-client -lwayland-egl -lEGL -lGLESv2 -lm  */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include <wayland-client.h> #include <wayland-egl.h> #include <EGL/egl.h> #include <GLES2/gl2.h>   #define WIDTH  800 #define HEIGHT 600   static struct wl_display       *wl_display    = NULL; static struct wl_compositor    *wl_compositor = NULL; static struct wl_shell         *wl_shell      = NULL; static struct wl_surface       *wl_surface    = NULL; static struct wl_shell_surface *shell_surface = NULL; static struct wl_egl_window    *egl_window    = NULL;   static EGLDisplay egl_display; static EGLContext egl_context; static EGLSurface egl_surface;   static const char *vertex_shader_src=     "attribute vec2 a_position;          \n"     "attribute vec3 a_color;             \n"     "varying vec3 v_color;               \n"     "uniform float u_angle;              \n"     "void main() {                       \n"     "  float c = cos(u_angle);           \n"     "  float s = sin(u_angle);           \n"     "  vec2 rot = vec2(                  \n"     "    a_position.x*c - a_position.y*s,\n"     "    a_position.x*s + a_position.y*c \n"     "  );                                \n"     "  gl_Position = vec4(rot, 0.0, 1.0);\n"     "  v_color = a_color;                \n"     "}                                   \n";   static const char *fragment_shader_src=     "precision mediump float;            \n"     "varying vec3 v_color;               \n"     "void main() {                       \n"     "  gl_FragColor = vec4(v_color, 1.0);\n"     "}                                   \n";   /* Vertices: position (x,y) + color (r,g,b) */ static const float vertices[] = {      0.0f,  0.8f,  1.0f, 0.0f, 0.0f,   /* Top    - Red   */     -0.7f, -0.5f,  0.0f, 1.0f, 0.0f,   /* Left   - Green */      0.7f, -0.5f,  0.0f, 0.0f, 1.0f,   /* Right  - Blue  */ };   static void registry_global(void *data, struct wl_registry *reg,                              uint32_t name, const char *iface, uint32_t ver) {     if (strcmp(iface, "wl_compositor") == 0)         wl_compositor = wl_registry_bind(reg, name, &wl_compositor_interface, 1);     else if (strcmp(iface, "wl_shell") == 0)         wl_shell = wl_registry_bind(reg, name, &wl_shell_interface, 1); } static void registry_global_remove(void *d, struct wl_registry *r, uint32_t n) {} static const struct wl_registry_listener registry_listener = {     registry_global, registry_global_remove };   static GLuint compile_shader(GLenum type, const char *src) {     GLuint shader = glCreateShader(type);     glShaderSource(shader, 1, &src, NULL);     glCompileShader(shader);     GLint ok; glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);     if (!ok) {         char log[512]; glGetShaderInfoLog(shader, 512, NULL, log);         printf("Shader error: %s\n", log); exit(1);     }     return shader; }   int main() {     wl_display = wl_display_connect(NULL);     if (!wl_display) { printf("Error: could not connect to Wayland\n"); return 1; }       struct wl_registry *registry = wl_display_get_registry(wl_display);     wl_registry_add_listener(registry, &registry_listener, NULL);     wl_display_dispatch(wl_display);     wl_display_roundtrip(wl_display);       wl_surface = wl_compositor_create_surface(wl_compositor);     shell_surface = wl_shell_get_shell_surface(wl_shell, wl_surface);     wl_shell_surface_set_toplevel(shell_surface);       egl_display = eglGetDisplay((EGLNativeDisplayType)wl_display);     eglInitialize(egl_display, NULL, NULL);     eglBindAPI(EGL_OPENGL_ES_API);       EGLint config_attribs[] = {         EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,         EGL_RED_SIZE,   8, EGL_GREEN_SIZE, 8,         EGL_BLUE_SIZE,  8, EGL_ALPHA_SIZE, 0,         EGL_DEPTH_SIZE, 16, EGL_NONE     };     EGLConfig egl_config; EGLint num_configs;     eglChooseConfig(egl_display, config_attribs, &egl_config, 1, &num_configs);       EGLint ctx_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };     egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, ctx_attribs);     egl_window  = wl_egl_window_create(wl_surface, WIDTH, HEIGHT);     egl_surface = eglCreateWindowSurface(egl_display, egl_config,                                           (EGLNativeWindowType)egl_window, NULL);     eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context);       printf("GPU: %s\n", glGetString(GL_RENDERER));     printf("OpenGL ES Version: %s\n", glGetString(GL_VERSION));       GLuint vs = compile_shader(GL_VERTEX_SHADER,   vertex_shader_src);     GLuint fs = compile_shader(GL_FRAGMENT_SHADER, fragment_shader_src);     GLuint program = glCreateProgram();     glAttachShader(program, vs); glAttachShader(program, fs);     glLinkProgram(program); glUseProgram(program);       GLint pos_loc   = glGetAttribLocation(program,  "a_position");     GLint color_loc = glGetAttribLocation(program,  "a_color");     GLint angle_loc = glGetUniformLocation(program, "u_angle");       glViewport(0, 0, WIDTH, HEIGHT);       float angle = 0.0f;     int frames = 0;     printf("Rendering spinning triangle (Ctrl+C to exit)...\n");       while (1) {         wl_display_dispatch_pending(wl_display);         glClearColor(0.1f, 0.1f, 0.15f, 1.0f);         glClear(GL_COLOR_BUFFER_BIT);         glUniform1f(angle_loc, angle);         glEnableVertexAttribArray(pos_loc);         glVertexAttribPointer(pos_loc,   2, GL_FLOAT, GL_FALSE, 5*sizeof(float), vertices);         glEnableVertexAttribArray(color_loc);         glVertexAttribPointer(color_loc, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), vertices + 2);         glDrawArrays(GL_TRIANGLES, 0, 3);         eglSwapBuffers(egl_display, egl_surface);         angle += 0.02f;         if (angle > 6.2832f) angle -= 6.2832f;         frames++;         if (frames % 300 == 0)             printf("Frame %d — angle: %.2f rad\n", frames, angle);     }       eglDestroyContext(egl_display, egl_context);     eglDestroySurface(egl_display, egl_surface);     eglTerminate(egl_display);     wl_display_disconnect(wl_display);     return 0; }   9.4 Compile and Run # Compile gcc -o triangle_gles triangle_gles.c \     -lwayland-client -lwayland-egl \     -lEGL -lGLESv2 -lm   # Make sure Weston is running and set Wayland environment export XDG_RUNTIME_DIR=/run/user/0 export WAYLAND_DISPLAY=wayland-0   # Run ./triangle_gles Expected terminal output: GPU: Vivante GC7000UL OpenGL ES Version: OpenGL ES 3.1 V6.4.3.p4.398061 Rendering spinning triangle (Ctrl+C to exit)... Frame 300 — angle: 6.00 rad Frame 600 — angle: 5.68 rad A RGB triangle spinning on a dark background will appear on screen, rendered by the GC7000UL GPU.       9.5 Yocto Recipe SUMMARY = "OpenGL ES 2.0 spinning triangle example — LS1028A" LICENSE = "MIT" LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"   SRC_URI = "file://triangle_gles.c"   DEPENDS = "virtual/libgles2 virtual/egl wayland"   S = "${WORKDIR}"   do_compile() {     ${CC} ${CFLAGS} -o triangle_gles triangle_gles.c \         -lwayland-client -lwayland-egl -lEGL -lGLESv2 -lm ${LDFLAGS} }   do_install() {     install -d ${D}${bindir}     install -m 0755 triangle_gles ${D}${bindir}/ }   9.6 Yocto Recipe for OpenCV with GPU Add to local.conf: IMAGE_INSTALL:append = " opencv python3-opencv" PACKAGECONFIG:append:pn-opencv = " opencl" bitbake ls-image-desktop   References: 1) https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors:QORIQ-ARM 2) https://www.khronos.org/news/permalink/vivante-gc7000-gpus 3) Layerscape Software Development Kit User Guide for Yocto : https://docs.nxp.com/bundle/GUID-E5527A77-2F97-4244-BF9C-D08F068EFD16/page/GUID-B386D634-B9B1-4980-AA56-9C705D7FBC52.html?gad_source=1&gad_campaignid=24106955438&gclid=EAIaIQobChMI3cKf4KqZlwMVbnJ_AB17dwoGEAAYASAAEgJURPD_BwE Regards  
記事全体を表示