1. Hybrid Device Driver Model
A. Miscellaneous equipment description
Hybrid Device Concept:
In a Linux system, there are a class of character devices, which have the same main device number (10), but the second device number is different, we call this device a hybrid device (Miscdevice). All of the hybrid devices form a linked list, and the kernel forms a linked list based on the hybrid device when accessing the device, and the kernel locates the corresponding promiscuous device according to the secondary device number when accessing the equipment.
Device Description:
struct Miscdevice {
int minor;//Secondary device number
const char *name;//device Name
const struct File_operations *fops;//file operation
struct List_head list;
struct device *parent;
struct device *this_device;
const char *nodename;
mode_t mode;
};
B. Hybrid Device Registration
int Misc_register (struct Miscdevice * misc)
It is divided into two steps: First initializing the hybrid device, then using Misc_register to register the hybrid device.
2.linux Interrupt Handling
A. Bare-metal interrupt handler process review
A.1 interrupts have a unified Portal: There is also a unified portal in the Linux kernel, which is ENTRY_ARMV. s inside the irq_svc:-> gets the number that generated the interrupt source-"Find Irq_desc (corresponding interrupt) according to the interrupt number->irq_desc remove the pre-registered interrupt handler function-" Action->action will find directly handler (The user's interrupt handler is stored inside).
What the driver does: 1. Implement interrupt handlers; 2. Registration interruption; 3. Logoff processing
A.2 Pre-Registration Interrupt Handler
Registration interrupted:
REQUEST_IRQ (unsigned int IRQ, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
A return of 0 indicates success, otherwise the return is garbled.
unsigned int irq//interrupt number.
void (*handler) (int,void *)//Interrupt handler function.
unsigned long flags//various options related to interrupt management.
const char * devname//device Name
void *dev_id//used when sharing interrupts
In the flags parameter, you can select some options related to interrupt management, such as:
? Irqf_disabled (Sa_interrupt)
If this bit is set, the expression is a "fast" interrupt handler, and if this is not set, then it is a "slow" interrupt handler.
? Irqf_shared (SA_SHIRQ)
This bit indicates that the interrupt number is shared by multiple devices
The main difference between a fast/slow interrupt is that a fast interrupt guarantees the atomicity of the interrupt processing (not interrupted), while a slow interrupt is not guaranteed. In other words, the "on interrupt" flag bit (processor if) is turned off when the fast interrupt handler is run, so when the service is interrupted it is not interrupted by other types of interrupts, while the other types of interrupts can still be serviced when slow interrupt processing is invoked.
The special point of an interrupt handler is that it runs in the context of an interrupt, and its behavior is subject to certain limitations:
1. Cannot use functions that may cause blocking
2. Cannot use functions that may cause scheduling
A.3 call Interrupt handler based on interrupt source number
Check if the device has an interrupt-"clear interrupt Generation flag-" corresponding hardware operation.
Logoff interrupts: When the device no longer needs to use interrupts (usually when the driver is unloaded), you should log them off and use the function:
void Free_irq (unsigned int irq, void *dev_id): Interrupt number and dev_id number are required for shared interrupts.
B.linux Interrupt Processing Process Analysis
C.linux Interrupt Handler Design
irqreturn_t key_int (int irq,void *dev_id)
{
1. Check if a key break has occurred because there is only one interrupt, so no detection is required.
2. Remove the key interrupt that has occurred, the internal hardware needs to clear the interrupt, but the key is at the processor level, so there is no need to clear the interrupt. such as the NIC chip will need to clear the interrupt.
3. Print Key values
}
3. Key-driven hardware operation implementation
Refer to the code for bare metal interrupts: the selection of the Button.c:gpio feature, set as an external interrupt, and the initialization of the hardware can be done in the functions of the open function and the module initialization.
c. Example-driven analysis
Touch key.c
chmod 777-r./
#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#define GPFCON 0x7f880030//drivers cannot use physical addresses, they must be converted to virtual addresses.
irqreturn_t key_int (int irq,void *dev_id)//Use the previous type to add a header file
{
1. Check if a key interrupt has occurred
2. Clear the key interrupt that has occurred
3. Print Key values
PRINTK ("key_down!\n");
}
void Key_hw_init ()
{
unsigned int = gpio_config;
unsigned short data;
Convert physical address to virtual address
Gpio_config = Ioremap (gpfcon,4);
data = READW (gpio_config);//Remove the value from the Register
Data &= ~0b11;//The corresponding bits in the register are cleared
Data |= 0b10;//to set the corresponding bit
Writew (data,gpio_config); Writes the value of data to the Register
}
int Key_open (struct inode *node,struct file *file)
{
return 0;
}
Stuct Miscdevice Key_miscdev = {
. minor = 200,
. Name = "Key",
. FoPs = &key_fops,
};
struct File_operations Key_fops =//Add header file Fs.h
{
. open = Key_open,
};
static int Key_init ()
{
Registering hybrid devices
Misc_register (&key_miscdev);
Registering an interrupt handler irqf_trigger_falling//indicates that interrupts are caused by high-to-low levels. This is the interrupt generated when the button is pressed. Interrupt number: Different from bare metal, first we need to find the Irqs.h header file corresponding to the development Board, in the header file has
REGISTER_IRQ (s3c_eint (0), key_int,irqf_trigger_falling, "key", 0);
Keystroke initialization
Key_hw_init ();
}
static void Key_exit ()
{
Unregister a promiscuous device
Misc_deregister (&key_miscdev);
Unregister interrupt Handlers
FREE_IRQ (s3c_eint (0), 0);
}
Module_init (Key_init);
Module_exit (Key_exit);
6410-Hybrid Device driver model