2024-10-15 11:33 AM
Hello all,
I have a very strange issue with QSPI peripheral. I am using it to store logs in external memory.
The flash that is used is MT25QL256ABA with a custom STM32WB55 board. I have connected PModSF3 using jumper wires that are at least 15cm long.
Issue: When I use the FAST READ (single data line, 1-1-1 mode), it works perfectly fine. I am able to validate it with the hex dump of a buffer that writes ASCII (0-9). But when I use it in QUAD OUTPUT FAST READ (1-1-4), I get some missing data that is probably shifted.
I have specified two dummy cycles based on the datasheet. Tried increasing it, does not make much of difference.
But reducing the clock speed by a factor of 100 seems to help, but then quad mode is useless.
The code is based mostly from the ST examples.
Can anyone help me in figuring out the issue? I can provide more data if needed.
static bool qspi_flash_read_fast_single_line(size_t address, uint8_t* pBuf, size_t length)
{
QSPI_CommandTypeDef sCommand;
dummy_cycles_cfg(&hqspi);
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
//! Send read command (Does not work)
sCommand.Instruction = 0x6B;
//! Address configuration
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;
sCommand.Address = address;
sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ; //< Two dummy cycles
//! Receive data configuration
sCommand.DataMode = QSPI_DATA_4_LINES;
sCommand.NbData = length;
if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
CONSOLE_LOG("Failed to send read command");
return false;
}
if (HAL_QSPI_Receive(&hqspi, pBuf, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
CONSOLE_LOG("Failed to receive data in quad mode");
return false;
}
return true;
}
2024-10-15 01:20 PM
Shouldn't a 256Mb / 32MB device be in a 4-byte / 32-bit addressing mode?
It's going to be a problem if the device configuration and peripheral configuration disagree.
If the read is too fast, you'll need to configure and use more dummy cycles so it can prefetch sufficiently quickly
2024-10-16 02:32 AM - edited 2024-10-16 02:34 AM
Hi @Tesla DeLorean,
Thank you for the reply!
This external flash also has a 3-byte addressing mode too. With which the upper or lower 128Mb can be used based on the configuration in volatile registers. I have interfaced this flash in SPI mode, it works really well.
Only the QSPI interface has issues when used in 1-1-4 mode.
I have increased the Dummy cycles from 2 to 10, yet there is no difference. Should I go even higher?
2024-10-20 04:30 AM
Another strange thing that I have observed when using Quad (1-1-4) addressing is that, when I write the same byte, the contents are perfectly read back.
stm32wb>qspi.flash.validate 0x00 256
| CONSOLE | QSPI flash sector erased at address 0x00000000
0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
10 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
20 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
30 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
40 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
50 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
60 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
70 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
80 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
90 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
A0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
B0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
C0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
D0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
E0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
F0 | AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA AA | ................
| CONSOLE | Flash contents are identical
[OK]
stm32wb>qspi.flash.validate 0x00 256
| CONSOLE | QSPI flash sector erased at address 0x00000000
0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
10 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
20 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
30 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
40 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
50 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
60 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
70 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
80 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
90 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
A0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
B0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
C0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
D0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
E0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
F0 | 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 | UUUUUUUUUUUUUUUU
| CONSOLE | Flash contents are identical
[OK]
To generate the above pattern, I have used a loop to write to a buffer. This buffer is written to the QSPI flash.
ok &= QSpiFlash_Erase(address, len);
for (int i = 0; i < len; i++)
{
pMemBufWrite[i] = (uint8_t) 0x55; // or 0xAA
}
ok &= QSpiFlash_Write(address, pMemBufWrite, len);
ok &= QSpiFlash_Read(address, pMemBufRead, len);
if (ok)
{
Utils_HexDump(address, pMemBufRead, len);
}
When the bytes are different (random), it fails to read. Almost seems like the data lines are pulled up and they stop working. The idea behind writing 0xAA or 0x55 is to see if all the lines are working as expected. Which to me seems like it is working well.
----------------------------------------------------------------------------------
Now, when I change the code to write an arbitrary pattern, it fails.
for (int i = 0; i < len; i++)
{
pMemBufWrite[i] = (uint8_t) i % 100;
}
stm32wb>qspi.flash.validate 0x00 256
| CONSOLE | QSPI flash sector erased at address 0x00000000
0 | 00 01 02 03 04 05 06 07 80 0A B0 00 0F FF FF FF | ................
10 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
20 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
30 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
40 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
50 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
60 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
70 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
80 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
90 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
A0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
B0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
C0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
D0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
E0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
F0 | FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF | ................
| CONSOLE | Failed to compare flash contents
[OK]
I can't seem to reason on why it fails for such a pattern.
Can anyone from ST please look into it?
2024-10-20 06:31 AM
>>Can anyone from ST please look into it?
I don't see that happening. The problem is almost certainly on your end. You'd need to provide code that would readily demonstrate failure, Ideally on an existing hw platform.
Discuss with your local rep or FAE (support engineer), assigned to your account.
>>I have connected PModSF3 using jumper wires that are at least 15cm long.
That does seem excessively long, the fixtures I've built are at least half that length, and wire-wrapped, not sketchy dupont wiring. For push fit connections perhaps look at Schmart jumper wires.
Are you sure the problem is on the read side? Is the read-back pattern consistent?
Could be an issue on the write? That wouldn't need dummy cycles, but does need bus integrity.
I tend to write a predictable pseudo-random sequence under known conditions, perhaps via programmer or in 1-1-1 modes, and then validating all the read methods (1,2,4-bit) against the gold-rom.
2024-10-20 06:35 AM
https://digilent.com/shop/pmod-sf3-32-mb-serial-nor-flash
https://schmartboard.com/jumper-wires/
2024-10-20 08:09 AM
Thank you for the reply!
@Tesla DeLorean wrote:That does seem excessively long, the fixtures I've built are at least half that length, and wire-wrapped, not sketchy dupont wiring. For push fit connections perhaps look at Schmart jumper wires
I suspect this issue, I will verify this once I have the custom PCB made with QSPI flash integrated on it.
@Tesla DeLorean wrote:Are you sure the problem is on the read side? Is the read-back pattern consistent?
Read pattern is not consistent in 1-1-4 and 1-1-2 modes, it reads different characters (only when the data bytes are not same). When the data bytes are of the pattern (0x00 to 0x64) only the first 10 or so bytes are correct, the rest are incorrect or 0xFF.
@Tesla DeLorean wrote:Could be an issue on the write? That wouldn't need dummy cycles, but does need bus integrity.
I tend to write a predictable pseudo-random sequence under known conditions, perhaps via programmer or in 1-1-1 modes, and then validating all the read methods (1,2,4-bit) against the gold-rom.
I have verified the write pattern in 1-1-1 mode, and works without issues. Data comparison always succeeds.
The pattern I wrote are bytes from 0x00 to 0x64 and repeating up to a specified length. This pattern works in 1-1-1 mode. I have compared it via hexdump (Visually) and memcmp and both validate the writes.
P.S - Write function is unchanged between different read modes.
Thank you for the links mentioned below. I have the same board from Digilent, I will give a try to the 5" jumpers.
2024-10-20 08:59 AM
So perhaps clock phase or edges? Especially as the data desync's as you proceed.
This is a MT25 not a older N25 ?
I linked for thread context, mainly to confirm what you wired. I didn't find a circuit diagram, assuming pull-ups on the signals.
I tend to use ZIF fixtures so I can test different parts readily.
2024-10-20 09:26 AM
@Tesla DeLorean wrote:So perhaps clock phase or edges? Especially as the data desync's as you proceed.
I can only assume so, as I do not have a logic analyzer to debug it. But what would be the reason that all the IO lines stay at logic high (resulting in 0xFF)?
> This is a MT25 not a older N25 ?
Yes, it is MT25. Although the schematic mentions otherwise.
I have attached a PDF of the schematic. PFA.
> I linked for thread context, mainly to confirm what you wired. I didn't find a circuit diagram, assuming pull-ups on the signals.
Ah okay! In the schematic, only IO2 and IO3 are pulled up.
Do you happen to have the part number for the ZIF socket shown in the picture?
2024-10-20 10:26 AM
Pretty generic SOIC16W to DIP16, 1.27-mm pitch, 300-mill / 7.5-mm width
Sourced mine via eBay / AliExpress, perhaps $3-4
Not sure I have a part# SOP16-1.27TP ?
https://www.amazon.com/SOIC16-Programming-Socket-1-27mm-Adapter/dp/B0779Z75DK
https://www.ebay.com/itm/181631340087
Reference programmers
https://www.embeddedcomputers.net/products/FlashcatUSB/
https://www.embeddedcomputers.net/products/SerialAdapters/