Project

General

Profile

Download (6.24 KB) Statistics
| Branch: | Tag: | Revision:
1 9d397dfb henryk
/* PIO IRQ Implementation for OpenPCD
2
 * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
3 aa804cf4 henryk
 * (C) 2007 Henryk Plötz <henryk@ploetzli.ch>
4 9d397dfb henryk
 *
5
 *  This program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by 
7
 *  the Free Software Foundation; either version 2 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 *
19
 */
20
21 b5be7c18 henryk
#include "FreeRTOS.h"
22
23 9d397dfb henryk
#include <errno.h>
24
#include <sys/types.h>
25
#include <lib_AT91SAM7.h>
26
#include <string.h>
27
#include "pio_irq.h"
28
#include "dbgu.h"
29
//#include <os/req_ctx.h>
30
#include "openpicc.h"
31
#include "board.h"
32
#include "led.h"
33
34
#include <FreeRTOS.h>
35
#include <task.h>
36
37
struct pioirq_state {
38
	irq_handler_t *handlers[NR_PIO];
39
	u_int32_t usbmask;
40
	u_int32_t usb_throttled; /* atomic? */
41
};
42
43
static struct pioirq_state pirqs;
44 3d0a9bd4 henryk
static unsigned long count = 0;
45 9d397dfb henryk
46 73d04ff8 henryk
/* This FIQ implementation of pio data change works in close cooperation with function fiq_handler  
47 aa804cf4 henryk
 * in os/boot/boot.s
48
 * This code uses fast forcing for the PIOA irq so that each PIOA data change triggers
49
 * a FIQ. The FreeRTOS code has been modified to not mask FIQ ever. This means that the FIQ
50
 * code will run asynchronously with regards to the other code and especially might invade critical
51
 * sections. The actual FIQ code must therefore be as short as possible and may not call into the
52
 * FreeRTOS API (or parts of the application that call into the FreeRTOS API).
53
 * Instead a trick will be attempted: The PIOA IRQ will be set to fast forcing with my_fiq_handler
54
 * as handler and the FIQ handler then does the absolutely time critical tasks without calling any
55
 * other code. Additionally a second, normal IRQ handler is set up for a reserved IRQ on the AIC 
56
 * that is not connected to any peripherals (see #define of PIO_SECONDARY_IRQ). After handling
57
 * the time critical tasks the FIQ handler will then manually assert this IRQ which will then
58
 * be handled by the AIC and priority controller and also execute synchronized with regards to 
59
 * critical sections. 
60
 * Potential problem: look for race conditions between PIO data change FIQ and handling 
61
 * of PIO_SECONDARY_IRQ.
62
 * 
63
 * Note: Originally I wanted to use 15 for the PIO_SECONDARY_IRQ but it turns out that that
64
 * won't work (the identifier is marked as reserved). Use 31 (external IRQ1) instead. Another
65
 * candidate would be 7 (USART1).
66
 */
67
#define USE_FIQ
68
#define PIO_SECONDARY_IRQ 31
69
extern void fiq_handler(void);
70
71
/* Will be used in pio_irq_demux_secondary below and contains the PIO_ISR value 
72
 * from when the FIQ was raised */
73 3d2ce8df henryk
volatile u_int32_t pio_irq_isr_value; 
74 aa804cf4 henryk
75
76 9d397dfb henryk
/* low-level handler, used by Cstartup_app.S PIOA fast forcing and
77
 * by regular interrupt handler below */
78 b5be7c18 henryk
portBASE_TYPE __ramfunc __pio_irq_demux(u_int32_t pio, portBASE_TYPE xTaskWoken)
79 9d397dfb henryk
{
80
	u_int8_t send_usb = 0;
81
	int i;
82 3d0a9bd4 henryk
	count++;
83 9d397dfb henryk
84
	DEBUGPCRF("PIO_ISR_STATUS = 0x%08x", pio);
85
86
	for (i = 0; i < NR_PIO; i++) {
87
		if (pio & (1 << i) && pirqs.handlers[i])
88 b5be7c18 henryk
			xTaskWoken = pirqs.handlers[i](i, xTaskWoken);
89 9d397dfb henryk
		if (pirqs.usbmask & (1 << i))
90
			send_usb = 1;
91
	}
92
93
	AT91F_AIC_AcknowledgeIt();
94
	//AT91F_AIC_ClearIt(AT91C_ID_PIOA);
95 b5be7c18 henryk
	return xTaskWoken;
96 9d397dfb henryk
}
97
98
/* regular interrupt handler, in case fast forcing for PIOA disabled */
99 5cc0ed49 henryk
static void pio_irq_demux(void) __attribute__ ((naked));
100
static void pio_irq_demux(void)
101 9d397dfb henryk
{
102 b5be7c18 henryk
	portENTER_SWITCHING_ISR();
103
	portBASE_TYPE xTaskWoken = pdFALSE;
104 9d397dfb henryk
	u_int32_t pio = AT91F_PIO_GetInterruptStatus(AT91C_BASE_PIOA);
105 b5be7c18 henryk
	xTaskWoken = __pio_irq_demux(pio, xTaskWoken);
106
	portEXIT_SWITCHING_ISR(xTaskWoken);
107 9d397dfb henryk
}
108
109 aa804cf4 henryk
/* nearly regular interrupt handler, in case fast forcing for PIOA is enabled and the secondary irq hack used */
110
static void pio_irq_demux_secondary(void) __attribute__ ((naked));
111
static void pio_irq_demux_secondary(void)
112
{
113 b5be7c18 henryk
	portENTER_SWITCHING_ISR();
114
	portBASE_TYPE xTaskWoken = pdFALSE;
115
	xTaskWoken = __pio_irq_demux(pio_irq_isr_value, xTaskWoken);
116 aa804cf4 henryk
	AT91F_AIC_ClearIt(PIO_SECONDARY_IRQ);
117 b5be7c18 henryk
	portEXIT_SWITCHING_ISR(xTaskWoken);
118 aa804cf4 henryk
}
119
120 9d397dfb henryk
void pio_irq_enable(u_int32_t pio)
121
{
122
	AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, pio);
