cancel
Showing results for 
Search instead for 
Did you mean: 

DUAL qspi writing error after 0x93000001 adress

erdalturkekul
Associate II

 

 Hi,

I'm trying to run dual QSPI Flash with my own design STM32H750XBH6. Flashes are 256 mbit MX25L25645. Single mode 32 mb flash read, write and boot succesfully. However, when I switch to dual chip mode, i get a write error (constant 0XFF) on the 2nd chip after 0x93000001 (48 mb) adresses. (adress 0x90000000 to 0x92FFFFFF  working very well. )

loadererror.jpgloadererror2.jpg

1 ACCEPTED SOLUTION

Accepted Solutions

Ok, but this isn't how it interleaves

/*modify buffer to enable quad mode*/
	test_buffer[0] |= 0x40;
	/*set dummy cycles*/
	test_buffer[1] |= 0xE0;
	test_buffer[2] |= 0x40;
	test_buffer[3] |= 0xE0;

The SR will need to be paired.

ie

test_buffer[0] = (test_buffer[0]) & 0xC3) | 0x40; // SR First Bank

test_buffer[1] = (test_buffer[1]) & 0xC3) | 0x40; // SR Second Bank

..

I would make sure the BP bits, which are sticky, are also cleared otherwise writes and erases can fail due to protection mechanics. This can be problematic when switching vendors as these bit definitions can be different. I've mostly seen myself locking Micron's by using Macronix code because the 0x40 is a Protection Bit in their context.

I'm also not sure you need to switch parts to use 4-Byte (32-bit) addressing mode, there are commands that explicitly define 3 or 4-byte .

For loaders, I'd keep them as simple as possible at the outset. You don't need to switch into the most exotic modes, performance is usually more to do with how fast the ST-LINK/V2 or V3 can shovel data across the interface.

In dual bank the page write can expand from 256 bytes to 512 bytes, as it interleaves between the two chips.

 

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

View solution in original post

17 REPLIES 17

The polling method would need to span both devices. ie you'd need to read status registers as a pair of bytes.

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

Thank you for nice tips Tesla DeLorean. I tried to edit to code as you said. But still can't write to 16 mb above to 2nd flash. I think the second flash does not switch to 4 byte (32 bit) adress mode.

QSPI_WriteEnable;

/* Configure automatic polling mode to wait for write enabling ---- */
	sConfig.Match = 0x0202;
	sConfig.Mask = 0x0202;
	sConfig.MatchMode = QSPI_MATCH_MODE_AND;
	sConfig.StatusBytesSize = 2;
	sConfig.Interval = 0x10;
	sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;

	 HAL_GPIO_TogglePin (GPIOE, GPIO_PIN_4);

	sCommand.Instruction = READ_STATUS_REG_CMD;
	sCommand.DataMode = QSPI_DATA_1_LINE;
	if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig,
	HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {

 QSPI_Configuration

	/*modify buffer to enable quad mode*/
	test_buffer[0] |= 0x40;

	/*set dummy cycles*/
	test_buffer[1] |= 0xE0;

	test_buffer[2] |= 0x40;

	test_buffer[3] |= 0xE0;
	if (QSPI_WriteEnable() != HAL_OK) {
				return HAL_ERROR;
			}

	sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
	sCommand.Instruction = WRITE_STATUS_REG_CMD;
	sCommand.AddressMode = QSPI_ADDRESS_NONE;
			sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
			sCommand.DataMode = QSPI_DATA_1_LINE;
			sCommand.DummyCycles = 0;
		//	sCommand.Address     = 0;
			sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
			sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
			sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
			sCommand.NbData = 4;

	if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
			!= HAL_OK) {
		return HAL_ERROR;
	}
if (HAL_QSPI_Transmit(&hqspi, test_buffer,
	HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
		Error_Handler();
		return HAL_ERROR;
	}

AN4760 only show quad line read squenze to dual flash. How to 1 line write squenze to instruction code data write?

quad.jpg 

FBL
ST Employee

Hello @erdalturkekul 

 

You may need to add HAL_QSPI_Command in QSPI_WriteEnable before configuring automatic polling mode to wait for reading out the values of configuration register.

You can refer to the example of cube.

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.


I'm out of offce with limited access to my emails.
Happy New Year!

@FBL still the same problem persist. 

 

In MX25L25645 datasheet says; if using larger than 128 mbit adress, you must execute Enable4ByteMode command.

My CSP_QSPI_Enable4ByteMode func.;

uint8_t CSP_QSPI_Enable4ByteMode(void) {
	QSPI_CommandTypeDef sCommand;
		if (QSPI_WriteEnable() != HAL_OK) {
			return HAL_ERROR;
		}
		
		sCommand.Instruction = ENTER_4BYTE_MODE_CMD;
		sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
		sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
		sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
		sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
		sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
		sCommand.AddressMode = QSPI_ADDRESS_NONE;
		sCommand.Address = 0;
		sCommand.DataMode = QSPI_DATA_NONE;
		sCommand.DummyCycles = 0;

		if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
				!= HAL_OK) {
			return HAL_ERROR;
		}

		if (QSPI_AutoPollingMemReady() != HAL_OK) {
					return HAL_ERROR;
				}
		return HAL_OK;
}

Is this function execute in lower and upper flash at same time?

.c and .h files attached

Ok, but this isn't how it interleaves

/*modify buffer to enable quad mode*/
	test_buffer[0] |= 0x40;
	/*set dummy cycles*/
	test_buffer[1] |= 0xE0;
	test_buffer[2] |= 0x40;
	test_buffer[3] |= 0xE0;

