2024-02-27 06:06 AM
2024-02-28 04:34 AM
Hello @BDoon.1 ,
Could you please give more details about your OCTOSPI configuration?
Which PSRAM memory reference are you using?
I recommend you to refer to the memory datasheet and AN5050 precisely section "6.2.4 OCTOSPI configuration and parameter settings" and check the OCTOSPI configuration Sample shifting, Delay hold quarter cycle, Chip select boundary, Refresh rate ......
May be this example can help you OSPI_PSRAM_MemoryMapped.
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.
2024-02-28 11:35 AM - edited 2024-02-29 07:32 AM
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_OSPI;
PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_SYSCLK;
HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
__HAL_RCC_OSPI2_CLK_ENABLE();
OSPI_HyperbusCfgTypeDef sHyperBusCfg = {0};
/* These settings chosen for HyperBus clock freq = 80MHz */
/* This driver is to support HyperRAM only, meaning that several of these options are fixed */
OSPI_HandleTypeDef hospi;
memset(&hospi, 0, sizeof(OSPI_HandleTypeDef));
self->hospi.Instance = OCTOSPI2;
self->hospi.Init.FifoThreshold = 1;
self->hospi.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
self->hospi.Init.MemoryType = HAL_OSPI_MEMTYPE_HYPERBUS;
self->hospi.Init.DeviceSize = 23;
self->hospi.Init.ChipSelectHighTime = 1;
self->hospi.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
self->hospi.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
self->hospi.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
// Find the closest prescaler for the desired clock frequency
uint32_t sourceClockFrequency = HAL_RCC_GetHCLKFreq();
self->hospi.Init.ClockPrescaler = 1;
for (uint32_t prescaler = 1; prescaler < PRESCALER_MAX; prescaler++)
{
uint32_t ospiClockFrequency = sourceClockFrequency / prescaler;
if (ospiClockFrequency <= self->config.ClockFrequency)
{
self->hospi.Init.ClockPrescaler = prescaler;
break;
}
}
self->hospi.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
self->hospi.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
self->hospi.Init.ChipSelectBoundary = 0;
self->hospi.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_USED;
self->hospi.Init.MaxTran = 0;
self->hospi.Init.Refresh = 160; // set a tCSM of 4us, the worst case at temperature for any of our parts
if (HAL_OSPI_Init(&hospi) != HAL_OK)
return false;
sHyperBusCfg.RWRecoveryTime = 6;
sHyperBusCfg.AccessTime = 6;
sHyperBusCfg.WriteZeroLatency = HAL_OSPI_LATENCY_ON_WRITE;
sHyperBusCfg.LatencyMode = HAL_OSPI_FIXED_LATENCY; // Can use variable if config reg 0 is modified
if (HAL_OSPI_HyperbusCfg(&hospi, &sHyperBusCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
return false;
// Find the closest DLYB offset
HAL_OSPI_DLYB_CfgTypeDef delayBlockConfig;
if(HAL_OSPI_DLYB_GetClockPeriod(&hospi, &delayBlockConfig) == HAL_OK)
{
/* The ST example project divides this down. Essentially, we want the phase shift to
* be just enough that we guarantee the data is valid but not so much as to reduce
* Thold too much. See section 7 of app note.*/
self->delayBlockConfig.PhaseSel /= 4;
}
else
return false;
// Configure the delay block after having discovered the settings
HAL_OSPI_DLYB_CfgTypeDef dlyb_cfg_test;
dlyb_cfg_test = delayBlockConfig;
HAL_OSPI_DLYB_SetConfig(&hospi, &dlyb_cfg_test);
HAL_OSPI_DLYB_GetConfig(&hospi, &dlyb_cfg_test);
if(delayBlockConfig.PhaseSel != dlyb_cfg_test.PhaseSel || self->delayBlockConfig.Units != dlyb_cfg_test.Units)
return false;
DelayMilliseconds(100); // without this delay, certain boards fail the subsequent call to ConfigureOSPILatency
// Configure latency after having discovered the settings
if(!ConfigureOSPILatency())
return false;
DelayMilliseconds(100);
if(!ConfigOSPIMemoryMap(self))
return false;
2024-02-29 12:34 AM
For displaying code, pleas use the </> button...
2024-02-29 06:42 AM
Almost readable...
Anyway, which RAM are you actually using?
sHyperBusCfg.AccessTime = 6;
There are a few parameters depending on the actual IC used.
I will be using an Infineon S70KL1282 soon, switching from H735-Disco's S70KL1281.
And the S70KL1282 needs one more clock cycle, 7 instead of 6.
I don't know if the above is that HAL setting, with direct register access, it's the TACC bits in HLCR:
/* HLCR: HyperBus latency configuration register
* TRWR[7:0] = x read write recovery time
* TACC[7:0] = y access time
* WZL = 0 latency on write access
* LM = 1 fixed latency
*/
pOspiHypRam->HLCR = (OSPI_HYPERRAM_RW_REC_TIME << OCTOSPI_HLCR_TRWR_Pos) |
(OSPI_HYPERRAM_LATENCY << OCTOSPI_HLCR_TACC_Pos) |
OCTOSPI_HLCR_LM;
2024-02-29 07:29 AM - edited 2024-02-29 07:33 AM
The ram we're using is an Infineon S27KL0642. We've scrutinized the settings for our application and clock setup. I should mention that the code will run correctly for days on end. We've just found a specific test case that produces this skipped read when left to run overnight.
Do you think an incorrect AccessTime value could cause it to skip 2 bytes but still clock the full transfer like we're seeing?
HAL_OSPI_HyperbusCfg does set HLCR. I've also updated the code in my post again, hopefully you'll find it more readable now!
2024-02-29 08:25 AM
> Do you think an incorrect AccessTime value could cause it to skip 2 bytes but still clock the full transfer like we're seeing?
Yes and no, strange that it is running for hours otherwise.
Guessing wildly: 1 latency clock cycle missing might lead to 2 missing bytes at double data rate.
So better check the datasheet again, I just had a quick glance at it and ... that was not enough to understand it, looks like latency count is not constant.
Maybe LatencyMode = HAL_OSPI_FIXED_LATENCY is not the right way, but again just guessing.
I just compared to my code for the S70KL1281 + H7 (IDK if the OCTOSPI peripheral is different from U5), as far as I can understand the HAL stuff...
- I use a FIFO threshold of 4, and because I read about some STM32 having trouble with mem mapped mode and PSRAMs and alignment, all the buffers I use have the __attribute__((aligned(4))) .
- OSPI_HYPERRAM_NCS_HITIME in DCR1 is set to 8 (yours: ChipSelectHighTime = 1)
- Delay Block is enabled, but delay set to 0, I don't know what the HAL stuff does
- I think you refresh every 2 µs with refresh rate of 160 at 80 MHz, but I might be wrong
Also check again the code before the read that fails. That any different from other reads?
2024-05-15 08:50 AM