cancel
Showing results for 
Search instead for 
Did you mean: 

Adjusting XSPI RAM Clock at runtime

exarian
Associate II

Good day folks, I trust you are well.

I am interfacing with a APMemory 256Mbit RAM (APS256XXN-OBR) via the 16 way XSPI.

The RAM registers can be configured correctly at 100MHz, as well as the whole 256 Mbits can be accessed via Mmap.

For Configuration I am using the `APS256_ReadReg()` and `APS256_WriteReg()` functions as provided by the

XSPI_PSRAM_MemoryMapped example.

By default the RAM supports a maximum of 133MHz, which is why I am using 100MHz on powerup.

exarian_0-1739428461225.png

The registers are being configured and verified as follows:

MR0 = 0x11 (200MHz, 50R interface)

MR4 = 0x20 (200MHz, 4X refresh)

MR8 = 0x4F (X16, Row crossing enabled, 2KB word wrap)

After the configuration I am trying to Reinit the XSPI clock using:

/**
  * @brief  Re-initializes the XSPI1 peripheral clock with a new clock divider.
  * @PAram  newDivider: New clock divider value. (e.g., 8 for 200MHz if PLL1 frequency is 1.6GHz)
  * @retval None. Calls Error_Handler() on failure.
  */
void XSPI1_ReInitClock(XSPI_HandleTypeDef* hxspi, uint32_t newDivider)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  __HAL_RCC_XSPIM_CLK_DISABLE();
  __HAL_RCC_XSPI1_CLK_DISABLE();

  /* Configure the peripheral clock for XSPI1 */
  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_XSPI1;
  PeriphClkInitStruct.Xspi1ClockSelection   = RCC_XSPI1CLKSOURCE_IC4;
  PeriphClkInitStruct.ICSelection[RCC_IC4].ClockSelection = RCC_ICCLKSOURCE_PLL1;
  PeriphClkInitStruct.ICSelection[RCC_IC4].ClockDivider   = newDivider;

  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /* Peripheral clock enable */
  __HAL_RCC_XSPIM_CLK_ENABLE();
  __HAL_RCC_XSPI1_CLK_ENABLE();

  HAL_Delay(10);
}

 On powerup the divider is 16, to provide 100MHz, I am trying to adjust it to 8 to bump it to 200MHz.

The CPU is currently running a clock of 400MHz.

What procedure is required to "reset" the XSPI interface to use the higher clock speed?

2 REPLIES 2
TDK
Guru

I'd modify the PRESCALER field in XSPI->DCR2 directly. Set the prescaler so that 100 MHz is generated during initialization then cut it in half after switching to high speed mode.

TDK_0-1739454868117.png

 

If you feel a post has answered your question, please click "Accept as Solution".

Thank you @TDK ,

Would the XSPI need to be reinitialized once that is done? I.e.

At what point will the clock actually be changed?

 

I am busy doing this which is working, however it's not optimal:

void XSPI1_ReInitClock(XSPI_HandleTypeDef* hxspi)
{
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};

  if (HAL_XSPI_DeInit(hxspi) != HAL_OK)
  {
    Error_Handler();
  }

  HAL_XSPI_higher_clock(true);

  HAL_Delay(10);

  MX_XSPI1_Init();

  HAL_Delay(10);
}
static bool gb_higher_clock = false;

void HAL_XSPI_higher_clock(bool b_higher)
{
  gb_higher_clock = b_higher;
}
void HAL_XSPI_MspInit(XSPI_HandleTypeDef* hxspi)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
  if(hxspi->Instance==XSPI1)
  {
  /* USER CODE BEGIN XSPI1_MspInit 0 */

  /* USER CODE END XSPI1_MspInit 0 */

  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_XSPI1;
    PeriphClkInitStruct.Xspi1ClockSelection = RCC_XSPI1CLKSOURCE_IC4;
    PeriphClkInitStruct.ICSelection[RCC_IC4].ClockSelection = RCC_ICCLKSOURCE_PLL1;

    /** Adjustment of the clock using variable */
    PeriphClkInitStruct.ICSelection[RCC_IC4].ClockDivider = gb_higher_clock ? 12 : 16; 
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }

With this I am able to  go from a Clock of 100MHz (16), to 133MHz (12).

The RAM is responding at the higher clock, although at 200MHz (8) it is not responding and `APS256_ReadReg()` fails.

I am testing through different RAM Mode Register configurations to get 200MHz working.