Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STM32L4: Adjusting RTC Synchronisation When Using MBED_TICKLESS in RTC Mode #7695

Closed
mattbrown015 opened this issue Aug 3, 2018 · 22 comments

Comments

@mattbrown015
Copy link
Contributor

Description

As discussed here How to Achieve Long Periods of Deep Sleep on STM32 #7156 and here deepsleep - LPTIM1 Vs RTC on STM32? it seems appropriate to use the RTC when enabling MBED_TICKLESS on STM32L4.

In our application we also want to use the RTC for recording the time at which a sample is taken. To achieve this our communication protocol includes a method of sending the Unix time to the device.

In an attempt to alleviate the obvious short comings of sending the Unix time via a non-deterministic transport we've also implemented a RTC synchronisation command. In other words, our protocol includes a command to adjust the time by +/-127 s although it is done in a series of 0.5 s steps.

To implement the 0.5 s time adjustment we've used the 'RTC Synchronisation' feature. With the error checking removed and various simplifications made, our code looks a bit like:

void rtc_synch() {
    uint32_t ShiftSecond = advance ? LL_RTC_SHIFT_SECOND_ADVANCE : LL_RTC_SHIFT_SECOND_DELAY;

    uint32_t prediv_s = LL_RTC_GetSynchPrescaler( rtc );
    uint32_t Fraction = (prediv_s + 1) / 2;  // i.e. 0.5 second

    LL_RTC_DisableWriteProtection( rtc );

    LL_RTC_TIME_Synchronize( rtc, ShiftSecond, Fraction );
}

The time adjustment was originally implemented without MBED_TICKLESS defined and it works. It still works when MBED_TICKLESS is defined.

The problem comes when I switch the 'lpticker' from the LPTIM to the RTC using "target.lpticker_lptim": 0 in mbed_app.json. In this mode something goes wrong and the application locks up when attempting to delay the RTC (I can advance the RTC).

I've done a bit of debugging and it appears to be stuck in SysTick_Handler. My feeling is that sys tick is continually firing, it never gets cleared, and no normal code is being run. But, I don't understand how the RTC, sys tick, etc. hang together to really understand.

This is pretty complicated stuff but I'd be grateful if anyone has any thoughts.

Issue request type

[X] Question
[ ] Enhancement
[ ] Bug

@0xc0170
Copy link
Contributor

0xc0170 commented Aug 6, 2018

@ARMmbed/team-st-mcd Please review

@jeromecoutant
Copy link
Collaborator

Hi
I think you need to implement something like in rtc_write procedure:

/* Need to update LP_continuous_time value before new RTC time */

@mattbrown015
Copy link
Contributor Author

Hi @jeromecoutant, funny that you should refer to that section of code because I was looking at it last week because it generates an unused variable warning. current_lp_time is assigned but not used.

I think I understand your point at a high level but not enough to implement anything!

Switching to tickless with the RTC isn't my most important problem at the moment, I shall give your point more thought sometime soon!

Thanks, Matt

@jeromecoutant
Copy link
Collaborator

2 things:

  • the unused variable will be removed with my next PR

  • In your rtc_synch() procedure, I didn't test, but after reading reference manual, it seems you need to poll the SHPF flag?
    Maybe you should try something like :

    LL_RTC_TIME_Synchronize( rtc, ShiftSecond, Fraction );
+   while (LL_RTC_IsActiveFlag_SHP(rtc)) {}

@mattbrown015
Copy link
Contributor Author

it seems you need to poll the SHPF flag

In the real code we do have a loop like you suggest, although I've never seen it iterate more than once.

@jeromecoutant
Copy link
Collaborator

Maybe add also some :

  • core_util_critical_section_enter();
  • core_util_critical_section_exit();
    ?

@jeromecoutant
Copy link
Collaborator

Any update ?
Thx

@mattbrown015
Copy link
Contributor Author

mattbrown015 commented Sep 18, 2018

Hi @jeromecoutant,

No, this is still an issue for me although I haven't looked at it since 9 Aug. I did try everything you mentioned.

I was wondering if it has anything to do with Add LPTICKER tests #8129.

This is because the wake up time passed to the rtc is ignored if the previous match is about to occur. This causes the device to get stuck in sleep.

Sounds suspiciously like what is happening here.

@mattbrown015
Copy link
Contributor Author

I was deliberately leaving this issue open because it is still an issue for me.

The are a number of PRs relating to the RTC stuck in the pipeline I'm hoping they will fix this. If they don't it will need investigating further.

Everyday I think the PRs are about to be merged and everyday they get put back; this is tricky stuff but fingers crossed they are nearly ready! :-)

@jeromecoutant
Copy link
Collaborator

@adbridge please reopen this issue
Thx

@adbridge
Copy link
Contributor

adbridge commented Oct 2, 2018

This was closed internally hence this was closed accordingly. If this is still an issue we'll re-open.

@adbridge
Copy link
Contributor

adbridge commented Oct 4, 2018

Internal Jira reference: https://jira.arm.com/browse/IOTPART-6065

@mattbrown015
Copy link
Contributor Author

I was hoping that #8242 would help me with this. It hasn't hasn't.

I just done a quick test and delaying the RTC still causes our app to hang.

@jeromecoutant
Copy link
Collaborator

Hi

Did you see that, since 5.11.1, L4 targets are now TICKLESS by default using LPTIM ?
Maybe we can make an update for this issue, or open a new one ?

