Running code from external memory with MCX N94x

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

Running code from external memory with MCX N94x

Running code from external memory with MCX N94x

 

The MCX  N series are MCUs with an integrated flash memory like many traditional MCU series. Having an embedded flash memory is particularly useful, as facilitates board design, development, simplifies BOM, software development.

 However, the size of the embedded flash might not meet applications required memory footprint. Some customers simply need more flash memory. For example, Graphical applications require store large image buffers in a non-volatile memory. Data logger devices that need to store large amounts of data. Or heavy inference models for object recognition.  Applications that need to store backup versions of their firmware or are way too complex and big. To solve this requirement the MCX N94x provides the capability to interface a great variety of wider and external memories. There are several traditional options to expand flash storage, but the one we are addressing is the use of external NOR  flash memories.

To access an external memory the MCX N94x integrates modules that support external memory interfacing, those are  FlexIO and the FlexSPI. The FlexSPI module is capable of communicating with several kinds of memories. One of them is the Serial NOR flash which can be used as booting device.

The goal of this article is to present the solution of a customer case scenario: How to run code from an external flash memory. Demonstrating the flexibility of the MCX N94x platform as well as introducing several tools, peripherals, and concepts that a developer will need to be familiar with while developing an application that runs from an external flash memory.

The below figure illustrates the goal of this article, Run code from an external flash memory. The same hello world application can be run from the internal and external memory, for example, a NOR serial QuadSPI memory, without any functionality changes. The core simply will fetch and execute the instructions, using dedicated peripherals like FlexSPI.

diego_charles_0-1705687146542.png

 

Figure 1 Executing same code from internal memory vs external memory.

The MCX N94x series integrates a FlexSPI module, which enables running code from an external NOR flash memory.

diego_charles_1-1705687146597.png

 

Figure 2 MCX N94x block diagram

To follow this article, you will need the  FRDM-MCXN947 Development board. Which is the evaluation board for the MCX N94x and N54x MCUs. The FRDM-MCXN947 integrates a W25Q64JVSSIQ QuadSPI flash memory. Therefore, this platform is perfect for creating an application that runs from an external flash memory.

Omar_Anguiano_0-1706559642157.png

Figure 3 External NOR flash memory on FRDM-MCXN947

 

Boot, PFR, and SPSDK

 

With the boot ROM  that the MCX  N integrates you can erase, program, and read the on-chip or external flash memory, which means you can use the boot ROM to download a boot image into the on-chip or external flash memory via the ISP interfaces. This article shows how to load a customized led_blinky demo, from the SDK  to the external flash memory using the boot ROM. However, other application projects may be used as well.

Also, the boot ROM takes responsibility for the boot flow. It selects whether to boot from on-chip flash memory, external flash memory, or ISP mode.  The figure below shows an extremely simplified boot flow, which gives an overall understanding of the chip boot flow.  For more details on the boot flow mechanism refer to the section Top-level boot flow of the MCX Nx4x Reference manual.

diego_charles_3-1705687146889.png

 

Figure 4 Simplified boot Flow

After the reset handling routine, the boot ROM will take control of the chip’s boot flow. It will begin with pertinent chip’s initialization. Then will check the status of the ISP pin. If the ISP pin is currently asserted, the ISP boot handling routine will be executed. ISP or  In-system programming is an execution mode where the boot ROM will wait for commands from an external host, over protocols like UART or USB, to do actions like read and write the chip memory, burn fuses, and many more. If the ISP pin is not asserted, the boot ROM will continue to determine the boot mode. Boot mode can be controlled with the CMPA[BOOT_SOURCE] bit of the CMPA of the PFR or eFUSES. If  CMPA[BOOT_SOURCE]= 01b the boot ROM will run FlexSPI NOR boot handling routine. If CMPA[BOOT_SOURCE] is 00b or 11b internal flash memory handling routine is executed. After the boot mode selection, the image will be validated. If it is not valid, for example, is not present in memory, is corrupted, or does not have proper format,  the ISP boot handling routine is executed. If the image is valid, finally the boot ROM will perform the jump to the user´s application.

The default boot flow is by internal flash, most of the SDK examples will be configured to boot from internal flash, as CMPA[BOOT_SOURCE] equals zero by default, or when CMPA area is erased. According to the Simplified bot Flow diagram, we need to make boot ROM go to FlexSPI NOR boot handling routine, to boot from the external flash. Therefore, we need to make   CMPA[BOOT_SOURCE] = 01b.

The PFR holds critical boot and security settings that are monitored by the boot ROM after every reset. As just described earlier, the CMPA area can be used to control boot mode. Therefore, PFR areas need to be carefully configured, as they control boot flow and also security features of the chip. The below figure shows a very minimalistic representation of the PFR containing the CMPA, next to the internal flash.

