Previous

Next

Bottom

Contents

Glossary

Index

 

Persistor CF1 User's Manual

Real Time Clock Drivers and Functions

Nov 2000

Revision 1.03

 Persistor Instruments Inc.
© 1998 All rights reserved.

Quick Reference Table

RTCAddChore

RTCErrorSignal

RTCclock

RTCGetTime

RTCCountdownReset

RTCInit

RTCCountdownTimeout

RTClocaltime

RTCCountdownTimerSetup

RTCRemoveChore

RTCDelayMicroSeconds

RTCSetTime

RTCDelayTicks

RTCStartClock

RTCElapsedTime

RTCStopClock

RTCElapsedTimerSetup

RTCtime

RTCEnableErrTrap

Introduction

The MC68CK338 has an onboard Real Time Clock (RTC) Submodule which is clocked by a separate 32768 Hz crystal, and powered by either the main supply or an off-board backup battery. The RTC is used as the time reference for the standard C library functions and specialty timer driver functions. The RTC crystal is a basic CX1V tuning fork resonator with an initial accuracy of +/-50ppm in a Pierce oscillator circuit with the parabolic temperature versus frequency curve typical of these types of crystals (see the electrical specifications for details and graphs).

Your programs interact with the RTC through a combination of low level drivers which are basically wrappers for accessing the hardware, standard C library functions like clock() and time(), and through a suite of high level functions that provide countdown timers, elapsed timers, synchronization timers, and delays. We'll start at the bottom and work our way up.

The lowest level driver functions interact with the RTC using its native time format of seconds as an unsigned long integer, and ticks as an unsigned short integer that increments by two for each oscillation of the crystal (0,2,4,...,65532,65534,0,2...). These low level drivers let you initialize the driver, start and stop the clock, and read or set the time in the RTCs native format.

Elapsed and Countdown Timers

The countdown and elapsed time functions provide convenient methods for measuring short intervals or waiting for a timeout. These functions work with and return values normalized to microseconds. Because internally the real time clock can only measure time in units of 32768 Hz ticks, the timer is internally counted as an integer number of ticks. Since one tick is approximately 30 µsecs and the calling overhead of the functions that interact with these counters is at least 20 µsecs, the timers have an effective resolution of no less than 60 µsecs. The elapsed and countdonw timers have a maximum span of about 1.2 hours before overflowing. Below is an example of usage:

    RTCTimer        tmtest;
     ...
    RTCElapsedTimerSetup(&tmtest);
     < code block being measured >
    printf("Elapsed time %ld us \n", RTCElapsedTime(&tmtest));

RTCAddChore -- Add an RTC interrupt chore

The Persistor's real time clock has the feature of being able to execute interrupt chores once a second. The real time clock can manage up to seven chores at once. Multiple chores will be executed with respect to the interrupt request level with which they are submitted via this function. Bear in mind that while the RTC will internally order the execution of these tasks by the priority with which they are submitted, no task will ever be executed at a higher actual interrupt level than the RTC was initialized with at start up time. Unless specifically modified, the RTC starts up at interrupt priority level 2. This function provides a good way to periodically take a quick look around for hardware problems and throw up a flag for a main loop to see.

Note that RTC needs an explicit re-initialization to start generating the 1Hz interrupts that fire the RTC chores and this is explained in the RTCInit function description.

Prototype:

bool RTCAddChore(vfptr chore, ushort intReqLevel);

Definition:

#include <cf1bios.h>

Inputs:

chore is a volatile function pointer to the chore to be executed at interrupt time
intReqLevel is the interrupt priority you wish the task to be executed at. This always effects the ordering and priority between multiple chores in the RTC chore list but the chore will not necessarily execute at this interrupt priority level.

Returns:

Returns a boolean that is TRUE if the chore was successfully added to the RTC chore list.

Notes:

These chores must be kept short. A good rule of thumb is that all of the RTC interrupt chores combined should not exceed 100 µsecs in execution time. This should be tested before attempting to install the chore.

Timing:

65 µsecs

RTCclock -- ANSI standard C library clock() equivalent function

