Skip to main content
NRedd.2
Associate III
October 15, 2024
Question

STM32WB with QSPI flash MT25QL256ABA (PMod SF3)

  • October 15, 2024
  • 3 replies
  • 4651 views

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.

NRedd2_1-1729016790809.png

 

NRedd2_0-1729016599271.png

 

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;
}

 

3 replies

Tesla DeLorean
Guru
October 15, 2024

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

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
NRedd.2
NRedd.2Author
Associate III
October 16, 2024

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? 

NRedd.2
NRedd.2Author
Associate III
October 20, 2024

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);
	}

 

NRedd2_0-1729423458842.png

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?

Tesla DeLorean
Guru
October 20, 2024

>>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. 

 

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Tesla DeLorean
Guru
October 20, 2024
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
NRedd.2
NRedd.2Author
Associate III
November 25, 2024

@Tesla DeLorean,

I can confirm that it was the long jumpers that were causing the issue. The same code works perfectly fine on the custom PCB.