diego_charles_4-1705687146894.png

 

Figure 5 PFR's CMPA area

 

For specific details of the PFR  please refer to the MCXNx4x_IFR.xlsx, attached to the MCX Nx4x Reference Manual.

To facilitate writing into the CMPA and other areas of the  PFR, signing applications, burning fuses.  programming applications, NXP already developed several host command tools, APIs, and applications and integrated into a python tool called SPSDK. The below figure shows all the tools contained by the SPSDK. To get  details on the SPSDK and description of APIs, Applications, and tools  refer to SPSDK documentation at  https://spsdk.readthedocs.io/en/latest/spsdk.html#

diego_charles_5-1705687146945.png

 

Figure 6 SPSDK API modules, applications, and tools

The above figure highlights 3 applications, provided by the SPSDK,  that is going to be used to configure the chip to boot from the external flash memory those are: nxpdebugmbox, PRF, and BLHOST. Detailed step-by-step usage of these applications will be described later on.

 The nxpdebugmbox application sends interfaces with the chip’s debug mailbox over SWD. The purpose of this tool is set MCU into ISP mode, without having to set low ISP pin,  also to make a mass erase to the chip's memory and PFR. Once the MCU enters ISP mode the host PC will be able to communicate with the boot ROM over UART or USB protocols. This enables the use of PFR and BLHOST applications. The PFR application will be used to write the CMPA[BOOT_SOURCE] = 01b and enable FlexSPI, port to probe and let the chip communicate with the external flash, in the CMPA area of the PFR. The BLHOST application will be used to erase the chip and program application image, in this particular case,  a led_blinky demo.

 

 External Serial NOR flash interfacing

 

The following terms are critical to understand how we can execute code in an external NOR flash memory with the MCX N94x.

First of all, Execute-in-Place refers to the capability that the MCU core has to fetch and execute instructions directly from the external memory. It refers to the capability that an MCU has to execute code from the flash memory instead of an internal and traditional flash.

To do XIP the MCX  N94x requires a capable peripheral with the ability to fetch instructions from the external memory. The FlexSPI module is capable of doing this. The FlexSPI does support several types of external memories. One of them is Serial NOR Flash.

To interface the external memory with the FlexSPI supports SPI. SPI is an excellent serial protocol for short-distance and high-speed communications. The term QuadSPI could be simply understood as an implementation of the SPI protocol, where instead of having a single Data line, there are 4 data lines. SPI also supports two, and eight data lines.

Flexible Serial Peripheral Interface (FlexSPI) memory controller supports connection to external serial NOR, NAND, and RAMs.

It supports two SPI channels and up to four external devices. Each channel supports Single/Dual/Quad/Octal mode data transfer (1/2/4/8 bidirectional data lines).

Flexible sequence engine (LUT table) to support various vendor devices (serial NOR, serial NAND, HyperBus, FPGA, etc).

Memory-mapped read/write access by AHB Bus

  • AHB RX Buffer implemented to reduce read latency. Total AHB RX Buffer size: 1024 Kbytes
  • 8 flexible and configurable buffers in AHB RX Buffer

Software triggered Flash read/write access by IP Bus

  • IP RX FIFO implemented to buffer all read data from External device. FIFO size: 1024 Bytes
  • IP TX FIFO implemented to buffer all Write data to External device. FIFO size: 1024 Bytes
  • DMA support to fill IP TX FIFO
  • DMA support to read IP RX FIFO
diego_charles_6-1705687146973.png

 

Figure 7 FlexSPI block diagram

 

FlexSPI system memory map regions are remapped to different addresses at the FlexSPI sub-module:

diego_charles_7-1705687147022.png

 

Figure 8 FlexSPI memory map

FlexSPI can support serial devices compliant with JESD216.

Pre-requisites

You will need the following Hardware:

  • FRDM-MCXN947 evaluation board.
  • USB C cable.
  • Windows or Linux PC.

You will need to install the following Software.

  • MCUXpresso IDE v11.9.0 or above. 
  • FRDM-MCXN947 SDK v2.15.0 or above. 
  • SPSDK and python. 

 

 SPSDK installation and virtual environment

 

We recommend to run the SPSDK on a python virtual environment, as this simplifies the installation of the SPSDK.

Before proceeding with installation steps for the SPSDK we recommend to create a folder in your computer. This is where the virtual environment will be running, the SPSDK tools will be called,  and all the files generated by the SPSDK will be stored.

  1. Open a terminal, command, or Power Shell prompt  and navigate to your folder and follow the SPSDK installation  commands listed in this guide: Installation Guide — SPSDK documentation

          

  1. To double check installation of the SPSDK run the following command in your virtual environment.

spsdk --version

       

