Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Notes on basic knowledge driven by Linux

2025-01-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)06/02 Report--

First, getting started

1. Character device driver

1) register the character device

Static inline int register_chrdev (unsigned int major, const char * name, const struct file_operations * fops)

2) cdev_add actually 1) calls cdev_add

Int cdev_add (struct cdev * p, dev_t dev, unsigned count); / * call relationship * / register_chrdev _ _ register_chrdev cdev_add

2. Data copy of user space and kernel space

1) copy_to_user/copy_from_user:// copies a space static _ _ always_inline unsigned long _ _ must_check copy_to_user (void _ _ user * to, const void * from, unsigned long n) Static _ _ always_inline unsigned long _ _ must_checkcopy_from_user (void * to, const void _ user * from, unsigned long n) 2) put_user (XQuery p) / get_user:// passes a single value # define put_user (x) from the p pointer Ptr)\ ({\ void _ _ user * _ p = (ptr) \ might_fault () \ access_ok (VERIFY_WRITE, _ p, sizeof (* ptr))?\ _ put_user ((x), ((_ _ typeof__ (* (ptr)) _ _ user *) _ p)):\-EFAULT \})

3. Check whether the space sent by the user is legal.

Access_ok (int, const void * addr,ulong) ex:if (! access_ok (verify_write,buffer,count)) return error

4. Asynchronous notification

Fasync_helper (int fd,struct file,int on,struct fasync_struct * *); / / on 0 means to remove asynchronous notification, 1 means to add asynchronous notification kill_fasync (stuct fasync_struct * * fp,int sig,int band); / / when the time arrives, it will be used to notify related processes

5 、 / proc

Through it, you can access the internal data structure of the kernel at run time, change kernel settings, and send information through it. The ps and top commands are used to read the files under / PROC to remove the information.

In general, proc loads automatically. If there is no automatic loading at startup, you can use: mount-t proc proc / proc

The kernel also provides some interface functions for the / proc file system: proc_mkdir;proc_create;proc_create_data;proc_remove;remove_proc_entry

Struct proc_dir_entry * proc_mkdir (const char * name,struct proc_dir_entry * parent)

6. Kernel makefile

Kbuild Makefile

Obj-y means connected to the kernel, and obj-m means compiled into a loadable module.

1) goal definition

Obj- (CONFIG_I2C_BOARDINFO) + = i2c-boardinfo.o

2) definition of multi-file module

Obj- (CONFIG_FB) + = fb.ofb-y:=fbmem.o fbmon.o.fb-objs:=$ (fb-y)

3) Directory iteration

Obj-$ (CONFIG_FB_OMAP) + = OMAP/

If the value of CONFIG_FB_OMAP is y or mPowerKBuid will include the omap directory in the target of iterating downwards, but its function is limited to this. As to whether the files in the omap directory should be compiled or linked into the kernel as modules, it is also determined by the contents of the makefile file in the omap directory.

Second, driving model

1. Kernel object

1) kobject (kernel object, which is the highest-level abstraction of the kernel device management mechanism): a kobject corresponds to a directory of the sysfs file system, and is also responsible for handling events such as device hot plug.

There should be some interface functions: kobject_init;kobject_add; adds kobject to the system; kobject_init_and_add;. Etc.

Void kobject_init (struct kobject * kobj, struct kobj_type * ktype); int kobject_add (struct kobject * kobj, struct kobject * parent,const char * fmt,...)

Common kobject includes:

Struct kobject * dev_kobh;// device object; kobject * sysfs_dev_char_kobj;// character device object; struct kobject * sysfs_dev_block_kobj;// block device object; kernel object under struct kobject * kernel_kobj;//sysfs.

2. The type of kernel object: kobj_type {.... sysfs_ops..}

Sysfs_ops is the interface of kernel objects in the sysyfs file system: show (kobject. ) shows that store (kobject. ) Stora

3. Kset kobject organizes hierarchical structure through kset.

