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

few tick timeout comparison and other issues/improvements: #223

Closed
mazgch opened this issue Mar 29, 2024 · 6 comments
Closed

few tick timeout comparison and other issues/improvements: #223

mazgch opened this issue Mar 29, 2024 · 6 comments

Comments

@mazgch
Copy link
Contributor

mazgch commented Mar 29, 2024

Hi @RobMeades

I had some time to screen the https://github.com/u-blox/ubxlib/tree/preview_fix_tick_wrap_rmea branch a bit and found some issues many of them timeout related but not only. Towards the end you also find a suggestion how to avoid these mistakes in the future with an improved timeout API that hides the MS handling from the user.

  1. (uPortGetTickTimeMs() < gStopTimeMs) &&

    change: (uPortGetTickTimeMs() < gStopTimeMs)
    to: (((uPortGetTickTimeMs - gStopTimeMs) < 0)
    suggest to use uPortTickTimeBeyondStopMs

  2. while ((gErrorCode == 0xFFFFFFFF) && (uPortGetTickTimeMs() < gStopTimeMs) &&

    change: (uPortGetTickTimeMs() < gStopTimeMs)
    to: (((uPortGetTickTimeMs - gStopTimeMs) < 0)
    or use uPortTickTimeBeyondStopMs

  3. dynamicsMinDistance.lastStatus.distanceMillimetres = uPortGetTickTimeMs();

    review: dynamicsMinDistance.lastStatus.distanceMillimetres = uPortGetTickTimeMs();
    possibly change to dynamicsMinDistance.lastStatus.timeMs = uPortGetTickTimeMs();

  4. (uPortGetTickTimeMs() < startTimeMs +

    change: (uPortGetTickTimeMs() < startTimeMs +
    (U_MQTT_CLIENT_RESPONSE_WAIT_SECONDS * 1000))
    to: (uPortGetTickTimeMs() - startTimeMs < (U_MQTT_CLIENT_RESPONSE_WAIT_SECONDS * 1000))
    or use uPortTickTimeExpiredMs

  5. if (now > pMsgInfo->timeOut)

    change: if (now > pMsgInfo->timeOut)
    to: if (now - pMsgInfo->timeOut > 0)
    suggest to rename now to startTimeMs and timeOut StopTimeMs
    sugguest to use uPortTickTimeBeyondStopMs

many more occasions throughout this file ....

if (now > s_pLastFlashBlockSent->timeOut)

if (now > s_aidingTimeout)

if (now > s_pLastFlashBlockSent->timeOut)

if (now > s_aidingTimeout)

... potentially more ..

  1. while ((gCallbackParameters.called < 2) && (uPortGetTickTimeMs() < gStopTimeMs)) {

    while ((gCallbackParameters.called < 2) && (uPortGetTickTimeMs() < gStopTimeMs)) {

    change: (uPortGetTickTimeMs() < gStopTimeMs)
    to: (uPortGetTickTimeMs() - gStopTimeMs < 0)
    suggest use of use uPortTickTimeBeyondStopMs

  2. while ((gErrorCode != 0) && (uPortGetTickTimeMs() < gStopTimeMs)) {

    chnage: (uPortGetTickTimeMs() < gStopTimeMs)
    to: (uPortGetTickTimeMs() - gStopTimeMs < 0)
    suggest use of use uPortTickTimeBeyondStopMs

maybe there are even more of these things ...

To avoid all such mistakes my suggestion is to have tick uPortGetTickTimeMs return a "handle" and move all the comparison functions into the function where this is allways properly handled. properly, this way the develpper can't make any mistakes as he does not know what using this handle has and how to convert it

TIMEOUTHANDLE_t uPortGetTimeoutHandle() {
    return (TIMEOUTHANDLE_t) uPortGetTickTimeMs();
}

You could extend the tick API with a elapsed millisecond and use this throughout the code in all the printfs

uint32_t uPortGetElapsedMs(TIMEOUTHANDLE_t timeoutHandle)
{ 
   return (uint32_t)(uPortGetTickTimeMs() - (int32-t)timeoutHandle); 
}
 
uint32_t uPortGetElapsedSeconds(TIMEOUTHANDLE_t timeoutHandle)
{ 
   return uPortGetElapsedMs() / 1000; 
}

of course the current API would also take only these handles

@RobMeades
Copy link
Contributor

Very useful indeed, thanks Michael, give me time to absorb and I will comment here, tagging issue #209 so that warasilapm sees this.

@mazgch
Copy link
Contributor Author

mazgch commented Mar 29, 2024

Some of the issues are just in test code, so will not affect a real application.

@mazgch
Copy link
Contributor Author

mazgch commented Mar 29, 2024

Here is some more:

  1. if ((pInstance->startTimeMs > 0) &&

    likely a bad idea, just remove?: (pInstance->startTimeMs > 0) &&
    either you need an extra bool flag to indicate that startTimeMs was never set.
    all the startTimeMs = 0 in this file are very supicious ... values <0 are valid values that uPortGetTickTimeMs can return

  2. int32_t startTimeMs = 0;

    probably better to init with uPortGetTickTimeMs or maybe this = 0 is not needed at all, but seting 0 here is not better than having a random value.
    same here...
    int32_t startTimeMs = 0;

  3. pInstance->startTimeMs = 500;

    looks suspicious but not sure ...

  4. static int32_t gStartTimeMs = -1;

    again supicious probably need a separate flag to track if gStartTimeMs was ever set.

  5. int32_t ticksLastRestart;

    reconsider if this is needed: ticksLastRestart
    it does not really do something maybe just there for debugging and can be removed:
    pInstance->ticksLastRestart = uPortGetTickTimeMs();

    pInstance->ticksLastRestart = 0;

@mazgch mazgch changed the title few tick comparison issues: few tick timeout comparison and probably other issues: Mar 29, 2024
@mazgch mazgch changed the title few tick timeout comparison and probably other issues: few tick timeout comparison and other issues/improvements: Mar 29, 2024
@warasilapm
Copy link

Yeah I've been noticing this repeatedly as well - though we've not been reviewing the test code applications. Zephyr does something similar as suggested by wrapping all "times" in an "opaque" (but not really) struct that is supposed to be passed into macros/static inlines to handle the encapsulated values. You can see the encapsulation in k_timeout_t here. I imagine you'd end up with a uTick_t struct similar to this.

Note Zephyr does some things differently as it generally leverages int64_t to avoid any wraparound issues. We've found a couple more edge cases to share on the other issue later today after we do some more investigation.

@RobMeades
Copy link
Contributor

Implementation in #225.

@RobMeades
Copy link
Contributor

The fix for this issue, as proposed (and reviewed) by @mazgch, can be found in commit 79e808e.

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

No branches or pull requests

3 participants