Returns clock time in ticks(1/65536'th of a second). The ulong that is returned is calculated by multiplying the seconds register of the real time clock (number of seconds since midnight Jan 1, 1970) by 65536 and adding the ticks register. The result of the clock function can be used for relative timing of short periods of time, but will not accurately return the number of ticks since the epoch due to overflows occurring approximately every 18 hours. Due to these overflows, it is inadvisable to use the RTCclock function for critical timing applications without using some other method to check and account for overflows.

Prototype:

ulong RTCclock(void);

Definition:

#include <cf1bios.h>

Returns:

Returns a ulong containing the seconds count since epoch times 65536 plus the contents of the ticks register.

Notes:

Overflows every 18 hours. Applications should check for overflow conditions or double-check the results of RTCclock against some other timing method.

Timing:

18 µsecs

RTCCountdownReset -- Reset a countdown timer to its initial state

RTCCountdownReset takes the timer pointed to by rt and resets it to the initial microseconds value specifed in RTCCountdownTimerSetup and starts it counting down again. This is useful if you are looking for an event to last or not occur for a given number amount of time. Calling RTCCountdownReset is equivalent to calling RTCCountdownTimerSetup with the same parameters that were used when the timer was originally set up.

Prototype:

void RTCCountdownReset(RTCTimer *rt);

Definition:

#include <cf1bios.h>

Inputs:

rt is a pointer to an RTCTimer structure that has already been set up and started by the RTCCountdownTimerSetup function;

Notes:

See the Elapsed and Countdown Timers description at the top.

Timing:

62 µsecs

RTCCountdownTimeout -- Check a countdown timer for timeout

Once a countdown timer has been set up and started with the RTCCountdownTimerSetup function, RTCCountdownTimeout is called with the pointer to the RTCTimer structure filled by the setup function. Then a boolean is returned indicate whether or not the counter has reached zero yet or not.

Prototype:

bool RTCCountdownTimeout(RTCTimer *rt);

Definition:

#include <cf1bios.h>

Inputs:

rt is a pointer to a RTCTimer struct, that was initialized by the RTCCountdownTimerSetup function prior to RTCCountdownTimeout being called.

Returns:

Returns a boolean indicating whether or not the countdown timer has reached zero or not.

Notes:

See the Elapsed and Countdown Timers description at the top.

Timing:

21 µsecs

RTCCountdownTimerSetup -- Setup a countdown timer (us)

RTCCountdownTimerSetup tells the real time clock to set up and start a descending counter that begins counting down at us microseconds. The timer will begin counting down until it hits zero and will then stop. Once the timer is set up and running, use the functions RTCCountdownTimeout and RTCCountdownReset to watch the counter.

Prototype:

void RTCCountdownTimerSetup(RTCTimer *rt, ulong us);

Definition:

#include <cf1bios.h>

Inputs:

rt is a pointer to a preallocated RTCTimer struct.
us is the number of microseconds for which you wish the timer to count down.

Notes:

See the Elapsed and Countdown Timers description at the top.

Timing:

69 µsecs

RTCDelayMicroSeconds -- Delay for microseconds

RTCDelayMicroSeconds provides a simple means to kill a specific amount of time, specified in microseconds. This performs much the same function as RTCDelayTicks but takes its argument in microseconds. The resolution of the calculation from microseconds to ticks which the real time clock can measure is about 30 µsecs.

Prototype:

bool RTCDelayMicroSeconds (ulong d);

Definition:

#include <cf1bios.h>

Inputs:

d is a ulong containing the number of microseconds to wait before returning.

Returns:

Returns a boolean that is TRUE unless the clock is stopped at the time RTCDelayMicroSeconds is called.

Notes:

RTCDelayMicroSeconds behavior in the event that the RTC is stopped is dependent on the action specified by RTCEnableErrTrap. Normally, it will simply return FALSE if the clock is stopped but if error trapping is enabled by RTCEnableErrTrap then the machine will crash and print debug information. Because internally the real time clock can only measure time in units of ticks, the countdown is counted in an integer number of ticks. Because one tick is approximately 30 µsecs and the calling overhead of the functions that interact with the clock is around 20 µsecs, delays of less than 60 µsecs are meaningless and that RTCDelayMicroSeconds has an effective resolution of 60 µsecs.

Timing:

Dependent on argument.

RTCDelayTicks -- Delay for clock ticks (1/65536 seconds)

RTCDelayTicks provides a simple means to kill a specific amount of time, specified in ticks (1/65536'th of a second).

Prototype:

bool RTCDelayTicks(ulong d);

Definition:

#include <cf1bios.h>

Inputs:

d is a ulong containing the number of ticks to wait before returning.

Returns:

Returns a boolean that is TRUE unless the clock is stopped at the time RTCDelayTicks is called.

Notes:

RTCDelayTicks's behavior in the event that the RTC is stopped is dependent on the action specified by RTCEnableErrTrap. Normally, it will simply return FALSE if the clock is stopped but if error trapping is enabled by RTCEnableErrTrap then the machine will crash and print debug information.

Timing:

Dependent on argument.

RTCElapsedTime -- Read the elapsed time (us)

Prototype:

ulong RTCElapsedTime(RTCTimer *rt);

Definition:

#include <cf1bios.h>

Inputs:

rt is a pointer to an RTCTimer struct that is preallocated and ready to be filled.

Returns:

Returns the elapsed time in microseconds.

Notes:

Because internally the real time clock can only measure time in units of ticks, the timer is internally counted as an integer number of ticks then normalized to microseconds. Because one tick is approximately 30 µsecs and the calling overhead of the functions that interact with these counters is at least 20 µsecs, the timers have an effective resolution of no less than 60 µsecs.

Timing:

31 µsecs

RTCElapsedTimerSetup -- Setup and start an elapsed timer (us)

RTCElapsedTimerSetup tells the real time clock to set up and start an ascending counter. The timer will immediately begin counting up from zero in microseconds. Once RTCElapsedTimerSetup returns, use the function RTCElapsedTime with the same RTCTimer struct to watch the counter.

Prototype:

void RTCElapsedTimerSetup(RTCTimer *rt);

Definition:

#include <cf1bios.h>

Inputs:

rt is a pointer to an RTCTimer struct that is preallocated and ready to be filled.

Notes:

See the Elapsed and Countdown Timers description at the top.

Timing:

18 µsecs

RTCEnableErrTrap -- Enable/Disable RTC off lockup error trapping

RTCEnableErrTrap is used to turn on and off error trapping in the RTC subsystem. When an RTC related function runs across an error, it may call the function RTCErrorSignal, which will by default simply return the boolean that was passed to it. However if this function has been used to turn on RTC error trapping, the machine will cease execution and print debugging messages.

Prototype:

void RTCEnableErrTrap(bool dotrap);

Definition:

#include <cf1bios.h>

Inputs:

dotrap is a boolean which if passed TRUE indicates that RTCErrorSignal should cease execution and print debugging messages when called, as opposed to simply returning.

Notes:

Timing:

4.4 µsecs

RTCErrorSignal -- Return error or take RTCErrorTrap

This function is called internally on return from the delay functions and possibly other to deal with error conditions such as the clock being stopped at the time of a RTCDelayTicks call for instance. It is listed here because it can be patched or can also be called by your functions to handle an error with respect to the setting of RTCEnableErrTrap. If the RTC error trapping is enabled (by using RTCEnableErrTrap) when this is called, the machine will crash and print debugging messages, which will include whatever was in offense. Otherwise it will simply return the same boolean passed to it in code. When this function is called by the system, offense will contain the table entry address in the dispatch table (see cf1bios.h) of the function that called RTCErrorSignal.

Prototype:

bool RTCErrorSignal(bool code, long offense);

Definition:

#include <cf1bios.h>

Inputs:

code is a boolean that contains what the calling function would have returned.
offense is the address of the table entry that contains a pointer to the function which originally called RTCErrorSignal, but can be anything and is simply a value that is displayed as a debug message if error trapping is enable and a crash is triggered.

Returns:

Returns a boolean equal to code if RTC error trapping is disabled.

Notes:

Timing:

N/A

RTCGetTime -- Get both seconds and ticks

The real time clock maintains two registers. One that keeps ticks (1/65536'ths of a second, but always incremented by two for approximately 30.5 µsec resolution) and one that keeps seconds. If the clock is properly set, the seconds and ticks registers reflect the time since the UNIX epoch which is midnight Jan 1, 1970. This function takes two pointers into which the contents of the two registers will be placed.

Prototype:

ulong RTCGetTime(ulong *seconds, ushort *ticks);

Definition:

#include <cf1bios.h>

Inputs:

seconds is a pointer to a ulong into which the current seconds counter will be placed.
ticks is a pointer to a ushort into which the current ticks count will be placed.

Returns:

Returns a ulong containing just the seconds count. This is useful when you do not wish to create placeholding variables. See note below.

Notes:

If either or both of the pointers are NULL, the function will not write into the base of memory, it will ignore the parameter and fill the other one, or if both are NULL, it will simply return the seconds count.

Timing:

12 µsecs

RTCInit -- Initialize the Real Time Clock module

This function is called automatically by the BIOS before PicoDOS or your program runs - but with the interrupt priority level set to zero. This means no 1Hz interrupts are generated and that RTC chores will not run until you explicitly call this function with a non-zero priority level. Calling RTCInit removes any currently installed RTC chores, so the proper sequence is to call RTCInit followed by one or more calls to RTCAddChore. The default interrupt priority for the real-time clock interrupts is defined in <cf1bios.h> as CTM_RTC_DEF_IPL - a fairly low level of two.

Prototype:

void RTCInit(short intReqLevel);

Definition:

#include <cf1bios.h>

Inputs:

intReqLevel is the CPU32 interrupt request level

Notes:

called automatically at system startup

Timing:

unspecified

RTClocaltime -- ANSI standard C library localtime equivalent function

RTClocaltime converts a ulong returned by RTCtime into a struct RTCtm which is the equivalent of a standard tm structure. The RTCtm structure contains the same elements as the system tm structure: tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year, tm_wday, tm_yday, tm_isdst.

Prototype:

RTCtm *RTClocaltime(const ulong *tp);

Definition:

#include <cf1bios.h>

Inputs:

tp is a pointer to a ulong where the time in the form of seconds since epoch is stored.

Returns:

Returns a pointer to struct of type RTCtm containing the parsed time and date information.

Notes:

Timing:

138 µsecs

RTCRemoveChore -- Remove an RTC interrupt chore (NULL vfptr for all)

RTCRemoveChore removes a chore from the RTC chore list that was put there by the RTCAddChore function. If chore is a null pointer, then all the chores will be removed from the list. RTCRemoveChore will return TRUE if the chore was removed successfully and FALSE if there was a problem such as the chore not being in the chore list at the time of removal.

Prototype:

bool RTCRemoveChore(vfptr chore);

Definition:

#include <cf1bios.h>

Inputs:

chore is a volatile function pointer to the chore that was installed in the RTC chore list by RTCAddChore.

Returns:

Returns a boolean that is TRUE if the chore was successfully removed from the chore list.

Notes:

Timing:

100 to 300 µsecs depending on the chore and the number of chores.

RTCSetTime -- Set both seconds and ticks

The real time clock maintains two registers. One that keeps ticks (1/65536'ths of a second) and one that keeps seconds. RTCSetTime loads values into those registers that are provided in the argument to the function. For standard operation these values should reflect the number of seconds and the number of ticks since the UNIX epoch which is midnight Jan 1, 1970, although there is no restriction that forces this to be true. RTCSetTime can be called regardless of whether the real time clock is running or stopped. If the clock is running, RTCSetTime will set the time and keep the clock running, as could be expected. If the clock is stopped, for instance if you wish to set the clock based on an external event, RTCSetTime will load the given values into the registers and then when/if the clock is started, it will continue to count from the values loaded.

Prototype:

void RTCSetTime(ulong secs, ushort ticks);

Definition:

#include <cf1bios.h>

Inputs:

secs is a ulong that contains the value intended for the seconds register of the Real Time Clock
ticks is a ushort that contains the value intended for the ticks register of the Real Time Clock

Notes:

Timing:

Timing-TBD

RTCStartClock -- Start the Real Time Clock module

The is the companion function to RTCStopClock(), and helper function for RTCInit(). You will not generally use this directly in your applications. See the RTCStopClock() description above, and the example code at the end of the section for information on how this fits into synchronizing the RTC clock to an external signal.

Prototype:

void RTCStartClock(void);

Definition:

#include <cf1bios.h>

Notes:

you do not need to explicitly turn on the RTC

Timing:

unspecified (tens of microseconds at 16MHz)

RTCStopClock -- Stop the Real Time Clock module

This dangerous function stops the RTC. It's dangerous because many other driver functions will fail, and possibly freeze the entire system if the RTC is not running. You should only use this function if you need to synchronize the RTC with some external time reference and cannot tolerate even small latencies between sync detect and the start action. If you must do this, do it with interrupts disabled, and while limiting calls to other driver functions that might depend on delays or timeouts expected of the RTC. Refer to the RTCSyncExample() sample code ahead to see how this would work.

Prototype:

void RTCStopClock(void);

Definition:

#include <cf1bios.h>

Notes:

you do not need to turn off the RTC for normal time setting operations

Timing:

unspecified (tens of microseconds at 16MHz)

RTCtime -- ANSI standard C library time() equivalent function

This function returns the contents of the real time clock's seconds register. In a system with a properly set clock, this will be equal to the number of seconds since midnight Jan 1, 1970. This number is copied into the ulong pointed to by tp.

Prototype:

ulong RTCtime(ulong *tp);

Definition:

#include <cf1bios.h>

Inputs:

tp is a pointer to a ulong where you wish the time to be placed on return.

Returns:

Returns the contents of the real time clock's seconds register.

Notes:

If tp is NULL, the function will not fail or write to the base of memory, it will simply do nothing with the argument and return the the contents of the real time clock's seconds register.

Timing:

16 µsecs

/*******************************************************************************
**  RTCSyncExample  // Example demonstrating how to synchronize the RTC
**
**  This example assumes that argument secs contains the time in seconds since
**  midnight, 1/1/70, which will become valid on the falling edge of a pulse
**  we will be monitoring on IRQ4 (pin 41). It also assumes that there's
**  nothing else important happening, as we may be turning off all interrupts
**  while we wait for the synchronization signal.
**  
**  secs and ticks are the time values to load into the clock (see RTCSetTime())
**  pin is the pin number (1..50) we look to for synchronization
**  detect is the pin level (0 or 1) we wait for to occur
**  
*******************************************************************************/
void RTCSyncExample(ulong secs, ushort ticks, short pin, short detect);
void RTCSyncExample(ulong secs, ushort ticks, short pin, short detect)
    {
    ushort      saveSR;     // to save the interrupt mask level
    
    saveSR = IEVSaveSRThenDisable();    // all interrupts now disabled
    RTCStopClock();                     // stop the clock
    RTCSetTime(secs, ticks);            // load the time into the stopped clock
    while (PIORead(pin) != detect)      // now we wait...
        ;
    RTCStartClock();                    // start the clock running again
    IEVRestoreSavedSR(saveSR);          // restore the entry mask level
 
    }   /* RTCSyncExample() */

 

For the ANSI C library functions:

time() returns the calendar time in seconds since midnight, 1/1/1970 as a value of type time_t which is typedef'd as an unsigned long. This numeric time is compatible with the Win32 numeric time values to simplify processing on the most likely target platform.

clock() returns the time in RTC ticks since the program started running, as dictated by the ANSI C standard. The ticks are the native 1/65536 second intervals of the real time clock as a value of clock_t, typedef'd as unsigned long. The limitations of 32 bit longs will cause the clock() value to reset to zero after about 18 hours. For this reason, we recommend that you limit the use of clock() to short run programs, or use the RTCclockZeroStart() function to periodically zero the start time at safe points in your long duration programs. Except for legacy and library code, the RTC driver library provides a suite of precision timing functions to pretty much eliminate the need for the standard C clock() function which was not really meant for the types of applications addressed by the CF1.

typedef unsigned long clock_t;
typedef unsigned long time_t;
#define CLOCKS_PER_SEC 32768

 

See Real Time Clock or information on the RTC hardware.

 

 

Previous

Next

Top

Contents

Glossary

Index

Tel: 508-759-6434

Fax: 508-759-6436

Copyright (C) 1998 Persistor Instruments Inc. - All Rights Reserved