Commonly used functions in driver development 2

Blocking state part of I/O model:

	wait_queue_head_t wq;
	//定义等待队列头
	init_waitqueue_head(&wq);
	//初始化等待队列头

<1> wait_event(wq, condition) //不可中断的等待态
	wait_event_interruptible(wq, condition)	//可中断的等待态
	功能:让当前的进程休眠
	参数:
		@wq :等待队列头
		(休眠的进程在内核中会被放到一个
		队列中,这里的wq就是队列头)
		@condition:条件为假,要休眠
		            为真,不需要休眠(数据准备好了)
	返回值:成功返回0,失败返回错误码
	
 <2> wake_up(&wq)	
    wake_up_interruptible(&wq)	
    功能:唤醒休眠的进程
    参数:
    @等待队列头	

epoll part:

 #include <sys/epoll.h>
 
 int epoll_create(int size);
 功能:创建一个epoll的实例
 参数:
 	@size: 已经不再使用,可以填写任意值
 返回值:成功返回epoll的文件描述符,失败返回-1;	
 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
	 功能:控制箱epfd中添加、修改、删除本次要监听的事件的类型
	 参数:
		@epfd:epoll的文件描述符
		@op  :EPOLL_CTL_ADD 添加事件
			  EPOLL_CTL_MOD 修改事件 
			  EPOLL_CTL_DEL 删除事件
		@fd  :文件描述符
		@event:事件的结构体对象
	 返回值:成功返回0,失败返回-1
 int epoll_wait(int epfd, struct epoll_event *revents,
                      int maxevents, int timeout);
	 功能:完成阻塞,如果有数据准备好,就返回
	 参数:
		@epfd     :epoll的文件描述符
		@revents  :返回的事件结构体
		@maxevents:最大的结构体个数
		@timeout  :超时时间
	返回值:1.成功返回准备好的文件描述符的个数
			2.超时返回0
			3.失败返回-1;

Linux kernel interrupt part

	int request_irq(unsigned int irq, irq_handler_t handler, 
		unsigned long flags,const char *name, void *dev)
	功能:在linux内核中注册中断处理函数
	参数:
		@irq  :软中断号:根据gpio号通过映射得到软中断号
		例:
						A    B    C    D   E
			组号m:	0    1    2    3   4
			A组内偏移号n: 0 - 31
			
			gpio的编号 = 组号*32+组内偏移号
			gpioc18:   =  2*32+18
			
			将gpio号映射成软中断号:
			软中断号 = gpio_to_irq(gpio号);
		   @handler:中断处理函数的指针
			typedef irqreturn_t (*irq_handler_t)(int, void *);
			
			中断函数
			@irqno :软中断号
			@args  :request_irq最后一个参数传递过来的值
			irqreturn_t handle_key_irq(int irqno, void * args)
			{                        
				return  IRQ_NONE  :
						1.中断处理函数执行失败,返回IRQ_NONE
						2.如果是共享中断,同时有两个中断处理函数,
						  都被同时触发了,不需要执行中断处理函数
						  的设备就返回IRQ_NONE
				return  IRQ_HANDLED  :中断正常执行成功了
			}
			
		@flags :中断的触发方式
				#define IRQF_TRIGGER_NONE	0x00000000
				#define IRQF_TRIGGER_RISING	0x00000001
				#define IRQF_TRIGGER_FALLING	0x00000002
				#define IRQF_TRIGGER_HIGH	0x00000004
				#define IRQF_TRIGGER_LOW	0x00000008
				#define IRQF_DISABLED		0x00000020 #快速中断,在处理本中断的时候关闭其他中断
				#define IRQF_SHARED		0x00000080     #共享中断
			
		@name  :中断的名字   cat /proc/interrupts(最后一个字段)
		@dev   :向中断处理函数传递的参数
			
	返回值:成功返回0,失败返回错误码		
void free_irq(unsigned int irq, void *dev_id)	
	功能:释放中断
	参数:
		@irq  :软中断号
		@dev_id:中断处理函数最后一个成员传递的参数
			
	按键中断:
		gpiob8   左键
		gpiob16  右键	

gpio subsystem part:

int gpio_request(unsigned gpio, const char *label)
	功能:申请一个gpio去使用
	参数:
		@gpio :gpio的编号
		@label:名字,NULL
	返回值:成功返回0,失败返回错误码
	int gpio_direction_input(unsigned gpio)
	功能:设置gpio为输入
	参数:
		@gpio :gpio编号
	返回值:成功返回0,失败返回错误码
int gpio_direction_output(unsigned gpio, int value)	
	功能:设置gpio为输出
	参数:
		@gpio :gpio编号
		@value: 1输出高  0输出低
	返回值:成功返回0,失败返回错误码	
void gpio_set_value(unsigned gpio, int value)
	功能:设置gpio输出的高低电平
	参数:
		@gpio :gpio编号
		@value: 1输出高  0输出低
int gpio_get_value(unsigned gpio)
	功能:获取gpio的高低电平的值
	参数:
		@gpio :gpio编号
	返回值:读到1表示输出高电平  读到0表示输出低

void gpio_free(unsigned gpio)
	功能:释放gpio
	参数:
		@gpio :gpio编号

Platform bus part:

struct resource *platform_get_resource(struct platform_device *dev,
				       unsigned int type, unsigned int num)
	功能:在驱动端获取设备信息
	参数:
		@dev  :设备端的对象的指针
		@type :资源的类型
		@num  :同类资源中的第几个,每种资源都是从0开始的。
	返回值:成功返回struct resource *的结构体指针
			失败返回NULL
