Skip to main content
DMast.1
Associate III
June 10, 2026
Question

STM32H723/735 external hyperram access

  • June 10, 2026
  • 5 replies
  • 165 views

Good morning,
I'm writing here to ask for help resolving a problem we're having with a custom board that uses a HYPERRAM bus and external RAM chip. Specifically, if Infineon S70KL1282GABHV020 memory is installed on the board, we can easily access byte/word/dword reads and writes, even at a 166MHz clock speed.

Needing more external RAM, we installed the ISSI IS66WVH64M8DBLL-166B1LI chip (64MB).However, we can no longer access it properly. Specifically, if we try to access bytes at even addresses, the system seems to work. If we access odd addresses, however, we start to experience access errors. Even lowering the clock frequency to 25MHz, the problem persists.

To avoid layout issues, we replaced the hyperram on the STM32H735-DK evb with the ISSI chip, and the behavior is similar.
Below is part of the hyperbus initialization code and the code we use for testing the entire memory.

  /* Initialize OctoSPI ----------------------------------------------------- */
OSPIHandle.Instance = OCTOSPI2;
HAL_OSPI_DeInit(&OSPIHandle);

OSPIHandle.Init.FifoThreshold = 4;
OSPIHandle.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
OSPIHandle.Init.MemoryType = HAL_OSPI_MEMTYPE_HYPERBUS;

OSPIHandle.Init.DeviceSize = POSITION_VAL(OSPI_RAM_SIZE);

OSPIHandle.Init.ChipSelectHighTime = 4;
OSPIHandle.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
OSPIHandle.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
OSPIHandle.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
OSPIHandle.Init.ClockPrescaler = 2;
OSPIHandle.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
OSPIHandle.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;//>> HAL_OSPI_DHQC_ENABLE;
OSPIHandle.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED; //>>HAL_OSPI_DELAY_BLOCK_USED;
OSPIHandle.Init.ChipSelectBoundary = 0;
OSPIHandle.Init.MaxTran = 0;
OSPIHandle.Init.Refresh = 400;

if (HAL_OSPI_Init(&OSPIHandle) != HAL_OK)
{
Error_Handler() ;
}


/* Configure the Hyperbus to access memory space -------------------------- */
sHyperbusCfg.RWRecoveryTime = 4;
sHyperbusCfg.AccessTime = 6;
sHyperbusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE;
sHyperbusCfg.LatencyMode = HAL_OSPI_FIXED_LATENCY;

