2024-07-16 09:16 AM
Hello community,
I'm looking for some direction on how to setup the OSPI bus to communitcate with an external PSRAM part from ISSI - IS66WVO8M8 (datasheet attached). I've read through application notes and a handful of example projects but am having a hard time getting the logic to sync.
A few things I've done:
If you look in the MX_OCTOSPI2_Init function, I am trying to read from the ID register to confirm the correct part, run a quick and dirty write/read check, and then use the part as a GUI framebuffer.
static void MX_OCTOSPI2_Init(void)
{
/* USER CODE BEGIN OCTOSPI2_Init 0 */
/* USER CODE END OCTOSPI2_Init 0 */
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
/* USER CODE BEGIN OCTOSPI2_Init 1 */
/* USER CODE END OCTOSPI2_Init 1 */
/* OCTOSPI2 parameter configuration*/
hospi2.Instance = OCTOSPI2;
hospi2.Init.FifoThreshold = 1;
hospi2.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi2.Init.MemoryType = HAL_OSPI_MEMTYPE_APMEMORY;
hospi2.Init.DeviceSize = 26;
hospi2.Init.ChipSelectHighTime = 1;
hospi2.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
hospi2.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
hospi2.Init.WrapSize = HAL_OSPI_WRAP_32_BYTES;
hospi2.Init.ClockPrescaler = 1;
hospi2.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi2.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
hospi2.Init.ChipSelectBoundary = 0;
hospi2.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
hospi2.Init.MaxTran = 0;
hospi2.Init.Refresh = 0;
if (HAL_OSPI_Init(&hospi2) != HAL_OK)
{
Error_Handler();
}
sOspiManagerCfg.ClkPort = 2;
sOspiManagerCfg.DQSPort = 2;
sOspiManagerCfg.NCSPort = 2;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_2_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_2_HIGH;
if (HAL_OSPIM_Config(&hospi2, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN OCTOSPI2_Init 2 */
OSPI_RegularCmdTypeDef command = { 0 };
// Read the ID register
command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
command.FlashId = HAL_OSPI_FLASH_ID_1;
command.Instruction = 0xC000;
command.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
command.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
command.Address = 0;
command.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
command.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_ENABLE;
command.AlternateBytes = HAL_OSPI_ALTERNATE_BYTES_NONE;
command.DummyCycles = 2;
command.DataMode = HAL_OSPI_DATA_8_LINES;
command.NbData = 4;
command.DataDtrMode = HAL_OSPI_DATA_DTR_ENABLE;
command.DQSMode = HAL_OSPI_DQS_ENABLE;
if (HAL_OSPI_Command(&hospi2, &command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
//
uint32_t id = 0;
if (HAL_OSPI_Receive(&hospi2, (uint8_t*) &id, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (id == 0)
{
Error_Handler();
}
// Read the config register
command.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
command.Instruction = 0xC000;
command.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
command.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
command.Address = 0x00040000;
command.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
command.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
command.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_ENABLE;
command.AlternateBytes = HAL_OSPI_ALTERNATE_BYTES_NONE;
command.DataMode = HAL_OSPI_DATA_8_LINES;
command.NbData = 4;
command.DataDtrMode = HAL_OSPI_DATA_DTR_ENABLE;
command.DummyCycles = 2;
command.DQSMode = HAL_OSPI_DQS_ENABLE;
if (HAL_OSPI_Command(&hospi2, &command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
uint32_t config = 0;
if (HAL_OSPI_Receive(&hospi2, (uint8_t*) &config, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
if (id == 0)
{
Error_Handler();
}
OSPI_MemoryMappedTypeDef config = {
.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE,
.TimeOutPeriod = 0,
};
if (HAL_OSPI_MemoryMapped(&hospi2, &config) != HAL_OK)
{
Error_Handler();
}
uint8_t* src;
uint32_t errorCount = 0;
// write test
src=(uint8_t*) OCTOSPI2_BASE;
for (uint32_t i = 0; i < 0x0FFFFFFF; i++)
*src++ = i & 0xFF;
// Read test
src=(uint8_t*) OCTOSPI2_BASE;
for (uint32_t i = 0; i < 0x0FFFFFFF; i++)
if (*src++ != (i & 0xFF))
errorCount++;
if (errorCount != 0)
while(1);
/* USER CODE END OCTOSPI2_Init 2 */
}
As it is now the read operation will stall if the DQSM is enabled. If I disable DQSM then the read returns `0x88888888` instead of an expected value.
Any feedback and help on this is appreciated. Thanks in advance!
- Taylor
2024-07-16 10:10 AM
Does the ID read properly, as what?
All the code beyond that is unworkable, for RAM you'd need to properly create Read and Write command templates.
With the right commands, and configuration operation type