The previous article recorded the Raspberry Pi's own Gpio driver (http://www.cnblogs.com/umbrellary/p/5164148.html), in the bcm2708_ GPIO.C realizes the Gpio drive, but also realizes the drive of the interrupt controller, this paper records the implementation of the driver in the BCM2708_GPIO.C.
A bcm2708_gpio_irq_init interrupt initialization function establishes a GPIO interrupt description table
Static voidBcm2708_gpio_irq_init (structBcm2708_gpio *UCB) {unsigned IRQ; PRINTK (Kern_err driver_name": Bcm2708_gpio_irq_init is not null!\n"); UCB->GC.TO_IRQ = BCM2708_GPIO_TO_IRQ;//gets the interrupt number corresponding to the port /*set up Irq_desc for each of the IRQ line*/ for(IRQ = Gpio_irq_start; IRQ < (Gpio_irq_start + Gpio_irqs); irq++) {Irq_set_chip_data (IRQ, UCB);//setting up private dataIrq_set_chip_and_handler (IRQ, &bcm2708_irqchip, HANDLE_SIMPLE_IRQ);//also set the HANDLE_IRQ callback and Irq_chip pointer in Irq_descset_irq_flags (IRQ, irqf_valid); } bcm2708_gpio_irq.dev_id= UCB;//for labeling uniqueness and passing private structuresSETUP_IRQ (Irq_gpio3, &BCM2708_GPIO_IRQ);//Irq_gpio3 responds to all interrupts of Bank1 and Bank2}
This function is called in the last face of this driver's Bcm2708_gpio_probe driver initialization function, which is the initialization interrupt.
1 · First assignment of the break number conversion function
UCB->GC. TO_IRQ = BCM2708_GPIO_TO_IRQ; //Get the interrupt number corresponding to this port
2. Use loops to create all interrupt description tables for the system
Irq_set_chip_data (IRQ, UCB); //Set private data
Irq_set_chip_and_handler (IRQ, &bcm2708_irqchip, HANDLE_SIMPLE_IRQ); //Set HANDLE_IRQ callback and Irq_chip pointer in Irq_desc
3. Register Irq_gpio3 this interrupt.
What is this interruption for? I've got a lot of posts to get a little bit of a glimpse of this. Irq_gpio3 the effect of this interrupt is that if any one of the pins in the BANK1 or BANK2 causes the interrupt to occur, the interrupt will be caused by this IRQ_GPIO3 interrupt variable. The driver then scans the register in the Irq_gpio3 interrupt callback function (Bcm2708_gpio_interrupt function) to find the interrupt number where the interrupt occurred, and invokes the corresponding callback function. (Analysis below)
Two Bcm2708_gpio_interrupt Interrupt handling function for Irq_gpio3 interrupts
StaticIrqreturn_t Bcm2708_gpio_interrupt (intIrqvoid*dev_id) {unsignedLongEDSR; unsigned bank; inti; unsigned gpio; unsigned level_bits; structBcm2708_gpio *gpio_data =dev_id; PRINTK (Kern_err driver_name": Bcm2708_gpio_interrupt%d\n", IRQ); /*Loop interrupts in the two bank*/ for(Bank =0; Bank < Gpio_banks; bank++) {EDSR= Readl (__io_address (gpio_base) + gpioeds (bank));//get the bank's base addresslevel_bits = Gpio_data->high[bank] | Gpio_data->Low[bank]; For_each_set_bit (i,&EDSR, +) {//loop to find a bit of 1 in EDSRGpio= i + Bank * +;//find out which gpio it is . /*ack Edge triggered IRQs immediately*/ if(! (Level_bits & (1<<i))) Writel (1<<i, __io_address (gpio_base) + gpioeds (bank));//Eliminate interrupt markingGeneric_handle_irq (GPIO_TO_IRQ (Gpio)); /*ack level triggered IRQ after handling them*/ if(Level_bits & (1<<i)) Writel (1<<i, __io_address (gpio_base) + gpioeds (bank));//prevent re-entry } } returnirq_handled;}
This function is the callback function of the Irq_gpio3 interrupt vector, which is to scan the register for the interrupt number of the interrupt, and call the corresponding callback function if the interrupt occurs.
1.for_each_set_bit (i, &EDSR, + ) //cycle to find a bit in the EDSR that is 1 is interrupted
2.Generic_handle_irq (Gpio_to_irq (GPIO));//interrupt callback function that calls the interrupt vector (will be filled in when the driver requests an IRQ resource) GPIO_TO_IRQ (GPIO) is the interrupt vector number where the interrupt occurred
Three • Interrupt Controller callback function
/*Interrupt Controller*/Static structIrq_chip bcm2708_irqchip ={. Name="GPIO",. Irq_enable= Bcm2708_gpio_irq_unmask,//enable the IRQ, which is usually called directly irq_unmask (). irq_disable = Bcm2708_gpio_irq_mask,//disables the IRQ, usually by calling Irq_mask directly. Irq_unmask = Bcm2708_gpio_irq_unmask,//unblock the IRQ. Irq_mask = Bcm2708_gpio_irq_mask,//block the IRQ. Irq_set_type = Bcm2708_gpio_irq_set_type,//setting an IRQ's electrical trigger condition};
The kernel abstracts the interrupts, and the necessary platform-related functions are expressed by irq_chip . In all of these callback functions, the interrupt is opened or masked by means of a write register.
Four · print experiment
Irq_gpio3 interrupts occur continuously when I Gpio4 the line with the baseline . At the application level, you can use the poll function to listen to this event for appropriate processing.
GENERIC_HANDLE_IRQ (gpio_to_irq(Gpio));
Raspberry Pi Official self-powered Gpio Interrupt Driver bcm2708_gpio.c principle Analysis Linux Interrupt architecture interrupt Subsystem