cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 Delay Block Configuration (LNGF does not get set)

JRS
Associate III

Hi,

I was trying to configure the Delay Block on the STM32H723xx for the Octo-SPI (in my case OCTOSPI2). The datasheet documentation on that part is quite simple with 6 steps, but I get stuck at the Line Length Valid Flag. After the first round (unit = 0) is ok, at the second unit (unit = 1) it gets stuck while waiting for the LNGF Flag which never comes.

Input Clock of the OSPI2 Module is 100 MHz (tried it with PLL or HCLK3). Hardware Registers of the OSPI2 in Debugger look fine: DLYB_CR-SEN|DEN, DLYB_CFGR-SEL=12, LNGF for first round =1, UNIT =1 for second round, but LNGF never gets set. Clock is activated, since I enabled the Memory Mapped mode for the peripheral prior to this.

The function I used (based on stm32h7xx_ll_delayblock, which gives also a timeout):

HAL_StatusTypeDef DelayBlock_Enable(DLYB_TypeDef *DLYBx)
{
	uint32_t line = 10;
	DLYBx->CR = DLYB_CR_DEN | DLYB_CR_SEN;	//DEN ->Enable, SEN- SamplerEnable -> Disable Clock Output for Entering Units
		/* lng_mask is the mask bit for the LNG field to check the output of the UNITx*/
		for (uint32_t unit_current = 0U; unit_current < DLYB_MAX_UNIT; unit_current++)
		{
			/* Set the Delay of the UNIT(s) and Select Bits to 12*/
			DLYBx->CFGR = DLYB_MAX_SELECT | (unit_current << DLYB_CFGR_UNIT_Pos);
			/* Waiting for a LNG valid value */
			const uint32_t tickstart = HAL_GetTick();
			while ((DLYBx->CFGR & DLYB_CFGR_LNGF) == 0U)  //<--at unit = 1 it gets stuck
			{
				if ((HAL_GetTick() - tickstart) >=  DLYB_TIMEOUT)  
				{
					DLYBx->CR   = DLYB_CR_DEN;
					return HAL_TIMEOUT;
				}
			}
			volatile uint32_t lngmask = DLYBx->CFGR&DLYB_CFGR_LNG_Msk;
			if (lngmask>0)
			{
				if (((lngmask&DLYB_CFGR_LNG_10)==0)
					||((lngmask&DLYB_CFGR_LNG_11)==0))
				{
					while (line>0)
					{
						if (lngmask&(1 << (DLYB_CFGR_LNG_Pos + line)))
						{
							break;
						}
						--line;
					}
					break;
				}
			}	
		}
	/* Apply the Tuning settings */
	DLYBx->CR   = 0U;
	DLYBx->CR   = DLYB_CR_DEN | DLYB_CR_SEN;
	DLYBx->CFGR = (line << DLYB_CFGR_UNIT_Pos);
	DLYBx->CR   = DLYB_CR_DEN;
	return HAL_OK;
}

1 ACCEPTED SOLUTION

Accepted Solutions
JRS
Associate III

Got it working with help from ST support. Key was the clock settings that I was missing (mainly free running clock and some configuration issues -> compare examples from STM32U5).

View solution in original post

10 REPLIES 10
JRS
Associate III

Got it working with help from ST support. Key was the clock settings that I was missing (mainly free running clock and some configuration issues -> compare examples from STM32U5).

CBecc.1
Associate II

Hi,

I'm working on the stm32h7b3 platform and I'm trying to read/write a hyperRAM by octospi1.

I want to make the design more reliable by using the delay block but I'm stuck exactly in your issue. DelayBlock_Enable exit with a timeout after first iteration.

Can you give me some hint about the way you solved the issue.

I tried to configure the octospi in free running as indicated in the manual before running the DelayBlock_Enable but with no luck.

Any help will be appreciated.

Thanks

JRS
Associate III

Hi CBecc,

the short answer would be from the last post: Get the examples from the STM32U5 (they can be downloaded e.g. via cubemx) and adapt them to your µC.I got it working from there with minimal changes.

CBecc.1
Associate II

Hi JRS,

thanks for you reply.

I downloaded the example and I noticed that the peripheral mode is octo-spi. In my case I'm using the hyperbus protocol (peripheral mode hyperbus) so I cannot use it as a reference.

In CubeMX in my case I don't even find the delay block section. I have only a generic delayblock entry that can be enabled or disabled under octospi peripheral but this has only the effect to set the DLYBYP bit in the OCTOSPI_DCR1 register.

