Linux Device Drivers

Linux Device Drivers

Character drivers
IO & Memory
Linux Kernel
Process Management
Process Address space

Linux Scheduler
Memory Management
System Calls
Kernel Synchronization
Linux Inter Process Communications

Serial Ports
Parallel Ports
Introduction to Hardware
Linux Timers
DMA in Linux
Linux Threads
Linux Thread Synchronization

Linux Multi Threading
Debugging in Linux
GDB GNU Debugger
KDB Kernel Debugger
KGDB Kernel GNU Debugger
Example Ethernet Driver






The user application requires use of timers for various functions. In order to deal with timer, let us look into the following points:


     Understanding kernel time

     Knowing the current time

     Delaying operation for a specified amount of time

     Scheduling asynchronous functions to happen after a specified time lapse



Two main kinds of Timing measurements


Keeping the current time and date, so that they can be returned to user programs: time(), ftime(), and gettimeofday().


Maintaining timers to notify the kernel that a certain interval of time is elapsed


Hardware clocks


Three clocks: The real-time clock, the time stamp counter and Programmable Interval Timer.


Real time clock


     Real time clock (RTC)-CMOS RAM and RTC in same Chip, Motorola 146818

     Periodic interrupt on IRQ8

     Ports 0x70 and 0x71


Time Stamp Counter


     Pentium includes a 64bit Time Stamp Counter (TSC), can be read by rdtsc instruction.

     Register is a counter that is incremented at each clock.

     If the clock rate is 400 MHz, TSC is incremented at every 2.5 nsec


Programmable Interval Timer


Time measuring device, based on PIT 8254


Interrupts on IRQ0 at every 10 msec


HZ 100





outb_p(0x34, 0x43);

outb_p(LATCH & 0xff, 0x40);

outb(LATCH >> 8, 0x40);



Time Intervals in the kernel


The timer interrupt is a mechanism the kernel uses to keep track of time intervals.


Timer interrupts are generated by timer chip at regular intervals, counted by timer interrupt in global variable jiffies.


The time interval is set by kernel according to value of HZ, defined in <linux/param.h>. Current Linux versions define HZ to be 100, i.e. one tick is 10 msec


Current Time


To get the current time, use the function do_gettimeofday

#include <linux/time.h>

void do_gettimeofday(struct timeval*tv);


Delaying Execution


Long Delays


unsigned long j = jiffies + delay * HZ;

while (jiffies < j)

/* nothing */;


Short Delay


The kernel functions udelay and mdelay


#include <linux/delay.h>

void udelay (unsigned long usecs);

void mdelay (unsigned long msecs);


Timer Interrupt Handler


     Major activities in handler:

     Updates the time elapsed since system startup

     Updates time and date

     Determines process scheduling

     Updates resource usage statistics

     Checks expiry of software timer


The first activity is done in timer, other activities are done in TIMER_BH bottom half.


The Role of Timers

A timer is software facility that allows functions to be invoked at some future moment.

A time-out denotes a moment at which the time interval associated with a timer has elapsed.

Timers are used both by the kernel and processes. Most device drivers make use of timers to detect anomalous conditions: floppy disk driver, use timers to switch off the device motor after the floppy has not been accessed for a while.

Timers are also used to force execution of specific functions at some future time.


System Timers


int init_timer(structtimer_list*timer);

The two functions to add/delete timers:

void add_timer(structtimer_list*timer);

int del_timer(structtimer_list*timer);




Static timers


There are 32 different timers. The static timers are stored in the timer-table array, which includes 32 entries.


Each entry consists of the following timer_struct structure:

struct timer_struct{

unsigned long expires;

void (*fn)(void);




The expires field specifies when the timer expires, expresses in terms of number of ticks (jiffies)

The fn field contains the address of the function to be executed when the timer expires.


Dynamic Timers


Dynamic timers may be dynamically created and destroyed.

No limit is placed on numbers of currently active dynamic timers.

A dynamic timer is stored in the following timer_list structure:

struct timer_list{

struct timer_list*next;

struct timer_list*prev;

unsigned long expires;

unsigned long data;

void (*function) (unsigned long);



System calls related to timing measurement

System calls allow user mode processes to read and modify the time and date and to create timers.


time() Returns number of elapsed seconds since midnight at the start of January 1, 1970.

ftime() Returns, in a data structure of type timeb, elapsed seconds and time zone.

gettimeofday() returns elapsed time and time zone in two data structures.


Current Time

Linux provides the gettimeofday system call, which returns the number of seconds since 00:00:00 GMT, January 1, 1970. It also returns time zone information.


#include <sys/time.h>

int gettimeofday(structtimeval*tvalptr, structtimezone*tzoneptr);

struct timeval{

long tv_sec;/* seconds since 00:00:00 GMT,

Jan. 1, 1970 */

long tv_usec;/* and microseconds */



It returns zero if all is OK, with the structure pointed to by the tvalptr filled in.

settimeofday() system call sets the time of day.


Delaying Execution

We also use the sleep function to pause for a specified number of seconds.

unsigned int sleep(unsigned int sec);


The sleep function usually sets a SIGALRM signal, which it catches.


Scheduling asynchronous functions to happen after a specified time lapse -alarm() system call


The alarm() system call is used for setting software timeouts. A process can set an alarm clock by calling the alarm system call

unsigned int alarm(unsigned int sec);


The sec argument specifies the number of seconds to elapse before the kernel is to send the process a SIGALRM signal. The argument specifies the real time, not the CPU time. If the argument is zero, any previous alarm clock for the process is cancelled. The value returned by the function is the time remaining, if any, from the previous call to the function.

The process has to set a signal handler to process the SIGALRM signal

signal (SIGALRM, handler);



setitimer() system call


Linux allows user mode processes to activate special timers called interval timers. The timers cause signals to be sent periodically to the process. It is also possible to activate an interval timer so that it sends just one signal.


The frequency at which the signals must be emitted, or a null value if just one signal is to be generated.

The time remaining until the next signal is to be generated.

ITMER_REAL: Actual elapsed time

ITIMER_VIRTUAL: Time spent is user process

ITIMER_PROF: Time spent both in user and kernel mode.


The following functions allow better time monitoring of a process than does alarm().


#include <sys/time.h>

int getitimer(int which, struct itimerval*value);

int setitimer(int which, const struct itimerval*value,

struct itimerval *ovalue);


The variable which specifies one of the special timer



The times are indicated in the following structure:

struct itimerval{

struct timevalit_interval;/* interval */

struct timevalit_value;/* starting value */