First, you need to understand the concept of Interruption: An "interruption" is just a signal. When the hardware needs to get attention from the processor, it can send this signal. The kernel maintains a registry for the interrupt signal line, which is similar to the I/O port registry.
The module must request an interrupt channel (or interrupt request IRQ) before using the interrupt, and then release the channel after using it. The APIs used are request_irq () and free_irq (). Note that it is best to call request_irq () and free_irq () after the first and last shutdown of the device.
For the interrupt processing routine, a typical task is: if the event waiting for the interrupt notification process has occurred, for example, when new data arrives, the sleep process on the device will be awakened. Whether it is a fast or slow processing routine,ProgramDevelopers should write processing routines that execute events as short as possible. If you need to execute a long computing task, you can use the upper and lower half processing mechanism to schedule computing tasks in a safer time.
The upper half functions to respond to interruptions. When an interruption occurs, it mounts the lower half of the interrupt processing routine in the device driver to the execution queue in the lower half of the device, and then waits for the new interruption to arrive. In this way, the execution speed of the upper half will be very fast, and it will be able to accept the interruptions caused by more devices it is responsible. The reason why the upper half is fast is that it completely blocks the interruption. If it is not completed, other interruptions cannot be handled in a timely manner. It can only wait until the interrupt processing program is executed. Therefore, to process as many device interruptions as possible, interrupt handling procedures must be fast.
The lower half is a complicated process. The biggest difference between the lower half and the upper half is that they can be interrupted, but the upper half cannot be interrupted. The lower half almost completes all the interrupt processing procedures, because the upper half only ranks the lower half in the processing queue of the device interruptions they are responsible for, and then does not do other processing. The lower part is generally responsible for viewing the device to obtain information about the event that causes the interruption, and processing the information based on the information (generally obtained by reading the registers on the device. The lower part can be interrupted, so if other devices are interrupted during operation, the lower part can be temporarily interrupted. When the upper half of the device is finished, run the lower half.
Most of the above are the knowledge we have obtained from reading materials and listening to the instructor. But how is it implemented?
Maybe we also know tasklet and work_queue. We know that the two are completed in the lower half. In the specific process, how can we implement it?
The initialization is completed before IRQ by creating a work queue, and the specific work is submitted to the work queue in irq_handler. The API used is queue_work (). We hope that readers can read the relevant information on their own.