i.MX RT685 SuperMonkey – QSPI Bring-up with MCUXpresso and Segger Ozone

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

i.MX RT685 SuperMonkey – QSPI Bring-up with MCUXpresso and Segger Ozone

Eli_H
NXP Pro Support
NXP Pro Support
2 0 3,684

In my prior article series, I detailed some important points when executing a hardware design with the i.MX RT685 crossover MCU.   The overarching goal was to illustrate a minimal configuration project which allows the CPU to boot with simple QSPI flash and the simplest power configuration.     As with all my content, I like to show the result as a realized piece of hardware, not just a theoretical exercise.   There is much to be learned during the actual execution of the design.    

In this article, I will show the realized design and illustrate board bring-up with a QSPI device.  There are some differences in the software project setup that need to be considered when transitioning from the RT685-EVK which uses an Octal Flash device connected FlexSPI Port B.

Eli_H_0-1635798852532.png

Figure 1.  The i.MX RT685 SuperMonkey

You can find source files for the hardware design on GitHub:

https://github.com/ehughes/rt_super

SuperMonkey Board Build

 

The SuperMonkey PCB design details are in Part 3 of the i.MX RT685 design articles.   For board fabrication and assembly, I used CircuitHub. CircuitHub handles all aspect of the fabrication process.   All you need to do is upload your design files and CircuitHub will acquire the raw PCBs, procure the components and stuff the boards.   The CircuitHub workflow also allows for consigned parts.    Given the current situation with the supply chain, this was a welcome feature.   I was able to send them some of the parts that were not available through normal channels as I had “banked” a few of the components several months ago.

The specs for this board have a small drill requirement (6mil) and a tight annual ring (3mil).   This drill geometry was used for filled via-in pad technology on the VFBGA176.    I chose this approach for fanning out the VFBGA176 package as it enabled looser specs on trace space/width.   The RT685-EVK did not use via-in-pad technology rather a 3mil trace space/width for escaping some of the signals.  I elected to use filled via-in-pad approach after some discussion with CircuitHub.   The end result was a fairly simple routing exercise on 4-layers. I do also want to point out that this design made use of 0201 sized decoupling capacitors.    The 0201 decoupling capacitors were placed on the bottom side of the board directly under the RT685 MCU.

Eli_H_1-1635799210361.png

 Figure 2.  0201 Decoupling Capacitors

 

I usually try to use packages that are as large as possible to ease manufacturing but in this case I elected to use an 0201 size capacitor to experiment with the “perfect 0201” land pattern provided by Chris Denny of Worthington Assembly.  I believe with some work, 0402 size capacitors could be used with the RT685 to relax manufacturing tolerance.   On my next project with the RT685, I may use a smaller number of 0402 0.22uF decoupling caps in place of 0201 sized 0.1uF decoupling caps.  

The simplest approach to providing power to the RT685 is using the NXP PCA9420BSAZ PMIC. The PCA9420BSAZ comes in an interesting QFN that also requires a soldered connection at the corners of the device package.

 

Eli_H_3-1635799442452.png

Eli_H_2-1635799436426.png

 Figure 3.  The PCA9420 PMIC for the i.MX RT685

Using a service such as a CircuitHub saved a lot of time and hassle as I did not have to worry about manually placing and reflowing these parts.  While the RT685 in the VFBGA176 is not at the extremes of package technology, I will gladly delegate the assembly work to a 3rd party to ensure success on the first attempt. 

i.MX RT685 Bring Up with QSPI Flash

 

The i.MX RT685 is a flashless MCU.  An external flash device is required for boot, or you need some other mechanism for loading code in the RAM.   The RT685-EVK uses an Octal Flash connected to FlexSPI port B.    Octal flash technology is still quite new to the MCU scene, and I really wanted to show an example of using lower cost (and better availability) QSPI Flash.     In many cases QSPI will be a suitable choice as code that needs high performance can be executed from the copious supply of internal SRAM in the RT685.     The RT685 implements a cache on the FlexSPI interface so execution from external memory is still acceptable for many applications.   Another consideration is that if a design requires access to all 8-DMIC channels, FlexSPI Port A must be used for code storage.  My intent was to design the SuperMonkey as a reference for using a QSPI device on FlexSPI port A.

Reviewing the Hardware Connections

 

