Skip to main content
juraj
Associate III
April 16, 2008
Question

RTC reading counter issue

  • April 16, 2008
  • 4 replies
  • 1024 views
Posted on April 16, 2008 at 12:18

RTC reading counter issue

    This topic has been closed for replies.

    4 replies

    daviddavid99
    Visitor II
    May 17, 2011
    Posted on May 17, 2011 at 12:30

    I would have heped that the RTC Count would have been a 32 bit register. Maybe it is a peripheral that originated in 16 bit land and has just been dropped in.

    14 bit ADCs and 16 bit counters on 8 bit micros have this coherency problem, one of the solutions is for the low value to be latched into a low shadow register when the high register is read or vice versa. If this were the case then we would have been told surely, lets assume no such mechanism was implemented.

    Any time that the low register is about to rollover we have danger. ie everytime CNTL == 0xFFFF we are in jeopardy. The nature of the error is read order dependent.

    Assume rolover between reads:

    CNTL = 0xFFFF -> 0x0000

    CNTH = CNTH   -> CNTH + 1

    L before H: Result is ((CNTH + 1) << 16) | 0xFFFF

    H before L Result is ((CNTH + 0) << 16) | 0x0000

    Should be            ((CNTH + 1) << 16) | 0x0000

    Error = 0xFFFF or 0x10000

    Be very careful.

    Note that if CNTH is 0x0000 and we read H before L then incorrectly we read ticks as 0x0

    Check against last_ticks which is 0x0

    return 0x0 instead of 0x10000

    Gut feeling is to set the initial value of last ticks as far from 0xnnnnFFFF and 0xnnnn0000 as possible eg 0x00007FFF

    togrady
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:30

    Yes I too think this is a problem. I changed it to keep reading until it gets two values the same which in 99.999% of cases will take just two reads.

    Code:

    u32 RTC_GetCounter(void)

    {

    u32 ticks, last_ticks = 0;

    for (;;)

    {

    ticks = (((u32)RTC->CNTH << 16 ) | RTC->CNTL);

    if (ticks == last_ticks)

    break;

    last_ticks = ticks;

    }

    return ticks;

    }

    juraj
    jurajAuthor
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:30

    Are these function from ST:

    Code:

    u32 RTC_GetCounter(void) {

    u16 tmp = RTC->CNTL;

    return (((u32)RTC->CNTH << 16 ) | tmp) ;

    }

    and

    Code:

    u32 RTC_GetDivider(void) {

    u32 tmp = 0x00;

    tmp = ((u32)RTC->DIVH & (u32)0x000F) << 0x10;

    tmp |= RTC->DIVL;

    return tmp;

    }

    safe to get always right information? Meaning that after reading first part of u32 value, the counter can be updated with overflow from lo-word to hi-word and the return values of these functions are not correct.

    Am I right?

    __________________

    Then, I found in the firmware more times the same as here, in the RTC_GetDivider(void) there is:

    Code:

    u32 tmp = 0x00;

    which is not needed operation. Why is this used widely?

    Thanks.

    picguy2
    Associate III
    May 17, 2011
    Posted on May 17, 2011 at 12:30

    The general way of reading a running two part counter is

    Loop:

      tempHi = ctrHi  //must read this one first

      tempLo = ctrLo

      if (tempHi != ctrHi) goto Loop

      return tempHi:tempLo

    The extra read of ctrHi when we “goto Loop� is more than offset by the simplicity of the above and the rareness of the goto event.