This figure shows the example of this command and the spsdk version used for this document.

diego_charles_9-1705687147030.png

 

Figure 9 SPSDK version.

 Setup

 This chapter describes all steps to generate and boot an image from the external memory.

 To run the commands listed in this document you will need use your python’s virtual environment. Use the virtual environment you created during SPSDK installation.

 PFR settings

This section describes the settings that need to be done in the MCX N94x PFR and bootable image.

 

     Create CMPA and CFPA yaml  templates

 
In the following steps, we are going to focus on editing CMPA area since it contains boot-related fields for external execution.  CFPA area is not required to be edited.           

Note:The commands used to generate the templates are based on ‘pfr’ tool  For details on the capabilities of these commands, visit: User Guide - pfr — SPSDK documentation

First we are going to use pfr to create our yml CMPA/CFPA templates. These templates contain only the default configurations specified for the CMPA and CFPA areas of  device.

If the command run successful the templates will be generated. As shown in figure this figures

diego_charles_10-1705687147034.png

 

Figure 10 Yaml template created.

 

Edit the CMPA and CFPA yaml templates

 

Open CMPA   template in any text editor and follow the below steps.

  1. Set DEFAULT_BOOT_SOURCE to FLEXSPI_FLASH_XIP_0b01
  2. Set FLEXSPI_AUTO_PROBE   to ENABLE
  3. Save the changes in the CMPA template.

     Create and write the  CMPA and CFPA binaries

 

      After editing the cmpa yaml, you will generate the CMPA/CFPA binaries from the yml templates.

 

  Import and edit image

 

This section shows how to create an XIP bootable image from the  MCUXpresso SDK  led_blinky example.

 

  1.  Import the led_blinky demo from the SDK.  Click on “Import SDK example(s)…” (1), then search and select the FRDM-MCXN947 (2), and click “Next” (3). Inside the “SDK import wizard” search and select the “led_blinky  demo (4) and click on “Finish” (5)
diego_charles_13-1705687147301.png

 

 

Figure 11 Import the blinky example.

 

 

  1.  Once the demo project is imported open the project properties. Do a right-click in the project’s name (1), then click on “Properties” option (2) and open the project properties(3)
diego_charles_14-1705687147391.png

 

Figure 12 Project ´properties

  1. Navigate to the Properties> C/C++ Build > MCU settings section

 

 

diego_charles_15-1705687147439.png

 

Figure 13 MCU settings window

  1. Make sure that there are two  Flash areas for the external memory: QSPI_FLASH and             QSPI_FCB as shown in Figure 14. If the areas are missing add them as shown in the next step.

 

diego_charles_16-1705687147459.png

 

Figure 14 External flash areas in the linker.

 

 

  1. Add the two flash areas for the  QSPI_FLASH and QSPI_FCB in the “Memory details” table, the move them to the Top.  Click in “Add Flash”  (1) twice, then click on “Move selected memory up in table” (2), the two newly created flash areas should be placed at the top.
diego_charles_17-1705687147485.png

 

Note: Moving a memory area to the top of the “Memory details” table indicates the linker that text and data should be placed preferably in that area.

  1. Update the newly created flash areas name and parameters with the ones from the below table.

 

Type

Name

Alias

Location

Size

Driver

Flash

QSPI_FLASH

Flash

0x80001000

0xFFFF000

MCXN9xx_SFDP_FlexSPI.cfx

Flash

QSPI_FCB

Flash 2

0x80000400

0x400

MCXN9xx_SFDP_FlexSPI.cfx

 

  1.   Make sure that the flash areas match the ones shown in the Figure 15.

 

diego_charles_18-1705687147517.png

 

Figure 15 Configured flash areas

 

  1.  Click “Build” (1), once compilation is finished, should return 0 errors (2).
diego_charles_19-1705687147573.png

 

Figure 16 Successfully compiled image.

                                     Note: You should see that the QSPI_FLASH section is being used and that the PROGRAM_FLASH section is not.

  1. Generate the binary. Navigate to the project’s debug folder and locate generated .axf (1). Then do a right-click in the .axf, and click on Binary utilities > Create Binary.
diego_charles_20-1705687147637.png

 

Figure 17 Create binary.

 

7 The binary should appear in the debug folder. Get  easily get the binary location by doing a right click on the binary and navigating to  “Show in>System Explorer”

diego_charles_21-1705687147691.png

 

Figure 18 Get created binary with ease.

  1. 8. Paste the binary into the workspace where you created the cmpa_bin.bin. This step is only to simplify the commands shown later on.

 

Erase and ISP mode entry     

 

ISP (In system programming ) is a mode where a host is able to instruct the ROM bootloader to program a new image or the PFR. The which holds the CMPA field with our configuration to do XIP from the external flash memory. Basically, the Host computer sends commands to the ROM bootloader to program the PFR using NXP’s BLHOST.

