cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H747 with Low-Power SDRAM (1.8V) read/write issue

RChie.2
Associate II

Hi Everyone:

we now have a problem running STM32H747XIH6 with Low-Power SDRAM (ISSI IS42VM32160E-75BLI) when the SDRAM clock is set to 100MHz, on our customized PCBA. I'd like to check if anyone has suggestions on how to debug.

■ Description of the setup:

A. Home-made PCBA with STM32H747XIH6, VDD = 1.8V, SMPS direct supply VCORE.

B. Low-Power SDRAM is ISSI IS42VM32160E-75BLI,

  133MHz, 64MB capacity with 32-bit Data Bus.

C. Our goal is to run SDRAM at 100MHz.

■ The Issue:

A. When running SDRAM at 50MHz (SDRAM clock frequency), everything goes fine, with CPU running at 200MHz.

AXI and FMC are running at 100MHz in this case.

B. When running SDRAM at 100MHz, memory read/write is incorrect.

In this case, CPU also runs at 200MHz, with AXI & FMC set to 200MHz.

C. The issue doesn't look like random error that may be caused by hardware timing problem. The following figure shows the printed test result from one memory test:

0693W00000AMlNBQA1.pngIn this test, the address of each memory cell is converted to data and written to it.

In the passed case, memory address and read data are the same,

While in the failed case, the address and read data are shifted by 12.

■ Some Analysis:

0693W00000AMlQAQA1.pngIn this table, Config A is 50MHz SDCLK which works fine.

Config B & C are running SDCLK at 100MHz with different CAS latency, both failed.

We do found two strange cases, with illegal settings, but actually works:

Config D is to set CAS latency of FMC and of SDRAM at different value: 3 for FMC and 2 for SDRAM (set to SDRAM mode register while initialization).

Config E is to set VOS voltage to 0. (This setting is illegal in the sense that according to data sheet, VOS 0 can only be used with LDO supply, while our board is using SMPS direct supply for VCORE power.)

■ Code Snippet

void BSP_FMC_Init(void)
{
 
  /* USER CODE BEGIN FMC_Init 0 */
  HAL_GPIO_WritePin(VDD_MEM_ON_GPIO_Port, VDD_MEM_ON_Pin, GPIO_PIN_SET);
  HAL_Delay(100);
 
  /* USER CODE END FMC_Init 0 */
 
  FMC_SDRAM_TimingTypeDef SdramTiming = {0};
 
  /* USER CODE BEGIN FMC_Init 1 */
 
  /* USER CODE END FMC_Init 1 */
 
  /** Perform the SDRAM1 memory initialization sequence
  */
  hsdram1.Instance = FMC_SDRAM_DEVICE;
  /* hsdram1.Init */
  hsdram1.Init.SDBank = FMC_SDRAM_BANK2;
  hsdram1.Init.ColumnBitsNumber = FMC_SDRAM_COLUMN_BITS_NUM_9;
  hsdram1.Init.RowBitsNumber = FMC_SDRAM_ROW_BITS_NUM_13;
  hsdram1.Init.MemoryDataWidth = FMC_SDRAM_MEM_BUS_WIDTH_32;
  hsdram1.Init.InternalBankNumber = FMC_SDRAM_INTERN_BANKS_NUM_4;
  hsdram1.Init.CASLatency = FMC_SDRAM_CAS_LATENCY_2;//FMC_SDRAM_CAS_LATENCY_2;
  hsdram1.Init.WriteProtection = FMC_SDRAM_WRITE_PROTECTION_DISABLE;
  hsdram1.Init.SDClockPeriod = FMC_SDRAM_CLOCK_PERIOD_2;//FMC_SDRAM_CLOCK_PERIOD_3;   // FMC kernal clock / SDClockPeriod = SDRAM clock
  hsdram1.Init.ReadBurst = FMC_SDRAM_RBURST_ENABLE;//FMC_SDRAM_RBURST_DISABLE;
  hsdram1.Init.ReadPipeDelay = FMC_SDRAM_RPIPE_DELAY_0;//FMC_SDRAM_RPIPE_DELAY_2;
  /* SdramTiming */
#ifndef SDRAM_100MHz
  SdramTiming.LoadToActiveDelay = 2;
  SdramTiming.ExitSelfRefreshDelay = 4;
  SdramTiming.SelfRefreshTime = 3;
  SdramTiming.RowCycleDelay = 4;//7;
  SdramTiming.WriteRecoveryTime = 1;//16;
  SdramTiming.RPDelay = 2;
  SdramTiming.RCDDelay = 2;
#else
  SdramTiming.LoadToActiveDelay = 2;
  SdramTiming.ExitSelfRefreshDelay = 8;
  SdramTiming.SelfRefreshTime = 5;
  SdramTiming.RowCycleDelay = 8;//7;
  SdramTiming.WriteRecoveryTime = 2;//16;
  SdramTiming.RPDelay = 3;
  SdramTiming.RCDDelay = 3;
#endif
 
  if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK)
  {
    Error_Handler( );
  }
}
 