if (HAL_OSPI_HyperbusCfg(&OSPIHandle, &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}

/* Memory-mapped mode configuration --------------------------------------- */
sCommand.AddressSpace = HAL_OSPI_MEMORY_ADDRESS_SPACE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
sCommand.Address = 0;
sCommand.NbData = 1;

if (HAL_OSPI_HyperbusCmd(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}

sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
sMemMappedCfg.TimeOutPeriod = 0x34; /* circa 50 cicli */
if( HAL_OSPI_MemoryMapped(&OSPIHandle, &sMemMappedCfg) != HAL_OK)
{
Error_Handler();
}


#define DATA_OFFSET 2u

errors = 0;
mod1errors = 0;
uint8_t *pzMem = (uint8_t*) OCTOSPI2_BASE;
uint32_t total_bytes = 64u * 1024u * 1024u;

for (i = 0; i < 100; i++)
{

for (uint32_t zIndex = 0; zIndex < total_bytes; zIndex += DATA_OFFSET)
{
pzMem[zIndex] = (uint8_t) (zIndex & 0xFF);
__asm("NOP");
}

for (uint32_t zIndex = 0; zIndex < total_bytes; zIndex += DATA_OFFSET)
{
uint8_t read_val = pzMem[zIndex];
uint8_t expected_val = (uint8_t) (zIndex & 0xFF);

if (read_val != expected_val) {
modAddress = zIndex % 8;
errors++;

if (modAddress == 1) {
mod1errors++;
}

}

__asm("NOP");
}

}

if  DATA_OFFSET                        2u → Even read/write access

if  DATA_OFFSET                        1u → Odd/Even read/write access

For your convenience, I am also attaching the Hyperram ISSI datasheet. issue. I'm available if anyone needs further information to understand what's going on. My guess is that some HYPERBUS configuration parameter is incorrect when I access the higher-capacity RAM.

I thank in advance anyone who can help resolve this

5 replies

KDJEM.1
ST Technical Moderator
June 10, 2026

Hello ​@DMast.1 ,

 

I noted in the memory datasheet that the memory requires the same time for Recovery and for Access.

Why you used different values?

 sHyperbusCfg.RWRecoveryTime   = 4;
sHyperbusCfg.AccessTime = 6;

The shared OCTOSPI configuration is not correct for OCTOSPI clock 25 MHz.

Could you provide more details about the OCTOSPI clock used and share the clock configuration?

 

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.
DMast.1
DMast.1Author
Associate III
June 11, 2026

Hi, here is the other initialization code that I’m using with STM32H735-DK with the ISSI

void HAL_MspInit(void)
{
GPIO_InitTypeDef GPIO_InitStruct;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Pull = GPIO_NOPULL;

/* Enable the OctoSPI memory interface clock */
OSPI2_CLK_ENABLE();

/* Reset the OctoSPI memory interface */
__HAL_RCC_OSPI2_FORCE_RESET();
__HAL_RCC_OSPI2_RELEASE_RESET();

/* Enable the GPIO clocks */
OSPI2_CS_GPIO_CLK_ENABLE();
OSPI2_CLK_P_GPIO_CLK_ENABLE();
OSPI2_D0_GPIO_CLK_ENABLE();
OSPI2_D1_GPIO_CLK_ENABLE();
OSPI2_D2_GPIO_CLK_ENABLE();
OSPI2_D3_GPIO_CLK_ENABLE();
OSPI2_D4_GPIO_CLK_ENABLE();
OSPI2_D5_GPIO_CLK_ENABLE();
OSPI2_D6_GPIO_CLK_ENABLE();
OSPI2_D7_GPIO_CLK_ENABLE();
OSPI2_DQS_GPIO_CLK_ENABLE();

/* OSPI CS GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_CS_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF3_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_CS_GPIO_PORT, &GPIO_InitStruct);

/* OSPI CLK GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_CLK_PIN;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_CLK_GPIO_PORT, &GPIO_InitStruct);

/* OSPI D0 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D0_PIN;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D0_GPIO_PORT, &GPIO_InitStruct);

/* OSPI D1 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D1_PIN;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D1_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D2 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D2_PIN;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D2_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D3 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D3_PIN;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D3_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D4 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D4_PIN;
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D4_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D5 GPIO pin configuration */
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
GPIO_InitStruct.Pin = OSPI2_D5_PIN;
HAL_GPIO_Init(OSPI2_D5_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D6 GPIO pin configuration */
GPIO_InitStruct.Pin = OSPI2_D6_PIN;
GPIO_InitStruct.Alternate = GPIO_AF3_OCTOSPIM_P2;
HAL_GPIO_Init(OSPI2_D6_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 D7 GPIO pin configuration */
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
GPIO_InitStruct.Pin = OSPI2_D7_PIN;
HAL_GPIO_Init(OSPI2_D7_GPIO_PORT, &GPIO_InitStruct);

/* OSPI2 DQS GPIO pin configuration */
GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P2;
GPIO_InitStruct.Pin = OSPI2_DQS_PIN;
HAL_GPIO_Init(OSPI2_DQS_GPIO_PORT, &GPIO_InitStruct);

/* Enable and set OctoSPI interrupt to the lowest priority */
HAL_NVIC_SetPriority(OCTOSPI2_IRQn, 0x0F, 0);
HAL_NVIC_EnableIRQ(OCTOSPI2_IRQn);
}

system clock:

static void SystemClock_Config(void)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_OscInitTypeDef RCC_OscInitStruct;
HAL_StatusTypeDef ret = HAL_OK;

/* The voltage scaling allows optimizing the power consumption when the device is
clocked below the maximum system frequency, to update the voltage scaling value
regarding system frequency refer to product datasheet. */
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}

/* Enable HSE Oscillator and activate PLL with HSE as source */
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSIState = RCC_HSI_OFF;
RCC_OscInitStruct.CSIState = RCC_CSI_OFF;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;

RCC_OscInitStruct.PLL.PLLM = 5;
RCC_OscInitStruct.PLL.PLLN = 80;
RCC_OscInitStruct.PLL.PLLFRACN = 0;
RCC_OscInitStruct.PLL.PLLP = 1;
RCC_OscInitStruct.PLL.PLLR = 2;
RCC_OscInitStruct.PLL.PLLQ = 4;

RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_1;
ret = HAL_RCC_OscConfig(&RCC_OscInitStruct);
if(ret != HAL_OK)
{
Error_Handler();
}

/* Select PLL as system clock source and configure bus clocks dividers */
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | \
RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1);

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
ret = HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3);
if(ret != HAL_OK)
{
Error_Handler();
}

/*
Note : The activation of the I/O Compensation Cell is recommended with communication interfaces
(GPIO, SPI, FMC, OSPI ...) when operating at high frequencies (please refer to product datasheet)
The I/O Compensation Cell activation procedure requires :
- The activation of the CSI clock
- The activation of the SYSCFG clock
- Enabling the I/O Compensation Cell : setting bit[0] of register SYSCFG_CCCSR

To do this please uncomment the following code

__HAL_RCC_CSI_ENABLE() ;

__HAL_RCC_SYSCFG_CLK_ENABLE() ;

HAL_EnableCompensationCell();
*/

}

and the MPPU config:

static void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;

/* Disable the MPU */
HAL_MPU_Disable();

/* Configure the MPU as Strongly ordered for not defined regions */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x00;
MPU_InitStruct.Size = MPU_REGION_SIZE_4GB;
MPU_InitStruct.AccessPermission = MPU_REGION_NO_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x87;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

// /* Configure the MPU attributes as WT for OCTOSPI2 */
// MPU_InitStruct.Enable = MPU_REGION_ENABLE;
// MPU_InitStruct.BaseAddress = OCTOSPI2_BASE;
// MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
// MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
// MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
// MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
// MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
// MPU_InitStruct.Number = MPU_REGION_NUMBER1;
// MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
// MPU_InitStruct.SubRegionDisable = 0x00;
// MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
//
// HAL_MPU_ConfigRegion(&MPU_InitStruct);


MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = OCTOSPI2_BASE;
MPU_InitStruct.Size = MPU_REGION_SIZE_64MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Enable the MPU */
HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
}

Let me know if you need something else.

Regards

KDJEM.1
ST Technical Moderator
June 11, 2026

Hello ​@DMast.1 ;

 

Could you please check the Recovery and for Access time, as I mentioned in my pervious comment.

The shared OCTOSPI configuration is not correct for OCTOSPI clock 25 MHz. What is the frequency of OCTOSPI use?

 

Thank you.

Kaouthar

 

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.
DMast.1
DMast.1Author
Associate III
June 16, 2026

Hello Kaouthar,

sorry for late reply but I was out of office.

I try to use the same Recovery and Access time as you suggest but the problem still present.

Now the OCTOSPI is running @ 50Mhz.

Thank you,

Renato

KDJEM.1
ST Technical Moderator
June 18, 2026

Hello ​@DMast.1 ;

 

The shared OCTOSPI configuration is not correct for OCTOSPI clock 50 MHz. Could you please refer to AN5050 Table 8. STM32CubeMX - Configuration of OCTOSPI parameters, and check your configuration.

 

Thank you.

Kaouthar

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.