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