AT91SAM9261的LINUX2.6 GPIO与GPIO中断

来源:互联网 发布:鸡肉生产企业知乎 编辑:程序博客网 时间:2024/04/29 00:41
关于LINUX对926X中断的实现(LINUX2.6.24中试用) 
一,926X中断的描述 
对于926X有先进中断控制器控制中断具体对应的中断有0~310为FIQ,1为系统,2~31对应设备.见DATASHEET 
二,926X中断的LINUX实现 
1,PIO的输入中断问题,手册描述了 
PIOA         2 
PIOB         3 
PIOC         4 
LINUX中AT91SAM926X.H定义了所有的中断分配号: 

* Peripheral identifiers/interrupts. 
*/ 
#define AT91_ID_FIQ             0       /* Advanced Interrupt Controller (FIQ) */ 
#define AT91_ID_SYS             1       /* System Peripherals */ 
#define AT91SAM9260_ID_PIOA     2       /* Parallel IO Controller A */ 
#define AT91SAM9260_ID_PIOB     3       /* Parallel IO Controller B */ 
#define AT91SAM9260_ID_PIOC     4       /* Parallel IO Controller C */ 
#define AT91SAM9260_ID_ADC      5       /* Analog-to-Digital Converter */ 
#define AT91SAM9260_ID_US0      6       /* USART 0 */ 
#define AT91SAM9260_ID_US1      7       /* USART 1 */ 
#define AT91SAM9260_ID_US2      8       /* USART 2 */ 
#define AT91SAM9260_ID_MCI      9       /* Multimedia Card Interface */ 
#define AT91SAM9260_ID_UDP      10      /* USB Device Port */ 
#define AT91SAM9260_ID_TWI      11      /* Two-Wire Interface */ 
#define AT91SAM9260_ID_SPI0     12      /* Serial Peripheral Interface 0 */ 
#define AT91SAM9260_ID_SPI1     13      /* Serial Peripheral Interface 1 */ 
#define AT91SAM9260_ID_SSC      14      /* Serial Synchronous Controller */ 
#define AT91SAM9260_ID_TC0      17      /* Timer Counter 0 */ 
#define AT91SAM9260_ID_TC1      18      /* Timer Counter 1 */ 
#define AT91SAM9260_ID_TC2      19      /* Timer Counter 2 */ 
#define AT91SAM9260_ID_UHP      20      /* USB Host port */ 
#define AT91SAM9260_ID_EMAC     21      /* Ethernet */ 
#define AT91SAM9260_ID_ISI      22      /* Image Sensor Interface */ 
#define AT91SAM9260_ID_US3      23      /* USART 3 */ 
#define AT91SAM9260_ID_US4      24      /* USART 4 */ 
#define AT91SAM9260_ID_US5      25      /* USART 5 */ 
#define AT91SAM9260_ID_TC3      26      /* Timer Counter 3 */ 
#define AT91SAM9260_ID_TC4      27      /* Timer Counter 4 */ 
#define AT91SAM9260_ID_TC5      28      /* Timer Counter 5 */ 
#define AT91SAM9260_ID_IRQ0     29      /* Advanced Interrupt Controller (IRQ0) */ 
#define AT91SAM9260_ID_IRQ1     30      /* Advanced Interrupt Controller (IRQ1) */ 

LINUX中AT91SAM926X.C分配中断分配号到PIOA,PIOB,PIOC中: 

static struct at91_gpio_bank at91sam9260_gpio[] = { 
      { 
            .id             = AT91SAM9260_ID_PIOA, 
            .offset         = AT91_PIOA, 
             .clock          = &pioA_clk, 
}, 
      { 
  .id             = AT91SAM9260_ID_PIOB, 
               .offset         = AT91_PIOB, 
               .clock          = &pioB_clk, 
       }, 

               .id             = AT91SAM9260_ID_PIOC, 
               .offset         = AT91_PIOC, 
               .clock          = &pioC_clk, 
       } 
}; 

这里调用允许中断函数 

At91_gpio_irq_setup();他的定义在gpio.c: 

static struct at91_gpio_bank *gpio; 
void __init at91_gpio_irq_setup(void) 

  unsigned        pioc, pin; 
  for (pioc = 0, pin = PIN_BASE; // #define PIN_BASE  NR_AIC_IRQS, include/asm-arm/arch-at91rm9200/gpio.h中定义
           pioc < gpio_banks; 
               pioc++) { 
               void __iomem    *controller; 
               unsigned        id = gpio[pioc].id; 
               unsigned        i; 
               clk_enable(gpio[pioc].clock);   
//处理/* enable PIO controller's clock */ 
                controller = (void __iomem *) AT91_VA_BASE_SYS + gpio[pioc].offset; 
               __raw_writel(~0, controller + PIO_IDR); 
                set_irq_data(id, (void *) pin); 
               set_irq_chip_data(id, controller); 
                for (i = 0; i < 32; i++, pin++) { 
 /* 
  * Can use the "simple" and not "edge" handler since it's 
* shorter, and the AIC handles interupts sanely. 
  */ 
                       set_irq_chip(pin, &gpio_irqchip); 
                       set_irq_handler(pin, handle_simple_irq); 
                       set_irq_flags(pin, IRQF_VALID); 
                } 
                set_irq_chained_handler(id, gpio_irq_handler); 

       } 

 }

如果使用PIO IO: 
直接用int at91_get_gpio_value(unsigned pin) 
int at91_set_gpio_value(unsigned pin, int value) 
就可以实现读写啦 

如果使用PIO的中断呢? 
一 设置为输入. 
二 设置毛刺(也可以不设置) 
三 调用 REQUEST_IRQ() 
at91_set_gpio_input(AT91_PIN_PB5,1); 
    result = request_irq(AT91_PIN_PB5, kirq_interrupt, SA_INTERRUPT,  "kirq", &kirq_dev); 
     if (result < 0){ 
         printk("register irq fail.%d\r\n",result); 
  return result; 
     } 

/************************************************************************************/
实验的结果(查看中断是否产生) 
/teset/irq # cat /proc/interrupts 
CPU0 
  1:      72905         AIC  at91_tick, atmel_serial 
10:          0         AIC  at91_udc 
20:          0         AIC  ohci_hcd:usb1 
21:       4754         AIC  eth0 
69:          0        GPIO  kirq 
101:          1        GPIO  at91_udc 

at91_set_gpio_input(AT91_PIN_PA5,1); 
    result = request_irq(AT91_PIN_PA5, kirq_interrupt, SA_INTERRUPT,  "kirq", &kirq_dev); 
     if (result < 0){ 
         printk("register irq fail.%d\r\n",result); 
  return result; 
     } 

实验的结果(查看中断是否产生) 
/teset/irq # cat /proc/interrupts 
           CPU0 
  1:       3295         AIC  at91_tick, atmel_serial 
10:          0         AIC  at91_udc 
20:          0         AIC  ohci_hcd:usb1 
21:       1801         AIC  eth0 
37:          1        GPIO  kirq 
101:          1        GPIO  at91_udc 
Err:          0四 其他设备的调用就直接用request_irq(IRQ_NUMBER,…)
原创粉丝点击