void BSP_SDRAM_Init(SDRAM_HandleTypeDef *hsdram)
{
  FMC_SDRAM_CommandTypeDef Command;
  //volatile uint32_t temp = 0;
  GPIO_InitTypeDef GPIO_InitStruct ={0};
  __IO uint32_t tmpmrd =0;
 
  /* Step 1:  Configure a clock configuration enable command */
  Command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2; //FMC_SDRAM_CMD_TARGET_BANK1
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = 0;
 
  /* Send the command */
  HAL_SDRAM_SendCommand(hsdram, &Command, SDRAM_TIMEOUT);
  HAL_Delay(1);
 
  /* Step 3: Configure a PALL (precharge all) command */
  Command.CommandMode = FMC_SDRAM_CMD_PALL;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = 0;
 
  /* Send the command */
  HAL_SDRAM_SendCommand(hsdram, &Command, SDRAM_TIMEOUT);
 
  /* Step 4 : Configure a Auto-Refresh command */
  Command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
  Command.AutoRefreshNumber = 8;
  Command.ModeRegisterDefinition = 0;
 
  /* Send the command */
  HAL_SDRAM_SendCommand(hsdram, &Command, SDRAM_TIMEOUT);
 
 
  /* Step 5: Program the external memory mode register */
  tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |
                     SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
                     SDRAM_MODEREG_CAS_LATENCY_2           |
                     SDRAM_MODEREG_OPERATING_MODE_STANDARD |
					 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;
 
  Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = tmpmrd;
 
  // Send the command
  HAL_SDRAM_SendCommand(hsdram, &Command, SDRAM_TIMEOUT);
  //HAL_Delay(1);
 
  /* Step 6: Set the refresh rate counter */
  /* Set the device refresh rate */
  HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT);
 
 
  // Step 7: Program the external memory extended mode register
  // Tested Dummy Read at BA1 = 1, BA0 = 0 region cannot keep state of BA1 at High level (to select extended mode register).
  // Need to config BA1 = FMC_A15 = GPIO PG5 as GPIO output High for extended mode register configuration.
  //temp = *(uint32_t *)0xD2000000;
 
  // Config BA1 pin to GPIO output High
  HAL_GPIO_WritePin(GPIOG, GPIO_PIN_5, GPIO_PIN_SET);
  GPIO_InitStruct.Pin = SDRAM_BA1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(SDRAM_BA1_GPIO_Port, &GPIO_InitStruct);
 
  // Send Extended Mode Register
  tmpmrd = (uint32_t)SDRAM_DRIVE_STRENGTH_FULL | SDRAM_SELF_REFRESH_ALL_BANK;
 
  Command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
  Command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
  Command.AutoRefreshNumber = 1;
  Command.ModeRegisterDefinition = tmpmrd;
 
  // Send the command
  HAL_SDRAM_SendCommand(hsdram, &Command, SDRAM_TIMEOUT);
 
  // Config BA1 back to FMC alternate function pin
  GPIO_InitStruct.Pin = SDRAM_BA1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
  GPIO_InitStruct.Alternate = GPIO_AF12_FMC;
  HAL_GPIO_Init(SDRAM_BA1_GPIO_Port, &GPIO_InitStruct);
}

2 REPLIES 2
MEdgerton
Senior

Hi, Did you fix this as I am having SDRAM issues on H753zi2 (worked on F767 no problem!)

Thanks,

Mark

Hi, we got support from local ST FAE, had some progress on this issue but not fully resolved yet.

■ The suggestion is to:

  1. Enable I/O compensation cell
  2. Enable HSLV (high-speed at low-voltage)

* Note that this HSLV setting should be used if VDD < 2.5V. (VDD for MCU & LP-SDRAM in our customized board is 1.8V.)

Reference manual says that enabling this bit when VDD > 2.5V will be destructive.

■ To do this, the option byte hslv should first be un-locked:

HAL_StatusTypeDef BSP_OB_Enable_HSLV(void)
{
	HAL_StatusTypeDef ret = HAL_ERROR;
	FLASH_OBProgramInitTypeDef OBInit;
	OBInit.Banks     = FLASH_BANK_1;
 
	HAL_FLASHEx_OBGetConfig(&OBInit);
 
	if((OBInit.USERConfig & FLASH_OPTSR_IO_HSLV) == OB_IOHSLV_DISABLE)
	{
		HAL_FLASH_OB_Unlock();
	    HAL_FLASH_Unlock();
 
	    OBInit.OptionType = OPTIONBYTE_USER;
	    OBInit.Banks      = FLASH_BANK_1;
	    OBInit.USERType   = OB_USER_IOHSLV;
	    OBInit.USERConfig = OB_IOHSLV_ENABLE;
 
	    HAL_FLASHEx_OBProgram(&OBInit);
 
	    if(HAL_FLASH_OB_Launch() != HAL_OK)
	    {
	    	while(1)
	        {
	    		HAL_Delay(100);
	        }
	    }
	}
	else
		printf("HSLV already enabled\r\n");
 
	HAL_FLASHEx_OBGetConfig(&OBInit);
	if((OBInit.USERConfig & FLASH_OPTSR_IO_HSLV) == OB_IOHSLV_ENABLE)
	{
		ret = HAL_OK;
		printf("HSLV Enable Done\r\n");
	}
 
	HAL_FLASH_OB_Lock();
	HAL_FLASH_Lock();
 
	return ret;
}

Then to enable IO Compensation Cell & HSLV:

  // Activate CSI clock & SYSCFG clock mandatory for I/O compensation cell
  __HAL_RCC_CSI_ENABLE();
  __HAL_RCC_SYSCFG_CLK_ENABLE();
  // Enable I/O compensation cell
  HAL_EnableCompensationCell();
  HAL_SYSCFG_EnableIOSpeedOptimize();

■ Test Result:

With IO compensation cell & HSLV turned on, LP-SDRAM can run at 100MHz "n principle in room temperature. (Read/write errors are still observed with low probability.)

The problem is that read/write tests soon failed at high temperature environment (~60 degree C).