This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAP L138 DSP 32 kHz timer counter register

Other Parts Discussed in Thread: OMAPL138

I'm trying to write a gettimeofday() function to calculate the time from the RTC into:

struct timeval{
    unsigned int tv_sec;
    unsigned int tv_usec;
}

#define RTC_OSC_ADDR		 (0x01C23054) /* Address for OSC register */

int rtc_gettimeofday(struct timeval *tv){
	double usecPerClk = 30.517578125; /* (1000000/32767) OSC is a 32.767 kHz counter */
	double usecCalc;
	time_t secs;
	unsigned int oscVal;

	oscVal = HWREG(RTC_OSC_ADDR);

	time(&secs);
	usecCalc = (oscVal * usecPerClk);

	tv->tv_sec = (unsigned int)secs;
	tv->tv_usec = (unsigned int)usecCalc;

	return 0;
}

The value for tv_sec is trivial as I can use  time.h library with a time() glue function - this is working fine and I can see the time incrementing.

In order calculate the microseconds, tv_usec, I'm trying to read the value for the OSC register which I believe holds the value for the 32.768 kHz counter, however the value for oscVal in my code above just stays at a value of 7.

EDIT: I've re-read the documentation and it seems that the OSC register doesn't hold the value for the timer counter as I thought. I can't see anywhere that references this counter, except for the Figure 2 in the RTC user guide (page 12).

