summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/nested_irq_test.c
blob: dd52c7f1fd6d06a4f587d8d0288d711362e09c17 (plain) (blame)
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
/*
 * Test nested interrupts.
 *
 * Author: Till Straumann <strauman@slac.stanford.edu>, 2007
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.com/license/LICENSE.
 */


/*
 * Needs board with 2 available openpic timers
 *
 * 'timer_instdis(timer, install, period)'
 *
 * installs 'timer_isr' to openpic timer # 'timer'.
 * The interrupt priority is set to 8 + timer#
 *
 * The timer_isr prints a message then polls
 * the variable 'timer_poll' while it has the value
 * of the timer # then sets it to -1 and prints
 * the 'leave' message.
 *
 * To test nested interrupts:
 *
 *  timer_instdis(0, 1, period)
 *  wait_a_bit()
 *  timer_instdis(1, 1, period)
 *  timer_poll = 0;
 *
 *  As soon as timer 0's IRQ fires the
 *  isr prints
 *     TIMER ISR (0) ...
 *  then starts polling (since timer_poll == 0 )
 *  eventually, timer 1 goes off, interrupts (because
 *  it's priority is 9 (i.e., higher than timer 0's priority)
 *  and prints
 *     TIMER ISR (1)
 *  it skips polling since timer_poll is 0, not 1 but
 *  resets timer_poll -1 and prints
 *     Leaving ISR (1)
 *  timer 0 isr resumes polling and finds timer_poll == -1
 *  so it also writes -1 to timer_poll and exits, printing
 *     Leaving ISR (0)
 *
 *  The timer IRQs can be unhooked with
 *     timer_instdis( 0, 0, period );
 *     timer_instdis( 1, 0, period );
 */
#include <rtems.h>
#include <rtems/bspIo.h>
#include <bsp/openpic.h>
#include <bsp/irq.h>
#include <inttypes.h>
#include <stdio.h>

volatile int timer_poll=-1;

static void timer_isr(rtems_irq_hdl_param p)
{
uint32_t top;
uint32_t r1;
uint32_t lat = (OpenPIC->Global.Timer[(int)p].Current_Count & 0x7fffffff);

	lat = OpenPIC->Global.Timer[(int)p].Base_Count - lat;

	asm volatile("mfspr %0, %2; mr %1, 1":"=r"(top),"=r"(r1):"i"(SPRG1));
	printk("Timer ISR (%i): LAT: 0x%08x, TOP 0x%08x, BOT 0x%08x, SP 0x%08x\n",
		(int)p, lat, top, top-rtems_configuration_get_interrupt_stack_size(), r1);
	printk("_ISR_Nest_level %i\n", _ISR_Nest_level);
	while ( timer_poll == (int)p )
		;
	timer_poll = -1;

	printk("Leaving ISR (%i)\n",(int)p);
}

int timer_instdis(int t, int inst, unsigned period)
{
rtems_irq_connect_data xx;
	xx.name   = BSP_MISC_IRQ_LOWEST_OFFSET + t;
	xx.hdl    = timer_isr;
	xx.handle = (rtems_irq_hdl_param)t;
	xx.on     = 0;
	xx.off    = 0;
	xx.isOn   = 0;
	if ( !inst ) {
		openpic_maptimer(t, 0);
		openpic_inittimer(t, 0, 0);
	}
	if ( ! ( inst ? BSP_install_rtems_irq_handler(&xx) : BSP_remove_rtems_irq_handler(&xx) ) ) {
		openpic_maptimer(t, 0);
		openpic_inittimer(t, 0, 0);
		fprintf(stderr,"unable to %s timer ISR #%i\n", inst ? "install" : "remove", t);
		return -1;
	}
	if ( inst ) {
		openpic_maptimer( t, 1 );
		openpic_inittimer( t, 8 + t, OPENPIC_VEC_SOURCE - BSP_PCI_IRQ_LOWEST_OFFSET + xx.name );
		openpic_settimer( t, period, 1 );
	}
	return 0;
}