File: rtc_fifo_test.c

package info (click to toggle)
rtlinux 3.1pre3-2
  • links: PTS
  • area: non-free
  • in suites: sarge, woody
  • size: 4,892 kB
  • ctags: 4,228
  • sloc: ansic: 26,204; sh: 2,069; makefile: 1,414; perl: 855; tcl: 489; asm: 380; cpp: 42
file content (117 lines) | stat: -rw-r--r-- 2,918 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117

/*  RTC_MEASURE
    uses real time clock to generate an interrupt and
    figure out elapsed time
    Originally by Michael "FZ" Barabanov(c) 1997, Released under the GPL.
    Modified by Victor Yodaiken (c) 1998, Released under the GPL.
    */

#include <linux/module.h>
#include <linux/kernel.h>
#include <asm/ptrace.h>
#include <rtl_core.h>
#include <asm/io.h>
#include <rtl_sync.h>
#include <rtl_fifo.h>
#include "common.h"


#include <linux/mc146818rtc.h>
char save_cmos_A;
char save_cmos_B;
void shutdown(void);
static int shutdown_flag = 0;
static  unsigned long max_diff = 0;
static  unsigned long min_diff = -1;
static  unsigned long last_time = 0;
static  unsigned long count = 0;


unsigned int  handler(unsigned int irq_number, struct pt_regs *p) {
	/* Do not	rt_task_wait() in a handler */
	unsigned long x,diff;
	struct sample samp;
	switch(shutdown_flag){
		case 0:
			rdtscl(x);
			if(last_time){
				diff = (last_time< x? x- last_time : 0); //ignore overflows
				if(diff > max_diff)max_diff=diff;
				if(diff < min_diff) min_diff = diff;
			}
			if(count++ > 10000){
				count = 0;
				samp.min = timespec_from_ns(min_diff);
				samp.max = timespec_from_ns(max_diff);
				rtf_put(0, &samp, sizeof(samp));
				max_diff = 0;
				min_diff = -1;
				printk("MAXDIFF=%x",(unsigned int)max_diff); 
			}

			(void) CMOS_READ(RTC_REG_C);  /* clear IRQ */ 
			rdtscl(last_time); /* after the conpr */
			break;
		case 1: 
			shutdown_flag = 2;
		default: /* do nothing */

	}
	rtl_hard_enable_irq(8);
	return 0;

}


int fifo_size=4000;
int init_module(void)
{
	unsigned char ctemp;
	int old_irq_state;
	int debug;
	int fifo_status = rtf_create(0, fifo_size);
	if (fifo_status) {
		printk("RTLinux measurement test fail. fifo_status=%d\n",fifo_status);
		return -1;
	}
        printk("Starting RTC measurement module\n");
	rtl_no_interrupts(old_irq_state);
	debug = rtl_request_global_irq(8, handler);
	rtl_hard_enable_irq(8);
	printk("Requested 8 and got %d\n",debug);
	/* program the RTC to interrupt at 8192 Hz */
	save_cmos_A = CMOS_READ(RTC_REG_A);
	save_cmos_B = CMOS_READ(RTC_REG_B);

	CMOS_WRITE(0x23, RTC_REG_A);  	/* 32kHz Time Base, 8192 Hz interrupt frequency */
	ctemp = CMOS_READ(RTC_REG_B);
	ctemp &= 0x8f;                	/* Clear */
	ctemp |= 0x40;                	/* Periodic interrupt enable */
	CMOS_WRITE(ctemp, RTC_REG_B); 

	(void) CMOS_READ(RTC_REG_C);
	rtl_restore_interrupts(old_irq_state);
	return 0;
}

void shutdown(){
	int old_irq_state;
	rtl_no_interrupts(old_irq_state);
	CMOS_WRITE(save_cmos_A, RTC_REG_A);
	CMOS_WRITE(save_cmos_B, RTC_REG_B);
	rtl_free_global_irq(8);
	rtf_destroy(0);
	rtl_restore_interrupts(old_irq_state);
}


void cleanup_module(void)
{
	int timeout = 100000;
	shutdown_flag = 1;
	while((shutdown_flag==1) && timeout--);
	/* so it's kinda sloppy, wait for timeout or for 
	   interrupt routine to ack shutdown, whatever comes
	   first */
	shutdown();
}