cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L4Q5AGIx Hyperbus PSRAM Issues

BComp
Associate

We are using a STM32L4Q5AGIx device with Hyperbus PSRAM IS66WVH8M8BLL chip on a custom board.  We are having a number of issues getting the RAM to work corectly on Port 2 and right now are isolating it to reading any of the 4 internal registers, ID0, ID1, CR0, CR1.  Assuming we can successfully read those registers, we will know our system is configured correctly and communicating properly. Our main clock is 120 MHz. We have setup to run the OSPI at 1MHz to aid debugging.

Here is what we observe when we attempt to read ID0;

  • Two Hyperbus commands are seen on the bus. (I would expect only one since we are reading only one register)
  • The first byte of the Command/Address (CA0) is correct, indicating a Read, Register Address Space, and Linear Burst.
  • The following bytes of the Command/Address fluctuate with seemingly spurious values.  I would expect these to be all zeros as the ID0 register is at address zero.
  • Looking at the AR register in our ospi->Instance, this should be set to zero, but it appears to randomly change.  Every time I pause the processor, the AR register is a new value.  This register should be set to zero in the function HAL_OSPI_HyperbusCmd.

Here is our CubeMx generated initialization:

 

 

/**
  * @brief OCTOSPI2 Initialization Function
  * @PAram None
  * @retval None
  */
static void MX_OCTOSPI2_Init(void)
{

  /* USER CODE BEGIN OCTOSPI2_Init 0 */

  /* USER CODE END OCTOSPI2_Init 0 */

  OSPIM_CfgTypeDef OSPIM_Cfg_Struct = {0};
  OSPI_HyperbusCfgTypeDef sHyperBusCfg = {0};

  /* USER CODE BEGIN OCTOSPI2_Init 1 */

  /* USER CODE END OCTOSPI2_Init 1 */
  /* OCTOSPI2 parameter configuration*/
  hospi2.Instance = OCTOSPI2;
  hospi2.Init.FifoThreshold = 1;
  hospi2.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
  hospi2.Init.MemoryType = HAL_OSPI_MEMTYPE_HYPERBUS;
  hospi2.Init.DeviceSize = 23;
  hospi2.Init.ChipSelectHighTime = 8;
  hospi2.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
  hospi2.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
  hospi2.Init.ClockPrescaler = 120;
  hospi2.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
  hospi2.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
  hospi2.Init.ChipSelectBoundary = 1;
  hospi2.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
  hospi2.Init.Refresh = 4;
  if (HAL_OSPI_Init(&hospi2) != HAL_OK)
  {
    Error_Handler();
  }
  OSPIM_Cfg_Struct.ClkPort = 2;
  OSPIM_Cfg_Struct.DQSPort = 2;
  OSPIM_Cfg_Struct.NCSPort = 2;
  OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_2_LOW;
  OSPIM_Cfg_Struct.IOHighPort = HAL_OSPIM_IOPORT_2_HIGH;
  if (HAL_OSPIM_Config(&hospi2, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    Error_Handler();
  }
  sHyperBusCfg.RWRecoveryTime = 3;
  sHyperBusCfg.AccessTime = 6;
  sHyperBusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE;
  sHyperBusCfg.LatencyMode = HAL_OSPI_FIXED_LATENCY;
  if (HAL_OSPI_HyperbusCfg(&hospi2, &sHyperBusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN OCTOSPI2_Init 2 */

  /* USER CODE END OCTOSPI2_Init 2 */

}

 

 

Here is our read register code:

 

 

uint16_t HyperbusReadReg(uint32_t reg)
{
	OSPI_HyperbusCmdTypeDef  sCommand;
	uint16_t retval = 0x42;

	/* Initialize the read command */
	sCommand.AddressSpace = HAL_OSPI_REGISTER_ADDRESS_SPACE;
	sCommand.AddressSize  = HAL_OSPI_ADDRESS_32_BITS;
	sCommand.Address      = reg;
	sCommand.DQSMode      = HAL_OSPI_DQS_ENABLE;
	sCommand.NbData       = 2U;

	/* Configure the command */
	if (HAL_OSPI_HyperbusCmd(&hospi2, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
	{
		return 0;
	}

	/* Reception of the data */
	if (HAL_OSPI_Receive(&hospi2, (uint8_t *)&retval, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
	{
		return 0;
	}

	return retval;
}

 

 

Some defines:

 

 

/**
 * IS66WVH8M8BLL-100B1LI Hyperbus PSRAM
 */
#define ISS66WVH8M8_CR0_ADDRESS         0x00001000U
#define ISS66WVH8M8_CR1_ADDRESS         0x00001002U
#define ISS66WVH8M8_ID0_ADDRESS			0x00000000U
#define ISS66WVH8M8_ID1_ADDRESS			0x00000002U

 

 

 Here is a logic analyser picture.  D0-D7 correspond to the data lines, D8 is DQS, D9 is CLK, and D10 is CS.

hyperbus_ScopePic.png

So from all this I'd love some insight into what is going on here.

  • Why are there two Hyperbus commands being sent?
  • Why are the address values in the CA section not all zeros (with the exception of CA47, 46, and 45)?
  • Why is hospi2->Instance.AR changing all the time?

Thanks for any help.

1 REPLY 1
KDJEM.1
ST Employee

Hello @BComp ,

Could you please check the OCTOSPI configuration like as Chip select boundary (CSBOUND)  and Refresh rate  These settings depend on the memory datasheet.

- The chip select must go high when crossing the page boundary (2^CSBOUND bytes defines the page size).

- The chip select must go high each (REFRECH x OCTOSPI clock cycles).

For the CSBOUND boundary configuration please refer to the errata sheet section 2.6 OCTOSPI.

May be this example can help you.

Thank you.

Kaouthar

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.