"Hybrid device Driver Model"
Description of the miscellaneous equipment
< blending in the concept of equipment >
in the Linux system, there is a class of character devices , they have the same main device number (ten), but the second device number is different, said that such devices are mixed in the device (missdevice ), all the hybrid devices form a linked list, access the device, and find the appropriate hybrid device in the list based on the secondary device number.
Note: Promiscuous devices are one of the character devices.
< device descriptors for hybrid devices >
struct Miscdevice
{
int minor; /* Secondary device number * /
const char *name; /* Device name * /
const struct File_operrations *fops; /* file Operation * /
struct List_head list;
struct device *parent;
struct device *this _device;
};
< device registration >
in the Linux System Central Europe uses the function misc_register () function to register a hybrid device driver.
Function Prototypes:
int Misc_register (struct miscdevice *misc)
< device logoff >
Function Prototypes:
int Mic_deregister (struct Miscdevice * misc)
"Linux Interrupt processing"
< interrupt processing process in bare metal >
the interruption will have a unified entrance: LDR pc,_irq --"Save environment Processing-" execution:bl handle_init directive-"according to the interrupt number, the corresponding interrupt handler is called."
analysis of interrupt processing process in <linux >
in the Linux system there is also an interrupt processing the same entry:irq_svc --"then do the corresponding environment save-" to get the interrupt source ( Register intpnd)--"Use the interrupt number to find irq_disc[*] This structure--" in action The user has written a written processing function in advance
Summary: What do drivers need to do?
1) implement interrupt handling process
2) registering the interrupt handler with the Linux system
interrupt Handlers in <linux >
1) registration interruption
Function Prototypes:
int REQUEST_IRQ (unsigned int irq, void (*handler) (int, void *,struct pt_regs*), unsigned long flags,const char*devname, VO ID *dev_id)
Parametric analysis :
unsigned int IRQ: Interrupt number
Note: The difference between the interrupt number and the interrupt type
#define S3C2410_CPUIRQ_OFFSET (16)
#define S3C2410_IRQ (x) ((x) + S3c2410_cpuirq_offset)
void (*handler )(int, void *, struct pt_regs *): Interrupt Handler
unsigned long flags: various options related to interrupt handling
Cases:
Irqf_disableed (sa_interrupt): Fast Interrupt handler, if no this bit, indicates slow interrupt handler
Note: The difference between a fast interrupt and a slow interrupt
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 interrupt flag bit (mask) is turned on (the processor IF), when running a fast interrupt program is turned off, the UK therefore does not interrupt other types of interrupts when the service is interrupted, whereas other types of interrupts can be serviced when slow interrupt processing is invoked.
Irqf_shared (SA_SHIRQ): indicates that the interrupt number is device-shared () that multiple devices can share multiple interrupts.
Irqf_trigger_falling: The falling edge creates an interrupt
const char * devname: device name
void * dev_id: used when sharing interrupts
return value:
returns 0 indicates success
Failed:
returns an error value that is not 0
Note: The interrupt handler runs in the context of the interrupt, and his behavior may be subject to certain limitations:
1) cannot use functions that may cause blocking
2) cannot use functions that may cause scheduling
2) Interrupt handling
General Processing Flow:
Check if the device has an interrupt --"Clear the interrupt flag (otherwise the next interrupt is not responding)-" corresponding hardware operation
3) Logout interrupt
Function Prototypes:
void Free_irq (unsigned int irq,void *dev_id)
Parametric analysis:
IRQ; interrupt number
DEV_ID: for shared interrupts, one interrupt number, corresponding to multiple interrupt programs, bit the interrupt handler to unload the load, each interrupt handler is numbered:dev_id
Interrupt tiering Technology
< interrupt nesting >
(1) interrupt in slow speed
When processing a slow interrupt, the interrupt switch (IF) is closed when, that is, can be interrupted by other interrupts, the execution of this interrupt until the processing is completed, and then returned to execute the execution before being interrupted when interrupted.
Note: If the execution is interrupted when the interrupt is interrupted by the same type when interrupted, the Linux system is not going to perform that interrupt at this time.
(2) fast interrupt
Can not be interrupted by another interrupt
< interrupt tiering technology >
Background:
The interrupt processing process can be broadly divided into hardware-related work, and hardware-independent when workingon a Linux system, the hardware-related work is put into the interrupt handler to do, and the other parts are put elsewhere. The goal is to reduce the time it takes to process interrupt processing. Use the following three-way processing and hardware-independent parts processing.
(1) soft interrupt
(2) Tasklet
(3) The Task Force column
by the can see, added that this is a 3- core when the CPU, each CPU followed by a queue, and the hardware does not have a relationship between the handlers inserted into these lists, the linux kernel creates a thread for each linked list, and the system will process the suspended thread once the CPU is relatively idle, and the linked list will disappear from the queue when it finishes processing a thread.
< using work queues for tiering >
(1) How to implement a work queue
struct WORKQUEUE_STRUCT
{
struct Cpu_workqueue_struct *cpu_wq;
struct List_head list;
const char *name; /*workqueue Name */
int signalthread;
int freezeable/*freeze Threads during suspend*/
int RT;
}
(2) How to describe a job
struct WORK_STRUCT
{
atomic_long_t data;
struct list _head entry;
work_fun_t func;
}
(3) implementation steps
1) Create a work queue
Function:
Create_workqueue ("name")
2) Create a job
Function:
Init_work (Work,fun)
3) Submit work (attach work to work queue)
Function:
Queue_work (Work_queue,work)
Note: To create a work queue, you must follow GPL Agreement.
Moudle_license ("GPL")
Note: However, in most cases, we do not need to define the work queue, theLinux system will have a default when the work queue keventd_wq, so only need to mount the work to the work queue.
Mount function:
Schedule_work (Work)
"Button to shake"
< background analysis >
In the press of the button, due to hardware design defects, will cause the signal spikes, resulting in inaccurate input signal.
< handling key jitter >
(1) hardware to shake
(2) software to shake
General software to shake using the way of delay:
1)for() loop
2) Timing delay
in the using a struct array in a Linux system:
struct timer_list
{
struct List_head entry;
unsigned long expires;
Viod (*function) (unsigned long);
unsigned long data;
struct Tvec_base *base;
}
Expires: Used to set the time
Functions: This function pointer points to the work that needs to be processed after the timer ends.
To describe a timer.
Note: The general operating system is highly efficient for processing and generally does not use the for () loop. Only use timers.
< timer processing flow >
(1) Defining timer Variables
(2) Initialize Timer
1)init_timer ()
2) Set the timeout function
(3) Add_timer () to register the timer with the kernel
(4) Mod_timer () Start timer
< multi-key driver optimization >
Relative to the driver of a key, need to register an interrupt, the registration interrupt needs to be in the hardware operating section more than a PIN function configuration.
Note: The appropriate hardware driver must be implemented first to make the appropriate system calls in the application.
< design of blocked drivers >
(1) blocking Necessary
What to do when a device fails to meet the user's read and write requests ? For example, if a function is used but there will be data later, or if a process attempts to write data to a device, however, the device is not ready to accept the data, and when this happens, the driver should ( the default ) blocks the process so that the process enters the waiting (sleep) state, knowing that the request is satisfied.
(2) Kernel wait Queue
In the implementation of the blocking drive, a similar "waiting room" to arrange for the rest of the blocking queue, when the wake-up condition is ripe, you can wake up the process from the waiting-room, which is waiting for the queue.
1) define the wait queue
wait_queue_head_t My_queue
2) Initialize the wait queue
Init_waitqueue_head (&my_queue)
3) or define and initialize the wait queue
Declare_wait_queue_head (My_queue)
4) Enter the waiting queue
Wait_event (queue,condition)
when condition(Boolean expression) is True, returns immediately, no person lets the process enter task_uninterruptible mode of sleep, and mounts to the queue parameter is specified on the wait queue.
Wait_event_interrupttible (queue,condition)
when condition(Boolean expression) is True, returns immediately, no person lets the process enter task_interruptible sleep, and mounts in the parameter queue parameter on the specified queue.
5) wake-up from the waiting queue
WAKE_UP (wait_queue_t *q)
All processes that wake the status to task_uninterruptible,task_interruptible,task_killable from the wait queue Q
Wake_up_interruptible (wait_queue_t *q)
from the wait queue Q, the process that wakes the state to task_interruptible .
(3) Blocking driver Optimization
L
Linux Key Driver