cancel
Showing results for 
Search instead for 
Did you mean: 

OctoSPI HYPERBUS PSRAM Memory Mapped - STM32H7B3I-EVAL

DReis.2
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions
DReis.2
Associate II

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

View solution in original post

2 REPLIES 2
ChahinezC
Lead

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
Associate II

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