Does anyone know if / how I can read the value of the 32 kHz RTC counter?

  • Hi,

    We would require time to check on this issue and we are working on it. We will get back to you on this as soon as we have answer.

    Thanks for your patience.

    Thanks & regards,
    Sivaraj K
  • Hi Chris,

    Chris says said:
    I'm trying to write a gettimeofday() function to calculate the time from the RTC into:


    I would recommend you to refer to the file, rtc.c of OMAPL138 starterware package which already has functions like "RTCTimeGet" and
    "RTCCalendarSet"; Which I hope will be sufficient for you. And also refer to other useful functions of RTC in the same file.



    /** \brief Base address of RTC memory */
    #define SOC_RTC_0_REGS (0x01C23000)

    #define RTC_SECOND (0x0)
    #define RTC_MINUTE (0x4)
    #define RTC_HOUR (0x8)
    #define RTC_DAY (0xC)
    #define RTC_MONTH (0x10)
    #define RTC_YEAR (0x14)

    unsigned int RTCTimeGet(unsigned int baseAdd)
    {
    unsigned int sec = 0, min = 0, hour = 0, mer = 0;

    /* Reading from SECOND register.*/
    sec = HWREG(baseAdd + RTC_SECOND);
    sec = (sec & (RTC_SECOND_SEC1 | RTC_SECOND_SEC0)) << SECOND_SHIFT;

    /* Reading from MINUTE register.*/
    min = HWREG(baseAdd + RTC_MINUTE);
    min = (min & (RTC_MINUTE_MIN1 | RTC_MINUTE_MIN0)) << MINUTE_SHIFT;

    /* Reading from HOUR register.*/
    hour = HWREG(baseAdd + RTC_HOUR);
    hour = (hour & (RTC_HOUR_HOUR1 | RTC_HOUR_HOUR0)) << HOUR_SHIFT;

    /* Reading MERIDIEM bit in HOUR register.*/
    mer = (HWREG(baseAdd + RTC_HOUR) & RTC_HOUR_MERIDIEM);


    return ( sec | min | hour | mer);
    }


    void RTCCalendarSet(unsigned int baseAdd, unsigned int calendar)
    {

    while(IS_RTC_BUSY);

    /* Writing to YEAR register.*/
    HWREG(baseAdd + RTC_YEAR) = (calendar & YEAR_MASK) >> YEAR_SHIFT;

    /* Writing to MONTH register.*/
    HWREG(baseAdd + RTC_MONTH) = (calendar & MONTH_MASK) >> MONTH_SHIFT;

    /* Writing to DAY register.*/
    HWREG(baseAdd + RTC_DAY) = (calendar & DAY_MASK) >> DAY_SHIFT;

    /* Writing to DOTW register.*/
    HWREG(baseAdd + RTC_DOTW) = (calendar & DOTW_MASK);

    }
  • Thanks for your answer. I'm already using these to get the time in seconds, but I need the time in millisecond or higher resolution. For this ideally I need to use the high-resolution RTC counter.

    I have a stopgap solution which is to have a PRD task running every millisecond that's initially synchronised with the RTC:

    unsigned int rtc_setCounter(unsigned int reset_value){
    	RTCCompensationSet(SOC_RTC_0_REGS, reset_value);
    	RTCSet32CounterEnable(SOC_RTC_0_REGS);
    	RTCSet32CounterDisable(SOC_RTC_0_REGS);
    
    	return RTCCompensationGet(SOC_RTC_0_REGS);
    }
    

    time_t time(time_t *_timer){
    	time_t timeCalc;
    	unsigned int RTCtime = RTCTimeGet(SOC_RTC_0_REGS);
    	unsigned int RTCdate = RTCCalendarGet(SOC_RTC_0_REGS);
    
    	timeNow.tm_sec = bcd2int((RTCtime & MASK_SECOND) >> SECOND_SHIFT);
    	timeNow.tm_min = bcd2int((RTCtime & MASK_MINUTE) >> MINUTE_SHIFT);
    	timeNow.tm_hour = bcd2int((RTCtime & MASK_HOUR) >> HOUR_SHIFT);
    
    	timeNow.tm_mday = bcd2int((RTCdate & MASK_DAY) >> DAY_SHIFT);
    	timeNow.tm_mon = bcd2int((RTCdate & MASK_MONTH) >> MONTH_SHIFT);
    	timeNow.tm_year = bcd2int((RTCdate & MASK_YEAR) >> YEAR_SHIFT) + 100; /* Time-travelling to before 2000 or after 2099 will require a firmware modification */
    	timeNow.tm_wday = bcd2int(RTCdate & MASK_DOTW);
    	timeCalc = mktime(&timeNow);
    
    	*_timer = timeCalc;
    
    	return timeCalc;
    }

    void timekeeping_update(void){
    	unsigned int counterValue;
    	time_t time_new, time_reset;
    	static Bool time_milliseconds_running = FALSE;
    
    	time(&time_new);
    
    	/* Reset the 32kHz counter on first run to sychronise RTC with milliseconds counter */
    	if(time_milliseconds_running == FALSE){
    		time_reset = time_new;
    		counterValue = rtc_setCounter(0);
    		time_now_G.milliseconds = 0;
    		time(&time_new);
    		LOG_printf(&trace, "timekeeping: set 32K counter to %u", counterValue);
    		LOG_printf(&trace, "timekeeping: time before = %u, time after = %u", time_reset, time_new);
    		time_milliseconds_running = TRUE;
    	}
    
    	/* Resetting milliseconds when seconds increment keeps things in sync */
    	if(time_new > time_now_G.seconds){
    		/* Seconds have incremented */
    		time_now_G.milliseconds = 0;
    	}
    	/* milliseconds stop at 999 if reached before seconds increment */
    	else if(time_now_G.milliseconds < 999){
    		time_now_G.milliseconds++;
    	}
    	else{
    		time_now_G.milliseconds = 999;
    	}
    
    	time_now_G.seconds = time_new;
    	time_str_G =  ctime(&time_new);
    
    	if(time_now_G.milliseconds % 100 == 0){
    		LOG_printf(&trace, "timekeeping: %u.%03u", time_now_G.seconds, time_now_G.milliseconds);
    	}
    }

    This isn't entirely accurate though, as the RTC runs from a different clock source to the PRD tasks so there could be instances where the milliseconds count goes from 998 straight to 0, or stays at 999 for longer than 1 millisecond. Also, every time I do this, the RTC will lose time. In an application where this would be switched on once or twice a day, I could lose a minute every month, which isn't acceptable. Also, it's duplication when there is already a high-resolution counter running for the RTC.

  • Hi Sivaraj,

    Did you manage to find out any more about the possibility of accessing the 32 kHz RTC counter?