summaryrefslogtreecommitdiff
path: root/libcpu
diff options
context:
space:
mode:
author[email protected] <[email protected]>2011-06-26 15:09:26 +0000
committer[email protected] <[email protected]>2011-06-26 15:09:26 +0000
commit1586a43f6c57432ffe459061eaa28fd091b8052b (patch)
treecc08ad8cdb4a7a7cdf090a40736be2e31d78b5a5 /libcpu
parent7beb4cd4cfca91a4d3f5c3e47fb92253d4a9340e (diff)
support gpio interrupt
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1539 bbd45198-f89e-11dd-88c7-29a3b14d5316
Diffstat (limited to 'libcpu')
-rwxr-xr-xlibcpu/arm/at91sam926x/at91_pdc.h21
-rwxr-xr-xlibcpu/arm/at91sam926x/at91sam926x.h2
-rw-r--r--libcpu/arm/at91sam926x/gpio.h119
-rwxr-xr-xlibcpu/arm/at91sam926x/interrupt.c127
4 files changed, 262 insertions, 7 deletions
diff --git a/libcpu/arm/at91sam926x/at91_pdc.h b/libcpu/arm/at91sam926x/at91_pdc.h
new file mode 100755
index 0000000000..1e52944c92
--- /dev/null
+++ b/libcpu/arm/at91sam926x/at91_pdc.h
@@ -0,0 +1,21 @@
+#ifndef __AT91_PDC_H__
+#define __AT91_PDC_H__
+
+#define AT91_PDC_RPR 0x100 /* Receive Pointer Register */
+#define AT91_PDC_RCR 0x104 /* Receive Counter Register */
+#define AT91_PDC_TPR 0x108 /* Transmit Pointer Register */
+#define AT91_PDC_TCR 0x10c /* Transmit Counter Register */
+#define AT91_PDC_RNPR 0x110 /* Receive Next Pointer Register */
+#define AT91_PDC_RNCR 0x114 /* Receive Next Counter Register */
+#define AT91_PDC_TNPR 0x118 /* Transmit Next Pointer Register */
+#define AT91_PDC_TNCR 0x11c /* Transmit Next Counter Register */
+
+#define AT91_PDC_PTCR 0x120 /* Transfer Control Register */
+#define AT91_PDC_RXTEN (1 << 0) /* Receiver Transfer Enable */
+#define AT91_PDC_RXTDIS (1 << 1) /* Receiver Transfer Disable */
+#define AT91_PDC_TXTEN (1 << 8) /* Transmitter Transfer Enable */
+#define AT91_PDC_TXTDIS (1 << 9) /* Transmitter Transfer Disable */
+
+#define AT91_PDC_PTSR 0x124 /* Transfer Status Register */
+
+#endif
diff --git a/libcpu/arm/at91sam926x/at91sam926x.h b/libcpu/arm/at91sam926x/at91sam926x.h
index 40d1436511..8101fecc9d 100755
--- a/libcpu/arm/at91sam926x/at91sam926x.h
+++ b/libcpu/arm/at91sam926x/at91sam926x.h
@@ -29,8 +29,10 @@ extern "C" {
#include "at91_pio.h"
#include "at91_serial.h"
#include "at91_tc.h"
+#include "at91_pdc.h"
#include "io.h"
#include "irq.h"
+#include "gpio.h"
/*
* Peripheral identifiers/interrupts.
diff --git a/libcpu/arm/at91sam926x/gpio.h b/libcpu/arm/at91sam926x/gpio.h
new file mode 100644
index 0000000000..e132b99823
--- /dev/null
+++ b/libcpu/arm/at91sam926x/gpio.h
@@ -0,0 +1,119 @@
+#ifndef __GPIO_H__
+#define __GPIO_H__
+
+#include <at91_aic.h>
+
+#define PIN_BASE AIC_IRQS
+
+#define MAX_GPIO_BANKS 3
+
+#define PIN_IRQS (MAX_GPIO_BANKS*32)
+
+/* these pin numbers double as IRQ numbers, like AT91xxx_ID_* values */
+
+#define AT91_PIN_PA0 (PIN_BASE + 0x00 + 0)
+#define AT91_PIN_PA1 (PIN_BASE + 0x00 + 1)
+#define AT91_PIN_PA2 (PIN_BASE + 0x00 + 2)
+#define AT91_PIN_PA3 (PIN_BASE + 0x00 + 3)
+#define AT91_PIN_PA4 (PIN_BASE + 0x00 + 4)
+#define AT91_PIN_PA5 (PIN_BASE + 0x00 + 5)
+#define AT91_PIN_PA6 (PIN_BASE + 0x00 + 6)
+#define AT91_PIN_PA7 (PIN_BASE + 0x00 + 7)
+#define AT91_PIN_PA8 (PIN_BASE + 0x00 + 8)
+#define AT91_PIN_PA9 (PIN_BASE + 0x00 + 9)
+#define AT91_PIN_PA10 (PIN_BASE + 0x00 + 10)
+#define AT91_PIN_PA11 (PIN_BASE + 0x00 + 11)
+#define AT91_PIN_PA12 (PIN_BASE + 0x00 + 12)
+#define AT91_PIN_PA13 (PIN_BASE + 0x00 + 13)
+#define AT91_PIN_PA14 (PIN_BASE + 0x00 + 14)
+#define AT91_PIN_PA15 (PIN_BASE + 0x00 + 15)
+#define AT91_PIN_PA16 (PIN_BASE + 0x00 + 16)
+#define AT91_PIN_PA17 (PIN_BASE + 0x00 + 17)
+#define AT91_PIN_PA18 (PIN_BASE + 0x00 + 18)
+#define AT91_PIN_PA19 (PIN_BASE + 0x00 + 19)
+#define AT91_PIN_PA20 (PIN_BASE + 0x00 + 20)
+#define AT91_PIN_PA21 (PIN_BASE + 0x00 + 21)
+#define AT91_PIN_PA22 (PIN_BASE + 0x00 + 22)
+#define AT91_PIN_PA23 (PIN_BASE + 0x00 + 23)
+#define AT91_PIN_PA24 (PIN_BASE + 0x00 + 24)
+#define AT91_PIN_PA25 (PIN_BASE + 0x00 + 25)
+#define AT91_PIN_PA26 (PIN_BASE + 0x00 + 26)
+#define AT91_PIN_PA27 (PIN_BASE + 0x00 + 27)
+#define AT91_PIN_PA28 (PIN_BASE + 0x00 + 28)
+#define AT91_PIN_PA29 (PIN_BASE + 0x00 + 29)
+#define AT91_PIN_PA30 (PIN_BASE + 0x00 + 30)
+#define AT91_PIN_PA31 (PIN_BASE + 0x00 + 31)
+
+#define AT91_PIN_PB0 (PIN_BASE + 0x20 + 0)
+#define AT91_PIN_PB1 (PIN_BASE + 0x20 + 1)
+#define AT91_PIN_PB2 (PIN_BASE + 0x20 + 2)
+#define AT91_PIN_PB3 (PIN_BASE + 0x20 + 3)
+#define AT91_PIN_PB4 (PIN_BASE + 0x20 + 4)
+#define AT91_PIN_PB5 (PIN_BASE + 0x20 + 5)
+#define AT91_PIN_PB6 (PIN_BASE + 0x20 + 6)
+#define AT91_PIN_PB7 (PIN_BASE + 0x20 + 7)
+#define AT91_PIN_PB8 (PIN_BASE + 0x20 + 8)
+#define AT91_PIN_PB9 (PIN_BASE + 0x20 + 9)
+#define AT91_PIN_PB10 (PIN_BASE + 0x20 + 10)
+#define AT91_PIN_PB11 (PIN_BASE + 0x20 + 11)
+#define AT91_PIN_PB12 (PIN_BASE + 0x20 + 12)
+#define AT91_PIN_PB13 (PIN_BASE + 0x20 + 13)
+#define AT91_PIN_PB14 (PIN_BASE + 0x20 + 14)
+#define AT91_PIN_PB15 (PIN_BASE + 0x20 + 15)
+#define AT91_PIN_PB16 (PIN_BASE + 0x20 + 16)
+#define AT91_PIN_PB17 (PIN_BASE + 0x20 + 17)
+#define AT91_PIN_PB18 (PIN_BASE + 0x20 + 18)
+#define AT91_PIN_PB19 (PIN_BASE + 0x20 + 19)
+#define AT91_PIN_PB20 (PIN_BASE + 0x20 + 20)
+#define AT91_PIN_PB21 (PIN_BASE + 0x20 + 21)
+#define AT91_PIN_PB22 (PIN_BASE + 0x20 + 22)
+#define AT91_PIN_PB23 (PIN_BASE + 0x20 + 23)
+#define AT91_PIN_PB24 (PIN_BASE + 0x20 + 24)
+#define AT91_PIN_PB25 (PIN_BASE + 0x20 + 25)
+#define AT91_PIN_PB26 (PIN_BASE + 0x20 + 26)
+#define AT91_PIN_PB27 (PIN_BASE + 0x20 + 27)
+#define AT91_PIN_PB28 (PIN_BASE + 0x20 + 28)
+#define AT91_PIN_PB29 (PIN_BASE + 0x20 + 29)
+#define AT91_PIN_PB30 (PIN_BASE + 0x20 + 30)
+#define AT91_PIN_PB31 (PIN_BASE + 0x20 + 31)
+
+#define AT91_PIN_PC0 (PIN_BASE + 0x40 + 0)
+#define AT91_PIN_PC1 (PIN_BASE + 0x40 + 1)
+#define AT91_PIN_PC2 (PIN_BASE + 0x40 + 2)
+#define AT91_PIN_PC3 (PIN_BASE + 0x40 + 3)
+#define AT91_PIN_PC4 (PIN_BASE + 0x40 + 4)
+#define AT91_PIN_PC5 (PIN_BASE + 0x40 + 5)
+#define AT91_PIN_PC6 (PIN_BASE + 0x40 + 6)
+#define AT91_PIN_PC7 (PIN_BASE + 0x40 + 7)
+#define AT91_PIN_PC8 (PIN_BASE + 0x40 + 8)
+#define AT91_PIN_PC9 (PIN_BASE + 0x40 + 9)
+#define AT91_PIN_PC10 (PIN_BASE + 0x40 + 10)
+#define AT91_PIN_PC11 (PIN_BASE + 0x40 + 11)
+#define AT91_PIN_PC12 (PIN_BASE + 0x40 + 12)
+#define AT91_PIN_PC13 (PIN_BASE + 0x40 + 13)
+#define AT91_PIN_PC14 (PIN_BASE + 0x40 + 14)
+#define AT91_PIN_PC15 (PIN_BASE + 0x40 + 15)
+#define AT91_PIN_PC16 (PIN_BASE + 0x40 + 16)
+#define AT91_PIN_PC17 (PIN_BASE + 0x40 + 17)
+#define AT91_PIN_PC18 (PIN_BASE + 0x40 + 18)
+#define AT91_PIN_PC19 (PIN_BASE + 0x40 + 19)
+#define AT91_PIN_PC20 (PIN_BASE + 0x40 + 20)
+#define AT91_PIN_PC21 (PIN_BASE + 0x40 + 21)
+#define AT91_PIN_PC22 (PIN_BASE + 0x40 + 22)
+#define AT91_PIN_PC23 (PIN_BASE + 0x40 + 23)
+#define AT91_PIN_PC24 (PIN_BASE + 0x40 + 24)
+#define AT91_PIN_PC25 (PIN_BASE + 0x40 + 25)
+#define AT91_PIN_PC26 (PIN_BASE + 0x40 + 26)
+#define AT91_PIN_PC27 (PIN_BASE + 0x40 + 27)
+#define AT91_PIN_PC28 (PIN_BASE + 0x40 + 28)
+#define AT91_PIN_PC29 (PIN_BASE + 0x40 + 29)
+#define AT91_PIN_PC30 (PIN_BASE + 0x40 + 30)
+#define AT91_PIN_PC31 (PIN_BASE + 0x40 + 31)
+
+
+static inline rt_uint32_t gpio_to_irq(rt_uint32_t gpio)
+{
+ return gpio;
+}
+
+#endif
diff --git a/libcpu/arm/at91sam926x/interrupt.c b/libcpu/arm/at91sam926x/interrupt.c
index 3412f6bd8c..dd556fb0a5 100755
--- a/libcpu/arm/at91sam926x/interrupt.c
+++ b/libcpu/arm/at91sam926x/interrupt.c
@@ -15,7 +15,7 @@
#include <rtthread.h>
#include "at91sam926x.h"
-#define MAX_HANDLERS 32
+#define MAX_HANDLERS (AIC_IRQS + PIN_IRQS)
extern rt_uint32_t rt_interrupt_nest;
@@ -82,6 +82,39 @@ rt_isr_handler_t rt_hw_interrupt_handle(rt_uint32_t vector)
return RT_NULL;
}
+rt_isr_handler_t at91_gpio_irq_handle(rt_uint32_t vector)
+{
+ rt_uint32_t isr, pio, irq_n;
+
+ if (vector == AT91SAM9260_ID_PIOA)
+ {
+ pio = AT91_PIOA;
+ irq_n = AIC_IRQS;
+ }
+ else if (vector == AT91SAM9260_ID_PIOB)
+ {
+ pio = AT91_PIOB;
+ irq_n = AIC_IRQS + 32;
+ }
+ else if (vector == AT91SAM9260_ID_PIOC)
+ {
+ pio = AT91_PIOC;
+ irq_n = AIC_IRQS + 32*2;
+ }
+ else
+ return;
+ isr = at91_sys_read(pio+PIO_ISR) & at91_sys_read(pio+PIO_IMR);
+ while (isr)
+ {
+ if (isr & 1)
+ {
+ isr_table[irq_n](irq_n);
+ }
+ isr >>= 1;
+ irq_n++;
+ }
+}
+
/*
* Initialize the AIC interrupt controller.
*/
@@ -93,7 +126,7 @@ void at91_aic_init(rt_uint32_t *priority)
* The IVR is used by macro get_irqnr_and_base to read and verify.
* The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
*/
- for (i = 0; i < MAX_HANDLERS; i++) {
+ for (i = 0; i < AIC_IRQS; i++) {
/* Put irq number in Source Vector Register: */
at91_sys_write(AT91_AIC_SVR(i), i);
/* Active Low interrupt, with the specified priority */
@@ -109,7 +142,7 @@ void at91_aic_init(rt_uint32_t *priority)
* Spurious Interrupt ID in Spurious Vector Register is NR_AIC_IRQS
* When there is no current interrupt, the IRQ Vector Register reads the value stored in AIC_SPU
*/
- at91_sys_write(AT91_AIC_SPU, MAX_HANDLERS);
+ at91_sys_write(AT91_AIC_SPU, AIC_IRQS);
/* No debugging in AIC: Debug (Protect) Control Register */
at91_sys_write(AT91_AIC_DCR, 0);
@@ -120,6 +153,22 @@ void at91_aic_init(rt_uint32_t *priority)
}
+static void at91_gpio_irq_init()
+{
+ at91_sys_write(AT91_PIOA+PIO_IDR, 0xffffffff);
+ at91_sys_write(AT91_PIOB+PIO_IDR, 0xffffffff);
+ at91_sys_write(AT91_PIOC+PIO_IDR, 0xffffffff);
+
+ isr_table[AT91SAM9260_ID_PIOA] = (rt_isr_handler_t)at91_gpio_irq_handle;
+ isr_table[AT91SAM9260_ID_PIOB] = (rt_isr_handler_t)at91_gpio_irq_handle;
+ isr_table[AT91SAM9260_ID_PIOC] = (rt_isr_handler_t)at91_gpio_irq_handle;
+
+ rt_hw_interrupt_umask(AT91SAM9260_ID_PIOA);
+ rt_hw_interrupt_umask(AT91SAM9260_ID_PIOB);
+ rt_hw_interrupt_umask(AT91SAM9260_ID_PIOC);
+}
+
+
/**
* This function will initialize hardware interrupt
*/
@@ -141,6 +190,8 @@ void rt_hw_interrupt_init(void)
isr_table[idx] = (rt_isr_handler_t)rt_hw_interrupt_handle;
}
+ at91_gpio_irq_init();
+
/* init interrupt nest, and context in thread sp */
rt_interrupt_nest = 0;
rt_interrupt_from_thread = 0;
@@ -148,14 +199,69 @@ void rt_hw_interrupt_init(void)
rt_thread_switch_interrput_flag = 0;
}
+static void at91_gpio_irq_mask(int irq)
+{
+ rt_uint32_t pin, pio, bank;
+
+ bank = (irq - AIC_IRQS)>>5;
+
+ if (bank == 0)
+ {
+ pio = AT91_PIOA;
+ }
+ else if (bank == 1)
+ {
+ pio = AT91_PIOB;
+ }
+ else if (bank == 2)
+ {
+ pio = AT91_PIOC;
+ }
+ else
+ return;
+ pin = 1 << ((irq - AIC_IRQS) & 31);
+ at91_sys_write(pio+PIO_IDR, pin);
+}
+
/**
* This function will mask a interrupt.
* @param vector the interrupt number
*/
void rt_hw_interrupt_mask(int irq)
{
- /* Disable interrupt on AIC */
- at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+ if (irq >= AIC_IRQS)
+ {
+ at91_gpio_irq_mask(irq);
+ }
+ else
+ {
+ /* Disable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IDCR, 1 << irq);
+ }
+}
+
+static void at91_gpio_irq_umask(int irq)
+{
+ rt_uint32_t pin, pio, bank;
+
+ bank = (irq - AIC_IRQS)>>5;
+
+ if (bank == 0)
+ {
+ pio = AT91_PIOA;
+ }
+ else if (bank == 1)
+ {
+ pio = AT91_PIOB;
+ }
+ else if (bank == 2)
+ {
+ pio = AT91_PIOC;
+ }
+ else
+ return;
+ pin = 1 << ((irq - AIC_IRQS) & 31);
+ at91_sys_write(pio+PIO_IER, pin);
}
/**
@@ -164,8 +270,15 @@ void rt_hw_interrupt_mask(int irq)
*/
void rt_hw_interrupt_umask(int irq)
{
- /* Enable interrupt on AIC */
- at91_sys_write(AT91_AIC_IECR, 1 << irq);
+ if (irq >= AIC_IRQS)
+ {
+ at91_gpio_irq_umask(irq);
+ }
+ else
+ {
+ /* Enable interrupt on AIC */
+ at91_sys_write(AT91_AIC_IECR, 1 << irq);
+ }
}
/**