2025-09-19 1:51 AM
Hi All!
I try to use 2 pieces of IS66WVO32M8 PSRAM with multiplexed OSPI ( only the NSS pins not shared ) with STM32F585 in memory mapped mode.
Previously, I used 2 pieces of APMemory's APS12808L in memory mapped mode without any issues.
I reconfigured all the necessary parameters to IS66... according the datasheets (AN5050, STM32F585 OSPI errata), and other's suggestions in the forum, like:
https://community.st.com/t5/stm32-mcus-products/problem-with-psram-peripherals-of-stm32h735/m-p/706406#M257198
or
https://community.st.com/t5/stm32-mcus-products/problem-with-psram-peripherals-of-stm32h735/td-p/706406
I can read the ID and configuration registers, I can also modify them (Yellow square), but when I write directly or indirectly to the memory area, and read back for verification, it causes an error.
I tried to change the OSPI speed, using 55, 80, 100 MHz (with recalculated refresh rate using 4us tCEM: 220, 320, 400, 640), with- or without delay block, DHQC enabled/disabled (I know the errata), and DQS values, etc., but didn't work, except that some settings were totally wrong for configuration registers.
I don't know exactly what the error is: writing to memory area or reading it.
My biggest success is that I can read the same data from the same address in both memory mapped mode and normal mode (blue and green squares), but this data is not the same as what I wrote (pink square).
There is someone who configured and use successfully this type of PSRAM ?
Maybe I missed something ?
There is My ISSI PSRAM related routines, please check it:
#define ISSI_READ_DUMMY_CYCLES 5
#define ISSI_WRITE_DUMMY_CYCLES 0
#define ISSI_READ_COMMAND 0xA000
#define ISSI_WRITE_COMMAND 0x2000
#define ISSI_WRAPPED_READ_COMMAND 0x8000
#define ISSI_WRAPPED_WRITE_COMMAND 0x0000
#define ISSI_READ_CFG 0xC000
#define ISSI_WRITE_CFG 0x4000
#define ISSI_READ_PATTERN 0xF000
/*************************************************************************
* @brief Write ISSI register
*
* @PAram Ctx Component object pointer
* @PAram reg Register
* @PAram Address Register address
* @PAram Value Register value pointer
* @retval error status
*************************************************************************/
uint32_t ISSI_WriteReg(OSPI_HandleTypeDef *Ctx, uint16_t reg, uint32_t Address, uint8_t *Value, uint32_t count)
{
OSPI_RegularCmdTypeDef sCommand1={0};
if (Ctx->Instance == OCTOSPI1) {
sCommand1.FlashId = HAL_OSPI_FLASH_ID_1;
} else
if (Ctx->Instance == OCTOSPI2) {
sCommand1.FlashId = HAL_OSPI_FLASH_ID_2;
}
sCommand1.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand1.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand1.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand1.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
sCommand1.Instruction = reg;
sCommand1.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand1.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand1.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand1.Address = Address;
sCommand1.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand1.DataMode = HAL_OSPI_DATA_8_LINES;
sCommand1.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand1.NbData = count;
sCommand1.DummyCycles = ISSI_WRITE_DUMMY_CYCLES;
sCommand1.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand1.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
// Configure the command
if (HAL_OSPI_Command(Ctx, &sCommand1, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
// Transmission of the data
if (HAL_OSPI_Transmit(Ctx, (uint8_t *)(Value), HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/*************************************************************************
* @brief Read ISSI register value
*
* @PAram Ctx Component object pointer
* @PAram reg Register
* @PAram Address Register address
* @PAram Value Register value pointer
* @PAram LatencyCode Latency used for the access
* @retval error status
*************************************************************************/
uint32_t ISSI_ReadReg(OSPI_HandleTypeDef *Ctx, uint16_t reg, uint32_t Address, uint8_t *Value, uint32_t count)
{
OSPI_RegularCmdTypeDef sCommand;
if (Ctx->Instance == OCTOSPI1) {
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
} else
if (Ctx->Instance == OCTOSPI2) {
sCommand.FlashId = HAL_OSPI_FLASH_ID_2;
}
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
sCommand.Instruction = reg;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.Address = Address;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.NbData = count;
sCommand.DummyCycles = ISSI_READ_DUMMY_CYCLES;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
// Configure the command
if (HAL_OSPI_Command(Ctx, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
// Reception of the data
if (HAL_OSPI_Receive(Ctx, (uint8_t *)Value, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return HAL_ERROR;
}
return HAL_OK;
}
/*********************************************
* @brief Configure ISSI PSRAM
*
* @PAram hospi OSPI handle
* @return Size of the RAM in megabytes
*********************************************/
uint16_t Configure_ISSI(OSPI_HandleTypeDef *hospi)
{
uint8_t regW_MR0[4]={0x31, 0x32, 0x33, 0x34}; // MR0 + MR1
uint8_t regR_MR0[4]={0};
uint16_t regVal = 0;
uint16_t id = 0;
uint32_t size = 0;
// Read ID
if (ISSI_ReadReg(hospi, ISSI_READ_CFG, 0x00000000, (uint8_t*)(&id), 2 ) == HAL_OK)
{
Debug("Memory ID reg: 0x%04X\n", id);
if ((id & 0x0F) == 0x03 ) // ISSI
{
size = (1 << (((id >> 4) & 0x0F)+1)) * (1<<(((id >> 8) & 0x0F)+1)) ;
Debug("Memory Type: ISSI Column: %d bits, Rows: %d bits, Voltage: %s V, Size = %d Mbytes \n",
((id >> 4) & 0x0F)+1,
((id >> 8) & 0x0F)+1,
(id >> 13) == 1?"3.0":"1.8",
size / 1024 / 1024
);
}
}
// Read and modify configuration register
if (ISSI_ReadReg( hospi, ISSI_READ_CFG, 0x00040000, (uint8_t*)( ®Val ), 2 ) == HAL_OK)
{
/* ISSI configuration register
default: 0xF022
F0 = 1 111 000 0 : Noraml op, 24Ohm, Reserved, DQSM: 0
22 = 0010 0 0 10 : Latency: 5Clock, Variable, 32 burst len
1111000000100010
1111000000001010
*/
Debug("ISSI Config value: 0x%04X\n",regVal);
regVal |= (1<<3); // Fix latency
// regVal &= ~(0x70); // Latancy code: 3 cycle
// Check the write was success
if (ISSI_WriteReg( hospi, ISSI_WRITE_CFG, 0x00040000, (uint8_t*)( ®Val), 2 ) == HAL_OK)
{
uint16_t newRegVal = 0;
ISSI_ReadReg( hospi, ISSI_READ_CFG, 0x00040000, (uint8_t*)( &newRegVal), 2 );
Debug("ISSI New Config value: 0x%04X -> 0x%04X - %s\n",
regVal, newRegVal, newRegVal == regVal?"SUCCESS":"FAIL");
}
else
ERROR("ISSI reRead Configuration Error!\n");
}
else
ERROR("ISSI Read Configuration Error!\n");
/*
// Read preamble register value
if (ISSI_ReadReg(hospi, ISSI_READ_PATTERN, 0x00000001, (uint8_t*)( ®Val), 2 ) == HAL_OK)
{
Debug("ISSI Preamble Pattern: 0x%04X \n", regVal);
}
else
ERROR("ISSI Read Preamble Error!\n");
*/
hexdump("ISSI Not memory mapped write buffer:",regW_MR0,4);
// Test conventioanl (direct) SPI transfer to memory
if (ISSI_WriteReg( hospi, ISSI_WRITE_COMMAND, 0x00000010, regW_MR0, 4 ) == HAL_OK)
{
if (ISSI_ReadReg( hospi, ISSI_READ_COMMAND, 0x00000010, regR_MR0, 4 ) == HAL_OK)
{
hexdump("ISSI continuous burst: Addr: 0x10",regR_MR0,4);
}
}
if (ISSI_WriteReg( hospi, ISSI_WRITE_COMMAND, 0x00000020, regW_MR0, 4 ) == HAL_OK)
{
if (ISSI_ReadReg( hospi, ISSI_READ_COMMAND, 0x00000020, regR_MR0, 4 ) == HAL_OK)
{
hexdump("ISSI continuous burst: Addr: 0x20",regR_MR0,4);
}
}
if (ISSI_WriteReg( hospi, 0x0000, 0x00000030, regW_MR0, 4 ) == HAL_OK)
{
if (ISSI_ReadReg( hospi, 0x8000, 0x00000030, regR_MR0, 4 ) == HAL_OK)
{
hexdump("ISSI wrapped burst: Addr: 0x30",regR_MR0,4);
}
}
return size / 1024 / 1024;
}
/*********************************************
* @brief Initialize OSPI to ISSI PSRAM
*
* @PAram hospi return handle of the configured OSPI
* @PAram Instance Instance of the OSPI (OCTOSPI1 / OCTOSPI2)
*********************************************/
void OSPI_ISSI_PSRAM_Init(OSPI_HandleTypeDef *hospi, OCTOSPI_TypeDef *Instance)
{
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
hospi->Instance = Instance;
hospi->Init.FifoThreshold = 4; //Not used in memory mapped mode
hospi->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi->Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX_RAM;
hospi->Init.DeviceSize = 25;
hospi->Init.ChipSelectHighTime = 3; // CS High time in clock period, before next Read/Write 100MHz = 10ns
hospi->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi->Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
hospi->Init.ClockPrescaler = 2; // Base: HSE = 16MHz PLL1*N=20 PLL1/Q=2 => Base=160MHz -> Precaler=2 -> OSPI=80 MHz
hospi->Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE; // None
hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
hospi->Init.ChipSelectBoundary = 8; //32 MB / 128 KB = 256 → 2^8
hospi->Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;
hospi->Init.MaxTran = 0;
hospi->Init.Refresh = 320; //640; //320 -> //
/*
Refresh value:
OCTOSPI Clock period x Refresh = tCEM
160MHz = 0,00000000625 sec
100MHz = 0,00000001 sec
80MHz = 0,0000000125 sec
55MHz = 0,0000000182 sec
4 us = 0,000004 sec
8 us = 0,000008 sec
Refresh = tCEM / Clock -> 640
4 us @ 80MHz -> 320
4 us @ 100MHz -> 400
4 us @ 160MHz -> 640
8 us @ 80MHz -> 640
8 us @ 160MHz -> 1280
4 us @ 55MHz -> 220
ISSI :
tCSM Chip Select Maximum Low Time ( ~ 85°C @ 166MHz ) = 4.0 us
APMem:
tCEM CE# low pulse width Standard temp @ 109MHz = 8 us
*/
if (HAL_OSPI_Init(hospi) != HAL_OK)
{
ERROR("OSPI Init Error!\n");
Error_Handler();
}
// OSPI Manager configuration : 2 device multiplexed , except CS
sOspiManagerCfg.ClkPort = 1;
sOspiManagerCfg.DQSPort = 1;
sOspiManagerCfg.NCSPort = (Instance == OCTOSPI1)?1:2;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
if (HAL_OSPIM_Config(hospi, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
ERROR("OSPI Manager Init Error!\n");
Error_Handler();
}
// Configure Delay block if need
if (hospi->Init.DelayBlockBypass == HAL_OSPI_DELAY_BLOCK_USED)
{
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
if (HAL_OSPI_DLYB_SetConfig(hospi, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
{
ERROR("OSPI Delay Block Init Error!\n");
Error_Handler();
}
}
Debug("%s() - Success!\n", __FUNCTION__);
}
/*********************************************
* @brief Initialize ISSI PSRAM to memory mapped mode
*
* @PAram hospi handle of the OSPI
* @return true - Initilaization success
* @return false - something went wrong
*********************************************/
bool PSRAM_ISSI_ModuleInit( OSPI_HandleTypeDef *hospi )
{
OSPI_MemoryMappedTypeDef sMemMappedCfg;
OSPI_RegularCmdTypeDef sCommand = {0};
/* Enable Compensation cell */
EnableCompensationCell();
Debug("CompensationCell enabled\n");
if (hospi->Init.DelayBlockBypass == HAL_OSPI_DELAY_BLOCK_USED)
{
LL_DLYB_CfgTypeDef dlyb_cfg, dlyb_cfg_test;
// Delay block configuration
if (HAL_OSPI_DLYB_GetClockPeriod(hospi,&dlyb_cfg) != HAL_OK)
{
Debug("%s() - HAL_OSPI_DLYB_GetClockPeriod Error!\n",__FUNCTION__);
Error_Handler() ;
}
dlyb_cfg.Units = 0;
// when DTR, PhaseSel is divided by 4 (emperic value)
dlyb_cfg.PhaseSel /= 4;
// save the present configuration for check
dlyb_cfg_test = dlyb_cfg;
// set delay block configuration
HAL_OSPI_DLYB_SetConfig(hospi,&dlyb_cfg);
// check the set value
HAL_OSPI_DLYB_GetConfig(hospi,&dlyb_cfg);
if ((dlyb_cfg.PhaseSel != dlyb_cfg_test.PhaseSel) || (dlyb_cfg.Units != dlyb_cfg_test.Units))
{
Debug("%s() - HAL_OSPI_DLYB_GetConfig Error!\n",__FUNCTION__);
return false ;
}
}
// Configure_APMemory(hospi);
uint16_t ramSize = Configure_ISSI(hospi);
// Configure Memory Mapped mode
if (hospi->Instance == OCTOSPI1)
{
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
}
else if (hospi->Instance == OCTOSPI2)
{
sCommand.FlashId = HAL_OSPI_FLASH_ID_2;
}
// Configure Write command
sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = ISSI_WRITE_COMMAND;//APS6408_WRITE_CMD;
sCommand.DummyCycles = ISSI_WRITE_DUMMY_CYCLES;//DUMMY_CLOCK_CYCLES_WRITE;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
sCommand.DataDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
ERROR("Configure Write Command Error! \n");
OSPI_Error();
return false;
}
// Configure read command
sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
sCommand.Instruction = ISSI_READ_COMMAND; //APS6408_READ_CMD;
sCommand.DummyCycles = ISSI_READ_DUMMY_CYCLES;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
ERROR("Configure Read Command Error !\n");
OSPI_Error();
return false;
}
// Enable memory mapped mode
sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;
sMemMappedCfg.TimeOutPeriod = 0xA0;//34;
if (HAL_OSPI_MemoryMapped(hospi, &sMemMappedCfg) != HAL_OK)
{
ERROR("Configure Memory mapped mode Error !\n");
OSPI_Error();
return false;
}
Debug("%s() - Success: %d Mbyte \n",__FUNCTION__, ramSize);
return true;
}
/*************************************
* @brief PSRAM Initialization
*************************************/
void PSRAM_Init()
{
bool ret = true;
Debug("=== PSRAM 1 INIT ===\n");
OSPI_ISSI_PSRAM_Init(&hospi1_psram, OCTOSPI1);
if (PSRAM_ISSI_ModuleInit( &hospi1_psram ) == true)
{
hexdump("OSPI1 Data MemoryMapped Mode",(uint8_t*)OCTOSPI1_BASE, 128 );
if (PSRAM_Test( OCTOSPI1_BASE ) == true){
Debug("PSRAM 1 test Success!\n");
} else {
ERROR("PSRAM 1 test Error!\n");
ret = false;
}
}
else
ret = false;
if (ret == false){
ERROR("OSPI PSRAM initialization failed!\n");
Error_Handler();
}
}
Thank You!
2025-09-19 7:30 AM
Hello @ccuebler ;
Could you please check the dummy cycle?
Is the cache enabled?
For CPU accesses, try to enable ICACHE and/or DCACHE, and configure the OCTOSPI memory as cacheable (CACHE only performs 32-bit read accesses).
I hope this help.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-21 11:32 PM
Hi @KDJEM.1 !
Thanks for the answer,
The ICache was always enabled on my fw. I also used DCache in Wrap and Incremental modes, but nothing changed...
I used only ICache With APMemory and it worked perfectly.
Thank You!
Krisztian
2025-09-22 2:36 AM
Hello @ccuebler ;
What about the dummy cycle? Does 5 correspond to the value mentioned in the memory datasheet?
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-22 4:03 AM
Hello @KDJEM.1
I somehow missed Your question.
I checked again the datasheet of PSRAM, and yes, I only used dummy cycles for read, but it need to writings.
According to the datasheet I'm using 10-10 cycles, and the result is a little closer to My expectations, but not perfect.
In memory mapped mode some data was almost good but not in the right address.
I tried to change the dummy cycles, and refresh time but this was the best result.
About the DCache, You are right, I disabled it last time for a test.
Now, It enabled again in incremental mode
Thank You.
2025-09-22 5:33 AM
Hello @ccuebler ;
This Overall FAQs for QUADSPI/OCTOSPI/HSPI/XSPI - STMicroelectronics Community FAQ can help you to understand when is Refresh rate used and how is it calculated?
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-22 11:42 PM
Hello @KDJEM.1
I read Your link earlier (it was very useful) , and I used this formula from the beginning.
My OSPI input clock is 160MHz and the OSPI prescaler is 2, so the OSPI drives the memory with 80MHz.
However the ISSSI datasheet not contain exact information from refresh time, I used 4us because it typically most of the (APMemory) PSRAMs. (May the ISSI is not so fast?). That's the reason why I tried some other refresh value.
I calculated the refresh to various scenario.( please take a look my source )
hospi->Instance = Instance;
hospi->Init.FifoThreshold = 4; //Not used in memory mapped mode
hospi->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi->Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX_RAM;
hospi->Init.DeviceSize = 25;
hospi->Init.ChipSelectHighTime = 2; // CS High time in clock period, before next Read/Write 100MHz = 10ns (min. 6ns)
hospi->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi->Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
hospi->Init.ClockPrescaler = 2; // Base: HSE = 16MHz PLL1*N=20 PLL1/Q=2 => Base=160MHz -> Precaler=2 -> OSPI=80 MHz
hospi->Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE; // None
hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
hospi->Init.ChipSelectBoundary = 8; //32 MB / 128 KB = 256 → 2^8
hospi->Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;
hospi->Init.MaxTran = 0;
hospi->Init.Refresh = 320;
/*
Refresh value:
OCTOSPI Clock period x Refresh = tCEM
160MHz = 0,00000000625 sec
100MHz = 0,00000001 sec
80MHz = 0,0000000125 sec
55MHz = 0,0000000182 sec
4 us = 0,000004 sec
8 us = 0,000008 sec
Refresh = tCEM / Clock -> 640
4 us @ 80MHz -> 320
4 us @ 100MHz -> 400
4 us @ 160MHz -> 640
8 us @ 80MHz -> 640
8 us @ 160MHz -> 1280
4 us @ 55MHz -> 220
ISSI :
tCSM Chip Select Maximum Low Time ( ~ 85°C @ 166MHz ) = 4.0 us
APMem:
tCEM CE# low pulse width Standard temp @ 109MHz = 8 us
*/
In this project I used 3 types of APMemory PSRAMs in same layout (2 chip ) with success.
Unfortunately the APMemory not have bigger capacity PSRAM with 3V power, and I need to change to ISSI, which is pin compatible with APMemory.
May I missed something?
Thank you.
2025-09-23 4:56 AM - edited 2025-09-23 6:46 AM
Hi @KDJEM.1
An addition information:
Now, the direct read / write is good with weird values:
refresh = 320, Write dummy cycle: 4, read dummy cycle: 5
I tried five times with 1024 bytes long buffer, in a different address.
Because it was good, I ran the delay block tuner (https://github.com/STMicroelectronics/STM32CubeU5/tree/main/Projects/B-U585I-IOT02A/Examples/DLYB/DLYB_OSPI_PSRAM_ExhaustiveTuning)
and I use that values :
dlyb_cfg.PhaseSel = 1;
dlyb_cfg.Units = 50;
I test it, but in memory mapped mode not works properly.
More interesting: The readed data shifted by 8 bytes...
I tried with or without DCache.
Have You any idea?
Thank You
Krisztian
2025-09-29 2:56 AM
Hello @ccuebler ,
Thank you for updating post.
For memory mapped issue, I recommend you to look at How to calibrate the delay block with the OCTOSPI interface. This article may help you to use and calibrate the delay block.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2025-09-30 12:59 AM - edited 2025-09-30 2:52 AM
Hi @KDJEM.1
Thank You, but as I mentioned, I ran this "delay block tuner / calibrator".
Finally, we replaced the ISSI to APS25608N (and configure it), and it works, but need to modify the whole product because of the 1.8V power supply.
So, if You or others in ST know the solution, please let me know.
Thank you.