If you change the peripheral mode to hyperbus you will find it.

In any case the delay block is never enabled or tuned and when I try to call the DelayBlock_Enable I got a timeout.

I'm wondering If you can elaborate about the free running clock you mentioned above because it seems that a free running clock must be provided in order to tune it. Even if it is a different scenario I would like to know your tuning steps if possible.

Thanks for your help.

JRS
Associate III

yes, in cube-mx you cannot directly configure the delay-block.

You need to use the low level driver for this (they are somewhere in the drivers folder of the stm32h7 fw, both have ...delayblock.c/h in their names..

Also the examples are in the STM32Cube\Repository\STM32Cube_FW_U5_V1.1.0\Projects\STM32U575I-EV\Examples\DLYB\DLYB_OSPI_NOR_FastTuning\

This should be available after downloading the firmware in the cubemx.

yes I found the code in the low level driver (it is waht I'm trying to do with no luck) and I downloaded all possible examples around but I didn't find anything on how to use the delay block with hyperram.

I found an example on accesing hyperram on H7 but it doesn't use the delay block.

I'm able to access the hyperram without the delay block but I'm not able to use the delay block since I got the timeout.

I suspect something is missing (the free running clock??).

Since you got a similar issue I was asking what you changed (if you can tell me) to make it work.

Maybe something you did can help me to understand the issue.

Right now no example helped me because I'm on a different mode...

Thanks

JRS
Associate III

The Hyperram is also using the octospi module. At the point of delayblock configuration it does not matter what protocol is used later on. You just need to specify the ospi module.

Should look like this:

	LL_DLYB_CfgTypeDef dlyb_cfg;
	if (HAL_OSPI_DLYB_GetClockPeriod(&hospi1, &dlyb_cfg) != HAL_OK)
	{
		Error_Handler();
	}
	/*when DTR, PhaseSel is divided by 4 (empiric value)*/
	dlyb_cfg.PhaseSel /= 4;
 
	/* save the present configuration for check*/
	const LL_DLYB_CfgTypeDef dlyb_cfg_test = dlyb_cfg;
 
	/*set delay block configuration*/
	HAL_OSPI_DLYB_SetConfig(&hospi1, &dlyb_cfg);
 
	/*check the set value*/
	HAL_OSPI_DLYB_GetConfig(&hospi1, &dlyb_cfg);
	if ((dlyb_cfg.PhaseSel != dlyb_cfg_test.PhaseSel) || (dlyb_cfg.Units != dlyb_cfg_test.Units))
	{
		Error_Handler();
	}

I understand the code but what it is generated in my case by CubeMX is different.

I don't have any HAL_OSPI_DLYB_GetClockPeriod or HAL_OSPI_DLYB_GetConfig/HAL_OSPI_DLYB_SetConfig.

The stm32h7xx_ll_delayblock.c contains only 3 functions:

  • DelayBlock_Enable
  • DelayBlock_Disable
  • DelayBlock_Configure

None of them get called in the octospi.

The DelayBlock_Enable should be called to get the clock period and obtain the filter length (H7 Manual). From there I should be able to select a value for the phase and for the units.

Basically the same steps you did.

Unfortunately I cannot get the filter length (the clock period) because the function goes almost immediately in timeout like if the clock was absent.... I don't know why you have those functions generated... Are you on H7?

I'm using Hyperbus Mode and maybe the code generated in Octospi Mode is different from Hyperbus. The difference can be that....

I thought that you were using DelayBlock_Enable anyway....in my case I get a timeout. Are you not using the DelayBlock_Enable anymore?

Thanks for you help

JRS
Associate III

As I said, please look at the example in STM32Cube\Repository\STM32Cube_FW_U5_V1.1.0\Projects\STM32U575I-EV\Examples\DLYB\DLYB_OSPI_NOR_FastTuning\

there in the main.c should be the functions you can adapt.See:

  if (HAL_OSPI_DLYB_GetClockPeriod(&hospi2,&dlyb_cfg) != HAL_OK)
  {
    BSP_LED_On(LED_RED);
  }
 
  /*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(&hospi2,&dlyb_cfg);
 
  /*check the set value*/
  HAL_OSPI_DLYB_GetConfig(&hospi2,&dlyb_cfg);
  if ((dlyb_cfg.PhaseSel != dlyb_cfg_test.PhaseSel) || (dlyb_cfg.Units != dlyb_cfg_test.Units))
  {
    BSP_LED_On(LED_RED);
  }