123
}
124
125
void pio_irq_disable(u_int32_t pio)
126
{
127
	AT91F_PIO_InterruptDisable(AT91C_BASE_PIOA, pio);
128
}
129
130 3d0a9bd4 henryk
/* Return the number of PIO IRQs received */ 
131
long pio_irq_get_count(void)
132
{
133
	return count;
134
}
135
136 9d397dfb henryk
int pio_irq_register(u_int32_t pio, irq_handler_t *handler)
137
{
138
	u_int8_t num = ffs(pio);
139
140
	if (num == 0)
141
		return -EINVAL;
142
	num--;
143
144
	if (pirqs.handlers[num])
145
		return -EBUSY;
146
147
	pio_irq_disable(pio);
148
	AT91F_PIO_CfgInput(AT91C_BASE_PIOA, pio);
149
	pirqs.handlers[num] = handler;
150
	DEBUGPCRF("registering handler %p for PIOA %u", handler, num);
151
152
	return 0;
153
}
154
155
void pio_irq_unregister(u_int32_t pio)
156
{
157
	u_int8_t num = ffs(pio);
158
159
	if (num == 0)
160
		return;
161
	num--;
162
163
	pio_irq_disable(pio);
164
	pirqs.handlers[num] = NULL;
165
}
166
167 5cc0ed49 henryk
static int initialized = 0;
168
void pio_irq_init_once(void)
169
{
170
	if(!initialized) pio_irq_init();
171
}
172
173 062f55ca henryk
174 9d397dfb henryk
void pio_irq_init(void)
175
{
176 5cc0ed49 henryk
	initialized = 1;
177 9d397dfb henryk
	AT91F_PIOA_CfgPMC();
178 616746c2 henryk
#ifdef USE_FIQ
179 73d04ff8 henryk
/*	This code is not necessary anymore, because fiq_handler is directly part of
180
	the vector table, so no jump will happen. 
181 616746c2 henryk
        AT91F_AIC_ConfigureIt(AT91C_ID_FIQ,
182
                              //0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &cdsync_cb);
183 73d04ff8 henryk
                              0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &fiq_handler);
184
*/
185 616746c2 henryk
        /* enable fast forcing for PIOA interrupt */
186
        *AT91C_AIC_FFER = (1 << AT91C_ID_PIOA);
187 aa804cf4 henryk
        
188
        /* Set up a regular IRQ handler to be triggered from within the FIQ */
189
	AT91F_AIC_ConfigureIt(PIO_SECONDARY_IRQ,
190
			      OPENPICC_IRQ_PRIO_PIO,
191
			      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, &pio_irq_demux_secondary);
192
        AT91F_AIC_ClearIt(PIO_SECONDARY_IRQ);
193
	AT91F_AIC_EnableIt(PIO_SECONDARY_IRQ);
194 616746c2 henryk
#else
195 9d397dfb henryk
	AT91F_AIC_ConfigureIt(AT91C_ID_PIOA,
196 3fb02f71 henryk
			      OPENPICC_IRQ_PRIO_PIO,
197 5cc0ed49 henryk
			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &pio_irq_demux);
198 616746c2 henryk
#endif
199 9d397dfb henryk
	AT91F_AIC_EnableIt(AT91C_ID_PIOA);
200 5cc0ed49 henryk
	(void)pio_irq_demux; // FIXME NO IRQ
201 9d397dfb henryk
}
Add picture from clipboard (Maximum size: 48.8 MB)