<< Previous | Index | Next >>

6. The Virtual Driver

Virtual Driver is the name given to some initialization services and a group of services performed by a periodic interrupt. These services are:

Initialization Services

Periodic Interrupt Services

6.1 Default Operation

The user should be aware that by default the Virtual Driver starts and runs in a Dynamic C program without the user doing anything. This happens because before main() is called, a function called premain() is called by the Rabbit kernel (BIOS) that actually calls main(). Before premain() calls main(), it calls a function named VdInit() that performs the initialization services, including starting the periodic interrupt. If the user were to disable the Virtual Driver by commenting out the call to VdInit() in premain(), then none of the services performed by the periodic interrupt would be available. Unless the Virtual Driver is incompatible with some very tight timing requirements of a program and none of the services performed by the Virtual Driver are needed, it is recommended that the user not disable it.

6.2 Calling _GLOBAL_INIT()

VdInit() calls _GLOBAL_INIT() which runs all #GLOBAL_INIT sections in a program. _GLOBAL_INIT() also initializes all of the CoData structures needed by costatements and cofunctions. If VdInit() is not called, users could still use costatements and cofunctions if the call to VdInit() was replaced by a call to _GLOBAL_INIT(), but the DelaySec() and DelayMs() functions often used with costatements and cofunctions in waitfor statements would not work because those functions depend on timer variables which are maintained by the periodic interrupt.

6.3 Global Timer Variables

SEC_TIMER, MS_TIMER and TICK_TIMER are global variables defined as shared unsigned long. These variables should never be changed by an application program. Among other things, the TCP/IP stack depends on the validity of the timer variables.

On initialization, SEC_TIMER is synchronized with the real-time clock. The date and time can be accessed more quickly by reading SEC_TIMER than by reading the real-time clock.

The periodic interrupt updates SEC_TIMER every second, MS_TIMER every millisecond, and TICK_TIMER 1024 times per second (the frequency of the periodic interrupt). These variables are used by the DelaySec, DelayMS and DelayTicks functions, but are also convenient for application programs to use for timing purposes. The following sample shows the use of MS_TIMER to measure the execution time in microseconds of a Dynamic C integer add. The work is done in a nodebug function so that debugging does not affect timing. For more information on the nodebug keyword, please see nodebug.


#define N 10000

main(){ timeit(); }

nodebug timeit(){
unsigned long int T0;
float T2,T1;
int x,y;
int i;

T0 = MS_TIMER;
for(i=0;i<N;i++) { }
// T1 gives empty loop time
T1=(MS_TIMER-T0);
T0 = MS_TIMER;
for(i=0;i<N;i++){ x+y;}
// T2 gives test code execution time
T2=(MS_TIMER-T0);
// subtract empty loop time and convert to time for single pass
T2=(T2-T1)/(float)N;
// multiply by 1000 to convert ms. to us.
printf("time to execute test code = %f us\n",T2*1000.0);
}

6.4 Watchdog Timers

Watchdog timers limit the amount of time your system will be in an unknown state.

6.4.1 Hardware Watchdog

The Rabbit CPU has one built-in hardware watchdog timer (WDT). The Virtual Driver hits this watchdog periodically. The following code fragment could be used to disable this WDT:


#asm
ld a,0x51
ioi ld (WDTTR),a
ld a,0x54
ioi ld (WDTTR),a
#endasm

However, it is recommended that the watchdog not be disabled. This prevents the target from entering an endless loop in software due to coding errors or hardware problems. If the Virtual Driver is not used, the user code should periodically call hitwd().

When debugging a program, if the program is stopped at a breakpoint because the breakpoint was explicitly set, or because the user is single stepping, then the debug kernel hits the hardware watchdog periodically.

6.4.2 Virtual Watchdogs

There are 10 virtual WDTs available; they are maintained by the Virtual Driver. Virtual watchdogs, like the hardware watchdog, limit the amount of time a system is in an unknown state. They also narrow down the problem area to assist in debugging.

The function VdGetFreeW(count) allocates and initializes a virtual watchdog. The return value of this function is the ID of the virtual watchdog. If an attempt is made to allocate more than 10 virtual WDTs, a fatal error occurs. In debug mode, this fatal error will cause the program to return with error code 250. The default run-time error behavior is to reset the board.

The ID returned by VdGetFreeW is used as the argument when calling VdHitWd(ID) or VdReleaseWd(ID) to hit or deallocate a virtual watchdog

The Virtual Driver counts down watchdogs every 62.5 ms. If a virtual watchdog reaches 0, this is fatal error code 247. Once a virtual watchdog is active, it should be reset periodically with a call to VdHitWd(ID) to prevent this. If count = 2 for a particular WDT, then VdHitWd(ID) will need to be called within 62.5 ms for that WDT. If count = 255, VdHitWd(ID) will need to be called within 15.94 seconds.

The Virtual Driver does not count down any virtual WDTs if the user is debugging with Dynamic C and stopped at a breakpoint.

6.5 Preemptive Multitasking Drivers

A simple scheduler for Dynamic C's preemptive slice statement is serviced by the Virtual Driver. The scheduling for µC/OS-II a more traditional full-featured real-time kernel, is also done by the Virtual Driver.

These two scheduling methods are mutually exclusive--slicing and µC/OS-II must not be used in the same program.


<< Previous | Index | Next >>
Z-World, Inc.
www.zworld.com
Phone: 1.530.757.3737
Fax: 1.530.757.3792
Rabbit Semiconductor
www.rabbitsemiconductor.com
Phone: 1.530.757.8400
Fax: 1.530.757.8402