The SR will need to be paired.

ie

test_buffer[0] = (test_buffer[0]) & 0xC3) | 0x40; // SR First Bank

test_buffer[1] = (test_buffer[1]) & 0xC3) | 0x40; // SR Second Bank

..

I would make sure the BP bits, which are sticky, are also cleared otherwise writes and erases can fail due to protection mechanics. This can be problematic when switching vendors as these bit definitions can be different. I've mostly seen myself locking Micron's by using Macronix code because the 0x40 is a Protection Bit in their context.

I'm also not sure you need to switch parts to use 4-Byte (32-bit) addressing mode, there are commands that explicitly define 3 or 4-byte .

For loaders, I'd keep them as simple as possible at the outset. You don't need to switch into the most exotic modes, performance is usually more to do with how fast the ST-LINK/V2 or V3 can shovel data across the interface.

In dual bank the page write can expand from 256 bytes to 512 bytes, as it interleaves between the two chips.

 

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

This should be closer to what's desired.

/*Enable quad mode and set dummy cycles count*/
uint8_t QSPI_Configuration(void)
{
  QSPI_CommandTypeDef sCommand = { 0 };
  uint8_t test_buffer[4] = { 0 };

// The QE bit enables the use of pins and extended quad command set
//  Need to send QPI ENABLE (0x35) for 4-4-4, otherwise 1-1-x or 1-x-x assumed

// You Enable 4-BYTE Addressing Mode via Control Register

  //sCommand.DataMode           = QSPI_DATA_4_LINES; // Decide Which Mode You're In
  sCommand.DataMode           = QSPI_DATA_1_LINE;

  sCommand.InstructionMode    = QSPI_INSTRUCTION_1_LINE;
  sCommand.AddressMode        = QSPI_ADDRESS_NONE;
  sCommand.AlternateByteMode  = QSPI_ALTERNATE_BYTES_NONE;
  sCommand.DummyCycles        = 0;
  sCommand.DdrMode            = QSPI_DDR_MODE_DISABLE;
  sCommand.DdrHoldHalfCycle   = QSPI_DDR_HHC_ANALOG_DELAY;
  sCommand.SIOOMode           = QSPI_SIOO_INST_EVERY_CMD;

  /*read status register*/
  sCommand.Instruction        = READ_STATUS_REG_CMD; // 0x05
  sCommand.NbData             = 2;

  if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
      != HAL_OK) {
    return HAL_ERROR;
  }
  if (HAL_QSPI_Receive(&hqspi, (uint8_t *)(&test_buffer[0]),
  HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
    return HAL_ERROR;
  }

  /*read configuration register*/
  sCommand.Instruction        = READ_CONFIGURATION_REG_CMD; // 0x15
  sCommand.NbData             = 2;

  if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
      != HAL_OK) {
    return HAL_ERROR;
  }
  if (HAL_QSPI_Receive(&hqspi, (uint8_t *)(&test_buffer[2]),
  HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
    return HAL_ERROR;
  }
  */

  /*modify buffer to enable quad mode*/
  if (QSPI_WriteEnable() != HAL_OK) {
          return HAL_ERROR;
        }
  test_buffer[0] = (test_buffer[0] & 0xC3) | 0x40; // Set QE, Clear BP
  test_buffer[1] = (test_buffer[1] & 0xC3) | 0x40; // Set QE, Clear BP

  test_buffer[2] |= 0xE0; // Dummy 8 (Single/Dual) / 10 (Quad)
  test_buffer[3] |= 0xE0; // DC1,DC0,4-BYTE ENABLE

  sCommand.Instruction        = WRITE_STATUS_REG_CMD; //  SR+CR or SR+SR+CR+CR in dual bank
  sCommand.NbData             = 4;

  if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE)
      != HAL_OK) {
    return HAL_ERROR;
  }

  if (HAL_QSPI_Transmit(&hqspi, (uint8_t *)(&test_buffer[0]),
  HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
    Error_Handler();
    return HAL_ERROR;
  }

  return HAL_OK;
}

Would probably lean to using the Quad Command's rather than engage QPI mode, so Init() path can be optimized

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

@Tesla DeLorean thank you for your solutions!! :) now work fine

Yes, stlink V3 is the bottleneck when writing flash. Its takes about 15-20 minutes when 64 mb flash writing.

But, dual qspi MemoryMappedMode better than single flash. I can run to tgfx animated picture on the 1024 x 600 pixel lcd without any flicker or frezing. H7 series mcu most performing one.  If there were no 256 mbyte limit, I would like to try two 1 gbit nor flash (with a little writing patience and more coffee breaks)

flashwrite.jpg

2x 1Gbit (128MB) will get you to the 256 MB ceiling for the 0x90000000..0x9FFFFFFF range

Are you using BGA24 parts?

You are getting to the limit of the SOIC16 NOR FLASH parts. With Micron beyond 1Gbit you're getting to stacked multi-die parts. The ready and die/mass erase mechanics get to be different. 

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

Tentative Dual MX25L256 build for your platform (blind port as can't test)

https://github.com/cturvey/stm32extldr/blob/main/h7_mx25l25645g/CLIVEONE-MX25L256_STM32H7XX-PF10-PB6-PF8-PF9-PF7-PF6-PH2-PH3-PG9-PG14.stldr

What Part# for the 1Gbit? MX66L1G ?

 

 

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