cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7A3ZITQ_LQFP144 QSPI Timeout Issue

khkim
Associate II
 

Hello,

I am using the STM32H7A3ZITQ and have encountered an issue while controlling the MT25QL128ABA1ESESF0IT flash memory during the flash read process. I am operating in QSPI mode. During extended aging evaluations, a 5-second timeout (a busy flag is not cleared) intermittently occurs in the LL_OSPI_Receive() function.

Since this issue occurs randomly, I tried to force the conditions to analyze the problem. I discovered that in debug mode, if I set a breakpoint and step over the function, the problem occurs 100% of the time.

Interestingly, if I add a variable inside the read function, the issue that occurs 100% of the time disappears. When examining the assembly code, I found that adding a volatile variable generates two additional assembly instructions, leading to a delay that seems to resolve the issue. However, attempting to induce a similar delay using asm("nop") did not resolve the issue.

I confirmed that adding a variable resolves the problem. Adding one, two, up to four variables resolves the issue, but adding five variables causes the issue to reappear. This leads me to believe that the problem might be due to something other than a timing issue.

I would appreciate any assistance you can provide regarding this phenomenon.

Thank you.

 

khkim_0-1719807496263.png

 

khkim_1-1719807509696.png
 
khkim_2-1719807523399.png

 

5 REPLIES 5
Saket_Om
ST Employee

Hello @khkim 

 

Please try to use the feature "Insert/Edit code sample" to share your code.

 

Saket_Om_0-1719828777130.png

 

 Concerning your issue, did you set the correct dummy cycle according to the device specification?

If your question is answered, please close this topic by clicking "Accept as Solution".

Thanks
Omar

You're pacing this transfer, how much data are you moving, what kind of clock speed do you have on the bus vs prescaler?

What do the registers show?

Don't break-point or put a peripheral view over the top of the QSPI/OSPI, the former at user response rates is problematic, the latter will break FIFO, etc. as invasive.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thanks for your answer,

 

Here is my initialization code for OctoSPI1. I evaluated the number of dummy cycles from 1 to 15. It only works correctly with 10 dummy cycles. based on this, I estimate that we are operating at a clock frequency of 125MHz(Flash to read only under the condition that the dummy cycle is 10.). I am currently reading only 4 bytes.


void OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
LL_OSPI_DeInit(OCTOSPI1);

/* USER CODE END OCTOSPI1_Init 0 */

OSPI_InitTypeDef OSPI_InitStruct = {0};

OSPIM_CfgTypeDef sOspiManagerCfg = {0};

LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

/*Set clock source*/
__LL_RCC_PLLCLKOUT_ENABLE(RCC_PLLCFGR_DIVQ1EN);
LL_RCC_SetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE_PLL2R);
//LL_RCC_SetOSPIClockSource(LL_RCC_OSPI_CLKSOURCE_PLL1Q);

/* OCTOSPI1 clock enable */
__LL_RCC_OCTOSPIM_CLK_ENABLE();
__LL_RCC_OSPI1_CLK_ENABLE();

/* Peripheral clock enable */
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOF);
LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_GPIOG);
/**OCTOSPI1 GPIO Configuration
PF6 ------> OCTOSPIM_P1_IO3
PF7 ------> OCTOSPIM_P1_IO2
PF8 ------> OCTOSPIM_P1_IO0
PF9 ------> OCTOSPIM_P1_IO1
PF10 ------> OCTOSPIM_P1_CLK
PG6 ------> OCTOSPIM_P1_NCS
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_6|LL_GPIO_PIN_7|LL_GPIO_PIN_8|LL_GPIO_PIN_9;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = LL_GPIO_AF_10;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_10;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = LL_GPIO_AF_9;
LL_GPIO_Init(GPIOF, &GPIO_InitStruct);

GPIO_InitStruct.Pin = LL_GPIO_PIN_6;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = LL_GPIO_AF_10;
LL_GPIO_Init(GPIOG, &GPIO_InitStruct);

/* USER CODE BEGIN OCTOSPI1_Init 1 */

