Difference between revisions of "Embedded-Linux-Device-Driver/C3/Interrupt-Handling/English"
(Created page with " {| border="1" |- || '''VISUAL CUE''' || '''NARRATION''' |- || Slide 1: Welcome slide: || Welcome to the spoken tutorial on '''Interrupt Handling.''' |- || Slide 2: Learnin...") |
Nancyvarkey (Talk | contribs) |
||
(One intermediate revision by the same user not shown) | |||
Line 13: | Line 13: | ||
Learning objectives: | Learning objectives: | ||
− | || In this tutorial, we will learn how to | + | || In this tutorial, we will learn how to handle the '''software interrupt''' in the '''driver'''. |
− | + | ||
|- | |- | ||
|| Slide 3: | || Slide 3: | ||
Line 29: | Line 28: | ||
Prerequisites: | Prerequisites: | ||
|| To follow this tutorial, you should be familiar with: | || To follow this tutorial, you should be familiar with: | ||
− | * '''C programming language | + | * '''C programming language''' and |
* '''Basics of Linux kernel''' | * '''Basics of Linux kernel''' | ||
Line 37: | Line 36: | ||
'''Interrupt handler''' | '''Interrupt handler''' | ||
− | || * The '''function''' that runs in response to a specific '''interrupt''' is called an '''interrupt handler''' | + | || |
+ | * The '''function''' that '''runs''' in response to a specific '''interrupt''' is called an '''interrupt handler''' | ||
* Different '''devices''' can be associated with different '''interrupts'''. | * Different '''devices''' can be associated with different '''interrupts'''. | ||
* A '''driver''' needs to handle the '''interrupts''' properly for its '''device'''. | * A '''driver''' needs to handle the '''interrupts''' properly for its '''device'''. | ||
Line 44: | Line 44: | ||
Working - '''Interrupt Handling.''' | Working - '''Interrupt Handling.''' | ||
− | || In this tutorial, a user program will '''open''' and '''close''' the device file. | + | || |
+ | *In this tutorial, a '''user program''' will '''open''' and '''close''' the '''device file'''. | ||
− | When the user program opens a device, the software interrupt will be triggered by the driver. | + | *When the '''user program''' opens a '''device''', the '''software interrupt''' will be triggered by the '''driver'''. |
− | When the kernel receives an interrupt, the registered handler from the driver will be executed. | + | *When the '''kernel''' receives an '''interrupt''', the '''registered handler''' from the '''driver''' will be '''executed'''. |
|- | |- | ||
|| Point to the folder and file in '''desktop''' | || Point to the folder and file in '''desktop''' | ||
Point to the '''files'''. | Point to the '''files'''. | ||
− | || Go to the '''DeviceDriver '''folder in the | + | || Go to the '''DeviceDriver '''folder in the '''Desktop''' which we have created earlier. |
In this directory, I have created a directory named '''Interrupt'''. | In this directory, I have created a directory named '''Interrupt'''. | ||
− | Here, I have saved an''' interrupt dot c , Makefile '''and''' user dot c files.''' | + | Here, I have saved an''' interrupt dot c, Makefile '''and''' user dot c files.''' |
I’ll use these files for demonstration. | I’ll use these files for demonstration. | ||
Line 76: | Line 77: | ||
Go to the directory where '''Interrupt '''is saved on your system. | Go to the directory where '''Interrupt '''is saved on your system. | ||
− | Press Enter key after every command. | + | Press '''Enter''' key after every '''command'''. |
|- | |- | ||
|| Type >>''' gedit interrupt.c''' | || Type >>''' gedit interrupt.c''' | ||
Line 87: | Line 88: | ||
Highlight '''<linux/interrupt.h>''' | Highlight '''<linux/interrupt.h>''' | ||
− | || We have to include an '''interrupt dot h kernel header file''' to register an '''interrupt'''. | + | || We have to include an '''interrupt dot h kernel header file''' to '''register''' an '''interrupt'''. |
The purpose of each file is mentioned as shown here. | The purpose of each file is mentioned as shown here. | ||
Line 96: | Line 97: | ||
Highlight '''irqreturn_t irq_handler()''' | Highlight '''irqreturn_t irq_handler()''' | ||
− | || We have defined the''' IRQ line number | + | || We have defined the''' IRQ line number''' as 2 which will be used in this '''driver'''. |
− | The '''devices''' can send interrupts to the '''processor''' using these '''IRQ''' lines. | + | The '''devices''' can send '''interrupts''' to the '''processor''' using these '''IRQ''' lines. |
We have implemented an '''interrupt handler''' as shown here. | We have implemented an '''interrupt handler''' as shown here. | ||
Line 108: | Line 109: | ||
Highlight''' request_irq()''' | Highlight''' request_irq()''' | ||
− | || In the '''initialization ''' | + | || In the '''initialization function''', we have to '''register''' the '''interrupt handler.''' |
− | '''Drivers''' can register an''' interrupt handler '''and enable a given '''interrupt line''' for handling. | + | '''Drivers''' can '''register''' an''' interrupt handler '''and enable a given '''interrupt line''' for handling. |
− | The '''request_irq ''' | + | The '''request_irq function''' is used to '''register''' an '''interrupt handler.''' |
|- | |- | ||
|| Highlight '''IRQ_NUM''' | || Highlight '''IRQ_NUM''' | ||
Highlight '''irq_handler''' | Highlight '''irq_handler''' | ||
− | || The first parameter specifies the '''interrupt number''' to allocate. | + | || The first '''parameter''' specifies the '''interrupt number''' to allocate. |
This value is typically hard-coded in the '''kernel'''. | This value is typically hard-coded in the '''kernel'''. | ||
− | The second parameter is a''' function pointer''' to the actual''' interrupt handler.''' | + | |
+ | The second '''parameter''' is a''' function pointer''' to the actual''' interrupt handler.''' | ||
This '''function''' is invoked whenever the '''kernel '''receives the '''interrupt'''. | This '''function''' is invoked whenever the '''kernel '''receives the '''interrupt'''. | ||
Line 126: | Line 128: | ||
|| Highlight '''flag''' | || Highlight '''flag''' | ||
− | || The third parameter can be either zero or one or any of the '''flags''' defined in the''' interrupt dot h .''' | + | || The third '''parameter''' can be either zero or one or any of the '''flags''' defined in the''' interrupt dot h.''' |
− | The fourth parameter is used to identify the '''device | + | The fourth '''parameter''' is used to identify the '''device interrupt''' name. |
− | The fifth parameter is used for shared '''interrupt lines.''' | + | The fifth '''parameter''' is used for shared '''interrupt lines.''' |
− | This parameter is used to identify the handlers on the same interrupt line. | + | This '''parameter''' is used to identify the '''handlers''' on the same '''interrupt line'''. |
|- | |- | ||
Line 144: | Line 146: | ||
'''IRQF_SHARED''' - Allows sharing the irq among several devices | '''IRQF_SHARED''' - Allows sharing the irq among several devices | ||
− | || Let us see some important '''flags''' that can be used by '''request_irq ''' | + | || Let us see some important '''flags''' that can be used by '''request_irq function'''. |
− | '''IRQF_DISABLED''' - It disables all interrupts when executing this interrupt handler. | + | *'''IRQF_DISABLED''' - It disables all '''interrupts''' when executing this '''interrupt handler'''. |
− | '''IRQF_SAMPLE_RANDOM '''- It specifies that interrupts should contribute to the kernel entropy pool. | + | *'''IRQF_SAMPLE_RANDOM '''- It specifies that '''interrupts''' should contribute to the '''kernel entropy''' pool. |
− | '''IRQF_TIMER''' - It is used to mark this interrupt as timer interrupt | + | *'''IRQF_TIMER''' - It is used to mark this '''interrupt''' as '''timer interrupt''' |
− | '''IRQF_SHARED''' - It allows sharing the irq among several devices. | + | *'''IRQF_SHARED''' - It allows sharing the '''irq''' among several '''devices'''. |
|- | |- | ||
|| | || | ||
Line 160: | Line 162: | ||
'''Highlight printk''' | '''Highlight printk''' | ||
− | || '''Request_irq function''' will register the '''irq_handler''' with the name '''my_interrupt.''' | + | || '''Request_irq function''' will '''register''' the '''irq_handler''' with the name '''my_interrupt.''' |
'''my_interrupt''' is used by '''slash proc slash interrupts''' for communication with the '''user'''. | '''my_interrupt''' is used by '''slash proc slash interrupts''' for communication with the '''user'''. | ||
Line 166: | Line 168: | ||
Here, we have used the''' IRQF_SHARED flag.''' | Here, we have used the''' IRQF_SHARED flag.''' | ||
− | On success,''' request_irq | + | On success,''' request_irq function''' returns zero. |
A nonzero value indicates an error. | A nonzero value indicates an error. | ||
Line 174: | Line 176: | ||
Highlight '''asm("int $50")''' | Highlight '''asm("int $50")''' | ||
− | || In the '''open() | + | || In the '''open() function asm("int $50")''' instruction will trigger the '''interrupt'''. |
− | We are not going to use any '''hardware''' | + | We are not going to use any '''hardware interrupt''' as they can come from anywhere at any time. |
Here, we are going to trigger a '''software interrupt''' using the '''int instruction.''' | Here, we are going to trigger a '''software interrupt''' using the '''int instruction.''' | ||
Line 186: | Line 188: | ||
Highlight '''02''' | Highlight '''02''' | ||
− | || Let us see how to calculate the interrupt line number. | + | || Let us see how to calculate the '''interrupt''' line number. |
− | In '''Linux | + | In '''Linux IRQ''' to '''vector''', mapping is done using '''FIRST_EXTERNAL_VECTOR macro'''. |
− | To raise an''' interrupt IRQ 2''', we have to add 2 to a vector of '''IRQ 0''' as shown here. | + | To raise an''' interrupt IRQ 2''', we have to add 2 to a '''vector''' of '''IRQ 0''' as shown here. |
|- | |- | ||
|| Highlight '''asm("int $50")''' | || Highlight '''asm("int $50")''' | ||
− | || The '''asm | + | || The '''asm''' instruction will be executed while opening the '''device file''' of our '''driver'''. |
− | When this ''' | + | When this instruction '''executes''', it will raise the''' interrupt IRQ 2.''' |
|- | |- | ||
|| Highlight '''free_irq(IRQ_NUM,(void *)irq_handler)''' | || Highlight '''free_irq(IRQ_NUM,(void *)irq_handler)''' | ||
Highlight '''IRQ_NUM''' | Highlight '''IRQ_NUM''' | ||
− | || When the '''driver''' unloads, we need to | + | || When the '''driver''' unloads, we need to un'''register''' the '''interrupt handler.''' |
The '''free_irq function''' is used to remove the '''handler''' and disable the line if not shared. | The '''free_irq function''' is used to remove the '''handler''' and disable the line if not shared. | ||
− | If it is shared and no | + | If it is shared and no '''handlers''' remain on the line, the given''' interrupt''' line will be disabled. |
|- | |- | ||
|| Highlight''' free_irq().''' | || Highlight''' free_irq().''' | ||
Line 210: | Line 212: | ||
|| In the '''exit function''', we have used the '''free function''' to remove the '''handler''' from the '''kernel'''. | || In the '''exit function''', we have used the '''free function''' to remove the '''handler''' from the '''kernel'''. | ||
− | It will | + | It will un'''register''' the''' interrupt handler''' from the '''kernel'''. |
|- | |- | ||
|| Save and close the '''file''' | || Save and close the '''file''' | ||
Line 242: | Line 244: | ||
Type >>''' insmod interrupt.ko''' | Type >>''' insmod interrupt.ko''' | ||
− | || Let’s compile the '''driver'''. | + | || Let’s '''compile''' the '''driver'''. |
Type''' make space all''' | Type''' make space all''' | ||
Line 261: | Line 263: | ||
'''Interrupt file''' in '''procfs''' contains the list of registered '''interrupts''' in the '''system'''. | '''Interrupt file''' in '''procfs''' contains the list of registered '''interrupts''' in the '''system'''. | ||
− | This '''command''' will show the '''registered interrupt | + | This '''command''' will show the '''registered interrupt my_interrupt '''and its '''IRQ''' line number. |
− | In the output, we can see our '''registered interrupt | + | In the output, we can see our '''registered interrupt''' name and '''IRQ '''number. |
− | It indicates that our '''interrupt handler '''is | + | It indicates that our '''interrupt handler '''is registered successfully. |
Clear the screen. | Clear the screen. | ||
Line 276: | Line 278: | ||
Type >>''' gcc -o user.out user.o''' | Type >>''' gcc -o user.out user.o''' | ||
− | || Now compile the''' user program.''' | + | || Now '''compile''' the''' user program.''' |
Type '''gcc hyphen c user dot c''' | Type '''gcc hyphen c user dot c''' | ||
Line 287: | Line 289: | ||
Type >> '''clear''' | Type >> '''clear''' | ||
− | || Now let us execute the''' user program.''' | + | || Now let us '''execute''' the''' user program.''' |
Type''' dot slash user dot out''' | Type''' dot slash user dot out''' | ||
Line 302: | Line 304: | ||
|| Type '''dmesg space pipe space grep space my_driver'''. | || Type '''dmesg space pipe space grep space my_driver'''. | ||
− | This message shows that the | + | This message shows that the '''device open function '''triggered the '''interrupt'''. |
− | It indicates that as soon as the '''interrupt''' triggered, its '''handler got''' executed. | + | It indicates that as soon as the '''interrupt''' triggered, its '''handler''' got '''executed'''. |
− | After the execution of the '''handler''', the remaining code''' ''' | + | After the '''execution''' of the '''handler''', the remaining code from the '''open function''' is '''executed'''. |
It shows that the '''driver''' properly handled the '''interrupt'''. | It shows that the '''driver''' properly handled the '''interrupt'''. | ||
Line 317: | Line 319: | ||
Type >>''' clear''' | Type >>''' clear''' | ||
− | || Now | + | || Now let's unload the '''driver'''. |
Type '''rmmod space interrupt dot ko''' | Type '''rmmod space interrupt dot ko''' | ||
Line 325: | Line 327: | ||
Type '''dmesg space pipe space grep space my_driver.''' | Type '''dmesg space pipe space grep space my_driver.''' | ||
− | Here, we can see our interrupt handler is | + | Here, we can see our '''interrupt handler''' is un'''registered''' from the '''kernel'''. |
Clear the screen. | Clear the screen. | ||
Line 348: | Line 350: | ||
|| As an assignment: | || As an assignment: | ||
# Open the''' interrupt.c driver file.''' | # Open the''' interrupt.c driver file.''' | ||
− | # Write the''' interrupt | + | # Write the''' interrupt''' instruction in the '''release function'''. |
− | # Compile and load the '''driver'''. | + | # '''Compile''' and load the '''driver'''. |
− | # Compile and execute the '''user program.''' | + | # '''Compile''' and '''execute''' the '''user program.''' |
# See the output using''' dmesg command.''' | # See the output using''' dmesg command.''' | ||
|- | |- | ||
Line 363: | Line 365: | ||
Spoken Tutorial workshops : | Spoken Tutorial workshops : | ||
− | || The Spoken Tutorial Project Team | + | || The Spoken Tutorial Project Team conducts workshops and gives certificates. |
− | + | ||
For more details, please write to us. | For more details, please write to us. | ||
Line 370: | Line 371: | ||
|| Slide 15: | || Slide 15: | ||
Forum questions : | Forum questions : | ||
− | || | + | || Please post your timed queries in this forum |
|- | |- | ||
|| Slide 16: | || Slide 16: | ||
Forum for specific questions : | Forum for specific questions : | ||
− | || * Do you have any general or technical questions on Embedded Linux Device Driver? | + | || |
+ | * Do you have any general or technical questions on Embedded Linux Device Driver? | ||
* Please visit the FOSSEE forum and post your question | * Please visit the FOSSEE forum and post your question | ||
|- | |- |
Latest revision as of 14:57, 12 February 2021
VISUAL CUE | NARRATION |
Slide 1:
Welcome slide: |
Welcome to the spoken tutorial on Interrupt Handling. |
Slide 2:
Learning objectives: |
In this tutorial, we will learn how to handle the software interrupt in the driver. |
Slide 3:
System Requirements: |
To record this tutorial, I am using,
|
Slide 4:
Prerequisites: |
To follow this tutorial, you should be familiar with:
If not, then go through the C/C++ and Linux spoken tutorials on this website |
Slide 6 :
Interrupt handler |
|
Slide :
Working - Interrupt Handling. |
|
Point to the folder and file in desktop
Point to the files. |
Go to the DeviceDriver folder in the Desktop which we have created earlier.
In this directory, I have created a directory named Interrupt. Here, I have saved an interrupt dot c, Makefile and user dot c files. I’ll use these files for demonstration. |
Slide:5
Code files: |
|
Open the terminal
Type >> cd Desktop/DeviceDriver/Interrupt |
Open the terminal by pressing ALT+Ctrl+T keys simultaneously.
Go to the directory where Interrupt is saved on your system. Press Enter key after every command. |
Type >> gedit interrupt.c | Type gedit space interrupt dot c. |
Highlight header files
Highlight <linux/interrupt.h> |
We have to include an interrupt dot h kernel header file to register an interrupt.
The purpose of each file is mentioned as shown here. In this file, I have implemented only open and close file operations for a device. |
Highlight IRQ_NUM
Highlight irqreturn_t irq_handler() |
We have defined the IRQ line number as 2 which will be used in this driver.
The devices can send interrupts to the processor using these IRQ lines. We have implemented an interrupt handler as shown here. When the kernel receives the respective interrupt, it will execute this handler. |
Highlight int_function()
Highlight request_irq() |
In the initialization function, we have to register the interrupt handler.
Drivers can register an interrupt handler and enable a given interrupt line for handling. The request_irq function is used to register an interrupt handler. |
Highlight IRQ_NUM
Highlight irq_handler |
The first parameter specifies the interrupt number to allocate.
This value is typically hard-coded in the kernel. The second parameter is a function pointer to the actual interrupt handler. This function is invoked whenever the kernel receives the interrupt. |
Highlight flag | The third parameter can be either zero or one or any of the flags defined in the interrupt dot h.
The fourth parameter is used to identify the device interrupt name. The fifth parameter is used for shared interrupt lines. This parameter is used to identify the handlers on the same interrupt line. |
Slide - Important flags :
IRQF_DISABLED - Disables all interrupts when executing this interrupt handler. IRQF_SAMPLE_RANDOM - Specifies that interrupts should contribute to the kernel entropy pool. IRQF_TIMER - Used to mark this interrupt as timer interrupt IRQF_SHARED - Allows sharing the irq among several devices |
Let us see some important flags that can be used by request_irq function.
|
Switch back to the code. | |
Highlight request_irq()
Highlight printk |
Request_irq function will register the irq_handler with the name my_interrupt.
my_interrupt is used by slash proc slash interrupts for communication with the user. Here, we have used the IRQF_SHARED flag. On success, request_irq function returns zero. A nonzero value indicates an error. |
Highlight open() function
Highlight asm("int $50") |
In the open() function asm("int $50") instruction will trigger the interrupt.
We are not going to use any hardware interrupt as they can come from anywhere at any time. Here, we are going to trigger a software interrupt using the int instruction. |
Highlight #define IRQ0_VECTOR()
Highlight FIRST_EXTERNAL_VECTOR Highlight 0x20 + 0x10 + 02 = 50 Highlight 02 |
Let us see how to calculate the interrupt line number.
In Linux IRQ to vector, mapping is done using FIRST_EXTERNAL_VECTOR macro. To raise an interrupt IRQ 2, we have to add 2 to a vector of IRQ 0 as shown here. |
Highlight asm("int $50") | The asm instruction will be executed while opening the device file of our driver.
When this instruction executes, it will raise the interrupt IRQ 2. |
Highlight free_irq(IRQ_NUM,(void *)irq_handler)
Highlight IRQ_NUM |
When the driver unloads, we need to unregister the interrupt handler.
The free_irq function is used to remove the handler and disable the line if not shared. If it is shared and no handlers remain on the line, the given interrupt line will be disabled. |
Highlight free_irq(). | In the exit function, we have used the free function to remove the handler from the kernel.
It will unregister the interrupt handler from the kernel. |
Save and close the file | Now, save and close the file. |
Type >> gedit user.c |
Let us now open the user program.
Type gedit space user dot c. The program will open and close a device using respective system calls. |
Save and close the file.
Clear the screen. |
Now, save and close the file.
Clear the screen. |
Type >> sudo su.
Type >> system password |
To be a superuser, type sudo space su.
Now type the system password. |
Type >> make all Type >> insmod interrupt.ko |
Let’s compile the driver.
Type make space all Clear the screen. Now let us load the driver into the kernel. Type insmod space interrupt dot ko. |
Type cat /proc/interrupts | grep my_interrupt
/proc/interrupts Type >> clear |
Type cat space slash proc slash interrupts space pipe space grep space my_interrupt.
Interrupt file in procfs contains the list of registered interrupts in the system. This command will show the registered interrupt my_interrupt and its IRQ line number. In the output, we can see our registered interrupt name and IRQ number. It indicates that our interrupt handler is registered successfully. Clear the screen. |
Type >> gcc -c user.c.
|
Now compile the user program.
Type gcc hyphen c user dot c Type gcc hyphen o user dot out user dot o. |
Type >> ./user.out
Highlight output Type >> clear |
Now let us execute the user program.
Type dot slash user dot out Here, output shows that the device opened and closed successfully. Clear the screen. |
Type >> dmesg | grep my_driver Type >> clear |
Type dmesg space pipe space grep space my_driver.
This message shows that the device open function triggered the interrupt. It indicates that as soon as the interrupt triggered, its handler got executed. After the execution of the handler, the remaining code from the open function is executed. It shows that the driver properly handled the interrupt. Clear the screen. |
Type >> rmmod interrupt.ko
Type >> dmesg | grep my_driver Type >> clear |
Now let's unload the driver.
Type rmmod space interrupt dot ko Let us see the unloaded printk messages. Type dmesg space pipe space grep space my_driver. Here, we can see our interrupt handler is unregistered from the kernel. Clear the screen. |
Type >> make clean. | To remove the object files, type make space clean. |
With this, we come to the end of this tutorial. Let us summarise. | |
Slide 11:
Summary: |
In this tutorial, we learnt
|
Slide 12:
Assignment : |
As an assignment:
|
Slide 13:
About Spoken Tutorial Project: |
|
Slide 14:
Spoken Tutorial workshops : |
The Spoken Tutorial Project Team conducts workshops and gives certificates.
For more details, please write to us. |
Slide 15:
Forum questions : |
Please post your timed queries in this forum |
Slide 16:
Forum for specific questions : |
|
Slide 17:
Acknowledgment: |
The Spoken Tutorial Project is funded by MHRD, Government of India. |
Slide 18:
Thank you slide: |
This tutorial has been contributed by FOSSEE and Spoken Tutorial Project, IIT Bombay.
This is Usha signing off. Thanks for watching. |