int platform_get_irq(struct platform_device *dev, unsigned int num)		
	功能:获取中断资源
	参数:
		@dev  :设备端的对象的指针
		@num  :中断资源中的第几个,每种资源都是从0开始的。
	返回值:成功返回中断号,失败返回错误码

i2c drive control part:

int i2c_register_board_info(int busnum,
		struct i2c_board_info const *info, unsigned len)
	功能:向控制器提交名字
	参数:
		@busnum :总线号(它和控制器的序号一一对应) 2
		@info   :被提交的信息
		@len    :提交的i2c_board_info的个数
	返回值:成功返回0,失败返回错误码	
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
	功能:消息的发送函数
	参数:
		@adap :总线驱动的对象  client->adapter
		@msgs :消息结构体指针
		@num  :消息的个数
	返回值:成功返回发送了的消息的格式,
			否者不是发送的消息的个数。

Block device driver part:

struct request_queue *blk_init_queue(request_fn_proc *rfn, spinlock_t *lock)
	功能:初始化一个队列
	参数:
		@rfn  :队列处理函数
		typedef void (request_fn_proc) (struct request_queue *q);
		//这个是队列处理函数的原型,在这个函数中要进行读写操作
		@lock :自旋锁
	返回值:成功返回初始化好的队列的指针
			失败返回NULL
struct request *blk_fetch_request(struct request_queue *q)
	功能:从队列中取出一个请求
	参数:
		@q :队列
	返回值:成功返回request结构体指针
			失败返回NULL
void blk_cleanup_queue(struct request_queue *q)
	功能:清除队列
	参数:
		@q:被清除的队列
	返回值:无
request的操作:
 sector_t blk_rq_pos(const struct request *rq)
	 功能:从请求中获取本次操作的起始的函数
	
	 unsigned int blk_rq_cur_sectors(const struct request *rq)
	 功能:获取本次想读写的扇区的个数
	 
	 int blk_rq_cur_bytes(const struct request *rq)
	 功能:获取本次想读写的字节的个数
	
	 rq_data_dir(rq)
	 功能:从request中获取本次是读还是写
	 rq_data_dir(rq) == READ  读
	 rq_data_dir(rq) == WRITE 写
	
	bool __blk_end_request_cur(struct request *rq, 0)
	功能:判断request的读写是否处理完了
	参数:
		@rq :请求队列
	返回值:真:表示数据没有处理完
			假:数据处理完成了

gendisk内存分配并初始化的函数
		struct gendisk *alloc_disk(int minors)
		功能:分配内存并初始一些内容
		参数:
			@minors :设备的个数
int register_blkdev(unsigned int major, const char *name)
	功能:申请块设备的设备号
	参数:
		@major :如果填写的是大于0的值静态指定设备号
				如果填写的是0表示动态申请设备号
		@name  :cat /proc/devices		
	返回值:
		major > 0   成功返回0,失败返回错误码
		major = 0   成功返回主设备号,失败返回小于等于0的值
		
void unregister_blkdev(unsigned int major, const char *name)
	功能:失败块设备的设备号
	参数:
		@major :主设备号
		@name  :名字
	返回值:无
void add_disk(struct gendisk *disk)
	功能:注册gendisk
	参数:
		@disk :gendisk对象的地址
	void del_gendisk(struct gendisk *disk)
	功能:注销gendisk
	参数:
		@disk :gendisk对象的地址

Linux memory allocation part:

void *kmalloc(size_t s, gfp_t gfp)
		功能:分配对应的虚拟内存
		参数:size:分配内存区的大小(2的次幂,最大是128K,连续)
			  flags:内存分配标志
				  GFP_KERNEL:内核可能被休眠,进程上下文,不能用于中断上下文中
				  GFP_ATOMIC:处理紧急的事务,用在中断上下文
			  
		返回值:对应虚拟地址
		特点:最大128k   , 分配虚拟地址,其虚拟地址空间连续,物理地址空间也是连续
		类似函数:kzalloc:kmalloc+memset(buf,0,sizeof(buf));
void kfree(const void *x)
		功能:释放对应的虚拟内存
		参数:x:虚拟内存的起始地址
		返回值:无
void *vmalloc(unsigned long size)
		功能:分配对应的虚拟内存
		参数:size:分配内存区的大小
		返回值:对应虚拟地址
		特点:分配虚拟地址,其虚拟地址空间连续,但是物理地址空间不一定连续
void vfree(const void *addr)
		功能:释放对应的虚拟内存
		参数:addr:虚拟内存区的首地址
		返回值:无
unsigned long __get_free_page(gfp_t gfp)
		功能:分配一个物理页
		参数:
			@gfp:
			GFP_KERNEL:内核可能被休眠,进程上下文,不能用于中断上下文中
			GFP_ATOMIC:处理紧急的事务,用在中断上下文
		void free_page(unsigned long addr)
unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order)
		功能:分配多个物理页
		参数:
			@gfp_mask:
			GFP_KERNEL:内核可能被休眠,进程上下文,不能用于中断上下文中
			GFP_ATOMIC:处理紧急的事务,用在中断上下文
			@order:填写的是想分配内存的次值n=get_order(57600)
				57600 = 2^n
				
		void free_pages(unsigned long addr, unsigned long order)

Guess you like

Origin blog.csdn.net/weixin_48430195/article/details/108669638