Thx

@mattbrown015
Copy link
Contributor Author

Hi @jeromecoutant ,

I'm still using the RTC because I believe it allows longer periods of deepsleep, especially since #8777.

Do you think I should reconsider using the LPTIM?

As things stand, I'm using tickless in RTC mode and adjusting the RTC is still a problem for me.

@jeromecoutant
Copy link
Collaborator

OK

And what about closing this issue?
Do you have a "simple" application we can use for debug ?

@mattbrown015
Copy link
Contributor Author

Unfortunately I don't have a simple example to hand and, while this is a problem for us, I think we can work around it and I have bigger issues to deal with at the moment.

If I did have time to create a simple app I would create a RTC tickless app that could handle a button (or digital input) event. When the button was pressed I'd nudge the RTC and see what happens.

Our real app gets commands from its RF interface. One of the commands is 'adjust the time'. When it receives this command it adjusts the the time in a series of 0.5 second steps. These steps are taken at each of our sampling intervals.

In the code below you can see the '0.5 second step' hardcoded in the calculation of subfs.

nudge( LL_RTC_SHIFT_SECOND_DELAY ) always causes the system to hang. It doesn't hang in nudge, hence I think adjusting the RTC has upsetting the ticker and scheduling in some way.

nudge( LL_RTC_SHIFT_SECOND_ADVANCE ) always works.

Here's our nudge code:

bool update_rtc_shiftr( const uint32_t ShiftSecond, const uint32_t Fraction )
{
    // see ST RM0351 Reference manual Rev 6 for section references.

    // we don't expect a shift to be in progress, but best to check
    if(LL_RTC_IsActiveFlag_SHP( rtc ))
        return false;

    // unlock RTC registers
    // see 38.3.7 - RTC initialization and configuration
    LL_RTC_DisableWriteProtection( rtc );

    LL_RTC_TIME_Synchronize( rtc, ShiftSecond, Fraction );

    // 38.6.11 - RTC shift control register (RTC_SHIFTR) says:
    //   "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."

    // Testing note: it seems that this typically takes 20ms

    if (LL_RTC_IsShadowRegBypassEnabled( rtc ))
    {
        // if the shadow registers are bypassed (as can be the case after
        // coming out of low-power mode, apparently, wait only for the
        // shift to be applied.
        while (!LL_RTC_IsActiveFlag_SHP( rtc ))
            ;
    }
    else
    {
        // if they're not bypassed, wait until they're updated, after the shift.
        while (!LL_RTC_IsActiveFlag_RS( rtc ))
            ;
    }

    return true;
}

uint32_t nudge( const uint32_t ShiftSecond )
{
    tr_debug( "nudge %s", ShiftSecond == LL_RTC_SHIFT_SECOND_ADVANCE ? "advance" : "delay" );

    // Fortuitously the calculation of subfs is the same for advance and delay.
    // Here's the working:
    //   Advance (seconds) = (1 - (SUBFS / (PREDIV_S + 1))).
    //   so 0.5 = 1 - SUBFS / (PREDIV_S + 1)
    //   so SUBFS = 0.5 * (PREDIV_S + 1)
    //
    //   Delay (seconds) = SUBFS / (PREDIV_S + 1)
    //   so 0.5 = SUBFS / (PREDIV_S + 1)
    //   so SUBFS = 0.5 * (PREDIV_S + 1);

    const uint32_t prediv_s = LL_RTC_GetSynchPrescaler( rtc );
    const uint32_t subfs = (prediv_s + 1) / 2;

    return (update_rtc_shiftr( ShiftSecond, subfs )) ? 5 : 0; // 5 tenths for success, 0 otherwise.
}

@ciarmcom
Copy link
Member

Thank you for raising this issue. Please note we have updated our policies and
now only defects should be raised directly in GitHub. Going forward questions and
enhancements will be considered in our forums, https://forums.mbed.com/ . If this
issue is still relevant please re-raise it there.
This GitHub issue will now be closed.

@OneTwoSteph
Copy link

Hey @mattbrown015,

Thanks for your post and details of your code.

I am currently working on the same subject and your post was very helpful.

Just one question/comment: LL_RTC_IsActiveFlag_SHP() is returning the value of the SHPF bit. This bit is set to 1 when a shift operation is pending. Therefore, your while loop is not correct if you want to wait for all the shift operations are done before doing a new one. I think the same applies to LL_RTC_IsActiveFlag_RS().

This solved my issue and now delaying and advancing RTC works fine.

Hope this can be helpful for you too !

Good luck and cheers,

OneTwoStéph

@jeromecoutant
Copy link
Collaborator

Hi @OneTwoSteph
Please push a pull request in order to make a fruitful review :-)
Thx

@OneTwoSteph
Copy link

Hey @jeromecoutant,

My comments were only about @mattbrown015's code he posted previously. Nothing to correct in the rep ;)

Cheers,

OneTwoStéph

@mattbrown015
Copy link
Contributor Author

Hi @OneTwoSteph ,

Thanks for your comment, you're right of course, there's a misplaced ! in our code. Way back in August Jerome posted while (LL_RTC_IsActiveFlag_SHP(rtc)) {}, i.e. no !, and I clearly didn't read it well enough.

I've taken the ! out now but unfortunately it doesn't solve my problem, I still get stuck somewhere in the RTOS scheduler. I'm not worrying about it though because our product seems to be doing OK without this feature.

Thanks,
Matt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants