on 2025-12-22 10:00 AM
This article continues the practical guide on integrating and debugging external memory with STM32 MCUs, focusing on firmware configuration, initialization, and comprehensive validation techniques. It highlights key firmware settings, middleware usage, and debugging strategies to ensure robust and reliable external memory operation in real-world applications.
Building on the hardware verification and memory device understanding covered in part 1, this second part dives into the firmware aspects critical to successful external memory integration. Proper firmware configuration translates memory datasheet specifications into working code, ensuring correct timings, modes, and command sequences. Additionally, thorough debugging and validation practices help confirm system stability and performance. This guide also introduces ST’s middleware tools designed to simplify and accelerate development with external memory on STM32 MCUs.
In part 1, we covered the first two essential steps of the external memory integration and debugging process: understanding your memory device and performing hardware-level verification. In this second part, we continue with steps 3 and 4 firmware configuration and initialization, followed by debugging and validation. Together, these stages complete the systematic approach needed for reliable and robust external memory operation on STM32 MCUs.
It’s easy to assume that if the hardware is correct, the rest is just a matter of “turning it on” in software. But with external memory, the firmware is responsible for translating the memory’s datasheet into real, working configuration timings, modes, and command sequences. Even a small mismatch (like an off-by-one timing parameter or a missed initialization step) can make the difference between a system that works and one that fails silently or intermittently.
Firmware-level checks are about bridging the gap between the physical world and the digital one. They ensure that the MCU and the memory are truly speaking the same language, and that every transaction is happening as intended. Debugging at this level is not just about fixing bugs, it’s about building confidence that your system is robust, reliable, and ready for production.
If you follow this checklist and leverage the debug output, you’ll be able to quickly identify and resolve most firmware-level issues with external memory on STM32. ST offers an external memory manager and external memory loader middleware (EMM/EML) for flash-less MCUs, featuring an API that supports access to various memory types, enables launching applications stored in external memory, and generates external memory loader files. If you need more guidance about the middleware, our wiki article is a great place to start.
Using the MX25U25645G as an example, here’s a correlation table for NOR FLASH timing parameters and how they map to STM32CubeMX external memory loader, manager, and XSPI settings.
|
Datasheet parameter |
Datasheet symbol/section |
Typical value (MX25U25645G) |
STM32CubeMX EML/EMM/XSPI setting |
Notes |
|
Max SPI clock |
fSCLK, Table 23: AC characteristics (see above) |
166 MHz |
Clock configuration → XSPI XSPI configuration → clock prescaler |
Set XSPI clock ≤ max value. For 133 MHz, prescaler = (kernel clock / 133 MHz) - 1. The XSPI AXI clock (xspi_aclk) has to be greater or equal than the XSPI kernel clock (xspi_ker_ck). |
|
Page size |
Table 14: SFDP Table Page Program Size Notes & Data |
256 bytes |
EML → Page Size |
Set to 256 bytes for program operations. |
|
Sector size |
Section 1: Features - General |
4 KB, 32 KB, or 64 KB |
EML → Sector Size |
Use 4 KB for finer erase granularity, 64 KB for faster bulk erase. |
|
Number of sectors |
Section 5: Memory Organization |
8192 for 4 KB sectors, 1024 for 32 KB sectors, 512 for 64 KB sectors |
EML → Number of Sectors |
Calculation: Memory size / sector size = Number of Sectors |
|
Memory size |
Page 1 |
256 M-Bit = 32 MB (megabytes) |
XSPI → Memory Size |
|
|
Page program time |
tPP, Table 23 |
Typ 0.15 ms, max 0.75 ms |
EML → Program Page Timeout |
Set value in STM32CubeMX 1-2ms over the datasheet value for margin. CubeMX default is often much higher (for example, 10 s) |
|
Sector erase time |
tSE, Table 23 |
Typ 25 ms, max 400 ms |
EML → Erase Sector Timeout |
Set to 500 – 1000 ms for margin. CubeMX default is often much higher (e.g. 6s). |
|
CS# deselect time |
tCSH |
From Read to next Read 7 ns. |
XSPI → Chip Select High Time Cycle |
CSHT + 1 defines the minimum number of CLK cycles where the chip-select (NCS) must remain high between commands issued to the external device. CS# Deselect time indicates the minimum time CS# must be high between commands. |
|
CS# Setup/Hold |
tCSS, tCHSH, Table 23 |
Min 3 ns for each setup and hold |
Not user settable |
Handled by XSPI hardware |
|
Clock high/low tsime |
tCH, tCL, Table 23 |
tCH and tCL are the same: Others (fSCLK) 45% x (1/ fSCLK) ns Normal Read (fRSCLK) 7 ns |
Not user settable |
The XSPIs must provide a clock to the external memory, with a duty cycle distortion generally lower than 5%. To reach this requirement, the kernel clock provided to the XSPIs has a typical duty cycle of 50%. |
|
Data valid after SCK |
tV, Clock Low to Output Valid, Table 23 |
Varies based on memory package and capacitive loading; anywhere from 4 ns to 8 ns |
XSPI → Sample Shifting and/or XSPI → Delay Hold Quarter Cycle (DHQC) |
tV tells you how long after the clock edge the NOR Flash guarantees valid data. If the SPI/XSPI clock is fast, you may need to enable Sample Shifting or DHQC in XSPI configuration to delay the sampling point. This ensures the MCU read valid data after tV has elapsed. |
|
Output disable time |
tDIS, Table 23 |
Max 8 ns |
Not directly settable |
Handled by XSPI peripheral; ensure not sampling too soon after CS# deassertion. |
|
Wrap size |
Not supported by this memory chip |
N/A |
XSPI → Wrap Size |
Wrap size is a feature used in some high-speed memory devices to optimize burst read/write operations, especially for XIP (eXecute In Place) and cache line alignment. |
|
I/O lines |
Pin Description, Table 2 |
1, 2, or 4 (QUAD) |
XSPI → Mode EMM → Number of Memory Data Line |
XSPI Mode à Quad SPI |
|
SPI mode |
Section 1: Features - General |
Mode 0 and Mode 3 |
XSPI → Clock Mode Low or High |
SPI Modes are defined by two parameters, Clock Polarity (CPOL) and Clock Phase (CPHA) that indicate what value means the clock is idle and when data is sampled. Mode 0 has both low, where Mode 3 has both high. As this device supports both, you can use either as long as the master and slave use the same mode. |
|
SFDP support |
Section 1: Features - General |
Supported |
EMM → Driver Type: NOR SFDP |
Use SFDP for autoconfiguration, but always verify detected parameters. |
Find the screenshots of the STM32CubeMX settings for "XSPI", "External Memory Loader", and "External Memory Manager" below:
/**
* @brief Retargets the C library printf function to the USART.
* None
* @retval None
*/
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
/* Private functions ---------------------------------------------------------*/
void EXTMEM_TRACE(uint8_t *Message) {
printf("%s", Message);
fflush(stdout);
}
#if defined(DEBUG_TRACE)
extern void EXTMEM_TRACE(uint8_t *Message);
/*
* @brief definition of the debug macro
*/
#define EXTMEM_MACRO_DEBUG(_MSG_) EXTMEM_TRACE((uint8_t *)_MSG_)
/*
* @brief debug level of the different layers
*/
#define EXTMEM_DEBUG_LEVEL 3
#define EXTMEM_DRIVER_NOR_SFDP_DEBUG_LEVEL 3
#define EXTMEM_DRIVER_PSRAM_DEBUG_LEVEL 0
#define EXTMEM_SAL_XSPI_DEBUG_LEVEL 0
#endif /* defined(DEBUG_TRACE) */
Now, you can use this custom external loader for your Boot and Appli projects!
Before moving on to debugging and validation, it’s important to recognize that even with careful hardware and firmware setup, real-world systems can still present unexpected challenges. Debugging is where you bring together your understanding of the memory device, your board, and your firmware to systematically verify that every part of the system is working as intended. This stage is about finding faults, confirming that your design is robust, your assumptions are correct, and your system is ready for real application use. Effective validation ensures that your external memory interface will be reliable in the lab and in the field.
Successfully debugging external memory on STM32 MCUs requires a systematic approach that combines thorough hardware verification, precise firmware configuration, and comprehensive validation. By understanding the unique characteristics of your memory device, carefully checking signal integrity and power stability, and leveraging ST’s middleware debug tools, you can efficiently identify and resolve issues that might otherwise cause subtle or intermittent failures. Following this guide and checklist helps you build confidence in your design, reduce development time, and ensure reliable operation of external memory in your application in the lab and in the field.