cancel
Showing results for 
Search instead for 
Did you mean: 

SHPF flag not getting cleared by hardware (Shift operation pending) after writing to RTC_SHIFTR register

A Maq
Senior

I am using STM32F779 and trying to use its RTC sub second functionality. Also, using a network time to synchronize with RTC. The issue I am having is as follows along with what I have already tried:

  1. In order to advance SSR register to synchronize with network clock first set RTC_SHIFTR_ADD1S bit and then put advance value into the SUBF (at the moment in order to test code i am just using constant lets say "4"
  2. Also tried with Delaying SSR (to test if RTC is faster than network clock) by same value of constant "4" after checking there is not RTC Register->RTC_SHIFTR.Set(Any_value); // tried various values to
  3. Code is as follows for synchronization
 if (precise_offset > prediv_s)
    {
        /* We check SS[15] is equal to 0 to avoid overflow */
        if ((RTCRegisters_m->RTC_SSR.Get() & 0x1000) == 0)
        {
            /* We set an advance */
            RTCRegisters_m->RTC_SHIFTR.Set(RTC_SHIFTR_ADD1S_MSK);
            rtc_shiftr_temp |= (0x00000004& RTC_SHIFTR_SUBFS_MASK)|RTC_SHIFTR_ADD1S_MSK;
           // rtc_shiftr_temp |= ((((precise_sub_second * 255) / 1000000)) & (RTC_SHIFTR_SUBFS_MASK));
            RTCRegisters_m->RTC_SHIFTR.Set(rtc_shiftr_temp);
        }
    }
 
    if (precise_offset < prediv_s)
    {
        /* We check SS[15] is equal to 0 to avoid overflow */
        if ((RTCRegisters_m->RTC_SSR.Get() & 0x1000) == 0)
        {
            /* We set a delay */
            rtc_shiftr_temp |= (0x4 &RTC_SHIFTR_SUBFS_MASK);
            RTCRegisters_m->RTC_SHIFTR.Set(rtc_shiftr_temp);
        }
 
    }
while ( (RTCRegisters_m->RTC_ISR.Get() & RTC_ISR_SHPF_MSK ) != 0)
    {
        __NOP();
    }

Problem:

  1. Problem is SHPF flag not getting cleared by hardware (Shift operation pending) after writing to RTC_SHIFTR register. It is right that it should get set after writing to the SHIFTR register but based on Ref Manual it gets cleared automatically after getting performing shift operation.

Code gets stuck forever here:

while ( (RTCRegisters_m->RTC_ISR.Get() & RTC_ISR_SHPF_MSK ) != 0)
 
    {
 
        __NOP();
 
    }

  1. Is there anything which I am missing?

Any help will be much appreciated.

1 ACCEPTED SOLUTION

Accepted Solutions

I don't use the subsecond counter but it perhaps might be consequence of this:

0693W000000VjIMQA0.png

JW

View solution in original post

7 REPLIES 7

What is this, C++? What does it actually do? Have you looked at the disasm? Have you looked at the actual registers in debugger, maybe even trying to do the shift "manually" in there?

JW

Hi Jan,

Thanks for your response.

yes it is C++.

It is actually synchronizing RTC sub second to Network time (precise_sub_second ) for the time being I have just used a constant value to Delay or Advance SUBFS . Once this issue of getting stuck on RTC_ISR_SHPF register is over i will focus on putting right value. I did not check disasm as i do not understand assembly language that much.

I looked at the registers in IAR register view window. I can see RTC_ISR_SHPF register bit is set along with INIT bit of ISR does that make any difference?

At which point in the RTC setting up process , this delay or advance to the SSR register should take place if that makes any difference?

> set along with INIT bit

That's probably not OK. INIT stops the counter, and while that's not written explicitly in the manuals, that prevents the shift to actually take place.

In other words, shift is intended to be performed on a running RTC.

JW

You are right when I changed the function call (which is performing above subsecond settings) after RTC Inititialization Exit i am not having situation of getting stuck SHPF flag is getting cleared by hardware.

A Maq
Senior

@Community member​ But after resolving above issue I am putting right values (for test earlier i was using fixed value) calculated for SUBFS using following code that does not seem right in terms of output i get for sub-seconds. My variable parameter passed to this function is in microsecond and then i apply calculations(are they right?)to convert it to value to be inserted into SUBFS for both scenarios advance and delay.

It shows a very large number when i print in sub second value read straight after executing SynchSubSecond() function.

while, i am printing only milliseconds converted from subsecond register value. i will attach below the actual output on tera term for value read. code is as follows:

void SynchSubSecond(long precise_sub_second)
{
    uint16_t prediv_s = RTCRegisters_m->RTC_PRER.Get() & RTC_PRER_PREDIVS_MSK;
    volatile uint32_t temp_sr = RTCRegisters_m->RTC_SSR.Get();
    uint32_t ssr = GetSubSecond(temp_sr);
    uint32_t rtc_shiftr_temp = 0x00000000;
    float fraction_sec_ssr = 0.0;
    float precise_offset = 0.0;
 
    // SSR counts down from PreDiv_S
 
    fraction_sec_ssr = (prediv_s - ssr) / (prediv_s + 1);
    // Convert to uSec (rounded to nearest)
    fraction_sec_ssr *=  1000000ULL;
 
    /* According to the offset measured, we update the RTC SHIFTR register */
    if (precise_sub_second > fraction_sec_ssr )
    {
        precise_offset = ((precise_sub_second - fraction_sec_ssr) * (prediv_s + 1)) / 1000000 ; // Advance
 
        /* We check SS[15] is equal to 0 to avoid overflow */
        if ((RTCRegisters_m->RTC_SSR.Get() & 0x1000) == 0)
        {
            /* We set an advance */
            rtc_shiftr_temp |= (((static_cast<uint32_t>(precise_offset)) & RTC_SHIFTR_SUBFS_MASK) | RTC_SHIFTR_ADD1S_MSK);
            RTCRegisters_m->RTC_SHIFTR.Set(rtc_shiftr_temp);
        }
    }
 
    if (precise_sub_second < fraction_sec_ssr)
    {
        precise_offset = ((fraction_sec_ssr -  precise_sub_second) * (prediv_s + 1)) / 1000000 ;
 
        /* We check SS[15] is equal to 0 to avoid overflow */
        if ((RTCRegisters_m->RTC_SSR.Get() & 0x1000) == 0)
        {
            /* We set a delay */
            rtc_shiftr_temp |= ((static_cast<uint32_t>(precise_offset)) & RTC_SHIFTR_SUBFS_MASK);
            RTCRegisters_m->RTC_SHIFTR.Set(rtc_shiftr_temp);
        }
 
    }
 
    volatile uint32_t temp_tr;
    volatile uint32_t temp_dr;
 
    // In shadow bypass mode we have to re-read till the register values are consistent
    //Note: Writing to SUBFS causes RSF to be cleared. Software can then wait until RSF=1 to be
    //sure that the shadow registers have been updated with the shifted time.
    do
    {
        temp_sr = RTCRegisters_m->RTC_SSR.Get();
        temp_tr = RTCRegisters_m->RTC_TR.Get();
        temp_dr = RTCRegisters_m->RTC_DR.Get();
    }
    while ((temp_sr != RTCRegisters_m->RTC_SSR.Get()) ||
            (temp_tr != RTCRegisters_m->RTC_TR.Get()) ||
            (temp_dr != RTCRegisters_m->RTC_DR.Get()));
 
    /* We wait for SHPF flag to be cleared by hardware (Shift operation pending) */
    while ( (RTCRegisters_m->RTC_ISR.Get() & RTC_ISR_SHPF_MSK ) != 0)
    {
        __NOP();
    }
}

0693W000000ViZMQA0.png

Terminal output for time read from RTC. last part of time after . is milliseconds using RTC sub sec register value

if you notice in image above as soon as i called that function to update RTC and its subsecond. rest is ok but sub second which i am printing in millisecond becomes a very large value which after a sec changes to normal value again that is 3 digit millisecond. Any idea what can cause such a large value in sub-second.

I don't use the subsecond counter but it perhaps might be consequence of this:

0693W000000VjIMQA0.png

JW

That is exactly the case based on my observations. After adjusting the clock based on if SSR greater than PREDIV_S it is giving me right values now. Thanks very much for your help.