NEWB Explanation of Read Syncing for RTC Clock on ATSAML22N16A Would be Fantastic

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I've been banging my head against a wall trying to figure out why I cannot read RTC clock values correctly. Most of the time (especially when the numbers of hours, minutes, and seconds are low), they read correctly, while at other times they most certainly do not. Hours have the most difficulty, especially with the first bit (even numbers are fine, odd numbers switch between the odd number and the even one below). Relevant code below with the most relevant bit bolded. Thanks in advance!

 

 

/* Initialize the RTC */
        REG_RTC_MODE2_CTRLA = 0b1000101100001000;                    //disable RTC
        while ((REG_RTC_MODE2_SYNCBUSY >> 1) & 1U) {asm("");}     //check that SYNCBUSY.ENABLE bit is cleared
        
        REG_OSC32KCTRL_RTCCTRL = 0;                                              //select 1.024kHz from OSCULP32K
        
        REG_RTC_MODE2_CTRLA = 0b1000101100001010;                    //set CTRLA and enable RTC
        while ((REG_RTC_MODE2_SYNCBUSY >> 1) & 1U) {asm("");}     //check that SYNCBUSY.ENABLE bit is cleared
        
        /* Set the time */
            int sec_set = 0b00110010;     //50
            int min_set = 0b00111011;    //59
            int hr_set = 0b0101;             //5
        
            while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}           //check that SYNCBUSY.CLOCK bit is cleared
            REG_RTC_MODE2_CLOCK = sec_set | (min_set << 6) | (hr_set << 12);
            while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}           //check that SYNCBUSY.CLOCK bit is cleared
        
    /* Replace with your application code */
    
    volatile int sec = 0;
    volatile int min = 0;
    volatile int hr = 0;
    volatile int clock = 0;
    
    while (1) 
        
    {
        /* Read time */
            //Hour is {hr}, min is {min}, sec is {sec}.
            while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}    //check that SYNCBUSY.CLOCK bit is cleared
            clock = REG_RTC_MODE2_CLOCK;
            while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}    //check that SYNCBUSY.CLOCK bit is cleared

            
            sec = clock & 0b111111;        //read seconds (bits 0:5 of CLOCK)
            min = (clock >> 6) & 0b111111;    //read minutes (bits 6:11 of CLOCK)
            hr = (clock >> 12) & 0b11111;    //read hours (bits 12:16 of CLOCK)

    }

This topic has a solution.
Last Edited: Thu. Feb 6, 2020 - 03:40 AM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

I have a SAML22N18A and I can't repeat the problem. This modified main loop has been running for more than 23 hours now:

    .
    .
    .
    volatile int err = 0;
    volatile int lastSec = sec_set;
    volatile int lastMin = min_set;
    volatile int lastHr = hr_set;
    while(1)
    {
        /* Read time */
        //Hour is {hr}, min is {min}, sec is {sec}.
        while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}    //check that SYNCBUSY.CLOCK bit is cleared
        clock = REG_RTC_MODE2_CLOCK;
        while ((REG_RTC_MODE2_SYNCBUSY >> 3) & 1UL) {asm("nop");}    //check that SYNCBUSY.CLOCK bit is cleared

        sec = clock & 0b111111;        //read seconds (bits 0:5 of CLOCK)
        min = (clock >> 6) & 0b111111;    //read minutes (bits 6:11 of CLOCK)
        hr = (clock >> 12) & 0b11111;    //read hours (bits 12:16 of CLOCK)
        if ((sec != 0 && sec < lastSec) ||
            (min != 0 && min < lastMin) ||
            (hr != 0 && hr < lastHr)) {
                err++;
            }
        lastSec = sec;
        lastMin = min;
        lastHr = hr;
    }

err is still 0. If I understand your description that test should detect "odd numbers switch between the odd number and the even one below".

 

BTW, not many are going to rush to help with this kind of code (looking up the bit positions in the data sheet):
 

REG_RTC_MODE2_CTRLA = 0b1000101100001000; 

There are definitions (RTC_MODE2_CTRLA... in this case) as well as structs (RTC->MODE2.CTRLA.bit.*) you can use.

/Lars

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Lars,

 

Thanks so much for this! That's incredible that you ran this for me on your hardware! I think I'm having a bit stability issue with that bit.

 

I just made a new board and I can't reproduce the issue (though the issue is still present on the original hardware). Everything works perfectly! I wonder if I could have damaged the bit, as I was running it without read syncing for quite a while until I read up on read syncing.

Also thank you for the advice on using structs for more readable code - I'll implement this in the future.

 

Can't thank you enough!

 

Alex