Przeglądaj źródła

support gpio interrupt

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1539 bbd45198-f89e-11dd-88c7-29a3b14d5316
luohui2320@gmail.com 14 lat temu
rodzic
commit
1586a43f6c

+ 21 - 0
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

+ 2 - 0
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.

+ 119 - 0
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

+ 120 - 7
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);
+	}
 }
 
 /**