To enter into ISP mode there are two options: ISP pin entry and Debugger mailbox. ISP pin entry requires keeping ISP pin asserted during reset sequence and de-asserting this pin after reset has been completed. Debugger mailbox only requires to use of a SWD debugger to make the ROM entry ISP mode.

To enter into ISP mode over ISP pins follow is necessary keep ISP pin asserted during reset sequence and de-assert this pin after reset has been completed. To use the debugger mailbox is only needed having a debugger.

For simplicity, the communication protocol will be USB. However, UART can be used as well.

  1. Erase the flash memory and enter ISP mode using the nxpdebugmbox. Proceed to run each command

nxpdebugmbox erase
 nxpdebugmbox ispmode -m 0

 

This figure shows the expected output when running the two commands from above.

diego_charles_22-1705687147824.png

 

This operation will erase the contents on the internal and external flash memory. Also the PFR contents. Repeating this operation can be useful to get the chip to boot from internal flash memory.

Note:  nxpdebugmbox commands need to be run using a SWD-JTAG debugger. For this example on-board debugger of the FRDM-MCXN947 is used.

Ping rom Bootloader

 Run the following command to ping the rom Bootloader, this way we can ensure that the device was set correctly in ISP mode.

blhost  -t 2000 -p COMxxx,115200 -j -- get-property 1

 

diego_charles_23-1705687147880.png

 

Figure 19 Ping rom Bootloader

From now on, an external debugger is not strictly required. The communication with the rom bootloader can be done over UART or USB. For simplicity, the UART protocol-based commands are used from now on in the rest of this document.

Write  image and PFR and run demo

 

We are going to follow the steps to write image. 

1 Write CMPA binary.

pfr write -p COMxxx,115200 -t cmpa -f mcxn9xx -b cmpa_bin.bin

 

2 Write CFPA binary.

pfr write -p COM140,115200 -t cfpa -f mcxn9xx -b cfpa_bin.bin

 

3 Provide FlexSPI flash memory configuration

blhost  -t 2000 -p COMxxx,115200 -- fill-memory 0x20000000 0x04 0xc0000405

 

4 Configure and fill memory.

blhost  -t 2000 -p COMxxx,115200 -- configure-memory 0x09 0x20000000

blhost  -t 2000 -p COMxxx,115200 -- fill-memory 0x20003000 0x04 0xf000000f

 

5 Erase flash

blhost  -t 2000 -p COMxxx,115200 -- flash-erase-region 0x80000000 0x100000

 

6 Configure memory.

blhost  -t 2000 -p COMxxx,115200 -- configure-memory 0x09 0x20003000

 

 7 Write image.

blhost  -t 2000 -p COMxxx,115200 write-memory 0x80001000 frdmmcxn947_led_blinky.bin

 

8 Reset.

blhost  -t 2000 -p COMxxx,115200 reset

You might use this command or directly press the reset button from the FRDM board.

The below image shows the successful execution of each command. Your FRDM-MCXN947  should be blinking by now.

diego_charles_24-1705687147891.png

Figure 20 Successful image write and reset.

Once the board is reset you will notice that the loaded example will begin to execute.

 

 Double-check execution from external flash

 

 To double-check that the image is executing from the external flash you can use the disassembly view from MCUXpresso.


1  Attach the debugger to the running target and place a breakpoint at any part of the code.

diego_charles_25-1705687147949.png

 

Figure 21 Attach debugger to a running target.

  1. Once your debug probe is discovered, click “OK.”
diego_charles_26-1705687147965.png

 

  1. Halt the processor execution. Use the debug button.
diego_charles_27-1705687147980.png

 

Figure 22 halt execution.

  1. Reset processor. Use the “Restart button”. The program should be stop at the first line of the main function.
diego_charles_28-1705687148022.png

 

Figure 23 Breakpoint at main.

  1. Find and open the disassembly view. Click on “Instruction Stepping Mode” button or search for disassembly. Any option will open the MCUXpresso “Disassembly” view.
diego_charles_29-1705687148087.png

 

Figure 24 Open "Disassembly" view

  1. Processor must be running at 0x8000_0000 address space. On the disassembly view you can check that the instructions are executed from address on the range of 0x8000_xxxx which is assigned for external flash.
diego_charles_30-1705687148158.png

 

Figure 25 Running code from external flash.

If you want to return the device to run from internal memory, then you need to go back to default values. If there are no modifications, to the ones shown in this document,  to the CMPA and CMPA areas, the nxpdebugmbox command can be executed.

 

 

 

100% helpful (3/3)
Version history
Last update:
‎02-06-2024 09:56 AM
Updated by: