int0.c
2.31 KB
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
#include <limits.h>
#include <os.h>
#include <os_internal.h>
#include <rmon.h>
#include <R4300.h>
#include "perf.h"
/*
* int0
*
* Measures:
* Interrupt latency, or more specifically:
*
* The time from when an interrupt condition becomes true and a
* thread blocking on the interrupt message wakes up reads the message.
*
*/
#define NUM_ITER 1000
static void slave(void *);
static OSMesgQueue sw1MesgQueue;
static OSMesg sw1MesgBuf[1];
static OSMesgQueue slaveMesgQueue;
static OSMesg slaveMesgBuf[1];
static OSThread slaveThread;
static char slaveStack[STACKSIZE];
void
int0(void)
{
OSIntMask savedMask;
unsigned int before, after, elapsed;
unsigned high, low, average;
register int i;
high = 0;
low = UINT_MAX;
average = 0;
savedMask = osSetIntMask(OS_IM_SW1);
osCreateMesgQueue(&sw1MesgQueue, sw1MesgBuf, 1);
osSetEventMesg(OS_EVENT_SW1, &sw1MesgQueue, (OSMesg)NULL);
osCreateMesgQueue(&slaveMesgQueue, sw1MesgBuf, 1);
osCreateThread(&slaveThread, 101, slave, (void *)0,
slaveStack+STACKSIZE, 20);
osStartThread(&slaveThread);
/*
* The master will snapshot the time and then trigger a SW1 interrupt,
* which will cause the slave to wake up. The slave will then immediately
* snapshot the time and return it to the master to do a difference.
*/
for (i = 0; i < NUM_ITER; i++) {
before = osGetCount();
__osSetCause(CAUSE_SW1);
(void)osRecvMesg(&slaveMesgQueue, (OSMesg *)&after, OS_MESG_BLOCK);
elapsed = after - before;
if (elapsed > high)
high = elapsed;
if (elapsed < low)
low = elapsed;
average += elapsed;
}
(void)osSetIntMask(savedMask);
average = average / NUM_ITER;
osSyncPrintf("interrupt latency (cycles) average %d high %d low %d\n",
average, high, low);
osSyncPrintf("interrupt latency (ns) average %lld high %lld low %lld\n",
OS_CYCLES_TO_NSEC(average),
OS_CYCLES_TO_NSEC(high),
OS_CYCLES_TO_NSEC(low));
}
static void
slave(void *arg)
{
OSMesg mesg;
register int i;
/*
* Block for the SW1 interrupt. When it wakes up, snapshot the
* time and send it to the master.
*/
for (i = 0; i < NUM_ITER; i++) {
(void)osRecvMesg(&sw1MesgQueue, &mesg, OS_MESG_BLOCK);
mesg = (OSMesg)osGetCount();
(void)osSendMesg(&slaveMesgQueue, mesg, OS_MESG_BLOCK);
}
}