Kset {struct list_head list;// list spinlock_t list_lock;// locks of the same kset kobjectstruct kset_uevent_ops * uenent_ops;//uevent related operations of struct kobject kobj;// itself, such as event filtering}

Common kset includes:

Struct kset * bus,*class,*system

4. Equipment model level: the model includes device, device_driver, bus, class (device type)

The device and the device bus are mounted on the bus, and the bus completes the matching of the device and the device driver.

Using class_create, you can create a class, and system-registered classes can be found in the / sysfs/class directory

5. Sysfs file system

Each kobject in the system corresponds to a directory in the sysyfs, while the directory in each sysyfs represents a kobject object, and each sysfs file represents the corresponding kobject attribute.

The most basic functions of the sysfs file system include:

Sysfs_create_file creates files, sysfs_create_dir_ns creates directories, etc.

Static inline int _ _ must_check sysfs_create_file (struct kobject * kobj,const struct attribute * attr)

6. The introduction of the concept of platform platform can better describe the resource information of the device, such as bus address, interrupt, dma information. Also known as virtual bus.

7. Attributes: devices, drivers and classes all have their own properties, which add display and storage interfaces on the basis of attribute structure.

Struct attribute {const char * name;umode_t mode;#ifdef CONFIG_DEBUG_LOCK_ALLOCbool ignore_lockdep:1;struct lock_classs * key;strct loce_class_key skey:}

8. Device event notification

1) kobject uevent is an event sent by the kernel from the Middle East to application layer devices.

Kobject uevent includes

Enum kobject_action {KOBJ_ADD,KOBJ_REMOVE,KOBJ_CHANGE,KOBJ_MOVE,KOBJ_ONLINE,KOBJ_OFFLINE,KOBJ_BIND,KOBJ_UNBIND,KOBJ_MAX}

Through the netlink mechanism, the kernel sends it to the netlink client through the kobject_uevent- > kobject_uevent_env function

2) uevent helper

If the kernel supports uevent helper, kobject_uevent_env will call the uevent helper program at the application layer

Device management under Linux usually uses udev tools. Mdev is used to replace udev in embedded systems. Udev contains a background process that runs all the time. Unlike udev, mdev is not a daemon that runs all the time. If it wakes up with the kernel, mdev is set to be a uevent_helper program.

3) udev

It is used to monitor udev client control information, kernel hotplug events, configuration file change events. When a device is plugged in, udev is notified. Based on the parameters in the event and the information in the sysfs, it calls the appropriate event handler to create and delete the / dev node.

Udev is the uevent event of the kernel obtained through the netlink mechanism. Mdev obtains device information by directly accessing the / sys/class/ directory.

Udev handles the uevent event according to the rules in the rule file, and the udev rule file is in the directory / etc/udev/rules.d. Udev monitors its rule file directory / etc/udev/rules.d through the inotify function of the file system, and reloads the rule file once the rule file in that directory changes. A line in the udev rules file that does not begin with "#" is a rule. Each rule contains a match key and an execution key. Configure the key to connect to the value with the sign "="; execute with "="

9. Equipment tree

The device tree is used to describe board-level hardware information. The device tree is located under the Linux kernel directory code arch/arm/boot/dts, the dts file is defined at the board level, and the dtsi crisis is defined at the soc level. The Linux device tree compiles make dtbs.

The device tree node is established when the kernel starts:

Setup_arch {mdesc=setup_machine_fdt (_ _ atags_pointer); / / create the device tree unflagten_device_tree (); / / scan the device tree and convert it to device_node. }

Bootloader passes the address of the device tree to the kernel, puts it in the R2 register, and assigns the same _ _ mmap_switched value to _ _ atags_pointer in the arch/arm/kernel/head-common.s file.

Third, kernel synchronization mechanism

1. Atomic operation

Typefef stuct (volatile int counter;) atomic_t

The volatile modifier tells the compiler not to optimize this type of data

2. Spin lock (which circulates until the condition is satisfied) reduces the efficiency of cpu.

Spin_lock_init;spin_lock;spin_trylock;spin_unlock

Spin_lock will be returned immediately after it is successfully obtained, otherwise it will spin around in place. The try function attempts to get it, and returns true if it gets it immediately, otherwise returns false.

Interrupt-safe spin lock function:

Hardware interrupt

Spin_lock_irq;spin_unlock_irq;spin_lock_irqsave;spin_unlock_irqresore

Software interruption

Spin_lock_bh;spin_unlock_bh

Disables interrupts and kernel preemption on the local cpu. Save saves local interrupt status, restore recovery

3. Read-write lock

Read-write lock (rwlock) is a special spin lock. Allows multiple readers to access shared resources at the same time. A read-write lock can only have one writer and multiple readers at the same time.

If the read-write lock is not currently read or written, the writer can acquire the read-write lock immediately, otherwise spin until there is no writing or reading. If the read-write lock has no writer, the reader can acquire the read-write lock immediately, otherwise spin until the write releases the read-write lock.

