summaryrefslogtreecommitdiff
path: root/openpicc/application/pio_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/application/pio_irq.c')
-rw-r--r--openpicc/application/pio_irq.c52
1 files changed, 49 insertions, 3 deletions
diff --git a/openpicc/application/pio_irq.c b/openpicc/application/pio_irq.c
index a92ceaa..04763a3 100644
--- a/openpicc/application/pio_irq.c
+++ b/openpicc/application/pio_irq.c
@@ -1,5 +1,6 @@
/* PIO IRQ Implementation for OpenPCD
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
+ * (C) 2007 Henryk Plötz <henryk@ploetzli.ch>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -40,6 +41,37 @@ struct pioirq_state {
static struct pioirq_state pirqs;
static unsigned long count = 0;
+/* This FIQ implementation of pio data change works in close cooperation with function my_fiq_handler
+ * in os/boot/boot.s
+ * This code uses fast forcing for the PIOA irq so that each PIOA data change triggers
+ * a FIQ. The FreeRTOS code has been modified to not mask FIQ ever. This means that the FIQ
+ * code will run asynchronously with regards to the other code and especially might invade critical
+ * sections. The actual FIQ code must therefore be as short as possible and may not call into the
+ * FreeRTOS API (or parts of the application that call into the FreeRTOS API).
+ * Instead a trick will be attempted: The PIOA IRQ will be set to fast forcing with my_fiq_handler
+ * as handler and the FIQ handler then does the absolutely time critical tasks without calling any
+ * other code. Additionally a second, normal IRQ handler is set up for a reserved IRQ on the AIC
+ * that is not connected to any peripherals (see #define of PIO_SECONDARY_IRQ). After handling
+ * the time critical tasks the FIQ handler will then manually assert this IRQ which will then
+ * be handled by the AIC and priority controller and also execute synchronized with regards to
+ * critical sections.
+ * Potential problem: look for race conditions between PIO data change FIQ and handling
+ * of PIO_SECONDARY_IRQ.
+ *
+ * Note: Originally I wanted to use 15 for the PIO_SECONDARY_IRQ but it turns out that that
+ * won't work (the identifier is marked as reserved). Use 31 (external IRQ1) instead. Another
+ * candidate would be 7 (USART1).
+ */
+#define USE_FIQ
+#define PIO_SECONDARY_IRQ 31
+extern void my_fiq_handler(void);
+extern void fiq_handler(void);
+
+/* Will be used in pio_irq_demux_secondary below and contains the PIO_ISR value
+ * from when the FIQ was raised */
+u_int32_t pio_irq_isr_value;
+
+
/* low-level handler, used by Cstartup_app.S PIOA fast forcing and
* by regular interrupt handler below */
void __ramfunc __pio_irq_demux(u_int32_t pio)
@@ -94,6 +126,16 @@ static void pio_irq_demux(void)
portRESTORE_CONTEXT();
}
+/* nearly regular interrupt handler, in case fast forcing for PIOA is enabled and the secondary irq hack used */
+static void pio_irq_demux_secondary(void) __attribute__ ((naked));
+static void pio_irq_demux_secondary(void)
+{
+ portSAVE_CONTEXT();
+ __pio_irq_demux(pio_irq_isr_value);
+ AT91F_AIC_ClearIt(PIO_SECONDARY_IRQ);
+ portRESTORE_CONTEXT();
+}
+
void pio_irq_enable(u_int32_t pio)
{
AT91F_PIO_InterruptEnable(AT91C_BASE_PIOA, pio);
@@ -147,9 +189,6 @@ void pio_irq_init_once(void)
if(!initialized) pio_irq_init();
}
-#define USE_FIQ
-extern void my_fiq_handler(void);
-extern void fiq_handler(void);
void pio_irq_init(void)
{
@@ -161,6 +200,13 @@ void pio_irq_init(void)
0, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &my_fiq_handler);
/* enable fast forcing for PIOA interrupt */
*AT91C_AIC_FFER = (1 << AT91C_ID_PIOA);
+
+ /* Set up a regular IRQ handler to be triggered from within the FIQ */
+ AT91F_AIC_ConfigureIt(PIO_SECONDARY_IRQ,
+ OPENPICC_IRQ_PRIO_PIO,
+ AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, &pio_irq_demux_secondary);
+ AT91F_AIC_ClearIt(PIO_SECONDARY_IRQ);
+ AT91F_AIC_EnableIt(PIO_SECONDARY_IRQ);
#else
AT91F_AIC_ConfigureIt(AT91C_ID_PIOA,
OPENPICC_IRQ_PRIO_PIO,
personal git repositories of Harald Welte. Your mileage may vary