i.MX RT Crossover MCUs Knowledge Base

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

i.MX RT Crossover MCUs Knowledge Base

ディスカッション

ソート順:
1 Introduction    With the quick development of science and technology, the Internet of Things(IoT) is widely used in various areas, such as industry, agriculture, environment, transportation, logistics, security, and other infrastructure. IoT usage makes our lives more colorful and intelligent. The explosive development of the IoT cannot be separated from the cloud platform. At present, there are many types of cloud services on the market, such as Amazon's AWS, Microsoft's Azure, google cloud, China's Alibaba Cloud, Baidu Cloud, OneNet, etc.    Amazon AWS Cloud is a professional cloud computing service that is provided by Amazon. It provides a complete set of infrastructure and cloud solutions for customers in various countries and regions around the world. It is currently a cloud computing with a large number of users. AWS IoT is a managed cloud platform that allows connected devices to easily and securely interact with cloud applications and other devices.    NXP crossover MCU RT product has launched a series of AWS sample codes. This article mainly explains the remote_control_wifi_nxp code in the official MIMXRT1060-EVK SDK as an example to realize the data interaction with AWS IoT cloud, Android mobile APP, and MQTTfx client. The cloud topology of this article is as follows: Fig.1-1 2 AWS cloud operation 2.1 Create an AWS account Prepare a credit card, and then go to the below amazon link to create an AWS account:    https://console.aws.amazon.com/console/home   2.2 Create a Thing    Open the AWS IOT link: https://console.aws.amazon.com/iot    Choose the Things item under manage, if it is the first time usage, customer can choose “register a thing” to create the thing. If it is used in the previous time, customers can click the “create” button in the right corner to create the thing. Choose “create a single thing” to create the new thing, more details check the following picture. Fig. 2-1 Fig.2-2 Fig.2-3 2.3 Create certificate    Create a certificate for the newly created thing, click the “create certificate” button under the following picture: Fig.2-4    After the certificate is built, it will have the information about the certificate created, it means the certificate is generated and can be used. Fig. 2-5 Please note, download files: certificate for this thing, public key, private key. It will be used in the mqttfx tool configuration. Click “A root CA for AWS for Download”, download the root CA for AWS IoT, the mqttfx tool setting will also use it. Open the root CA download link, can download the CA certificate. RSA 2048 bit key: VeriSign Class 3 Public Primary G5 root CA certificate Fig. 2-6 At last, we can get these files: 7abfd7a350-certificate.pem.crt 7abfd7a350-private.pem.key 7abfd7a350-public.pem.key AmazonRootCA1.pem Save it, it will be used later. Click “active” button to active the certificate, and click “Done” button. The policy will be attached later.   2.4 Create Policies     Back to the iot view page: https://console.aws.amazon.com/iot/     Select the policies under Secure item, to create the new policies.  Fig. 2-7 Input the policy name, in the action area, fill: iot:*, Resource ARN area fill: * Check Allow item, click the create button to finish the new policy creation. Fig. 2-8 2.5 Things attach relationship     After the thing, certificate, policies creation, then will attach the policy to the certificate, and attach the certificate to the Things. Fig. 2-9 Choose the certificates under Secure item, in the related certificate item, choose “…”, you will find the down list, click “attach policy”, and choose the newly created policy. Then click attach thing, choose the newly created thing. Fig. 2-10 Fig. 2-11 Fig. 2-12 Now, open the Things under Mange item, check the detail things related information. Fig.2-13 Double click the thing, in the Interact item, we can find the Rest API Endpoint, the RT code and the mqttfx tool will use this endpoint to realize the cloud connection. Fig. 2-14 Check the security, you will find the previously created certificate, it means this thing already attach the new certificates: Fig. 2-15 Until now, we already finish the Things related configuration, then it will be used for the MQTT fx, Android app, RT EVK board connections, and testing, we also can check the communication information through the AWS shadow in the webpage directly.       3 Android related configuration 3.1 AWS cognito configuration    If use the Android app to communicate with the AWS IoT clould, the AWS side still needs to use the cognito service to authorize the AWS IoT, then access the device shadows. Create a new identity pools at first from the following link: https://console.aws.amazon.com/cognitohttps://console.aws.amazon.com/cognito Fig. 3-1 Click “manage Identity pools”, after enter it, then click “create new identity pool” Fig. 3-2 Fig. 3-3 Fig. 3-4 Here, it will generate two Roles: Cognito_PoolNameAuth_Role Cognito_PoolNameUnauth_Role Click Allow, to finish the identity pool creation. Fig. 3-5 Please record the related Identity pool ID, it will be used in the Android app .properties configuration files. 3.2 Create plicies in IAM for cognito   Open https://console.aws.amazon.com/iam   Click the “policies” item under “access management” Fig. 3-6 Choose “create policy”, create a IAM policies, in the Policy JSON area, write the following content: Fig. 3-7 { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "iot:Connect" ], "Resource": [ "*" ] }, { "Effect": "Allow", "Action": [ "iot:Publish" ], "Resource": [ "arn:aws:iot:us-east-1:965396684474:topic/$aws/things/RTAWSThing/shadow/update", "arn:aws:iot:us-east-1:965396684474:topic/$aws/things/RTAWSThing/shadow/get" ] }, { "Effect": "Allow", "Action": [ "iot:Subscribe", "iot:Receive" ], "Resource": [ "*" ] } ] }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Please note, in the JSON content: "arn:aws:iot:<REGION>:<ACCOUNT ID>:topic/$aws/things/<THING NAME>/shadow/update", "arn:aws:iot:<REGION>:<ACCOUNT ID>:topic/$aws/things/<THING NAME>/shadow/get" Region:the us-east-1 inFig. 3-5 ACCOUNT ID, it can be found in the upper right corner my account side. Fig 3-8 Fig 3-9 After finished the IAM policy creation, then back to IAM policies page, choose Filter policies as customer managed, we can find the new created customer’s policy. Fig. 3-10 3.3 Attach policy for the cognito role in IAM   In IAM, choose roles item: Fig. 3-11 Double click the cognito_PoolNameUnauth_Role which is generated when creating the pool in cognito, click attach policies, select the new created policy. Fig. 3-12 Fig. 3-13 Until now, we already finish the AWS cognito configuration.   3.4  Android properties file configuration Create a file with .properties, the content is:     customer_specific_endpoint=<REST API ENDPOINT>     cognito_pool_id=<COGNITO POOL ID>     thing_name=<THING NAME>     region=<REGION> Please fill the correct content: REST API ENDPOINT:Fig 2-14 COGNITO POOL ID:fig 3-5 THING NAME:fig 2-14,upper left corner REGION:Fig 3-5, the region data in COGNITO POOL ID Take an example, my properties file content is:  customer_specific_endpoint=a215vehc5uw107-ats.iot.us-east-1.amazonaws.com  cognito_pool_id=us-east-1:c5ca6d11-f069-416c-81f9-fc1ec8fd8de5  thing_name=RTAWSThing  region=us-east-1 In the real usage, please use your own configured data, otherwise, it will connect to my cloud endpoint. 4. MQTTfx configuration and testing MQTT.fx is an MQTT client tool which is based on EclipsePaho and written in Java language. It supports subscribe and publish of messages through Topic. You can download this tool from the following link:   http://mqttfx.jensd.de/index.php/download    The new version is:1.7.1.   4.1 MQTT.fx configuration     Choose connect configuration button, then enter the connection configuration page: Fig. 4-1 Profile Name: Enter the configuration name Broker Address: it is REST API ENDPOINT。 Broker Port:8883 Client ID: generate it freely CA file: it is the downloaded CA certificate file Client Certificate File: related certificate file Client key File: private key file Check PEM formatted。 Click apply and OK to finish the configuration. 4.2 Use the AWS cloud to test connection   In order to test whether it can be connected to the event cloud, a preliminary connection test can be performed. Open the aws page: https://console.aws.amazon.com/iot here is a Test button under this interface, which can be tested by other clients or by itself.Both AWS cloud and MQTTfx subscribe topic: $aws/things/RTAWSThing/shadow/update MQTTfx publishes data to the topic: $aws/things/RTAWSThing/shadow/update It can be found that both the cloud test port and the MQTTfx subscribe can receive data: Fig. 4-2 Below, the Publish data is tested by the cloud, and then you can see that both the MQTTFX subscribe and the cloud subscribe can receive data: Fig. 4-3 Until now, the AWS cloud can transfer the data between the AWS iot cloud and the client. 5 RT1060 and wifi module configuration   We mainly use the RT1060 SDK2.8.0 remote_control_wifi_nxp as the RT test code: SDK_2.8.0_EVK-MIMXRT1060\boards\evkmimxrt1060\aws_examples\remote_control_wifi_nxp Test platform is:MIMXRT1060-EVK Panasonic PAN9026 SDIO ADAPTER + SD to uSD adapter The project is using Panasonic PAN9026 SDIO ADAPTER in default. 5.1 WIFI and the AWS code configuration    The project need the working WIFI SSID and the password, so prepare a working WIFI for it. Then add the SSID and the password in the aws_clientcredential.h #define clientcredentialWIFI_SSID       "Paste WiFi SSID here." #define clientcredentialWIFI_PASSWORD   "Paste WiFi password here." The connection for AWS also in file: aws_clientcredential.h #define clientcredentialMQTT_BROKER_ENDPOINT "a215vehc5uw107-ats.iot.us-east-1.amazonaws.com" #define clientcredentialIOT_THING_NAME       "RTAWSThing" #define clientcredentialMQTT_BROKER_PORT      8883   5.2 certificate and the key configuration Open the SDK following link: SDK_2.8.0_EVK-MIMXRT1060\rtos\freertos\tools\certificate_configuration\CertificateConfigurator.html Fig. 5-1 Generate the new aws_clientcredential_keys.h, and replace the old one. Take the MCUXPresso IDE project as an example, the file location is: Fig. 5-2 Build the project and download it to the MIMXRT1060-EVK board. 6 Test result Androd mobile phone download and install the APK under this folder: SDK_2.8.0_EVK-MIMXRT1060\boards\evkmimxrt1060\aws_examples\remote_control_android\AwsRemoteControl.apk SDK can be downloaded from this link: Welcome | MCUXpresso SDK Builder  Then, we can use the Android app to remote control the RT EVK on board LED, the test result is 6.1 APP and EVK test result MIMXRT1060-EVK printf information: Fig. 6-1 Turn on and turn off the led:   Fig. 6-2                                        Fig. 6-3 6.2 MQTTfx subscribe result MQTTfx subscribe data Turn on the led, we can subscribe two messages: Fig. 6-4 Fig. 6-5   Turn off the led, we also can subscribe two messages: Fig. 6-6 Fig. 6-7 In the two message, the first one is used to set the led status. The second one is the EVK used to report the EVK led information. MQTTfx also can use the publish page, publish this data: {"state":{"desired":{"LEDstate":1}}} or {"state":{"desired":{"LEDstate":0}}} To topic: $aws/things/RTAWSThing/shadow/update It also can realize the on board LED turn on or off. 6.3 AWS cloud shadows display result Turn on the led: Fig. 6-8 Turn off the led: Fig. 6-9 In conclusion, after the above configuration and testing, it can finish the Android mobile phone to remote control the RT EVK on board LED and get the information. Also can use the MQTTFX client tool and the AWS shadow page to check the communication data.
記事全体を表示
Slides from webinar hosted by NXP on Dec 10, 2019.
記事全体を表示
These lab guides provide step-by-step instructions on how to take a quantized TensorFlow Lite model and use the Neutron Conversion Tool found in eIQ Toolkit to convert the model to run on the eIQ Neutron NPU found on i.MX RT700 devices.  The eIQ Neutron NPU for i.MX RT700 Lab Guide documents focus on using the eIQ Toolkit GUI method to convert a model and then import that converted model into an eIQ MCUXpresso SDK example. There are two versions depending on if MCUXpresso SDK is downloaded from the MCUXpresso SDK Builder website as a zip file or if MCUXpresso SDK is downloaded from the NXP Github repository.    The labs were designed to run on the i.MX RT700 EVK, but the same concepts can be applied to MCX N boards as well and are similar to the MCX N eIQ Neutron NPU labs.  Also be sure to check out AN14700 - i.MX RT700 eIQ Neutron NPU Enablement and Performance which goes into more details on the eIQ Neutron N3-64 NPU found on i.MX RT700. 
記事全体を表示
This is a guide line to run both the master core and slave core projects as XIP targets from one flash.
記事全体を表示
Recovery Methods for RT595 and RT685 Development Boards When Programming Fails During the development and use of RT595 and RT685 development boards, developers often encounter a common issue reported by users: persistent errors during programming via a debugger, making it impossible to reprogram the board and effectively rendering it “bricked.” These issues can arise from various causes, such as incorrect FCB writing, interruptions during the download process, or other unknown anomalies. This article introduces two effective recovery methods: Using the SEC TOOL utility. Using an external J-Link programmer. Note: Both methods require setting the RT595 and RT685 boards to Serial ISP mode beforehand. NXP has released two RT685-based development boards (MIMXRT685-AUD-EVK and MIMXRT685-EVK) and one RT595 board. Since the RT595 board operates similarly to the RT685 boards, this article uses the MIMXRT685-AUD-EVK board for demonstration. Ensure the SDK version is correct during the process. 1. Preparation: Entering Serial ISP Mode Using the MIMXRT685-AUD-EVK board as an example, set switches SW5[1-3] to “ON OFF OFF” to enter Serial ISP mode. This corresponds to the following pin levels: PIO1_17: High PIO1_16: High PIO1_15: Low Refer to the RT600 User Manual for detailed mappings between ISP pins and boot modes.   2. Method 1: Recovery Using SEC TOOL  1. Preparation: Generate APP Image Import SDK Demo: Open MCUXpresso IDE and import the demo project mimxrt685audevk_lpc_gpio_led_output_cm33.   Modify Project Settings: Make two key configuration changes to ensure successful image generation. Generate Hex File: After configuration, build the project to generate a Hex file for use with SEC TOOL. 2. Using SEC TOOL Download SEC TOOL: https://www.nxp.com/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-secure-provisioning-tool:MCUXPRESSO-SECURE-PROVISIONING Create Workspace: Launch SEC TOOL and create a new workspace for MIMXRT685S. Select Connection Method: RT500 and RT600 support USB, UART, SPI, and I2C. Choose one (e.g., UART via J5 or USB via J7). Only one protocol can be used at a time. If switching, power cycle the board. Configure Flash Type and Test: Select the default external NOR Flash for MIMXRT685-AUD-EVK, apply settings, and run a test. Build Image: Use the previously generated App image and click “Build Image.”    Program Image: Flash the image to the RT685 chip.   Switch Boot Mode: Power off the board and set Boot mode to FlexSPI Boot from PortB: PIO1_17: Low PIO1_16: High PIO1_15: Low SW5[1-3]: “ON OFF ON” Power on the board again. It should now operate normally and run the program successfully. 3. Method 2: Recovery Using J-Link Programmer 1. Preparation: Generate Flashable File Import the same demo project into MCUXpresso IDE and compile it without modifications to generate a Hex or S19 file. Download and install SEGGER J-Flash from SEGGER Official Website. 2. Hardware Setup Board Modifications: Connect pins 2 and 3 of JP2. Remove jumpers JP17, JP18, JP19 (ensure p3 is disconnected). Set SW5 to “ON OFF OFF”. Device Connection: Connect J-Link Plus to J19 on the board. Connect J6 to the PC to power the board. 3. Programming with J-Flash Create New Project: Open J-Flash and create a new project for MIMXRT685S. Note: RT685 supports only SWD, not JTAG. Flash Program: Load the Hex file and flash it to the board.   Switch Boot Mode: After flashing, power off the board and set Boot mode to FlexSPI Boot from PortB: PIO1_17: Low PIO1_16: High PIO1_15: Low SW5[1-3]: “ON OFF ON” Power on the board again. It should now function normally and run the program successfully.   Conclusion By following either of the two methods described above, developers can effectively recover RT595 and RT685 development boards from programming failures and restore normal operation. Choose the method that best suits your specific situation. 
記事全体を表示
4-TX Line Audio Playback via SAI1 on MIMXRT1170 and CS42448 1. Introduction This document focuses on utilizing the MIMXRT1170-EVKB development board and the CS42448 audio expansion board to achieve specific audio playback functionality through four TX data lines of the SAI1 module. With its real-time performance and high integration, the i.MX RT1170 is widely used in automotive, industrial, and IoT fields. The Arm Cortex-M7 core runs at up to 1GHz, features 2MB on-chip RAM, and offers various memory and connectivity interfaces. It supports multiple audio interfaces, including SAI-1, SAI-2, SAI-3, SAI-4, PDM, ASRC, SPDIF, and MQS. This document details the implementation of 8-channel audio output using the RT1170 EVKB development board and CS42448 Audio Card via four TX data lines of the SAI1 module. It also explains how to generate 8-channel audio data compatible with SDK example requirements. The CS42448 Audio Card can be directly connected to the RT1170 EVKB board, enabling developers to build more complex audio applications. The NXP SDK provides the example 'evkbmimxrt1170_sai_edma_multi_channel_transfer_cm7,' which by default enables two transmission channels (TX_DATA0 and TX_DATA1). When running, 1kHz sine wave audio signals can be heard from the J6 and J7 interfaces of the CS42448 Audio Card. However, when customer requirements demand four TX data lines (TX_DATA0 to TX_DATA3), each transmitting different audio, how can this be achieved? This document explores and validates this scenario in depth. 2. SAI Overview (1) RT1170 Chip SAI Module Features According to the IMXRT1170RM datasheet, SAI2, SAI3, and SAI4 modules each have only one data line for input/output, while SAI1 has four, making it the only module supporting multi-line communication. (2) Configuration Highlights To implement the four TX data line solution, it is crucial to configure the Transmit Configuration 3 (TCR3) TCE register correctly. According to IMXRT1170RM Table 54-2, Option0 should be selected for pin configuration. To enable TX_DATA0 to TX_DATA3, set bits 16–19 of the SAI1 TCR3 register to '1111'. Similarly, for multiple Rx data lines, configure bits 16–19 of the SAI1 RCR3 register (RCE).   3. Hardware Preparation (1) Required Hardware - Mini/micro USB cable - MIMXRT1170-EVKB development board - Personal computer - Headphones (OMTP standard) - CS42448 Audio Card (2) Hardware Modifications on MIMXRT1170-EVKB Solder Resistors: R2008, R2022, R2011, R2021, R2009, R2010, R2012, R2016, R1998, R2013, R2014, R2018, R2017, R2000 Remove Resistors: R2001, R2002, R2003, R2004, R2005, R2006, R2007 After completing the hardware modifications, connect the CS42448 Audio Card to the J76 interface of the MIMXRT1170-EVKB board. 4. Audio Source Preparation The free and powerful audio editing software Audacity is used to convert MP3 files to .wav format. Since each TX data line transmits two audio channels, a total of 8 channels are needed. (1) Audio Channel Allocation Strategy Using Audacity, multiple audio channels were generated. 'HelloWorld' is mono and reused. Allocation is as follows: - TX_DATA0: HelloWorld → Channel 1 & Channel 5 - TX_DATA1: Audio1 → Left: Channel 2, Right: Channel 6 - TX_DATA2: Audio2 → Left: Channel 3, Right: Channel 7 - TX_DATA3: Audio3 → Left: Channel 4, Right: Channel 8 On the CS42448 Audio Card: - J6 plays TX_DATA0 (HelloWorld) - J7 plays  TX_DATA1(Audio1) - J8 plays TX_DATA2(Audio2) - J9 plays TX_DATA3(Audio3) (2) Audio Format Requirements The converted .wav files must match the format used in the NXP SDK example: 48kHz sampling rate and 16-bit width. Ensure these parameters are correctly set in Audacity during conversion. (3) Audio Data Processing To convert the generated HelloWorld-8-channel.wav file into a C language array using WinHex, you need to remove the first 44 bytes, which constitute the standard WAV file header. This step is crucial because the SDK example utilizes raw audio data. For those interested, examining the structure of a WAV file can provide deeper insight into this process. Alternatively, this conversion from WAV format to a C array can also be accomplished using other tools or methods. 5. Software Modifications (1) Configure SAI1 Module Registers To enable four TX data lines, set the TCE bits in the SAI1 TCR3 register. In the NXP SDK code, modify the macro DEMO_SAI_CHANNEL_MASK and configure saiConfig in I2S mode. The function SAI_TransferSendEDMA will set the TCR3 TCE register accordingly. (2) Replace Audio Data and Modify Macros Replace the uint8_t music[] array in the SDK example’s music.h file with the C array generated earlier. Also, update the macro MUSIC_LEN to match the byte length of the new array, ensuring it is a multiple of 1600. After completing all steps, compile and flash the program to the MIMXRT1170-EVKB board. Connect headphones to the CS42448 Audio Card’s J6,J7,J8,J9 interfaces to hear the respective audio outputs.   6. Conclusion This project successfully implements the transmission of four TX data lines via the SAI1 module using the CS42448 Audio Card and MIMXRT1170-EVKB development board. Experimental validation confirms support for multi-channel independent audio output. Each TX data line can output distinct audio content through the CS42448’s physical interfaces (J6–J9), meeting the needs of complex audio scenarios.
記事全体を表示
This article uses i.MXRT1170 as an example, but the rules apply to the i.MX RT series. 1. Backgroud and Questions DataSheets (e.g, RT1170A , RT1170B) show the 'NON JEDEC'  Package as following, but the Product quality page (e.g MIMXRT1172AVM8A) is marked as WSL 3 (Moisture Sensitivity Level 3), which is one of the moisture sensitivity levels defined in JEDEC-STD-020. Is there a contradiction? Does the product comply with JEDEC-STD-020?  2. What is JEDEC-STD-020? JEDEC-STD-020 is a standard that defines the moisture sensitivity level (MSL) and preconditioning requirements for surface-mount devices (SMDs) during the reflow soldering process. Compliance with this standard means that the device's storage and handling before reflow soldering meet industry specifications, making it suitable for automated manufacturing environments. 3. WSL 3 and JEDEC-STD-020 Compliance  On NXP’s product quality page, some i.MX RT1170 variants are marked as WSL 3 (Moisture Sensitivity Level 3), which is one of the levels defined in JEDEC-STD-020. This means: The device can be exposed to ambient conditions for 168 hours before reflow soldering;  It must be stored in dry-pack packaging; It complies with JEDEC-STD-020 handling and processing requirements. This indicates that i.MX RT1170 series have been tested and qualified according to JEDEC-STD-020. Key parameters from NXP Product pages: MSL (Moisture Sensitivity Level): 3 Peak Package Body Temperature: 260°C Time at Peak: 40 seconds 4. “NON JEDEC” Packge in the Datasheet In the i.MX RT1170 datasheet, some package types are labeled as “NON JEDEC”, which typically means: The package dimensions or layout do not strictly follow JEDEC standard outlines; The device has not undergone the formal JEDEC-STD-020 certification process. For example, the IMXRT1170BCEC Rev.1 datasheet states: Package Information: Plastic Package 289-pin MAPBGA, 14 x 14 mm, 0.8 mm pitch Package Type: NON JEDEC [1] This indicates that the package is not a JEDEC-standard mechanical outline. However, it does not necessarily mean the device fails to meet the moisture sensitivity requirements defined in JEDEC-STD-020. 5. In summary 'NON JEDEC' refers only to mechanical form, not to reliability standards. The "NON JEDEC" marking on a datasheet refers to the ​​physical package outline​​, while the MSL 3 rating on the product quality page is a ​​reliability and handling specification​​ determined through JEDEC test methods. JEDEC-STD-020 is a moisture sensitivity level testing standard for non-hermetic surface-mount devices. i.MX RT explicitly states that its MSL rating is based on the JEDEC-STD-020 testing process. Whether a package conforms to a JEDEC standard (such as MO-220) has no direct bearing on whether it can be tested under JEDEC-STD-020. ‘NON JEDEC’是指物理封装中的机械形式,不是可靠性标准。 JEDEC-STD-020 是针对非气密性表面贴装器件的湿敏等级测试标准; NXP 明确表示i.MX RT产品 MSL 等级是依据 JEDEC-STD-020 测试流程; 封装是否为 JEDEC 标准(如 MO-220)与是否能进行 JEDEC-STD-020 测试无直接关系。 6. Reference NXP i.MX RT1170 Product Page: https://www.nxp.com/part/MIMXRT1172AVM8A  i.MX RT1170 Datasheet: https://www.nxp.com/docs/en/data-sheet/IMXRT1170CEC.pdf  JEDEC-STD-020 Standard: https://www.jedec.org/document_search/field_doc_type/151?search_api_views_fulltext=%E2%80%8BJ-STD-020&order=title&sort=asc       
記事全体を表示
There are two version of the i.MX RT1170 Evaluation Kit:  MIMXRT1170-EVK (no longer available for purchase) MIMXRT1170-EVKB   The key differences between the two versions of are laid out in the MIMXRT1170-EVKB Board Hardware User Guide:    One important change is the QuadSPI flash used on each board. This means that if you attempt to use SDK projects created for the RT1170-EVKB, it will not run properly on an older RT1170-EVK board due to using the mismatched QSPI configuration data. And new releases of MCUXpresso SDK only support the newer EVKB board.  However there is a simple fix to get those newer i.MX RT1170 EVKB MCUXpresso SDK projects to run on the older i.MX RT1170 EVK hardware. Simply download the MCUXpresso SDK 2.16.00 for the original RT1170-EVK board, unzip the archive file, and then copy the evkmimxrt1170_flexspi_nor_config.h and evkmimxrt1170_flexspi_nor_config.c files found in \SDK_2_16_000_MIMXRT1170-EVK\boards\evkmimxrt1170\xip into your EVKB project's xip folder. Then either delete/rename the EVKB version of the evkbmimxrt1170_flexspi_nor_config.c and evkbmimxrt1170_flexspi_nor_config.h files from the project to avoid compiler conflicts. This will update the QSPI configuration for that project to be compatible with the QSPI hardware on the original EVK. As an exmaple, here is the RT1170 Hello World project with that change - the EVKB files were renamed with a .orig extension so they would not be included in the compilation:    Note that due to the new hardware features found on the EVKB board there are some EVKB SDK projects that simply can't be supported on the original EVK board. But this work-around will provide support for many MCUXpresso SDK projects that don't require those new EVKB board features. 
記事全体を表示
​​迁移重点​​: ​​检查GPIO配置​​:利用新时序建议优化设计。 ​​更新SDK至25.06+​​:确保芯片版本识别和ROM API兼容。 ​​验证SEMC设计​​:若使用CSX1/2/3,需按ERR052401调整时序。 ​​工具链升级​​:J-Link v8.38+和MCUXpresso脚本更新。   0. 本文目的    若您并未遇到RT1170 FSGPIO漂移老化问题,请忽略本文档。 若您遇到RT1170A的ERR052351(输出电压>1.98V时参数漂移)和ERR050643(上电瞬间误触发上拉脉冲)问题,并想通过迁移到新硅片RT1170B,请查看本文完成迁移。 ​ 1. 硅片变更 (Silicon Changes)​ ​ ​​GPIO修复​​: 解决了RT1170A的ERR052351(输出电压>1.98V时参数漂移)和ERR050643(上电瞬间误触发上拉脉冲)问题。 影响范围:GPIO_AD/GPIO_LPSR/GPIO_DISP_B2 bank。 ​​ROM更新​​: 清理ROM补丁(不影响开放API)。 ​​HAB API向量表地址​​:从 0x0021_1C0C (A版)改为 0x0021_1C14 (B版)。 ROM_FLEXSPI_NorFlash_ClearCache() 入口地址变更(详见第6节)。 ​​芯片ID变更​​: MISC_DIFPROG 寄存器的 CHIPID 复位值变化: A版: 0x001170A0 B版: 0x001170B0 (需通过bit[7:4]区分:A版= 1011 ,B版= 1100 )。 ​​2. 数据手册变更 (Data Sheet Changes)​ ​ ​​型号命名​​:所有型号后缀从 A 改为 B (例: MIMXRT117xxxxxB )。 ​​GPIO电气规范​​: ​​表37​​:GPIO_AD/LPSR/DISP_B2的驱动电流调整(如DSE=1时IOH从-10mA→-9mA)。 ​​表40​​: 新增 Vpead 参数。 上升/下降时间调整(如DSE=0/SRE=1时从6ns→7.5ns)。 ​​关键建议​​: 3.3V模式:≥25MHz用连续范围模式(Continuous Range),<25MHz用高范围模式(High Range)。 1.8V模式:推荐低范围模式(Low Range)。 ​​其他更新​​: 存储温度范围:-40℃ → ​​-55℃​​。 SDR50/SDR104时序:输入建立时间从2.5ns→2.0ns。 FlexSPI时序:TDVO最大值从4→1,TDHO最小值从2→0。 ​​3. 参考手册变更 (Reference Manual Changes)​ ​ ​​芯片ID识别​​: MISC_DIFPROG[7:4] 复位值从固定值改为​​芯片版本标识​​(A版= 1011 ,B版= 1100 )。 ​​4. 勘误变更 (Errata Changes)​   参考资料:i.MX RT1170A Errata,  i.MX RT1170B Errata​ ​​修复问题​​: 移除ERR052351(GPIO参数漂移)和ERR050643(上电脉冲问题)。 ​​新增问题​​: ​​ERR052401​​:SEMC_CSX1/2/3信号时序退化(SYNC模式最大延迟增加2.4ns)。 ​​规避方案​​: SYNC模式:优先使用SEMC_CSX0或SEMC_RDY作为片选。 Async模式:调整SEMC配置寄存器(SRAMCR1/NORCR1的CES位)。 ​​5. SDK代码变更 (SDK Code Changes)​ ​ ​​SDK 25.06​​(2025年6月底发布)支持B版。 ​​关键代码调整​​: ChipID 和  ROM_API bootloader入口地址  变更 /*! * @brief ROM API init. */ void ROM_API_Init(void) { if (ANADIG_MISC->MISC_DIFPROG == 0x001170a0U) // A版 { g_bootloaderTree = ((bootloader_api_entry_t *)*(uint32_t *)0x0020001cU); } else // B版 { g_bootloaderTree = ((bootloader_api_entry_t *)*(uint32_t *)0x0021001cU); } } FlexSPI缓存清除函数入口地址变更 :ROM_FLEXSPI_NorFlash_ClearCache /*! @brief Software reset for the FLEXSPI logic. */ void ROM_FLEXSPI_NorFlash_ClearCache(uint32_t instance) { uint32_t clearCacheFunctionAddress; if (ANADIG_MISC->MISC_DIFPROG == 0x001170a0U) { clearCacheFunctionAddress = 0x0020426bU; } else if (ANADIG_MISC->MISC_DIFPROG == 0x001170b0U) { clearCacheFunctionAddress = 0x0021a3b7U; } else { clearCacheFunctionAddress = 0x0021a3bfU; } HAB API vector table addresses变更 :从0x0021_1C0C(i.MX RT1170A) to 0x0021_1C14(i.MX RT1170B). SDK无影响,SBL github已经解决。 ​​6. 工具变更 (Tool Changes)​ ​ ​​J-Link​​:需升级至​​v8.38或更高版本​​。 ​​MCUXpresso​​:v24.12及更早版本需更新 RT1170_reset.scp 脚本中的芯片ID检测逻辑。 ​​7. 通用数据手册更新 (Appendix A)​ ​ ​​电压范围​​: NVCC_GPIO重命名为​​NVCC_AD​​(后续版本将恢复原名)。 NVCC_AD/DISP2/LPSR最大值从1.95V→​​1.98V​​。 ​​GPIO模式定义​​: 统一命名:​​连续范围模式​​(原Normal/Derated)、​​低范围模式​​(原Low)、​​高范围模式​​(原High)。 ​​时序优化​​: LPSPI主模式频率上限从30MHz→​​60MHz​​,建立时间从10ns→3ns。 ​​新增警告​​: GPIO_AD/LPSR/DISP_B2的NVCC不可悬空,否则可能漏电​​500μA/每Bank​​。 ​​8. 其他信息​ ​ ​​文档版权​​:示例代码遵循​​BSD-3-Clause许可证​​。 ​​参考文档​: AN14716 MCUXPresso SDK i.MX RT
記事全体を表示
1. Backgroud Customers adopting multi-i.MXRT master-slave architectures (one master, multiple slaves) aim to meet functional requirements while simultaneously reducing costs and improving system efficiency through optimized hardware design. 2.  Multi-i.MXRT Architecture Design 2.1 Independent Flash Architecture (Master-Slave) In multi-i.MXRT systems, a typical design adopts a master-slave architecture where one i.MXRT acts as the master and others as slaves. Since the i.MXRT chip lacks on-chip non-volatile memory, each i.MXRT requires an independent boot device (e.g., NOR Flash connected via FlexSPI) to load programs and initiate startup.  Traditional Architecture: - Each i.MXRT has its own dedicated Flash memory, ensuring operational independence. Advantages: - Full System Independence: Each i.MXRT operates independently with its own firmware and boot configuration. Fault isolation: A failure in one Flash or i.MXRT does not affect others. - Simplified Firmware Management: Independent firmware updates for each i.MXRT without coordination. Easier OTA version control (each device has its own update path). Disadvantages: - Complex programming workflow (multiple Flash devices need individual firmware updates). - Higher hardware complexity, larger PCB footprint, and increased cost due to multiple Flash chips. 2.2 Shared Flash Architecture (Master-Slave with Flash Sharing) A single Flash device is connected to multiple i.MXRTs. The master i.MXRT controls the POR_B (Power-On Reset) signal of all slave i.MXRTs, enabling shared access to the same Flash. Boot Process: 1. The master i.MXRT boots first in Non-XIP mode. 2. The master sequentially releases the POR_B signals of slave i.MXRTs, allowing them to occupy the Flash and boot in Non-XIP mode one at a time. Advantages: - Reduced cost and simplified hardware design. - Smaller PCB footprint with only one Flash required. - Streamlined firmware programming (single Flash update) for mass production. Disadvantages: - If slave i.MXRTs require different firmware, the Flash must be partitioned into regions, leading to: - Complex OTA version management challenges. - Reduced system independence among slave devices. 3. Hardware Platform Setup Master Board: MIMXRT1010-EVK Slave Board: MIMXRT1010-EVK Rework: Remove U13 (Flash) from the slave board. Retain U13 on the master board and fly-wire it to U13 of the slave board (only CS, SCLK, IO0, IO1 are required for low-speed boot). Connect GPIO_11 signal of the master i.MXRT1010 to POR_B of the slave i.MXRT1010 (Pin3/4 of SW3).   4. Software Design Due to both master and slave i.MXRTs sharing a single application (differentiated via conditional branches), the app must be Non-XIP. Therefore, we designed a boot_loader project that copies and jumps to the boot_app, instead of using SPT or MCUBootUtility. 🔗 Key modules: /boards/evkmimxrt1010/demo_apps/boot_loader /boards/evkmimxrt1010/demo_apps/boot_app . ├── boards │ └── evkmimxrt1010 │ ├── demo_apps │ │ ├── boot_app │ │ ├── boot_loader │ │ ├── hello_world │ │ └── led_blinky │ └── xip │ ├── evkmimxrt1010_flexspi_nor_config.c │ └── evkmimxrt1010_flexspi_nor_config.h ├── CMSIS │ ├── Core │ ├── Driver │ ├── DSP │ ├── LICENSE.txt │ ├── NN │ └── RTOS2 ├── components │ ├── lists │ ├── serial_manager │ └── uart ├── devices │ └── MIMXRT1011 ├── LICENSE └── README.md Note: Please see the whole reference project from attchement.  4.1 boot_loader Design The boot_loader is a XiP project directly booted by the chip's BootROM. It can be based on the SDK's hello_world example ( flexspi_nor target). The FCB boot header should be modified as follows (1-bit SPI, 30MHz, Normal Read Mode): // boot_loader // xip/evkmimxrt1010_flexspi_nor_config.c const flexspi_nor_config_t qspiflash_config = { .tag = FLEXSPI_CFG_BLK_TAG, .version = FLEXSPI_CFG_BLK_VERSION, .readSampleClksrc=kFlexSPIReadSampleClkLoopbackInternally, .csHoldTime = 3u, .csSetupTime = 3u, .deviceType = kFlexSpiDeviceTypeSerialNOR, .sflashPadType = kSerialFlash_1Pad, .serialClkFreq = kFlexSpiSerialClk_30Hz, .sflashA1Size = 16u * 1024u * 1024u, .lookupTable = { // Read LUTs FLEXSPI_LUT_SEQ(CHIP_SELECT, FLEXSPI_1PAD, 0x03, RADDR_SDR, FLEXSPI_1PAD, 0x18), FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_1PAD, 0x04, STOP, FLEXSPI_1PAD, 0x0), }, .pageSize = 256u, .sectorSize = 4u * 1024u, .blockSize = 64u * 1024u, .isUniformBlockSize = false, }; The boot_app is a Non-XIP project (based on SDK’s debug target). Its binary is imported into the boot_loader project. With proper linking address and memory layout, the copy & jump logic can be implemented with standard code. The finalized boot_loader can then be downloaded to Flash using an IDE. 4.2 boot_app Design The boot_app is also derived from the SDK's hello_world . It supports receiving simple UART commands ( A , B , etc.) for various tests. Currently, six test commands are supported:  Commands Target Device i.MX RT Description 'A' Master Drive master i.MXRT's GPIO_11 high to pull POR_B high and release slave i.MXRT from reset. 'B' Master Drive master i.MXRT's GPIO_11 low to pull POR_B low and hold slave i.MXRT in reset.   Commands Target Device Description 'F' Salve Toggle GPIO_11 periodically with a timer to blink the D25 LED.   Commands Target Device Description 'C' Master or Slave  Initialize Flash-related pins for FlexSPI functionality. 'D' Master or Slave  Restore Flash-related pins to default GPIO state. 'E' Master or Slave  Erase, program, and read U13 Flash.   Notes: Commands A and E may cause conflicts when both master and slave i.MXRT attempt to drive the same Flash through FlexSPI pins. Before executing Command A (to release the slave), the master should first execute Command D, calling the following function to restore FlexSPI pins to GPIO mode. Otherwise, the slave may fail to boot normally (BootROM configures these pins as FlexSPI during boot). void bsp_deinit_flexspi_pins(void) { IOMUXC_SetPinMux(IOMUXC_GPIO_SD_06_GPIO2_IO06, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_SD_07_GPIO2_IO07, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_SD_09_GPIO2_IO09, 0U); IOMUXC_SetPinMux(IOMUXC_GPIO_SD_10_GPIO2_IO10, 0U); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_06_GPIO2_IO06, 0x10A0U); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_07_GPIO2_IO07, 0x10A0U); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_09_GPIO2_IO09, 0x10A0U); IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_10_GPIO2_IO10, 0x10A0U); } Commands C and E are typically used together. If the slave has already executed them and remains active, the master must either: The Master execute Command B to reset the slave which resets FlexSPI pin configurations The Slave to execute Command D before running C/E. 5. On-Board Testing Power up both boards. Download the boot_loader (containing embedded boot_app ) to Flash. Quick Test: Sending Command A initially may not start the slave properly. However, after executing Command D followed by Command A, the slave boots successfully. Both master and slave boards can read/write the shared Flash normally, verifying the feasibility of this innovative shared flash boot method. Note: Please see readme.md from attchement for more details. 6. Conclusion The i.MXRT master-slave architectures (Independent Flash vs. Shared Flash) offer distinct trade-offs: - Independent Flash: Prioritizes system reliability and independent firmware management at the cost of higher hardware complexity and cost. - Shared Flash: Reduces costs and PCB footprint but introduces firmware dependency and OTA management challenges. The prototype successfully validated the Shared Flash approach, demonstrating its feasibility for cost-sensitive, mass-production scenarios. Customers can choose between these designs based on their specific priorities: high reliability with independence (Independent Flash) or cost-efficiency with streamlined workflows (Shared Flash).
記事全体を表示
The table below contains notable updates to the current release of the Reference Manual. The information provided here is preliminary and subject to change without notice. ​​​​​​​​​​​​​​​​​​ Affected Modules Issue Summary Description Date QDC Incorrect Input Filter Register (FILT) configuration.  FILT_PRSC bitfield is not implemented in Design. 22 May 2025 ​ ​
記事全体を表示
​ The table below contains notable updates to the current release of the Reference Manual. The information provided here is preliminary and subject to change without notice. ​​​​​​​​​​​​​​​​​​ Affected Modules Issue Summary Description Date System Boot Incorrect encoding for BOOT_CFG[9] - ECC Selection The encoding for the boot configuration bit for the ECC selection is incorrect. Device ECC should be 0 and Software ECC should be 1. Before:    After:    - ​
記事全体を表示
Porting JLink RTT to RT595 Porting JLink RTT to RT595         1. Introduction         2. RTT (Real-Time Terminal)         3. Porting                  Steps for Porting         4. Conclusion 1. Introduction For most beginners learning MCU or embedded systems, the first step often involves simple tasks like "lighting up an LED" or a "Hello World" program. Today, we will discuss a topic closely related to "Hello World." Serial output is a highly effective debugging tool, allowing developers to monitor program states, interact with the program, and diagnose issues. This is a familiar friend to anyone engaged in embedded development. The most common approach, as seen in NXP SDK examples, uses a UART peripheral for logging: Initialize the MCU's UART: Configure clock frequency, pin multiplexing, pin settings, baud rate, etc. Open a serial tool on the PC and configure the correct baud rate. Use the UART driver in the project to enable serial logging. This is the simplest and most widely used method for serial output. However, what if the precious UART resource is already occupied? Here's a great alternative: porting SEGGER's RTT (Real-Time Terminal) driver and using the JLink RTT functionality for logging. The biggest advantage of this approach is conserving UART resources! Next, let’s explore the powerful capabilities of JLink RTT. 2. RTT (Real-Time Terminal) RTT, developed by SEGGER, is a real-time terminal solution for interactive communication in embedded applications. Beyond conserving UART resources, RTT offers significant advantages over semi-hosting methods provided by tools like MCUXpresso IDE. RTT allows for high-speed bidirectional data transfer between the MCU and the host without compromising real-time performance. Key features of JLink RTT include: Low Overhead: Efficient data transfer mechanisms ensure minimal impact on target system performance. Real-Time Capability: Developers can output debugging information or receive data from the target system in real time without halting execution. Flexibility: Supports multiple channels for transmitting different types of data, such as debugging logs and performance metrics. OS Independence: Unlike traditional printf debugging methods, RTT can be used on embedded systems without an operating system. JLink RTT typically pairs with JLink debuggers and SEGGER's development tools, providing powerful support for debugging and tracking embedded systems. To try out this functionality, a JLink debugger is essential. Using the classic RT595-EVK as an example, we will demonstrate how to port RTT. 3. Porting The development environment includes the MCUXpresso IDE and the hello_world project from the SDK. The SDK version is not critical. Steps for Porting Locate RTT Resources According to SEGGER's official documentation, RTT resources can be found in the JLink installation directory:   C:\Program Files\SEGGER\JLink\Samples\RTT Copy Required Files Copy the following files to the source folder of the hello_world project: SEGGER_RTT_Syscalls_GCC.c SEGGER_RTT_Conf.h SEGGER_RTT_printf.c SEGGER_RTT.c SEGGER_RTT.h Copy these source files to the source folder of the hello_world project:   Integrate into Project If using Keil or IAR, you may need to add header file dependencies. However, since the RTT files are placed directly in the MCUXpresso project’s source folder, you only need to call the relevant RTT functions in hello_world.c.   Initialize and Configure Buffers Add the following code to initialize RTT and create up/down buffers: SEGGER_RTT_Init(); uint8_t rx_buffer[32], tx_buffer[32]; SEGGER_RTT_ConfigUpBuffer(0, "RTTUP", rx_buffer, sizeof(rx_buffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); SEGGER_RTT_ConfigDownBuffer(0, "RTTDOWN", tx_buffer, sizeof(tx_buffer), SEGGER_RTT_MODE_NO_BLOCK_SKIP); SEGGER_RTT_SetTerminal(0); SEGGER_RTT_printf(0, "hello world\r\n"); Use RTT for sending: SEGGER_RTT_SetTerminal(0); SEGGER_RTT_printf(0, "hello world\r\n"); Here, after we port the file and add the RTT operation to the source code of hello_world, the code part is ready to be completed. Use JLink RTT Viewer Launch the JLink RTT Viewer program, select the appropriate device number, run the program, and open "Terminal 0" to view the output.   4. Conclusion Compared to traditional UART-based logging, utilizing the debugger’s built-in RTT functionality reduces peripheral usage and eliminates the need for UART initialization and configuration. With JLink, RTT is essentially plug-and-play, providing convenient and fast logging and interaction. In addition to basic functionality, SEGGER offers advanced features such as changing font colors. Explore more on SEGGER's official website: SEGGER RTT Documentation   For Chinese version and demo project, please check this link: https://www.nxpic.org.cn/module/forum/forum.php?mod=viewthread&tid=803638&fromuid=3253523
記事全体を表示
Compared with the RT10xx series, the i.MX RT117x has an additional M4 core, which makes multi-core collaboration possible. The general practice of multi-core operation is to run in independent program data space and communicate through a shared memory space. For example, in the official SDK routine, the M7 code runs in Flash, while the M4 code runs in SRAM, and they communicate from each other via a shared SRAM space, which can ensure the maximum performance. However, during the development stage, customers may need to put both the M7 and M4 codes in external SDRAM for debugging. Although this will affect some performance, it will not perform too many erase and write operations on the flash, which also has certain practical significance.
記事全体を表示
 This article provides a generic introduction related to the cryptographical algorithms and HW acceleration. By using i.MX RT117x with related hands-on examples, it aims at helping NXP customers to quickly understand how to use and make a well decision regarding the selection of cryptographic algorithms to use in their products and systems. Note: TL, DR. If the reader has the basic knowledge of the cryptography, please skip to chapter 3. A cryptographic accelerator is a co-processor designed specifically to perform computationally intensive cryptographic operations, there are different names from different chip manufactures. For NXP, ‘CASPER’ on LPC55xx series, but ‘DCP’ or ‘CAAM’ for i.MX and i.MX RT. i.MX RT Name Features i.MXRT10xx   DCP (Data Co-Processor) Symmetric Engines: AES-128 Hash Engines: SHA-1, SHA-256   i.MXRT11xx CAAM  (Cryptographic Acceleration and Assurance Module) Symmetric Engines: AES 128, 192, 256; 3DES, DES; PKHA: RSA, ECDSA,DH,ECDH  Hash Engines: SHA-1, SHA-2, MD5, HMAC Random Number Generation It shows cryptographic features and benchmark performance with 2 examples: Features: CAAM usage in mbedTLS. Performance: Benchmark of HW acceleration or software only   CAAM Features Key Function APIs JobRing0 kCAAM_Sha256 kCAAM_HmacSha1/sha224/384/512 kCAAM_Aes_cbc-128/192/256 RunShaExamples(base,&caamHandle); RunHmacExamples(base,&caamHandle); RunAesCbcExamples(base,&caamHandle); JobRing1 kCAAM_Aes_gcm RunAesGcmExamples(base,&caamHandle); JobRing2 kCAAM_Aes_cbc RunAesCbcExamples(base,&caamHandle); JobRing3 kCAAM_Aes_gcm kCAAM_RNG kCAAM_Red-Block kCAAM_Black-Block kCAAM_CRC RunAesGcmExamples(base,&caamHandle); RunRngExample(base, &caamHandle); RedBlobExample(base, &caamHandle); BlackBlobExample(base, &caamHandle); RunCrcExamples(base, &caamHandle);   Key words: Cryptography, Cryptographic HW Acceleration, i.MX RT   
記事全体を表示
Frequently, we receive questions related to the DQS pins present on i.MXRT whether how to use it and what it is exactly the function of this as well as why it is important to use it. The goal of this document is answering common questions and expose the most common mistakes when connecting this pin. Lets start defining why DQS signal is helpful for memory interfaces; DQS stands as data strobe and it is the clock signal for the data lines used to solve an issue during the memory read. The controller must first transmit the clock to memory, where it arrives x ns later, then the memory sends data bits to the controller and this takes x nanoseconds. There is a clock skew, which limits how fast you can transmit. On iMXRT family it is present on FlexSPI and SEMC interfaces where you can connect multiple memories, it also allows to have multiple configurations as not all memories provide DQS signal on the memory. The next section will detail the particular configuration on each memory interface, RT1170 data will be used but information on RT10xx family is also applicable on this.  SEMC SEMC has two configurations for DQS pad, on DQSMD register.   For DQSMD = 0: We do not have an exact maximum/minimum for the achievable frequency, we only know that when DQSMD we will not reach the maximum SEMC frequency on SDRAM. There could be variations on the frequency on this mode. It is impossible to run at the max 200MHz 1 and meet this input timing spec on datasheet, so the clock frequency needs to be decreased to ensure you still meet timing., this depends on the data output delay spec for the memory that is being used. For DQSMD = 1: As the signal delay is calculated in DQS pad, 200MHz 1 frequency can be achieved on this mode, please consider that the pin needs to be floating or apply extra capacitance on special cases which will be discussed below. As SDRAM device don't output DQS signal, so it take DQS pad as loopback and measure signals delay, and take this delay to compensate and get the correct data strobe point, this can cover most application case and get the good performance, however, if external signal delay is big, it has the complicated topology and long trace, so it can't take DQS pad delay to compensate external SDRAM signal delay. There are two methods to adjust the delay, the first one is using Delay Chain Control Register(DCCR) while the other one is adding capacitance to the DQS pad; unfortunately there is no formula to calculate the register value and capacitance as this is related to SDRAM signal layout, different layout will get the different signal delay. There are some particular cases where more than 3 SDRAMs were added to RT1xx, since the combined memories capacitance exceeded the pad capacitance there were issues using the memory at the max speed; this was solved by adding extra capacitance to DQS pin.   FlexSPI FlexSPI DQS pins behaves similarly as the one we found on SEMC with some difference on the available configuration and maximum speeds. For FlexSPI device there are three different modes of configuration controlled by the RXCLKSRC field on MCR0 register. RXCLKsrc=0x0 (Internal dummy read strobe and internal loopback) In this mode DQS pin not used so an alternative option for this pin can be configured, however the achieved frequency is the lowest as the timings for highest speeds cannot be achieved.   RXCLKsrc=0x1 (Internal dummy read strobe and loopback from DQS pad) In this mode FlexSPI uses DQS pin and it must be configured for the FlexSPI function, it is not an option to use it for a different purpose in this mode. The internally generated read strobe is sent to the DQS pin and is sampled at the pin to match more closely the data pin timings. The timing for sampling with an internal dummy read strobe loopback is very similar to the timing for loopback from pad but it can achieve a higher frequency than loopbacking internally however not the highest one. Similarly to the described on the SEMC side, there are some special cases where signal delay is big, the design has a complicated topology or long traces were the solution is adding extra capacitance to DQS pad, As this is dependent of design there is no formula to calculate the needed capacitance.   RXCLKsrc=0x3 (Flash-memory-provided read strobe) In this mode DQS signal is provided by the connected memory, this mode allows maximum frequency for the memory however only certain memories provide this signal. The FlexSPI controller delays the read strobe for one half cycle of the serial root clock (with DLL), then samples read data with the delayed strobe. Conclusion On i.mxRT family commonly uses external memories to execute code or access important data where good performance on the device is needed. To optimize the access speed of the memory DQS signal is always needed as it may limit the speed rate. 1 Please consult the device specific datasheet for detailed rates.   
記事全体を表示
1. Abstract This article aims to implement the simultaneous input of 4 groups of 48Khz 32bit 2ch audio data on the RT685 platform, and then assemble the received data into a 48Khz 32bit 8ch audio and output it through I2S. This solution is also done at the request of customers, because there are always harmonic problems when customers make it. After analyzing the customer's situation, it is found that the customer has two main problems: (1) Harmonic problem: After receiving 4 channels of 8 bytes, it is directly copied to the sending buffer. This will cause timing problems. It does not take into account the problem of buffering data in the audio data storage pool. The time required to receive enough audio data is at least greater than the time required for copying and sending. Therefore, the problem is reflected in the problem that the customer found harmonic problems when testing the output audio waveform. (2) Audio synchronization problem: After the customer received 4 channels of audio data, he tested the receiving buffer and found that the 4 channels of data were out of sync. Therefore, in order to help customers, I helped customers make this application demo directly, and made a matching test audio source to send a set of 48Khz sampling rate 32bit dual-channel, fixed increment audio data in a loop, such as 0X00-0XFF in a loop. The following is the block diagram of this application platform:   Figure 1 System Block Diagram In the above figure, a MIMXRT685-EVK implements the function of outputting 48Khz, 32bit*2ch, and sends data in a loop: 0X00, 0X01….0XFF. Another MIMXRT685-EVK is the focus of this article, which implements 4 groups of I2S to receive data at a sampling rate of 48khz and 32bit*2ch, and then assembles the received data into audio data with a sampling rate of 48Khz and 32bit*8ch and sends it out. In the above figure, in order to reduce the connection of external lines, for BCLK and WS signals, only one group is directly connected to I2S3, and the other I2S2, I2S4, and I2S5 share the I2S3 signal internally. Then, for DATA data, a line is made externally with 4 heads, and connected to the data pins of each group of audio interfaces respectively. The following is a detailed description of this solution. 2. Hardware platform establish The pinouts of the two boards are given below. Because the platform uses many pins, specific allocation is required. 2.1 Audio source board A MIMXRT685-EVK is used as an audio source, and the pinouts for sending 48Khz 32bit*2ch are as follows:   Figure 2 Pinout of audio source board 2.2 Audio transceiver board Another MIMXRT685-EVK is used as an audio transceiver board to receive 4-channel audio synchronization data sent by the audio source and assemble it into a 48Khz 32bit*8ch waveform for transmission.   Figure 3 Pin assignment of audio transceiver board 2.3 Dual-board hardware connection The source and target connections of the two boards are as follows:   Figure 4 Two board pin connection   Figure 5 two board connection After the hardware is ready, the software solution and code are provided. 3. Software solution and software implementation In the process of writing the code, we tried many solutions, such as: (1) When receiving, directly assemble it into the TDM format buffer to be sent, and then send it. However, since it is assembled into TDM, one I2S needs to receive 8 byte per frame, and then do the offset to receive the next one. If the reception is carried out according to the 8-byte DMA, the callback of the 4 groups of I2S will enter frequently, resulting in a large CPU load, so this solution is abandoned. (2) The 4 groups of I2S are connected to each other, and the 10ms buffer is connected, and then the DMA method is used to copy from memory to memory. However, since the DMA of RT685 is relatively weak, it can only achieve a maximum offset of 32bit 4word=16byte, that is, a 16-byte offset. However, in fact, a group of audio data is 32bit*2, and 4 groups are 32bit*8=32byte offset, so DMA cannot meet the requirements. Therefore, the DMA memory-to-memory copy solution is abandoned and memcpy is used instead. (3) Use the I2S_RxTransferReceiveDMA function to perform DMA reception. However, in fact, when one group is called, it starts receiving directly, and waits until the next group of I2S interfaces calls I2S_RxTransferReceiveDMA. This has caused an asynchronous situation. Even if the I2S enable is turned off in I2S_RxTransferReceiveDMA, the 4th group of I2S is enabled after the several groups of I2S of I2S_RxTransferReceiveDMA are called. This method can only achieve the synchronization of the reception of the first group of data, because later, it is necessary to go to the callback to re-trigger the reception of the second frame of data. Therefore, the callback of the 4 groups of I2S calls I2S_RxTransferReceiveDMA, which will inevitably cause new synchronization problems. Therefore, this method is abandoned and it is considered to use two groups of DMA descriptors to do ping-pong. In this way, the reception will continue in a loop without the intervention of CPU code. 3.1 Solution Implementation Several solutions have been described above. Finally, we choose to use 4 audio channels to receive audio data and cache 10ms audio data buffer. The conversion from receiving buffer to sending buffer adopts memcpy method, and test whether this copy time can meet the actual needs, to ensure that the buffer pool of receiving buffer is greater than this copy time, which is enough to prepare the sending buffer. The solution for receiving data transfer is as follows:   Figure 6 Data buffer transfer The above is 4 groups of I2S receiving their own 10ms data respectively. The buffer is actually prepared for 20ms. A single DMA receives a frame for 10ms, and the other 10ms is used for pingpong buffer. The sending buffer is used to copy the received 4 groups of I2S buffers into a 32bit*8ch array in TDM format, and then two groups of ping-pong buffers are also made. In fact, it is to cache 10ms data. The buffer prepares two groups of 10ms. When the first 10ms frame is received, the second buffer is used to receive it. At the same time, the data of the first buffer is copied to the first buffer of the sending buffer, and the first buffer is used for sending. After the sending is completed, it is transferred to the second buffer to receive and send. In this way, as long as the time is controlled well, there will be no data error problem. The data volume of 10ms is 3840Byte, because the receiving frequency is 48Khz, that is, there are 48000 frames in 1s, and each frame is 32bit*2=8Byte, then 10ms=>4800*8Byte=38400Byte. 3.2 Software code implementation The software code implementation part is mainly divided into 4 I2S receiving signal sharing, I2S DMA pingpong configuration, data transfer, sending I2S and other parts. The details are given below 3.2.1 4-way I2S receiving From the above, we can know that the 4 I2S receiving signal is not completely connected with wires, but adopts the method of sharing BCLK and WS signals and receiving DATA separately. I2S2, I2S4, I2S5 share the BCLK of I2S3, and the WS code is as follows: /* Set shared signal set 0: SCK, WS from Flexcomm1 */ I2S_BRIDGE_SetShareSignalSrc(kI2S_BRIDGE_ShareSet0, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_Flexcomm3); I2S_BRIDGE_SetShareSignalSrc(kI2S_BRIDGE_ShareSet0, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_Flexcomm3); /* Set flexcomm3 SCK, WS from shared signal set 0 */ I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm2, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm2, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm4, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm4, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm5, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm5, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_ShareSet0); 3.2.2 I2S DMA pingpong configuration In order to achieve 4-channel audio synchronization and receive 10ms audio buffer, two I2S DMA descriptors are used to implement the ping-pong function to collect data to two ping-pong buffers in turn. The code is as follows: #define I2S_BUFFER_SIZE 3840 //10ms SDK_ALIGN(static dma_descriptor_t I2S2_s_rxDmaDescriptors[2U], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); SDK_ALIGN(static dma_descriptor_t I2S3_s_rxDmaDescriptors[2U], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); SDK_ALIGN(static dma_descriptor_t I2S4_s_rxDmaDescriptors[2U], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); SDK_ALIGN(static dma_descriptor_t I2S5_s_rxDmaDescriptors[2U], FSL_FEATURE_DMA_LINK_DESCRIPTOR_ALIGN_SIZE); SDK_ALIGN(static uint8_t I2S2_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S3_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S4_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S5_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); static i2s_transfer_t I2S2_s_RxTransfer[2] = {{ .data = I2S2_s_Buffer[0], .dataSize = I2S_BUFFER_SIZE, }, { .data = I2S2_s_Buffer[1], .dataSize = I2S_BUFFER_SIZE, }}; static i2s_transfer_t I2S3_s_RxTransfer[2] = {{ .data = I2S3_s_Buffer[0], .dataSize = I2S_BUFFER_SIZE, }, { .data = I2S3_s_Buffer[1], .dataSize = I2S_BUFFER_SIZE, }}; static i2s_transfer_t I2S4_s_RxTransfer[2] = {{ .data = I2S4_s_Buffer[0], .dataSize = I2S_BUFFER_SIZE, }, { .data = I2S4_s_Buffer[1], .dataSize = I2S_BUFFER_SIZE, }}; static i2s_transfer_t I2S5_s_RxTransfer[2] = {{ .data = I2S5_s_Buffer[0], .dataSize = I2S_BUFFER_SIZE, }, { .data = I2S5_s_Buffer[1], .dataSize = I2S_BUFFER_SIZE, }}; I2S_RxGetDefaultConfig(&I2S2_s_RxConfig); I2S2_s_RxConfig.divider = DEMO_I2S_CLOCK_DIVIDER; I2S2_s_RxConfig.masterSlave = DEMO_I2S_TX_MODE;//DEMO_I2S_RX_MODE I2S_RxInit(DEMO_I2S2_RX, &I2S2_s_RxConfig); I2S_RxGetDefaultConfig(&I2S3_s_RxConfig); I2S3_s_RxConfig.divider = DEMO_I2S_CLOCK_DIVIDER; I2S3_s_RxConfig.masterSlave = DEMO_I2S_TX_MODE;//DEMO_I2S_RX_MODE I2S_RxInit(DEMO_I2S3_RX, &I2S3_s_RxConfig); I2S_RxGetDefaultConfig(&I2S4_s_RxConfig); I2S4_s_RxConfig.divider = DEMO_I2S_CLOCK_DIVIDER; I2S4_s_RxConfig.masterSlave = DEMO_I2S_TX_MODE;//DEMO_I2S_RX_MODE I2S_RxInit(DEMO_I2S4_RX, &I2S4_s_RxConfig); I2S_RxGetDefaultConfig(&I2S5_s_RxConfig); I2S5_s_RxConfig.divider = DEMO_I2S_CLOCK_DIVIDER; I2S5_s_RxConfig.masterSlave = DEMO_I2S_TX_MODE;//DEMO_I2S_RX_MODE I2S_RxInit(DEMO_I2S5_RX, &I2S5_s_RxConfig); DMA_Init(DEMO_DMA); DMA_EnableChannel(DEMO_DMA, DEMO_I2S2_RX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S2_RX_CHANNEL, kDMA_ChannelPriority1); DMA_CreateHandle(&I2S2_s_DmaRxHandle, DEMO_DMA, DEMO_I2S2_RX_CHANNEL); I2S_RxTransferCreateHandleDMA(DEMO_I2S2_RX, &I2S2_s_RxHandle, &I2S2_s_DmaRxHandle, I2S2_RxCallback, (void *)&I2S2_s_RxTransfer); DMA_EnableChannel(DEMO_DMA, DEMO_I2S3_RX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S3_RX_CHANNEL, kDMA_ChannelPriority1); DMA_CreateHandle(&I2S3_s_DmaRxHandle, DEMO_DMA, DEMO_I2S3_RX_CHANNEL); I2S_RxTransferCreateHandleDMA(DEMO_I2S3_RX, &I2S3_s_RxHandle, &I2S3_s_DmaRxHandle, I2S3_RxCallback, (void *)&I2S3_s_RxTransfer); DMA_EnableChannel(DEMO_DMA, DEMO_I2S4_RX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S4_RX_CHANNEL, kDMA_ChannelPriority1); DMA_CreateHandle(&I2S4_s_DmaRxHandle, DEMO_DMA, DEMO_I2S4_RX_CHANNEL); I2S_RxTransferCreateHandleDMA(DEMO_I2S4_RX, &I2S4_s_RxHandle, &I2S4_s_DmaRxHandle, I2S4_RxCallback, (void *)&I2S4_s_RxTransfer); DMA_EnableChannel(DEMO_DMA, DEMO_I2S5_RX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S5_RX_CHANNEL, kDMA_ChannelPriority2); DMA_CreateHandle(&I2S5_s_DmaRxHandle, DEMO_DMA, DEMO_I2S5_RX_CHANNEL); I2S_RxTransferCreateHandleDMA(DEMO_I2S5_RX, &I2S5_s_RxHandle, &I2S5_s_DmaRxHandle, I2S5_RxCallback, (void *)&I2S5_s_RxTransfer); I2S_TransferInstallLoopDMADescriptorMemory(&I2S2_s_RxHandle, I2S2_s_rxDmaDescriptors, 2U); I2S_TransferInstallLoopDMADescriptorMemory(&I2S3_s_RxHandle, I2S3_s_rxDmaDescriptors, 2U); I2S_TransferInstallLoopDMADescriptorMemory(&I2S4_s_RxHandle, I2S4_s_rxDmaDescriptors, 2U); I2S_TransferInstallLoopDMADescriptorMemory(&I2S5_s_RxHandle, I2S5_s_rxDmaDescriptors, 2U); if (I2S_TransferReceiveLoopDMA(DEMO_I2S2_RX, &I2S2_s_RxHandle, &I2S2_s_RxTransfer[0], 2U) != kStatus_Success) { assert(false); } if (I2S_TransferReceiveLoopDMA(DEMO_I2S3_RX, &I2S3_s_RxHandle, &I2S3_s_RxTransfer[0], 2U) != kStatus_Success) { assert(false); } if (I2S_TransferReceiveLoopDMA(DEMO_I2S4_RX, &I2S4_s_RxHandle, &I2S4_s_RxTransfer[0], 2U) != kStatus_Success) { assert(false); } if (I2S_TransferReceiveLoopDMA(DEMO_I2S5_RX, &I2S5_s_RxHandle, &I2S5_s_RxTransfer[0], 2U) != kStatus_Success) { assert(false); } I2S_Enable(DEMO_I2S2_RX); I2S_Enable(DEMO_I2S3_RX); I2S_Enable(DEMO_I2S4_RX); I2S_Enable(DEMO_I2S5_RX); Here, the code has been modified, mainly the I2S_TransferLoopDMA function in fsl_i2s_dma.c, which is blocked: I2S_Enable(base); In order to realize the function of 4-channel synchronous reception. 3.2.3 Audio data received and transferred Because when receiving, each audio interface takes turns to receive its own 2ch data, but when sending, it is necessary to send 4-channel received audio dual-channel data, that is, 32bit*8ch data, so after receiving ping, the ping data needs to be transferred to the sending ping buffer. The code for transfer is as follows: #define I2S_BUFFER_SIZE 3840 //10ms SDK_ALIGN(static uint8_t I2S2_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S3_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S4_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S5_s_Buffer[2][I2S_BUFFER_SIZE], sizeof(uint32_t)); SDK_ALIGN(static uint8_t I2S1_s_Buffer[2][I2S_BUFFER_SIZE*4], sizeof(uint32_t)); if( s_pingpong == 1) { for(ch = 0;ch < 480; ch++) //480=I2S_BUFFER_SIZE(3840)/8 { memcpy(&I2S1_s_Buffer[0][0 + (32*ch)], &I2S2_s_Buffer[0][8*ch], 8); memcpy(&I2S1_s_Buffer[0][8 + (32*ch)], &I2S3_s_Buffer[0][8*ch], 8); memcpy(&I2S1_s_Buffer[0][16 + (32*ch)], &I2S4_s_Buffer[0][8*ch], 8); memcpy(&I2S1_s_Buffer[0][24 + (32*ch)], &I2S5_s_Buffer[0][8*ch], 8); } } else { for(ch = 0;ch < 480; ch++) { memcpy(&I2S1_s_Buffer[1][0 + (32*ch)], &I2S2_s_Buffer[1][8*ch], 8); memcpy(&I2S1_s_Buffer[1][8 + (32*ch)], &I2S3_s_Buffer[1][8*ch], 8); memcpy(&I2S1_s_Buffer[1][16 + (32*ch)], &I2S4_s_Buffer[1][8*ch], 8); memcpy(&I2S1_s_Buffer[1][24 + (32*ch)], &I2S5_s_Buffer[1][8*ch], 8); } } 3.2.4 Send TDM audio code The sending code also uses the I2S DMA method, but because there is no need to send multiple channels at the same time, only a single channel, there is no need to consider the synchronization problem, and no DMA descriptor is used. After the sending buffer is ready, the I2S_TxTransferSendDMA method is used. The code is as follows: I2S_TxGetDefaultConfig(&I2S1_s_TxConfig); I2S1_s_TxConfig.divider = DEMO_I2S1_CLOCK_DIVIDER; I2S1_s_TxConfig.masterSlave = kI2S_MasterSlaveNormalMaster; I2S1_s_TxConfig.wsPol = true; I2S1_s_TxConfig.mode = kI2S_ModeDspWsLong;//kI2S_ModeDspWsShort; I2S1_s_TxConfig.dataLength = 32U; I2S1_s_TxConfig.frameLength = 32 * 8U; I2S1_s_TxConfig.position = DEMO_TDM_DATA_START_POSITION; I2S1_s_TxConfig.pack48 = true; I2S_TxInit(DEMO_I2S1_TX, &I2S1_s_TxConfig); I2S_EnableSecondaryChannel(DEMO_I2S1_TX, kI2S_SecondaryChannel1, false, 64 + DEMO_TDM_DATA_START_POSITION); I2S_EnableSecondaryChannel(DEMO_I2S1_TX, kI2S_SecondaryChannel2, false, 128 + DEMO_TDM_DATA_START_POSITION); I2S_EnableSecondaryChannel(DEMO_I2S1_TX, kI2S_SecondaryChannel3, false, 192 + DEMO_TDM_DATA_START_POSITION); DMA_EnableChannel(DEMO_DMA, DEMO_I2S1_TX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S1_TX_CHANNEL, kDMA_ChannelPriority3); DMA_CreateHandle(&I2S1_s_DmaTxHandle, DEMO_DMA, DEMO_I2S1_TX_CHANNEL); I2S_TxTransferCreateHandleDMA(DEMO_I2S1_TX, &I2S1_s_TxHandle, &I2S1_s_DmaTxHandle, I2S1_TxCallback, (void *)&I2S1_s_TxTransfer); if( s_pingpong == 1) { I2S1_s_TxTransfer.data = I2S1_s_Buffer[0]; I2S1_s_TxTransfer.dataSize = I2S_BUFFER_SIZE*4; I2S_TxTransferSendDMA(DEMO_I2S1_TX, &I2S1_s_TxHandle, I2S1_s_TxTransfer); } else { I2S1_s_TxTransfer.data = I2S1_s_Buffer[1]; I2S1_s_TxTransfer.dataSize = I2S_BUFFER_SIZE*4; I2S_TxTransferSendDMA(DEMO_I2S1_TX, &I2S1_s_TxHandle, I2S1_s_TxTransfer); } 3.2.5 Send and receive I2S callback processing For the receiving I2S2, 3, 4, 5, there are 4 channels in total. Each time 10ms of data is received, a callback will be entered. In the callback, you only need to record the flag. When all 4 flags are recorded, it means that the 4 channels of the same 10ms data have been received, and the data can be copied to the sending buffer. Of course, in order to test whether the callback entry frequency is once every 10ms, this article makes a GPIO callback for testing. The following is the code for recording I2S callback static void I2S2_RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { s_allRXTriggerred |= 0x01; } static void I2S3_RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { s_allRXTriggerred |= 0x02; } static void I2S4_RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { s_allRXTriggerred |= 0x04; } static void I2S5_RxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { /* Enqueue the same original buffer all over again */ s_allRXTriggerred |= 0x08; GPIO_PortToggle(GPIO, 1, 1<<0); if( s_pingpong == 0) { s_pingpong = 1; } else { s_pingpong = 0; } } static void I2S1_TxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { GPIO_PortToggle(GPIO, 1, 1<<8); //__NOP(); } So far, all functions of a MIMXRT685-EVK for 4 I2S reception and 1 I2S TDM transmission have been completed. 3.2.6 Audio source code The audio source is made on another MIMXRT685-EVK to send 48Khz, 32bit*2ch audio data, and the data is sent in a loop from 0X00 to 0XFF. The code is as follows: int main(void) { BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); BOARD_I3C_ReleaseBus(); BOARD_InitI3CPins(); CLOCK_EnableClock(kCLOCK_InputMux); /* attach main clock to I3C (500MHz / 20 = 25MHz). */ CLOCK_AttachClk(kMAIN_CLK_to_I3C_CLK); CLOCK_SetClkDiv(kCLOCK_DivI3cClk, 20); /* attach AUDIO PLL clock to FLEXCOMM1 (I2S1) */ CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM1); /* attach AUDIO PLL clock to FLEXCOMM3 (I2S3) */ CLOCK_AttachClk(kAUDIO_PLL_to_FLEXCOMM3); /* attach AUDIO PLL clock to MCLK */ CLOCK_AttachClk(kAUDIO_PLL_to_MCLK_CLK); CLOCK_SetClkDiv(kCLOCK_DivMclkClk, 1); SYSCTL1->MCLKPINDIR = SYSCTL1_MCLKPINDIR_MCLKPINDIR_MASK; wm8904Config.i2cConfig.codecI2CSourceClock = CLOCK_GetI3cClkFreq(); wm8904Config.mclk_HZ = CLOCK_GetMclkClkFreq(); /* Set shared signal set 0: SCK, WS from Flexcomm1 */ I2S_BRIDGE_SetShareSignalSrc(kI2S_BRIDGE_ShareSet0, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_Flexcomm1); I2S_BRIDGE_SetShareSignalSrc(kI2S_BRIDGE_ShareSet0, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_Flexcomm1); /* Set flexcomm3 SCK, WS from shared signal set 0 */ I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm3, kI2S_BRIDGE_SignalSCK, kI2S_BRIDGE_ShareSet0); I2S_BRIDGE_SetFlexcommSignalShareSet(kI2S_BRIDGE_Flexcomm3, kI2S_BRIDGE_SignalWS, kI2S_BRIDGE_ShareSet0); #if 1 PRINTF("Configure codec\r\n"); /* protocol: i2s * sampleRate: 48K * bitwidth:16 */ if (CODEC_Init(&codecHandle, &boardCodecConfig) != kStatus_Success) { PRINTF("codec_Init failed!\r\n"); assert(false); } /* Initial volume kept low for hearing safety. * Adjust it to your needs, 0-100, 0 for mute, 100 for maximum volume. */ if (CODEC_SetVolume(&codecHandle, kCODEC_PlayChannelHeadphoneLeft | kCODEC_PlayChannelHeadphoneRight, DEMO_CODEC_VOLUME) != kStatus_Success) { assert(false); } PRINTF("Configure I2S\r\n"); #endif /* * masterSlave = kI2S_MasterSlaveNormalMaster; * mode = kI2S_ModeI2sClassic; * rightLow = false; * leftJust = false; * pdmData = false; * sckPol = false; * wsPol = false; * divider = 1; * oneChannel = false; * dataLength = 16; * frameLength = 32; * position = 0; * watermark = 4; * txEmptyZero = true; * pack48 = false; */ I2S_TxGetDefaultConfig(&s_TxConfig); s_TxConfig.divider = DEMO_I2S_CLOCK_DIVIDER; s_TxConfig.masterSlave = DEMO_I2S_TX_MODE; I2S_TxInit(DEMO_I2S_TX, &s_TxConfig); DMA_Init(DEMO_DMA); DMA_EnableChannel(DEMO_DMA, DEMO_I2S_TX_CHANNEL); DMA_SetChannelPriority(DEMO_DMA, DEMO_I2S_TX_CHANNEL, kDMA_ChannelPriority3); DMA_CreateHandle(&s_DmaTxHandle, DEMO_DMA, DEMO_I2S_TX_CHANNEL); StartSoundPlayback(); while (1) { } } static void StartSoundPlayback(void) { PRINTF("Setup looping playback of sine wave\r\n"); s_TxTransfer.data = &g_Music[0]; s_TxTransfer.dataSize = sizeof(g_Music); I2S_TxTransferCreateHandleDMA(DEMO_I2S_TX, &s_TxHandle, &s_DmaTxHandle, TxCallback, (void *)&s_TxTransfer); /* need to queue two transmit buffers so when the first one * finishes transfer, the other immediatelly starts */ I2S_TxTransferSendDMA(DEMO_I2S_TX, &s_TxHandle, s_TxTransfer); I2S_TxTransferSendDMA(DEMO_I2S_TX, &s_TxHandle, s_TxTransfer); } static void TxCallback(I2S_Type *base, i2s_dma_handle_t *handle, status_t completionStatus, void *userData) { /* Enqueue the same original buffer all over again */ i2s_transfer_t *transfer = (i2s_transfer_t *)userData; I2S_TxTransferSendDMA(base, handle, *transfer); } Audio data buffer:   Figure 7 Audio source sends buffer The corresponding test results are given:   Figure 8 Audio source sending data test It can be seen that the data sent by the audio source is cyclical and can be sent in an increasing loop. 4. Test results There are several points to verify about the test results: (1) 4-channel audio receives pingpong buffer, whether a single buffer is 10ms, that is, a 10ms audio data pool. (2) How long is the data memory copy time, whether it will exceed the length of the receiving audio data pool. (3) Whether the received 4-channel data is synchronized, whether the assembled send buffer data is the 32bit*8ch data assembled from the corresponding 4-channel 2ch data. (4) Whether the sent audio waveform is the correct 32bit*8ch TDM data. The following are the verification test results for these points. 4.1 4 I2S audio 10ms data pool This verification is very simple. Define a pin GPIO, initialize the output to 0, and then reverse it in the received callback interrupt. This article chooses to reverse it in the I2S5 callback. The test results are as follows:   Figure 9 ch1 10ms duration Channel 1 is the exact 10ms because of the callback reversal received. Here is a general picture of the test:   Figure 10 Time test overview Ch1: I2S5 callback entry frequency Ch2: memory copy time Ch3: Send callback entry frequency It can be seen that the frequency of sending and receiving is 10ms, because the sending frequency is also 48Khz, but because it is 8ch, the data volume is 4 times that of receiving, and all the data of the 4 receiving channels need to be stuffed in. 4.2 Time consumption of receiving and copying to sending buffer For data copying, that is, assembling the data received from 4 I2S channels into 4 buffers into the sending buffer, this time test is on the second channel of the oscilloscope, and the results are as follows:   Figure 11 copy data time It can be seen that the copying time is less than 500us, which is much shorter than the 10ms of the audio receiving data pool. Therefore, you can use memcpy casually without worrying about the copying time being too long. This also makes up for the regret that I wanted to use DMA for memory to memory copying before, but it could not be realized due to DMA performance issues. 4.3 Verification of the synchronization of the data received on the 4 I2S In order to verify the synchronization, this article closes the 4 I2S receiving channel after receiving 100times 10ms, and prints out the corresponding 4 I2S audio receiving buffer. The results of the 4 I2S buffer are as follows:   Figure12 I2S2 receive buffer   Figure 13 I2S3 receive buffer   Figure 14 I2S4 receive buffer   Figure 15 I2S5 receive buffer It can be seen that the receive buffer data of the 4 I2S are completely synchronized, and all start from 0XB8.   4.4 Send buffer corresponding to 4-channel audio TDM The send buffer is printed after 100 receptions, and then memcpy is performed to the send buffer, and the printout of the send buffer data is as follows:   Figure 16 I2S1 transfer buffer It can be seen that the buffer also starts from 0XB8, and the 4 groups of received data are copied to the send buffer and assembled into 32bit*8ch data. It can be seen that the TDM send buffer is also correct.   4.5 Sending 48Khz 32bit 8ch audio data waveform   Figure 17 Transmitting and receiving audio waveforms The upper group is the waveform of the audio source, and the lower group is the waveform of TDM transmission. Due to the limitation of the analysis software of the logic analyzer, it can only analyze 2ch 64bit data at most, so only part of the data can be seen here, but from the waveform, it can be seen that the waveform of sending TDM can achieve 32bit*8ch, and every 8byte data in a frame is the same, which also explains the synchronization of 4-channel audio reception. In the above figure, the data of ch2 is actually 00, 01, 02, 03, 04, 05, 06, 07, 4 groups of the same data in one frame, and the waveform can also be seen that there are 4 groups of the same data, and 4 groups of 2ch are enough to form 32bit 8ch TDM. Finally, here is another TDM waveform tested on the oscilloscope:   Figure 18 Sending TDM waveform It can be seen that BCLK=12.28Mhz is consistent with the expected 48khz*32bit*8=12.288Mhz. The WS signal is also measured to be 48Khz, which meets the set 48Khz sampling rate. DATA is also transmitting with data changes, and it can be seen that the waveform pattern within a frame is repeated by about 4 groups, which also shows that the 4 groups of received data are synchronized. So far, the function of RT600 4-channel 48KHZ 32bit*2ch input and assembling into 48Khz 32bit*8ch output has been realized!  
記事全体を表示
RT1170 camera CSI Y8 format modification 1.Abstract RT1170's CSI can support YUV format. The so-called YUV is divided into three components: Y represents luminance, that is, grayscale value; UV represents chrominance, which describes chroma and saturation. Similar to RGB, YUV is also a color encoding method, which can separate luminance information Y from chroma information UV. If you want to display black and white, you can have no UV information, only Y information, that is, Y800=Y8, and you can also display the complete image. For RT1170 YUV, the official SDK provides demo based on the YUV444 format, but in actual use, some customers need the function of the Y8 format, so how should they configure it based on the existing YUV SDK? From the reference manual of RT1170, you can see the following information: Fig 1 This description can be understood as requiring the Y8 mode, as long as the configuration: CSI_CR20[BINARY_EN]=0 CSI_CR20[BIG_END]=1 However, in reality, with this configuration, the original YUV code cannot display the camera data. So how should the camera's Y8 configuration be done to display black and white images on the LCD? This article will give a detailed explanation. 2. RT1170 CSI Camera Y8 format configuration and testing 2.1 Hardware and software situation Board:MIMXRT1170-EVK REV C4 LCD:  RK055AHD091 Camera:OV5640 Code:SDK_2_15_000_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\csi\mipi_yuv\cm7 IDE: MCUXPresso IDE v11.9.0 2.2 Y8 formation configuration   In fact, for CSI_CR20 configuration, you also need to enable the Histogram function, which is the following register bits: Fig 2 Here, based on the current SDK demo evkmimxrt1170_csi_mipi_yuv_cm7 demo, modify it to the Y8 format, list the modification points, mainly modify the file:csi_mipi_yuv.c (1) static void DEMO_InitPxp(void) Modify: PXP_SetCsc1Mode(DEMO_PXP, kPXP_Csc1YCbCr2RGB); To: PXP_SetCsc1Mode(DEMO_PXP, kPXP_Csc1YUV2RGB); If this item is not modified, LCD will just display the Green color. (2)static void DEMO_InitCamera(void) Before BOARD_InitMipiCsi(); Add the this code: CSI->CR20 |= CSI_CR20_QRCODE_EN_MASK | CSI_CR20_HISTOGRAM_EN_MASK; Here, didn’t configure CSI_CR20[BINARY_EN]=0, as after reseting, this bit is default to 0. If in the practical usage, this bit is modified to 1, then here, need to modify BINARY_EN to 0, it means the format is Y8, not Y1. The reason that can’t display the correct Y8 previously, is caused by the bit HISTOGRAM_EN is not set. (3) static void DEMO_CSI_MIPI_YUV(void) Modify structure psBufferConfig as follows: pxp_ps_buffer_config_t psBufferConfig = { .pixelFormat = kPXP_PsPixelFormatY8, //kPXP_PsPixelFormatYUV1P444, /* Note: This is 32-bit per pixel */ .swapByte = false, .bufferAddrU = 0U, .bufferAddrV = 0U, .pitchBytes = DEMO_CAMERA_WIDTH,//DEMO_CAMERA_WIDTH * DEMO_CAMERA_BUFFER_BPP,// }; Mainly 2 points: .pixelFormat = kPXP_PsPixelFormatY8, .pitchBytes  = DEMO_CAMERA_WIDTH, If you only change the pixel format to Y8, but pitchBytes is not changed to the camera width, the resulting LCD display will be a small strip on the top, instead of the entire LCD screen showing the camera's Y8 format black and white image. So far, all Y8-related modification projects have been completed. Finally, it should be noted that the default SDK LCD display is not the one selected in this article: RK055AHD091. So you need to modify the DEMO_PANEL macro in display_support.h to the following: #define DEMO_PANEL DEMO_PANEL_RK055AHD091 Then, build the project, and download it to the board MIMXRT1170-EVK. 2.3 Test result after modification Below we use the same color picture to test the YUV and Y8 display effects in front of the camera. here are the pictures:  the camera format of the picture on the left is YUV444, and the picture on the right is in Y8 format. You can see that the left one is in color, and the right one is in black and white. The black and white Y8 camera data acquisition and LCD display have been successfully completed.
記事全体を表示