Rwlock_t x _ x _ rwlocklockinit (x); / / dynamic initialization of read-write lock rwlock_t x=RW+LOCK_UNLOCKED// static initialization

Read and write attempt

Read_lock;wirte_lock;read_trylockread_unlock;wirte_unlock; write_trylock

4. Rcu (read-copy-modify) is used in the case of more reading and less writing.

The principle is that for a shared data institution protected by rcu, the reader does not need to acquire any locks to access it, but the writer needs to make a copy first, then modify the copy, and finally call a function to modify it at the right time. That is, all tasks that reference data exit.

Readers

# define rcu_read_lock () preempt_disable () / / enter the read operation critical section mark # define rcu_read_unlock () preempt_enable () / exit the read operation critical area

The writer generally operates on the copy, then sets the copy to the original, and finally releases the old one synchronously or asynchronously.

Struct rcu_head {struct tcu_head*next;// the next rcu_headvoid (* func) (stuct rcu_head*); / / the processing function after obtaining the competition condition}

Add callback function to synchronize rcu

Void call_rcu (struc rcu_head*,rcu_callback_T func);\ void synchronize_rcu (void)

After the call_rcu function is called, it returns directly, and the rcu soft interrupt will call the callback sweat to release the old data pointer. The sysnchronize_rcu function waits in place, and when it is awakened, it releases the old data pointer.

5. Semaphore: it is a sleep lock. If the semaphore is occupied, the semaphore will add its caller to the waiting queue.

The first difference between spin locks and semaphores: the former does not cause the caller to sleep. The selection of spin lock and semaphore mainly depends on the length of time the lock is held. If it is short, spin lock is used. The second difference: semaphores have multiple holders, while spin locks can have only one holder.

Sema_init (struct semaphore * sem,int val); down () down_trylock () down_interruptible (can be interrupted by signal); get, up () release, wake up waiting queue

6. Read-write semaphore: the principle is similar to that of read-write lock.

7. Mutex: mutex, only one visitor is allowed at a time. If the mutex fails to lock, it will go to sleep and wait for awakening.

Mutex_init (mutex); void mutex_lock (mutex*);; int mutex_trylock (); void mutex_unlock ()

8. Waiting queue

Waiting queues are used for asynchronous notification and blocking access. If the process needs to wait for certain conditions to be released before continuing, you can use the wait queue mechanism. Waiting queues are usually used in the Linux kernel to achieve blocking access.

Initialize a waiting queue

Void init_waitqueue_head (wait_queue_head_t*q)

Wait for the event occurrence function:

Wait_event (wq,condition) / / uninterruptible waiting wait_event_interruptible (wq,condition) / / interruptible waiting wait_event_timeout (wq,condition,timeout) wait_event_interruptible_timeout

Wake up waiting queue

Wake_up (wait_queue_head_t,*Q); / / Wake up all processes waiting for Q wake_up_interruptible (* Q); / / only wake up processes that can interrupt hibernation

Join or exit the waiting queue

Add_wait_queue (wait_queue_head_t *, wait_queue_t*) add_wait_queue_exclusiveremove_wait_queue

The thread that joins the waiting queue will wait to wake up. Blocking character drivers generally wait in the read function and use the wake_up function to wake up the waiting queue in an interrupt or kernel thread.

Memory management and linked list

1. Physical address and virtual address

If the cpu does not have a mmu, the address is sent directly to the chip pin, which is the physical address; if there is a mmu, the address sent is the virtual address, and mmu maps the virtual address to the physical address.

Mmu maps virtual addresses to physical addresses on a page-by-page basis, and for 32-bit cpu, usually a page 4KB. A page in physical memory is called a physical page or page frame. Mmu uses a page table to record the mapping between virtual address pages and physical memory pages.

2. Memory allocation

Longest memory request and release functions:

Void* kmalloc (size_t size,gfp_t flags); void* kzalloc (size_t size,gfp_t flags); / / call kmalloc to allocate memory and zero void kfree (const void*x)

The address space allocated by the Kmalloc function is linearly mapped, and it generally allocates memory smaller than 128kb.

Used by flags GFP_KERNEL kernel space processes. GFP_USER allocates space for user space, and GFP_HIGHUSER allocates space from high-end addresses. Etc.

If you want to allocate large chunks of memory, you should use page-oriented technology

Unsigned long get_zeored_page (gfp_t gfp_mask); / / returns a single, zero-filled page unsigned long _ _ get_free_pages (gfp_t mask,unsigned int order); / / directly gets the memory of the whole page (the number of pages is a power of 2) free_page (addr,order)

If you need to apply for a continuous virtual address memory, the physical address is not contiguous, the page table is queried frequently, and the efficiency is low:

Void * vmalloc (size); void * vmalloc_user (size); allocate memory void vfree for user space (void * addr)

3 、 cache

Cache. Linux uses the slab mechanism to manage cache. Kmem_cache_create creates a slab cache.

Kmem_cache_alloc// allocates memory from cache kmem_cache_freekmem_cache_destroy// destroys slab cache

4. IO port to virtual address mapping

In arm, the port 0 of peripherals iUnix has the same physical address as memory, and the address of iUnix O memory resources of peripherals is known, which is determined by hardware design. The driver of Linux cannot directly access the memory resources of Imax 0 through the physical address, but must translate the physical address into a virtual address.

1) static mapping

