Skip to main content
AlbertoGarlassi
Associate II
November 19, 2022
Solved

Fractional mode register changes need a delay?

  • November 19, 2022
  • 5 replies
  • 3296 views

I'm trying to change the PLLxFRACR on-the fly. Per the reference manual something like this should work:

__HAL_RCC_PLL2FRACN_DISABLE();

__HAL_RCC_PLL2FRACN_CONFIG(8191);

__HAL_RCC_PLL2FRACN_ENABLE();

On a STM32H750 this code seems to have no effect. But works OK wihen a delay between the disable and the config lines is inserted. Some microseconds is enough.

Is it really this way or am I missing something?

Regards

Alberto

This topic has been closed for replies.
Best answer by FBL

Hello @AlbertoGarlassi​ 

When PLLxFRACEN = ‘0’, the Sigma-Delta modulator is still operating with the 

value latched into SH_REG.

Application must wait for 3 clock period of refx_ck (bit propagation delay)

Once the reference manual is updated, I will get back to you to confirm the delay.

5 replies

Technical Moderator
November 25, 2022

Hello @AlbertoGarlassi​,

Please make sure that you follow properly the "PLL Initialization phase" as described in the RM0433

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Piranha
Principal III
November 26, 2022

His HAL code is doing exactly what is described in point 4 of that section and the "Figure 48. PLLs Initialization Flowchart".

Also the RCC_PLL3FRACR register bit field FRACN3 description has an error:

---------

In order to change the FRACN value on-the-fly even if the PLL is enabled, the application has to proceed as follow:

– set the bit PLL1FRACEN to ‘0’, 

– write the new fractional value into FRACN1

– set the bit PLL1FRACEN to ‘1’.

---------

Obviously the there should be PLL3FRACEN and FRACN3. Such errors would not be there, if the registers with the same functionality would be documented once using the PLLxFRACEN and FRACNx like it's done for GPIO registers.

Technical Moderator
November 28, 2022

@Piranha, thanks for reporting the typo. An internal ticket has been submitted.

Internal ticket number: 139857 (This is an internal tracking number and is not accessible or usable by customers).

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Pavel A.
Super User
November 27, 2022

@AlbertoGarlassi It is a known issue with STM32H7. Writes to some registers need extra time to get thru, because of obscure reasons (bus matrix, space-time continuum...)

Try to insert a __DSB() after disable, or read the register back. The read ensures that previous write to same location sinks thru.

Technical Moderator
November 28, 2022
To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
Piranha
Principal III
November 30, 2022

This is not an answer and should not be marked like that!

For draining the write buffer a DMB is enough - no need for a more restrictive DSB. Anyway these instructions just guarantee that the write has been done from the CPU side, but cannot guarantee that the write has gone through the bus matrix till the other end.

Yes, a read operation from the same peripheral guarantees the completion of the previous write operation. In the example code the ENABLE macro after the CONFIG macro does a read and write to the same peripheral and therefore guarantees that the write by CONFIG macro has reached the peripheral before the ENABLE macro.

If there is a timeout, ST must document how long and based on which clock it is!

AlbertoGarlassi
Associate II
November 28, 2022

Thanks to everybody for the help.

I will test the __DSB() ASAP, right now I moved inbetween some existing code and use it as a delay without penalties and I'm fine with it.

Regards

Alberto

AlbertoGarlassi
Associate II
November 29, 2022

1) __DSB();

Makes no difference. Fractional divider is set only about 1 in 10 executions.

2) __DSB();

__DMB();

__ISB();

Same as above. Tested just in case.

3) volatile uint32_t i;

   for (i=0; i< 10; i++)

   {

      i++;

      i--;

   }

Same as above but with higher success rate.

4) volatile uint32_t i;

   for (i=0; i< 50; i++)

   {

      i++;

      i--;

   }

Works perfectly every time, it seems.

It looks like it is not some creepy CPU architecture issue, but likely related to the delta sigma modulator counter.

But I don't know. You are the experts.

Regards

Alberto

FBLBest answer
Technical Moderator
December 23, 2022

Hello @AlbertoGarlassi​ 

When PLLxFRACEN = ‘0’, the Sigma-Delta modulator is still operating with the 

value latched into SH_REG.

Application must wait for 3 clock period of refx_ck (bit propagation delay)

Once the reference manual is updated, I will get back to you to confirm the delay.

To give better visibility on the answered topics, please click on "Best answer" on the reply which solved your issue or answered your question.Best regards,FBL
AlbertoGarlassi
Associate II
December 24, 2022

Ok, it makes sense, thanks. Only thing I can add is that it seems that the delay needed is not fixed, sometimes the register is updated even without any delay. So we need a worst-case value.