/* USER CODE END OCTOSPI1_Init 1 */
OSPI_InitStruct.FifoThreshold = 4;
OSPI_InitStruct.DualQuad = LL_OSPI_DUALQUAD_DISABLE;
OSPI_InitStruct.MemoryType = LL_OSPI_MEMTYPE_MICRON;
OSPI_InitStruct.DeviceSize = 24;
OSPI_InitStruct.ChipSelectHighTime = 6;
OSPI_InitStruct.FreeRunningClock = LL_OSPI_FREERUNCLK_DISABLE;
OSPI_InitStruct.ClockMode = LL_OSPI_CLOCK_MODE_0;
OSPI_InitStruct.WrapSize = LL_OSPI_WRAP_NOT_SUPPORTED;
OSPI_InitStruct.ClockPrescaler = 1;
OSPI_InitStruct.SampleShifting = LL_OSPI_SAMPLE_SHIFTING_HALFCYCLE;
OSPI_InitStruct.DelayHoldQuarterCycle = LL_OSPI_DHQC_DISABLE;
OSPI_InitStruct.ChipSelectBoundary = 0;
OSPI_InitStruct.DelayBlockBypass = LL_OSPI_DELAY_BLOCK_BYPASSED;
OSPI_InitStruct.MaxTran = 0;
OSPI_InitStruct.Refresh = 0;
LL_mDelay(1);
if (LL_OSPI_Init(OCTOSPI1, &OSPI_InitStruct) != SUCCESS)
{
Error_Handler();
}

 

ErrorStatus LL_OSPI_Receive(OCTOSPI_TypeDef *OSPIx, uint8_t *pData, uint32_t Timeout)
{
ErrorStatus status;
uint32_t tickstart = GetTick();
__IO uint32_t *data_reg = &OSPIx->DR;
uint32_t addr_reg =OSPIx->AR;
uint32_t ir_reg = OSPIx->IR;
uint8_t *pBuffPtr;
__IO uint32_t XferSize;
__IO uint32_t XferCount;

/* Check the data pointer allocation */
if (pData == NULL)
{
status = ERROR;
}
else
{

/* Configure counters and size */
XferCount = READ_REG(OSPIx->DLR) + 1U;
XferSize = XferCount;
pBuffPtr = pData;

/* Configure CR register with functional mode as indirect read */
MODIFY_REG(OSPIx->CR, OCTOSPI_CR_FMODE, OSPI_FUNCTIONAL_MODE_INDIRECT_READ);

/* Trig the transfer by re-writing address or instruction register */
if ((READ_REG(OSPIx->DCR1) >> OCTOSPI_DCR1_MTYP_Pos) == 1UL)
{
WRITE_REG(OSPIx->AR, addr_reg);
}
else
{
if (READ_BIT(OSPIx->CCR, OCTOSPI_CCR_ADMODE) != LL_OSPI_ADDRESS_NONE)
{
WRITE_REG(OSPIx->AR, addr_reg);
}
else
{
WRITE_REG(OSPIx->IR, ir_reg);
}
}

do
{
/* Wait till fifo threshold or transfer complete flags are set to read received data */
status = OSPI_WaitFlagStateUntilTimeout(OSPIx, (LL_OSPI_FLAG_FT | LL_OSPI_FLAG_TC), SET, tickstart, Timeout);

if (status != SUCCESS)
{
break;
}

*pBuffPtr = *((__IO uint8_t *)data_reg);
pBuffPtr++;
XferCount--;
} while(XferCount > 0U);

if (status == SUCCESS)
{
/* Wait till transfer complete flag is set to go back in idle state */
status = OSPI_WaitFlagStateUntilTimeout(OSPIx, LL_OSPI_FLAG_TC, SET, tickstart, Timeout);
//while((__LL_OSPI_GET_FLAG(OSPIx, LL_OSPI_FLAG_TC)) != SET){}
//if ((__LL_OSPI_GET_FLAG(OSPIx, LL_OSPI_FLAG_TC)) == SET)
//{
// status = SUCCESS;
//}

if (status == SUCCESS)
{
/* Clear transfer complete flag */
__LL_OSPI_CLEAR_FLAG(OSPIx, LL_OSPI_FLAG_TC);

}
}

}

/* Return function status */
return status;
}


sOspiManagerCfg.ClkPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = LL_OSPIM_IOPORT_1_LOW;
if (LL_OSPIM_Config(OCTOSPI1, &sOspiManagerCfg) != SUCCESS)
{
Error_Handler();
}

/* USER CODE BEGIN OCTOSPI1_Init 2 */
//__LL_OSPI_ENABLE(OCTOSPI1);


/* USER CODE END OCTOSPI1_Init 2 */
}

 

 

khkim_0-1719894995303.png

khkim_1-1719895019437.png

khkim_0-1719909507577.png

 

khkim_3-1719895390576.png

 

 

khkim_1-1719996492674.png

In the conditions where the issue occurs, the clock continuously generates without interruption, and the data line remains consistently high and CS line low.

Hi, 
Could you please provide some advice to help identify the root cause?