cancel
Showing results for 
Search instead for 
Did you mean: 

QSPI External Loader WriteMemory Fail

YCF.1
Associate III

I use STM32H750B-DK to do external loader function.

"H750_External_Loader.zip" is my test code.

On below have error happen, I got error while memcmp

0693W00000JMSYpQAP.png 

That's the code that I've used as my base:

https://github.com/WellinZHANG/External_Loader

QSPI Setting

0693W00000JMSZYQA5.png 

EVM STM32H750B-DK Flash0693W00000JMSZiQAP.png

1 ACCEPTED SOLUTION

Accepted Solutions
YCF.1
Associate III

This issue had to solve.

The code had some error, must change code like below.

Thanks.

0693W00000Y6qyaQAB.png

View solution in original post

16 REPLIES 16
SofLit
ST Employee

Dear @YCF.1​  (Community Member)​ 

Please double check if you're not in the case of the errata "2.4.4 Memory-mapped read of last memory byte fails". If yes, please configure FSIZE the double size of the real size of your memory.

SofLit

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

Hi Soft.it~

The issue may be memory ​mapped fail, because I try to

memcmp(buffer_test,(uint8_t*) (0x90000000 + var * MEMORY_SECTOR_SIZE),1) still fail.

I don't know if you solved the problem or not, but this is how the check goes.

//add
 
/* USER CODE BEGIN 2 */
  uint8_t buffer_testW[MEMORY_SECTOR_SIZE];
  uint8_t buffer_testR[MEMORY_SECTOR_SIZE];
  uint32_t var = 0, i = 0;
  uint8_t* address = (uint8_t*) 0x90000000;
 
 
for (var = 0; var < SECTORS_COUNT; var++)
  {
	  for (i = 0; i < MEMORY_SECTOR_SIZE; i++)
	  {
		  buffer_testR[i] = ((address + i) + (var * MEMORY_SECTOR_SIZE));
	  }
 
	  if (memcmp(buffer_testW
	                 ,buffer_testR,
	                 MEMORY_SECTOR_SIZE) != HAL_OK)
      {
          while (1)
  			;	//breakpoint - error detected
      }
  }
 
/* USER CODE END 2 */

The *.stldr file compiles, but when you try to load the test file, the flash memory remains untouched. At the same time, the STM32CubeProgrammer program reacts correctly to all actions. Can someone tell me what I did wrong? then I will provide an archive with my External loader project for W25Q128 for stm32f746vgt6.

This code isn't reading memory content

buffer_testR[i] = ((address + i) + (var * MEMORY_SECTOR_SIZE));

Not clear how buffer_testW fills

memcmp() doesn't return HAL codes, but will be non-zero if the data doesn't match. ie did write properly, or didn't read back properly. I'd probably look at what and how much is actually different, and if there's some kind of pattern.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

The memory mapping needs to be working

https://github.com/WellinZHANG/External_Loader/blob/main/QSPI%20testing/main_test.c#L36

If it's already failing at the first byte then perhaps the command/template is wrong.

Check dummy cycles, command format, etc.

On the H7 there's an issue at the end of memory, about 32-bytes / cache-line that has an errata issue, but you'd need to be using the whole memory.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

and if so

buffer_testR[i] = (((uint8_t*)(0x90000000 + i)) + (var * MEMORY_SECTOR_SIZE));

I posted only a part of the code that was affected by the change. The memcmp function compares two arrays and returns "0" if too early. buffer_testW is filled at the beginning of main.

/* USER CODE BEGIN 2 */
  uint8_t buffer_testW[MEMORY_SECTOR_SIZE];
  uint8_t buffer_testR[MEMORY_SECTOR_SIZE];
  uint32_t var = 0, i = 0;
  uint8_t* address = (uint8_t*) 0x90000000;
 
 
  CSP_QUADSPI_Init();
 
  for (var = 0; var < MEMORY_SECTOR_SIZE; var++) {
      buffer_testW[var] = (var & 0xff);
  }
 
//------------------------------------------------------
//       original code
//------------------------------------------------------ 
 
  for (var = 0; var < SECTORS_COUNT; var++)
  {
	  for (i = 0; i < MEMORY_SECTOR_SIZE; i++)
	  {
		  buffer_testR[i] = ((address + i) + (var * MEMORY_SECTOR_SIZE));
	  }
 
	  if (memcmp(buffer_testW
	                 ,buffer_testR,
	                 MEMORY_SECTOR_SIZE) != HAL_OK)
      {
          while (1)
  			;	//breakpoint - error detected
      }
  }
 
  /* USER CODE END 2 */

Still looks to be casting, not reading content.

Why does it need to be buffering this?

If you've memory mapped the QSPI you should be able to memcmp() it directly.

If that fails it is probably because the content is wrong/different. Focus on WHY

buffer_testR[i] = address[ i + (var * MEMORY_SECTOR_SIZE)]; // would actual read the bytes

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

The fact that the memcmp function does not work correctly is related to the development environment setting. If the CSP_QSPI_EnableMemoryMappedMode() function did not work, then there is no way to read the memory from the address 0x90000000, I also checked the contents of the memory on the programmer. In a word, the fact that this function does not work correctly is a problem of the CubeIDE development environment or its compilation settings. In the video on creating an External Loader, everything is described very superficially, it’s good that they drew attention to a couple of nuances. There is only one answer to all questions, to the forum. But even here, as I see it, there are only a few specialists. If anything, in order to understand the operation of the QSPI protocol, I wrote code for stm32f103ve by reading PDF on Q25WXX and emulating it on this MK, the only thing I could not do was the page writing algorithm.

The documentation and implementation are indeed very poor

Not sure I buy compiler issues here, I'm building loaders with GNU/GCC. Perhaps one problem here is the lack of main() and the initialization of the statics.

Memory Mapping mode should work, it's just a repeating instance of other QSPI Read functionality.

If the QSPI side memory mapping fails, or you want to leave it, the defined method is to HAL QSPI Abort, and you can go back to sending commands.

If you tell the tools you're an SPI FLASH device they will use the Read() method instead of trying to access at the 0x90000000 address space directly without the loader.

You could implement your loop as a read/comparison with a QSPI Read into the buffer, and then compare the content written vs that read back.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..