> ## 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

> - Call `_GLOBAL_INIT()`
> - Initialize the global timer variables
> - Start the virtual driver periodic interrupt

> ### Periodic Interrupt Services

> - Decrement software (virtual) watchdog timers
> - Hitting the hardware watchdog timer
> - Increment the global timer variables
> - Drive uC/OS-II preemptive multitasking
> - Drive slice statement preemptive multitasking

> ### 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 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()` were 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

> The following variables `SEC_TIMER`, `MS_TIMER` and `TICK_TIMER` are global variables defined as `shared` `unsigned long`. On initialization, `SEC_TIMER` is synchronized with the real time clock so that the date and time can be accessed more quickly than reading the real time clock simply by reading `SEC_TIMER`.

> 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 users to use for timing purposes. The following sample shows the use of `MS_TIMER` to measure the execution time in micro seconds of a Dynamic C integer add. The work is done in a "nodebug" function so that the debugging does not affect timing:

> ###

>     #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
>     ioi ld a,0x51
>         ld (WDTTR),a
>     ioi ld a,0x54
>         ld (WDTTR),a
>     #endasm

> However, it is recommended that the watchdog not be disabled. This prevents the target from "locking up" by 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.

Z-World http://www.zworld.com Voice: (530) 757-3737 FAX: (530) 757-3792 sales@zworld.com