Configuring External XSPI PSRAM on STM32H7R
Hi all,
I am trying to bring up a new custom board with an STM32H7R7 and external flash as well as external PSRAM. While I managed to get the external flash working after some try and error, the external PSRAM seems to be more stubborn.
- The board uses a IS66WVO8M8DALL-200BLI from ISSI (https://www.issi.com/WW/pdf/66-67WVO8M8DALL-BLL.pdf)
- The PSRAM is connected to XSPI1 in OctoSPI mode.
- The XSPI clock is configured to 133MHz.
- At the moment the MPU is completely disabled to not having to debug several things at once.
The MX_XSPI1_Init() currently looks like this:
static void MX_XSPI1_Init(void)
{
/* USER CODE BEGIN XSPI1_Init 0 */
/* USER CODE END XSPI1_Init 0 */
XSPIM_CfgTypeDef sXspiManagerCfg = {0};
/* USER CODE BEGIN XSPI1_Init 1 */
/* USER CODE END XSPI1_Init 1 */
/* XSPI1 parameter configuration*/
hxspi1.Instance = XSPI1;
hxspi1.Init.FifoThresholdByte = 2;
hxspi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hxspi1.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX_RAM;
hxspi1.Init.MemorySize = HAL_XSPI_SIZE_64MB;
hxspi1.Init.ChipSelectHighTimeCycle = 3;
hxspi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hxspi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hxspi1.Init.WrapSize = HAL_XSPI_WRAP_32_BYTES;
hxspi1.Init.ClockPrescaler = 0;
hxspi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hxspi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_8KB;
hxspi1.Init.MaxTran = 0;
hxspi1.Init.Refresh = 262;
hxspi1.Init.MemorySelect = HAL_XSPI_CSSEL_NCS1;
if (HAL_XSPI_Init(&hxspi1) != HAL_OK)
{
Error_Handler();
}
sXspiManagerCfg.nCSOverride = HAL_XSPI_CSSEL_OVR_NCS1;
sXspiManagerCfg.IOPort = HAL_XSPIM_IOPORT_1;
sXspiManagerCfg.Req2AckTime = 1;
if (HAL_XSPIM_Config(&hxspi1, &sXspiManagerCfg, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN XSPI1_Init 2 */
/* USER CODE END XSPI1_Init 2 */
}
And my MX_EXTMEM_MANAGER_Init() like this:
void MX_EXTMEM_MANAGER_Init(void)
{
/* USER CODE BEGIN MX_EXTMEM_Init_PreTreatment */
/* USER CODE END MX_EXTMEM_Init_PreTreatment */
HAL_RCCEx_EnableClockProtection(RCC_CLOCKPROTECT_XSPI);
/* Initialization of the memory parameters */
memset(extmem_list_config, 0x0, sizeof(extmem_list_config));
/* EXTMEMORY_1 */
extmem_list_config[0].MemType = EXTMEM_NOR_SFDP;
extmem_list_config[0].Handle = (void*)&hxspi2;
extmem_list_config[0].ConfigType = EXTMEM_LINK_CONFIG_8LINES;
/* EXTMEMORY_2 */
extmem_list_config[1].MemType = EXTMEM_PSRAM;
extmem_list_config[1].Handle = (void*)&hxspi1;
extmem_list_config[1].ConfigType = EXTMEM_LINK_CONFIG_8LINES;
extmem_list_config[1].PsramObject.psram_public.MemorySize = HAL_XSPI_SIZE_64MB;
extmem_list_config[1].PsramObject.psram_public.FreqMax = 133 * 1000000u;
extmem_list_config[1].PsramObject.psram_public.NumberOfConfig = 1u;
/* Config */
extmem_list_config[1].PsramObject.psram_public.config[0].WriteMask = 0x40u;
extmem_list_config[1].PsramObject.psram_public.config[0].WriteValue = 0x28u;
extmem_list_config[1].PsramObject.psram_public.config[0].REGAddress = 0x00u;
/* Memory command configuration */
extmem_list_config[1].PsramObject.psram_public.ReadREG = 0xC0u;
extmem_list_config[1].PsramObject.psram_public.WriteREG = 0x40u;
extmem_list_config[1].PsramObject.psram_public.ReadREGSize = 2u;
extmem_list_config[1].PsramObject.psram_public.REG_DummyCycle = 4u;
extmem_list_config[1].PsramObject.psram_public.Write_command = 0x20u;
extmem_list_config[1].PsramObject.psram_public.Write_DummyCycle = 8u;//4u;
extmem_list_config[1].PsramObject.psram_public.Read_command = 0xA0u;
extmem_list_config[1].PsramObject.psram_public.WrapRead_command = 0x80u;
extmem_list_config[1].PsramObject.psram_public.Read_DummyCycle = 8u;
EXTMEM_Init(EXTMEMORY_1, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI2));
EXTMEM_Init(EXTMEMORY_2, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI1));
/* USER CODE BEGIN MX_EXTMEM_Init_PostTreatment */
/* USER CODE END MX_EXTMEM_Init_PostTreatment */
}
But in both cases I am not sure if the parameter are set correctly. I tried copying my STM32H7S78-DK board where it seemed reasonable and adjust the parameter I could find in the datasheet.
In order to test the correct function of the PSRAM I added some user code just after the memory is mapped in the BOOT_Application() function created by CubeMX:
BOOTStatus_TypeDef BOOT_Application(void)
{
BOOTStatus_TypeDef retr;
/* Mount the memory */
retr = MapMemory();
uint32_t ram_data0[8] = {0};
uint32_t ram_data1[8] = {0};
uint32_t ram_data2[8] = {0};
uint32_t ram_data3[8] = {0};
uint32_t *ext_ram = (uint32_t *)0x90000000;
// Ram test 0 - reading what is originally in the section
for (int32_t i = 0; i < 8; i++) {
ram_data0[i] = ext_ram[i];
}
// Ram test 1 - setting the section to zero and reading back
memset(ext_ram, 0x0, 8*sizeof(uint32_t));
for (int32_t i = 0; i < 8; i++) {
ram_data1[i] = ext_ram[i];
}
// Ram test 2 - setting the section to 0xAA and reading back
memset(ext_ram, 0xAA, 8*sizeof(uint32_t));
for (int32_t i = 0; i < 8; i++) {
ram_data2[i] = ext_ram[i];
}
// Ram test 3 - settinig the section to ascending numbers and reading back
uint8_t *ext_ram_bytes = (uint8_t*)0x90000000;
for (int i = 0; i < 32; i++) {
ext_ram_bytes[i] = (uint8_t)(i + 1);
}
// Then read back as uint32_t:
for (int i = 0; i < 8; i++) {
ram_data3[i] = ext_ram[i];
}
if (BOOT_OK == retr)
{
/* Jump on the application */
retr = JumpToApplication();
}
return retr;
}
Where the four test sections shall help to identify if the PSRAM is correctly mounted and working. The tests modify and then read 8 times 32bit sections. While I can see in my debugging sessions that the code is somewhat working I can never get it right so that all 8 x 32 bits are correctly written and read back. There is always a couple bits that are wrongly written or not written at all or perhaps wrongly read back ( I can currently not distinguish between write errors and read errors). Since I manage to write/read some of the bits correct I assume the hardware is correct and I am just missing the right settings in my boot software.
Can someone help me or point me further in the right direction as to how to find the right parameter in the two init functions above?
Any help is appreciated!
Regards
Sascha