In arm storage system, mmu is used to realize the mapping from virtual address to physical address. The implementation process of mmu is actually a process of lookup table mapping. The establishment of page table is an indispensable step to realize mmu function. The page table is located in the memory of the system, and each item of the page table corresponds to a mapping of a virtual address to a physical address.

The create_mapping function of Linux memory creates a linear mapping table.

Stuct map_desc {unsigned ling virtual;// virtual address unsigned long pfn;//__phys_to_pfn (phy_addr) unsiged long length;// length unsiged int type;} void _ _ init create_mapping (struct map_desc*md); / * example: arm platform uses iotable_init to create platform-specific mapping: * / void _ init iotable_init (struct map_desc* io_desc,int nr); static struct mcp_Desc smdk6410_iodesc [] = {} / / add s3c64xx_init_io (smdk6410_iodesc,ARRAY_SIZE (smdk6410_iodesc)); {iotable_init (smdk6410_iodesc,ARRAY_SIZE (smdk6410_iodesc));;.} to the mapping to be established.

2) ioremap

If you need to map IO dynamically in the module, you can use the ioremap function. This function maps the physical address of the iCompo memory resource to the core virtual address space.

Typedef phys_addr_t resource_size_t;void _ _ iomem * ioremap (resource_size_t res_cookie/* physical address * /, size_t size); void iounmap (volatile void _ _ iomem * iomem_cookie); / / Unmap

Example:

Reserve_virt_addr=ioremap (100,1024, 1024, 1024, 1024); / / Map the 10MB address starting with 101MB to the virtual address.

5. Mapping from kernel space to user space

Mmap interface. By mapping the kernel address to the user address, the application can access the memory address directly.

System call

Unsigned long mmap (unsigned long addr,unsigned long len,int prot,int flags,int fd,long off); / / Unmap the munmap function

The driver needs to be implemented

Memapmem_fops {... mmap = memapmem_mmap;}

Example:

Fd=open ("/ dev/mmap", O_RDWR); addr=mmap (NULL,4096,PROT_READ | PROT_WRITE,MAP_SHARED,fd,0)

6. DMA mapping

1) establish consistent DMA mapping: dma_alloc_coherent (prohibit Cacheable entries and Bufferable of page tables)

2) establish non-consistent DMA mapping: dma_alloc_noncoherent

7. Linked lists are bi-directional linked lists: they can be traversed in both directions

V. tasks and scheduling

1 、 schedule

While waiting for the resource to be ready, the linux process can actively give up the cpu, go into hibernation, and continue to check whether the resource is ready after waking up. The process can call the schedule function to give up the cpu, and when the process is awakened, it will start execution from the next code of the schedule function.

Void _ sched schedule (void) signed long _ sched schedule_timeout (timeout) / / scheduling example with timeout: process a:set_current_state (TASK_INTERRUPTIBLE); spin_lock (& list_lock); if (list_empty (& list_head)) {spin_unlock (& list_lock); schedule (); spin_lock (& list_lock);} set_current_state (SASK_RUNNING); spin_unlock (& list_lock); process b:spin_lock (& list_lock) List_add_tail (& list_head,new_node); spin_lock (& list_lock); wake_up_process (process a)

2. Kernel thread kthread_create

The thread created by kthread_cretate cannot be run immediately and needs to be woken up by the wake_up_process function. The kthread_run (call kthread_create first, then wake_up_process) macro completes the kthread_create and wake_up_process steps. When kthread_stop ends the kernel thread, you should make sure that the thread function is not finished, otherwise it will wait forever.

3. The kernel calls the application

Int call_usermodehelper (char * path,char * * argv,char * envp,int wait)

Path program path, argv parameter, envp environment variable, wait wait end flag

4. Soft interrupt mechanism

1) principle

The hardware interrupt is the interrupt signal generated by the hardware, and the soft interrupt is the interrupt simulated by software. After an interrupt occurs in the hardware, the interrupt will be notified to the cpu,cpu query vector table to map the interrupt to a specific program. The soft interrupt is completed within the operating system, and the kernel runs a daemon to query and execute the interrupt. the function of this thread is similar to the interrupt controller of the processor. The core elements of software interrupt mechanism include: software interrupt state (soft interrupt state), soft interrupt vector table (softirq_vec), soft interrupt thread (softirq thread).

The system calls the _ _ do_softirq loop in the ksoftirqd kernel process to detect whether the soft interrupt is in the pending state, and if so, executes the corresponding handler.

There can be up to 10 soft interrupts in the linux 4.5 kernel, including timer, network soft interrupt, and tasklet. The priority is from 0 to 9, corresponding to 10 functions that have been defined.

The kernel divides the whole interrupt processing flow into the upper part and the lower part. The first half is the interrupt handler function mentioned earlier, which can respond to the interrupt as quickly as possible and do something that must be done immediately after the interrupt response. For some operations that need to continue after the interrupt handler, the kernel recommends that it be executed in the lower half.

2) tasklet

Soft interrupt is an interrupt mechanism simulated by software, which is often used to perform asynchronous tasks. Tasklet is a lower half mechanism implemented by soft interrupt.

Soft interrupt and tasklet have higher priority, better performance, fast scheduling, but can not sleep. The work queue is the process scheduling of the kernel, which is relatively slow, but can sleep. So, if you need sleep in the lower half, you can only choose the work queue. Otherwise, you'd better use tasklet.

Three steps:

(1) write tasklet handler static void tasklet_callback (ulong data); (2) declare taskletDECLEARE_TASKLET (tasklet,tasklet_callback,0); (3) schedule taskletstatic irqreturn_t irq_handler (int irq,void * arg) {tasklet_schedule (& tasklet); return IRQ_HANDLED;}

5. Work queue

1) principle

The work queue, like tasklet, allows the caller to request a function to be called at some point in the future. Tasklet is allowed in the context of soft interrupts, so tasklet executes quickly. The work queue runs in the context of a special kernel process, has a lot of flexibility, and can sleep. The work queue consists of a series of tasks to be performed and the kernel threads that perform them. Each work queue has a dedicated thread, and all tasks must be run in the context of the process so that they can sleep safely. Linux provides a series of global work queue, including system_wq, system_highpri_wq, and so on. Drivers can create and use their own work queues.

2) delayed work queue: the delayed work queue is based on the work queue, which can be delayed for a period of time and then join the work queue.

6. Kernel time

1) the concept of time

(1) clock cycle (clock cycle): the number of clock pulses generated by the crystal oscillator in 1 s. Linux uses macro lock _ TICK_RATE to represent the frequency of the input clock pulse of the counter.

(2) clock tick (clock tick): a clock interrupt produces a clock tick. The system generates a clock interrupt per clock cycle.

(3) clock tick frequency: the number of clock ticks in 1 s. The Linux kernel uses HZ to represent the frequency of clock ticking, while HZ is usually 1s.

(4) Global variable (jiffies): a 32 is an unsigned integer that represents the number of clock ticks since the kernel was last started. With each tick, the kernel's clock interrupt handler timer_interrupt increments the variable by 1. 0.

(5) xtime:timeval structure global variable, which records the current time of the system since boot. The benchmark is 1970.1.1.

(6) system clock: also a software clock, which is timed by the software according to the time interrupt.

The kernel can obtain and set the system time in response to the following functions:

Void do_gettimeofday (struct timeval * tv); int do_settimeofday (struct timespec * tv) timeval and timespec convert timespec_to_jiffies;timeval_to_jiffies to jiffies

2) delay under Linux

The kernel defines a bunch of macros to achieve latency:

# define time_after (AMaginb) # define time_before#define time_after_eq (aMagneb) # define ndelay (n) / / nanosecond # define udelay (n) / / microsecond # define mdealy (n) / / millisecond

All of the above are busy waits, which will cause other tasks to be unable to use cpu at this time. Here is a short delay method that does not have to wait:

Void msleep (u int); ulong msleep_interruptible (u int); unit is milliseconds.

3) Internal approval timer

Timer_list {struct list_head list;ulong ecpires;// timer expiration time void (* fun) (ulong) passed to the handler by ulong data;//; / / callback function}

Action:

Added: add_timer (timer_list *)

Delete: del_timer

Modify the ecPire value: mod_timer

VI. Simple hardware device driver

1. The processor accesses the hardware device in the following ways:

(1) memory mode. The memory space of the peripheral is mapped to the address space of the processor, and the processor accesses the hardware by accessing the mapped address

(2) Icano interface. The processor is connected with the Icano device through a certain interface, and this interface is the Icano interface. The Icano interface includes a set of registers and a control circuit.

(3) pin (pin). Pins can be used to reset the chip and receive interrupt signals from the device. In addition, some chips can also be configured in simple mode through pins.

In x86 system, the Imax O address space is separated from the memory address space, and the register is located in the Imax O space, which is called the Imax O port. In arm and other systems, iUnigram O is usually compiled with memory, also known as Imax O memory, which is the fastest memory in the system.

2. The composition of embedded Linux system

Bootlader (pass parameters, device tree (R2 register), etc.)-"kernel-" root file system-"other file systems are mounted under the root file system

3. Hardware initialization

Hardware initialization is placed in the arch directory under kernel, such as arch/arm/mach-xxx/mach-xxxx.c

DT_MACHINE_START (LS1021A, "Freescale LS1021A"). Smp = smp_ops (ls1021a_smp_ops), .dt_compat = ls1021a_dt_compat,MACHINE_END

4. Clk system

A clock is like a human heartbeat. Without a clock, peripherals cannot run. Clock-related code is in / driver/clk

5. Dev/mem and dev/kmem

/ dev/mem is a mapping of physical memory, which can be used to access physical Imax O devices, such as registers of interface controllers. / dev/kmem is a mapping of virtual memory, which can be used to look at kernel variables and other information.

Example:

Target = strtoul (argv [1], 0charge 0)

Open the memory device:

Fd=open ("/ dev/mem", O_RDWR | O_SYNC)

Map a page

Map_base=mmcp (0makeshift SIZEMagneRead | PORT_WRITE,MAP_SHARED,fd,target&~MAP_MASK)

Get the value of memory according to the data type

Vir_addr = map_base+ (target&map_mask)

You can then manipulate the corresponding registers by manipulating vir_addr.

6. Register access

1) for example, the S3C6410X processor supports 32 physical address space, which is divided into two parts, one for storage and the other for peripherals.

Access the main memory through spine bus, and the main memory range I is 0x00000000~0x6fffffff

Boot mirror area:-0x07ffffff

Internal storage area:-0x0fffffff

Static storage:-0x3fffffff is used to access SROM,SRAM NOR FLASH

Dynamic storage:-0x6fffffff

The peripheral area is accessed through peri bus, and the range is 0X70000000-0X7FFFFFFF.

Linux must map the physical address of the peripheral to a virtual address before it can be used.

Fixed address mapping can be used for address mapping

# define S3C_VA_IRQ S3C_ADDR (0X00000000) / * irq Controller * /

Another way is to use the ioremap function.

When the Icano register is uniformly addressed with the memory, the Iwhite O register is also called the Icando O memory. When the Icano register is addressed separately from the memory, the Igamot O register is also known as the Igamot O port. In order to ensure the cross-platform of the driver after the address of the memory resource is mapped to the virtual address, the specific function in Linux should be used to access the memory resource instead of through the pointer to the virtual address.

Void writew (u16 _ volatile void _ _ iomem*addr); void iowrite16 (u16 _ iomem*addr,void _ iomem*addr); void iorwrite16_rep (const volatile void _ _ iomem*addr,void * buffer,uint cont); / / continuous

2) watchdog

In order to ensure that the system can start automatically when there is an anomaly, the processor provides watchdog function. The watchdog unit can not only generate a reset signal, but also be used as a common 16-bit interval timer to generate interruption of service.

Watchdog register

WTCON 0x7e004000 routine watchdog timer control register

WTDAT 0X7E004004 Randall W watchdog timer data register

WTCNT 0X7E004008 R _ paw W watchdog counter counter controller

WTCLRINT 0X7E00400C W interrupt clear register

WTDAT saves watchdog timer overload count values. WTCNT saves the current value of the watchdog timer. WTCLRINT is used to clear the watchdog fixed time interrupt, writing any value will clear the interrupt.

7. Level control

The general level includes high level and bottom level. The commonly used levels include TTL level, CMOS level and RS232 level. The voltage range of each level is different. TTL level signal + 5V is equivalent to logic 1min 0V is equivalent to 0. General input, 2.0V is high, output, 2.4 high. Level control is inseparable from GPIO control.

8. Hardware interrupt handling

An electrical signal generated by hardware and sent directly to the input pin of the interrupt controller, and then the corresponding signal is sent to the processor by the interrupt controller.

If the interrupt handling process is very complex, it can be divided into two parts: the upper part and the lower part. The first half completes some urgent things, and the bottom half completes the rest. The upper part can not be interrupted, and the lower part can. The lower part of Linux includes soft interrupt, tasklet mechanism, work queue, timer and so on.

When an interruption occurs:

Cpu jumps to "vector_irq", saves the scene, and calls the C function handle_arch_irq

Handle_arch_irq:

a. Read int controller and get hwirq

b. Get virq from hwirq

c. Call irq_ handle [virq] .handle _ irq

Driver registration interrupt handling function: driver request_irq (virq, my_handler)

9. Watchdog driven frame

In the Linux/drivers/watchdog directory.

Watchdog equipment structure

Struct watchdog_device

Registration and logout watchdog: int watchdog_register_device (watchdog_device *); void watchdog_unregister_device ()

Watchdog has an important parameter, which is watchdog operation:

Struct watchdog_ops {int (* start) (struct watchdog_device*);...}

Watchdog_register_device invokes a miscellaneous device driver to register a character device driver.

Example:

Static const struct watchdog_info s3c2410_wdt_ident = {. Options = OPTIONS,.firmware_version = 0Power.identity = "S3C2410 Watchdog",}; static const struct watchdog_ops s3c2410wdt_ops = {.owner = THIS_MODULE,.start = s3c2410wdtoriginstart.stop = s3c2410wdtroomstop.ping = s3c2410wdtroomkeepalive.setorigintimeout = s3c2410wdtroomsetheartbeat.restart = s3c2410wdt_restart,} Static const struct watchdog_device s3c2410_wdd = {. Info = & s3c2410wdtpaper.ops = & s3c2410wdtpaperops.timeout = S3C2410_WATCHDOG_DEFAULT_TIME,}; watchdog_register_device (& wdt- > wdt_device); register

10. RTC driver

Embedded systems generally have two times, one is RTC time, the other is Linux system time. The RTC time is stored in the RTC controller. After the system is powered off, it is powered by the battery to ensure that the system can read the correct time the next time it is powered on again. The RTC time is usually read in the system startup script and the RTC time is set to the system time. The date command in Linux is used to read and set the system time, while the hwclock command is used to read and set the RTC time.

Register and unregister RTC drivers

Devm_rtc_device_register (& pdev- > dev, "s3c", & s3cantirtcopsTHISTOMODULE)

Operation function Interface of RTC device Class

Struct rtc_class_ops {int (* ioctl) (struct device *, unsigned int, unsigned long); int (* read_time) (struct device *, struct rtc_time *); int (* set_time) (struct device *, struct rtc_time *); int (* read_alarm) (struct device *, struct rtc_wkalrm *); int (* set_alarm) (struct device *, struct rtc_wkalrm *); int (* proc) (struct device *, struct seq_file *) Int (* set_mmss64) (struct device *, time64_t secs); int (* set_mmss) (struct device *, unsigned long secs); int (* read_callback) (struct device *, int data); int (* alarm_irq_enable) (struct device *, unsigned int enabled); int (* read_offset) (struct device *, long * offset); int (* set_offset) (struct device *, long offset);}

The RTC driver also contains a general device layer, which is responsible for creating / dev/trc devices and providing a unified interface to the application layer (call devm_rtc_device_register to register RTC, which calls the create device node function)

11. Led equipment

The Linux kernel defines LED lights for LED devices that specifically handle a variety of peripherals.

Struct led_classdev {..} # define led_classdev_register (parent, led_cdev)\ of_led_classdev_register (parent, NULL, led_cdev) void led_classdev_unregister (struct led_classdev * led_cdev)

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report