Drive learning-daily notes day7

[1] Interrupts in the
Linux kernel
The principles of interrupts in the Linux kernel are the same as those in the bare metal learned in the ARM course . Both need to follow four major steps and three small steps.

在linux内核中注册中断处理函数
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  右键	

PM:
[1] Error when installing the driver:
1. The error prompted is: Resource is busy (146 interrupt is occupied)

2.通过命令  cat /proc/interrupts
		"nxp-keypad"
	
3.在内核中通过搜索找到了驱动的文件
	nxp_io_key.c
	
	通过Makefile知道选项名KEYBOARD_NXP_KEY
	                                                       │  

│ Type : tristate │
│ Prompt: SLsiAP push Keypad support │
│ Defined at drivers/input/keyboard/Kconfig:583 │
│ Depends on: !S390 && !UML && INPUT [=y] && INPUT_KEYBOARD [=y] && ARCH_CPU_SLSI [=y] │
│ Location: │
│ -> Device Drivers │
│ -> Input device support │
│ -> Generic input layer (needed for keyboard, mouse, …) (INPUT [=y]) │
│ -> Keyboards (INPUT_KEYBOARD [=y])

4.将上述路径的	SLsiAP push Keypad support 前的*去掉

5.重新编译内核
	make uImage
	
6.将uImage文件拷贝到tftpboot目录

7.让开发板重新上电

8.重新安装驱动
	insmod farsight_irq.ko

[2] Key debounce
Because there can be no delay or time-consuming operation in the interrupt processing function.
The key debounce here cannot be completed with delay. You can use the Linux
kernel timer to complete the debounce.

[3] Linux kernel timer
1. How to obtain the current time of the kernel timer?
jiffies: The number of kernel clock ticks
. This value will increase since the Linux kernel is powered on . jiffies is a 64-bit integer.

2.内核定时器加1代表走多长时间?
	在内核的顶层目录.config这个文件CONFIG_HZ=1000,
	它就是内核定时器的频率值
	
	A53 = 内核定时器加1代表走了1ms的时间。
	ubuntu = 内核定时器加1代表走了4ms的时间。
	
	
1.内核定时器的对象
	struct timer_list {
		unsigned long expires;  //定时的时间
		void (*function)(unsigned long data);//定时器的处理函数
		unsigned long data;	  //向定时器处理函数传递的参数	
	}		
	struct timer_list mytimer;		
2.初始化
	void timer_function(unsigned long data)
	{
		
	}
	mytimer.expires = jiffies+10;
	mytimer.function  = timer_function;
	mytimer.data = 0;
	
	init_timer(&mytimer); //初始化定时器中其他的成员
	
	
3.定时器的注册
	add_timer(struct timer_list *timer)
	定时器注册,定时器就会启动了,并且只会执行一次
	定时器只能被注册一次,如果下一次在注册定时器,此时
	linux内核就崩溃了。

4.重新启动定时器
	int mod_timer(struct timer_list *timer, unsigned long expires)
	参数:
		@timer :定时器结构体指针
		@expires:下一次定时的时间
	返回值:如果定时器再次启动成功了返回1,否则返回0
	
5.定时器的删除
	int del_timer(struct timer_list *timer)
	功能:注销定时器
	参数:
		@timer :定时器结构体指针
	返回值:删除不活动的定时器返回1,删除活动的定时器返回0;

[4] gpio subsystem (gpiolib.c)
int gpio_request(unsigned gpio, const char *label)
function: apply for a gpio to use
Parameters:
@gpio: gpio number
@label: name, NULL
return value: return 0 successfully, Return error code on failure

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编号

[5] The mechanism of the bottom half of
the interrupt. In the upper half of the interrupt, delay or relatively time-consuming operations cannot be performed,
but in the actual development process, it is inevitable to deal with delay
or relatively time-consuming operations when the interrupt comes . For this reason, the Linux kernel introduced a
mechanism to interrupt the bottom half. Soft interrupt, tasklet, work queue.

软中断:软中断在linux内核中是有32个个数限制的,一般留给
		操作系统使用,在写驱动的时候不使用。
tasklet:taklet是基于软中断实现的,没有个数显
		示,tasklet工作在中断上下文。
		原理:在中断上半部执行完之后会清除中断状态标志位,
		只要中断状态标志位被清除了,就可以响应下一次中断了。
		在清除中断状态标志位下面,就可以启动中断底半部工作。
		这个中断底半部也属于中断的一个部分,所以它工作在中断
		上下文。由于它工作在中断上下文不在在这个底半部执行
		能够引起系统调用的操作。
		
1.分配tasklet对象
	struct tasklet_struct
	{
		//struct tasklet_struct *next; //指向下一个节点
		//unsigned long state;         //是否需要执行中断底半部的状态标识
		//atomic_t count;              //计数
		void (*func)(unsigned long);   //中断底半部处理函数
		unsigned long data;            //向中断底半部处理函数传递的参数
	};
	struct tasklet_struct tasklet;

2.初始化tasklet
	void tasklet_init(struct tasklet_struct *tasklet,
                            void (*func)(unsigned long),
                            unsigned long data)

3.调用底半部处理函数执行
	void tasklet_schedule(struct tasklet_struct *tasklet)
	在中断顶半部即将执行结束的时候调用底半部执行
	


工作队列:在linux内核启动的时候会启动一个events的内核线程,
		默认这个内核线程是休眠的,它内部维护了一个队列。如
		你想让队列执行,只需要向这个队列尾部添加自己的work.
		添加完之后调用一个唤醒的函数,当这个events被唤醒之后
		会从工作队列中取出一个work在这个events的线程内执行。
		所以它工作在进程上下文,可以脱离中断执行。在工作队列
		中可以有延时、耗时、甚至休眠的操作。


	1.分配工作队列对象
		struct work_struct {
			work_func_t func;
		};
		typedef void (*work_func_t)(struct work_struct *work);

	2.工作队列的初始化
		void work_func(struct work_struct *work)
		{
			
		}
		INIT_WORK(&work, work_func);
		
	3.调用执行
		schedule_work(&work); 

Guess you like

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