Skip to main content
DReis.2
Associate II
October 8, 2021
Solved

OctoSPI HYPERBUS PSRAM Memory Mapped - STM32H7B3I-EVAL

I am trying to use the OCTOSPI2 (connector MB1242) in dev kit STM32H7B3I-EVAL with the Hypebus PSRAM IS66WVH8M8ALL-100.

I successfully configured the memory to write and read in memory map mode, however this can only be done if the write is immediately followed by the read. For instance, if I add a 1ms delay after write an address, reading the same address will return wrong content.

HyperBus Configuration

__weak HAL_StatusTypeDef MX_OSPI_RAM_Init(OSPI_HandleTypeDef *hospi, MX_OSPI_InitTypeDef *Init) {
	OSPI_HyperbusCfgTypeDef sHyperbusCfg;
	HAL_StatusTypeDef status;
 
	/* OctoSPI initialization */
	hospi->Instance = OCTOSPI2;
	HAL_OSPI_DeInit(hospi);
 
	/*
	 * With Init->ClockPrescaler = 3, the RAM will run at 40 MHz
	 * ClockPrescaler = 3
	 * Refresh = 160
	 */
 
	hospi->Init.FifoThreshold = 4;
	hospi->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
	hospi->Init.MemoryType = HAL_OSPI_MEMTYPE_HYPERBUS;
	hospi->Init.DeviceSize = Init->MemorySize;
	hospi->Init.ChipSelectHighTime = 8;
	hospi->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
	hospi->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
	hospi->Init.ClockPrescaler = Init->ClockPrescaler;
	hospi->Init.SampleShifting = Init->SampleShifting;
	hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
	hospi->Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
	hospi->Init.Refresh = 160;//373; /*4us @40MHz*/
	hospi->Init.ChipSelectBoundary = 1;
	hospi->Init.ClkChipSelectHighTime = 0;
	hospi->Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
 
	status = HAL_OSPI_Init(hospi);
 
	if (status == HAL_OK) {
		sHyperbusCfg.RWRecoveryTime = RW_RECOVERY_TIME;
		sHyperbusCfg.AccessTime = DEFAULT_INITIAL_LATENCY;
		sHyperbusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE;
		sHyperbusCfg.LatencyMode = HAL_OSPI_FIXED_LATENCY;
 
		status = HAL_OSPI_HyperbusCfg(&hospi_ram[0], &sHyperbusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
	}
 
	return status;
}
 
int32_t BSP_OSPI_RAM_Init(uint32_t Instance, BSP_OSPI_RAM_Init_t *Init) {
	int32_t ret;
	MX_OSPI_InitTypeDef ospi_init;
 
	/* Check if the instance is supported */
	if (Instance >= OSPI_RAM_INSTANCES_NUMBER) {
		ret = BSP_ERROR_WRONG_PARAM;
	} else {
		/* Check if the instance is already initialized */
		if (Ospi_Ram_Ctx[Instance].IsInitialized == OSPI_ACCESS_NONE) {
#if (USE_HAL_OSPI_REGISTER_CALLBACKS == 0)
			/* Msp OSPI initialization */
			OSPI_RAM_MspInit(&hospi_ram[Instance]);
#else
 /* Register the OSPI MSP Callbacks */
 if(OspiRam_IsMspCbValid[Instance] == 0UL)
 {
 if(BSP_OSPI_RAM_RegisterDefaultMspCallbacks(Instance) != BSP_ERROR_NONE)
 {
 return BSP_ERROR_PERIPH_FAILURE;
 }
 }
#endif /* USE_HAL_OSPI_REGISTER_CALLBACKS */
 
			/* Fill config structure */
			ospi_init.ClockPrescaler = 7; /* OctoSPI clock = 280MHz / ClockPrescaler = 40MHz */
			ospi_init.MemorySize = (uint32_t)POSITION_VAL(ISS66WVH8M8_RAM_SIZE);
			ospi_init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
 
			/* STM32 OSPI interface initialization */
			if (MX_OSPI_RAM_Init(&hospi_ram[Instance], &ospi_init) != HAL_OK) {
				ret = BSP_ERROR_PERIPH_FAILURE;
			}
			/* Configure the memory */
			else if (BSP_OSPI_RAM_ConfigHyperRAM(Instance,
					Init->LatencyType,
					Init->BurstType,
					Init->BurstLength) != BSP_ERROR_NONE) {
				ret = BSP_ERROR_COMPONENT_FAILURE;
			}
			else {
				ret = BSP_ERROR_NONE;
			}
		} else {
			ret = BSP_ERROR_NONE;
		}
	}
 
	/* Return BSP status */
	return ret;
}

Test code

BSP_OSPI_RAM_Init_t sOSPI_RAM_Init;
 
	/** Init external ram **/
	sOSPI_RAM_Init.LatencyType = BSP_OSPI_RAM_FIXED_LATENCY;
	sOSPI_RAM_Init.BurstType = BSP_OSPI_RAM_LINEAR_BURST;
	sOSPI_RAM_Init.BurstLength = BSP_OSPI_RAM_BURST_32_BYTES;
	if (BSP_OSPI_RAM_Init(0, &sOSPI_RAM_Init) != BSP_ERROR_NONE) {
		Error_Handler();
	}
 
	/** Put exRam in memory mapped mode **/
	if (BSP_OSPI_RAM_EnableMemoryMappedMode(0) != BSP_ERROR_NONE) {
		Error_Handler();
	}
 
 while (1) {
		mem_addr = (__IO uint16_t*)(OCTOSPI2_BASE + address);
 
		for (index = 0; index < BUFFERSIZE; (index += 2)) {
			/* Writing Sequence --------------------------------------------------- */
			*mem_addr = *(uint16_t*)&aTxBuffer[index];
			//HAL_Delay(1); <<<---- Adding this delay cause the read to fail
			/* Reading Sequence --------------------------------------------------- */
			if (*mem_addr != *(uint16_t*)&aTxBuffer[index]) {
				BSP_LED_On(LED_RED);
			}
 
			mem_addr++;
		}
 
		BSP_LED_Toggle(LED_GREEN);
		HAL_Delay(100);
 
		address += OSPI_HYPERRAM_INCR_SIZE;
		if (address >= OSPI_HYPERRAM_END_ADDR) {
			address = 0;
		}
 }

I tried changing the timming configuration in many ways but none with success. Currently the MCU is running at 280MHz and the OctoSPI Clock is 40MHz.

Does anybody have a similar issue?

This topic has been closed for replies.
DReis.2
DReis.2Best answer
Associate II
October 8, 2021

ChahinezC Thank you for the tip.

I actually found that I forgot to fit resistor R75 in the EVAL board.

Now everything is working fine

2 replies

ChahinezC
Associate II
October 8, 2021

Hello @DReis.2​,

I suggest you setting the ChipSelectBoundary to 0.

Please keep me informed whether this helped you solve your problem.

Chahinez.

DReis.2
DReis.2AuthorBest answer
Associate II
October 8, 2021

ChahinezC Thank you for the tip.

I actually found that I forgot to fit resistor R75 in the EVAL board.

Now everything is working fine