2025-02-12 10:54 PM
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.
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?
2025-02-13 05:55 AM
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.
2025-02-13 06:05 AM
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.
2025-02-13 06:19 AM
Just setting the field should work.
Haven't used the XSPI on the H5, but that's how similar peripherals work on other chips. Perhaps change in this manner from 1 MHz to 2 MHz and verify on a scope or logic analyzer that everything is copasetic.