What I personally love about QSPI is its simplicity.   For the SuperMonkey, I used a low cost 8MiB Winbond QSPI flash memory which only requires 6 connections.     I elected to use +3.3v on all I/O banks.   This means the QSPI flash is powered from +3.3v.    The i.MX RT685 EVK uses +1.8v IO for the Octal Flash connection.    The RT685 is very flexible in its power supply configuration which can be potentially daunting during the initial design phase.    The +3.3v QSPI flash represents the simplest use case.

Eli_H_0-1635800463274.png

 Figure 4.  i.MX RT685 QSPI Connections

At powerup, the RT685 executes boot code from ROM.   The bootloader is configurable and requires the boot source to be specified via three ISP pins.  It is important to leave the ability to select other boot sources.     In addition to booting from external flash, there is boot mode that uses a USB or a serial connection to programing internal fuses and perform production programming operations.    I find that indicating the boot options on the schematic is a good design practice to ensure the other utility boot modes do not get overlooked.

 

The RT685 Boot Header

 

From the build tooling perspective, there are a couple changes that are necessary to use QSPI flash with the RT685.     You can use an MCUXpresso SDK example project as a starting point even though it is configured to use octal flash.   The RT685 ROM bootloader will attempt to access an external device on FlexSPI A or B (depending on the ISP[2:0] pins) using a 1-bit IO mode.     A special data structure, the boot header, is to be located at a 0x400 byte offset from the start of external flash.  This boot header provides additional configuration details to the bootloader about the attached flash device.   All the example RT685 projects in the MCUXPresso SDK have a boot header for suitable for an octal flash device.  You can find the boot header in flash_config/flash_config.c and it will need to be modified to support QSPI boot.

 

Eli_H_1-1635801819192.png

 Figure 5.  Boot Header Location In Source

 

If you dig into the linker file generated by the build tools,   it specifies a special section that is placed in the QSPI memory region.   Note that the .ld linker files are automatically generated by default by MCUXpresso and placed in the build configuration output folder (for example, “debug”).   

Eli_H_2-1635801865698.png

 Figure 6.  Boot Header Placement with the Linker

Here is an example of a functional QSPI boot header:

 

/*
 * Copyright 2020 NXP
 * All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */
#include "flash_config.h"
#include "board.h"

/* Component ID definition, used by tools. */
#ifndef FSL_COMPONENT_ID
#define FSL_COMPONENT_ID "platform.drivers.flash_config"
#endif

/*******************************************************************************
 * Code
 ******************************************************************************/
#if defined(BOOT_HEADER_ENABLE) && (BOOT_HEADER_ENABLE == 1)
#if defined(__ARMCC_VERSION) || defined(__GNUC__)
__attribute__((section(".flash_conf")))
#elif defined(__ICCARM__)
#pragma location = ".flash_conf"
#endif

const flexspi_nor_config_t flexspi_config = {
    .memConfig =
        {
            .tag                 = FLASH_CONFIG_BLOCK_TAG,
            .version             = FLASH_CONFIG_BLOCK_VERSION,
            .csHoldTime          = 3,
            .csSetupTime         = 3,

            .waitTimeCfgCommands = 1,

            .controllerMiscOption =
                (1u << kFlexSpiMiscOffset_SafeConfigFreqEnable),
            .deviceType    = 0x1,
            .sflashPadType = kSerialFlash_4Pads,
            .serialClkFreq = kFlexSpiSerialClk_SDR_48MHz,
            .sflashA1Size  = 0x1000000,
            .sflashA2Size  = 0,
            .sflashB1Size  = 0,
            .sflashB2Size  = 0,
            .lookupTable =
                {
                    /* Read */
                    [0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
                    [1] = FLEXSPI_LUT_SEQ(DUMMY_SDR, FLEXSPI_4PAD, 0x06, READ_SDR, FLEXSPI_4PAD, 0x04),

                    /* Read Status */
                    [4 * 1 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),

                    /* Write Enable */
                    [4 * 3 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP_EXE, FLEXSPI_1PAD, 0x00),

                },
        },
    .pageSize           = 0x100,
    .sectorSize         = 0x1000,
    .ipcmdSerialClkFreq = 1,
    .blockSize          = 0x10000,
};
#endif /* BOOT_HEADER_ENABLE */

 

Once the boot header is built into your image, the RT685 becomes “stand-alone” after a power cycle.    Note that if your project does not have a boot header, or if it is not valid, the ROM bootloader will jump to USB/serial downloader mode.      There are tools, such as

https://github.com/JayHeng/NXP-MCUBootFlasher

that can also generate a boot header as well as place it in the proper location in flash.  I personally like to bake it into the C source code so the project is “bootable” without any additional steps. 

 

MCUXpresso Flash Programming Configuration

 

Once the MCUXpresso is able build a valid, bootable image we need a method to program it.    One approach is to use the serial/USB downloader build into ROM. I prefer like to use a debugger tool over the SWD port.  There are several options available, but I want to present two that can perform flash programming and debugging over the SWD connection

MCUXpresso + MCU-Link

 

MCUXpresso is capable of programming QSPI flash on the RT685 with the low-cost MCU-Link debug adapter.    This is a path for quick success but requires a change to the MCUXpresso project to indicate the type of flash connected and the FlexSPI port.

Eli_H_0-1635802564585.png

 Figure 7.  QSPI Flash Programming Driver in MCUXpresso

Ensure that  “MIMXRT600_FlexSPI_A_SFDP_QSPI.cfx” is selected as the “Driver” for the flash region.    Once this change is made,  you can simply start a debug session and MCUXpresso will be able to program a QSPI flash connected to FlexSPI port A.

mcux.jpg

mcux.gif

 Figure 8.  Programming and Debug with an NXP MCU-Link Probe

 

Segger J-Link + Segger Ozone

 

A tool that has become a favorite in my arsenal is Segger’s Ozone Debugger.    It is a full featured source level graphically debugger designed to work with a Segger J-Link.  All you have to do is point to your .elf or .axf file and Ozone handles the rest.  I have found Ozone to be a great option as it is very fast,  can inspect variables without halting the MCU and works with all of NXP’s ARM MCUs.   I discovered it back in 2014 were I needed a better way of performing dual core debugging on the NXP LPC4357 and have been using it ever since.

When setting up an Ozone project, there are a couple of setting that are required for working with the i.MX RT685.  Per Segger’s Wiki Article for the RT600, use the MIMXRT685SFAWBR device when your flash device is on FlexSPI port A.

Eli_H_0-1635812708865.png

 Figure 9.  Segger i.MX RT685 QSPI on FlexSPI Port A Setup

Also per Segger’s Wiki Article working on with a bootloader,   make sure to uncomment  AfterTargetDownload() and AfterTargetReset(). 

Eli_H_1-1635812740132.png

I leave the Exec.Reset() to make sure to reset the CPU after programming so the ROM bootloader can take over.  Lastly, make sure TargetReset() is left commented outEli_H_2-1635812754592.png

I did find that the built in programming algorithm the J-Link seems to not erase used/dirty sectors.     I added a "full target erase" command to fix the issue.

Eli_H_1-1639406443541.png

**Note**   The need for "Target.EraseChip"  was fixed as of J-Link Software version V7.65A.   See Here:

https://community.nxp.com/t5/i-MX-RT/i-MX-RT685-QSPI-Port-A-Segger-Flash-Programming-Fix/m-p/1440741...

An alternate programming algorithm was suggest here:

https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/RT600-MCUXpresso-JLINK-debug-QSPI-flash/ta-p/134...

These steps are important so that the ROM bootloader functions in i.MXRT685 are not interfered with after the flash is programmed and the target is reset. Once we have a working boot header and the ability to program the board, the first order of business is to toggle an IO pin.  My first test program toggled a couple IO every 50mS.

jlink.jpg

ozone.gif

Eli_H_3-1635812876615.png

 Figure 10 .  Programming and Debug with a Segger J-Link and Segger Ozone.

At this point, we have successfully brought up the RT685 with QSPI on FlexSPI port A and successfully have toggled an IO.  From here I can start working on IO interfaces, increase clock rates to the various subsystems, etc.   I hope this article series has been helpful in introducing the i.MX RT685 and showing a simple configuration.       In case you missed them, here are links to previous content on the i.MX RT685.    I hope you find the information helpful and are successful with your own i.MX RT600 based project.

Links:

Crossing Over With the i.MX RT600 Part 1 of 2

Crossing Over With the i.MX RT600 Part 2 of 2

i.MX RT685 Hardware Design 1 of 3 - Power and Package

i.MX RT685 Hardware Design 2 of 3 - Flash Memory and Boot Configuration

i.MX RT685 Hardware Design 3 of 3 - The SuperMonkey Design

i.MX RT685 SuperMonkey QSPI Bringup with MCUXpresso and Segger J-Link

Creating a Custom Zephyr Board for the i.MX RT685 SuperMonkey 

Tags (1)