linux中断
【一】、中断底半部
1. 软中断 --->>> 执行在中断上下文 --->>> 会被中断打断,不会被软中断或进程打断 --->>> 可以完成耗时操作
2. tasklet --->>> 执行在中断上下文 --->>> 会被中断打断,不会被软中断或进程打断 --->>> 可以完成耗时操作
3. 工作队列 --->>> 执行在进程上下文 --->>> 会被中断、中断底半部、进程打断 --->>> 可以完成耗时操作,同时
也可以有进程调度相关的函数
中断底半部实现:
[1]. 软中断
init/main.c
--->>> start_kernel
--->>> softirq_init();
/***********************************************************************
*功能:开启(初始化)软中断
*参数:
* @nr 软中断枚举值
* @action 中断底半部处理函数
**********************************************************************/
void open_softirq(int nr, void (*action)(struct softirq_action *))
/************************************************
*功能:调度中断底半部
*参数:
* @nr 软中断枚举值
***********************************************/
void raise_softirq(unsigned int nr)
[2]. tasklet
1. struct tasklet_struct 数据类型
2. 定义、初始化
/*******************************************************************************
*功能:定义并初始化tasklet
*参数:
* @name tasklet结构体变量名
* @func tasklet底半部处理函数指针
* @data 私有数据
******************************************************************************/
#define DECLARE_TASKLET(name, func, data) \
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
/**********************************************************************************************
*功能:初始化tasklet
*参数:
* @t tasklet结构体指针
* @func tasklet底半部处理函数指针
* @data 私有数据
*********************************************************************************************/
void tasklet_init(struct tasklet_struct *t,void (*func)(unsigned long), unsigned long data);
3. 调度tasklet底半部
/********************************************************************
*功能:调度tasklet底半部
*参数:
* @t tasklet结构体指针
*返回值:void
*******************************************************************/
void tasklet_schedule(struct tasklet_struct *t)
[3]. 工作队列
<linux/workqueue.h>
1. 工作队列结构体
struct work_struct
2. 定义、初始化
typedef void (*work_func_t)(struct work_struct *work);
/**********************************************************
*功能:定义并初始化workqueue
*参数:
* @n 工作队列变量名
* @f 工作队列底半部处理函数指针
*********************************************************/
#define DECLARE_WORK(n, f) \
struct work_struct n = __WORK_INITIALIZER(n, f)
/**********************************************************
*功能:初始化工作队列
*参数:
* @_work 工作队列结构体指针
* @_func 工作队列底半部处理函数指针
*********************************************************/
INIT_WORK(struct work_struct * _work, _func)
3. 调度工作队列
/****************************************************
*功能:调度工作队列底半部
*参数:
* @work 工作队列结构体指针
***************************************************/
bool schedule_work(struct work_struct *work)
【二】、定时器
<linux/timer.h>
jiffies :计数值
HZ
expires = jiffies + HZ; //定时1s
expires - jiffies + n*HZ; //定时ns
struct timer_list {
unsigned long expires; //定时器的定时时间 --->>> 计数值
void (*function)(unsigned long); //定时器中断处理函数指针
unsigned long data; //私有数据
};
/***************************************************************************
*功能:定义并初始化定时器
*参数:
* @_name 定时器变量名
* @_function 定时器中断处理函数指针
* @_expires 定时时间计数值
* @_data 私有数据
**************************************************************************/
#define DEFINE_TIMER(_name, _function, _expires, _data) \
struct timer_list _name = \
TIMER_INITIALIZER(_function, _expires, _data)
/**********************************
*功能:初始化定时器
*参数:
* @timer 定时器指针
*********************************/
init_timer(struct timer_list * timer)
/* 开启定时器 */
void add_timer(struct timer_list *timer)
/* 关闭定时器 */
int del_timer(struct timer_list *timer)
/************************************************************************
*功能:修改定时器定时时间
*参数:
* @timer struct timer_list *
* @expires 定时时间值
***********************************************************************/
int mod_timer(struct timer_list *timer, unsigned long expires)
【三】、按键消抖
采用定时器延时消抖
延迟机制:
1. 定时器
2. 中断底半部
软中断
tasklet
工作队列
3. 内核延时函数
void ndelay(unsigned long x)
mdelay(n)
4. 内核睡眠函数
void msleep(unsigned int msecs);
unsigned long msleep_interruptible(unsigned int msecs);
void ssleep(unsigned int seconds)
【四】、IIC总线
platform IIC SPI
dev platform_device i2c_client spi_device
drv platform_driver i2c_driver spi_driver
bus bus_type
电气特性:
SDA:数据线
SCK:时钟线
同步 半双工 串行
时序(时序图):
起始信号:时钟线高电平期间,数据线产生负跳变
结束信号:时钟线高电平期间,数据线产生正跳变
协议:
a). signal read:
| start signal | Device address[6:0],W[7] | slave ACK | register address[7:0] | slave ACK | --->>>
SR | Device address[6:0],R[7] | slave ACK | Data[7:0] | MACK | SP |
b). signal write:
| start signal | Device address[6:0],W[7] | slave ACK | register address[7:0] | slave ACK | --->>>
Data[7:0] | slave ACK | SP |
W: write = 0
R: read = 1
SR:repeated start condition
SP:stop condition
IIC驱动:
设备驱动层:
需要驱动工程师完成的,向应用层提供操作的接口(fops),向下层操作硬件
核心层: i2c-core.c
内核提供好的,提供设备驱动和总线驱动注册和注销的方法,还提供设备驱动和总线驱动的匹配方式
总线驱动层:i2c-s3c2410.c
内核提供好的,按照用户传递的数据和操作时序操作硬件
IIC设备驱动:<linux/i2c.h>
struct i2c_driver {
int (*probe)(struct i2c_client *, const struct i2c_device_id *);
int (*remove)(struct i2c_client *);
struct device_driver driver;
const struct i2c_device_id *id_table; //i2c idtable表
};
struct i2c_device_id {
char name[I2C_NAME_SIZE]; //IIC设备名
kernel_ulong_t driver_data; //私有数据
};
/********************************************************
*功能:注册i2c驱动
*参数:
* @driver struct i2c_driver *
*******************************************************/
#define i2c_add_driver(driver) \
i2c_register_driver(THIS_MODULE, driver)
void i2c_del_driver(struct i2c_driver *driver);
i2c设备驱动注册过程:
i2c_register_driver
--->>> driver_register(&driver->driver);
--->>> bus_add_driver(drv);
--->>> driver_attach(drv);
--->>> bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
--->>> __driver_attach
--->>> driver_match_device(drv, dev)
--->>> drv->bus->match ? drv->bus->match(dev, drv) : 1
static int i2c_device_match(struct device *dev, struct device_driver *drv)
{
struct i2c_client *client = i2c_verify_client(dev);
struct i2c_driver *driver;
if (!client)
return 0;
/* 设备数匹配 */
if (of_driver_match_device(dev, drv))
return 1;
/* Then ACPI style match */
if (acpi_driver_match_device(dev, drv))
return 1;
driver = to_i2c_driver(drv);
/* idtable表匹配 */
if (driver->id_table)
return i2c_match_id(driver->id_table, client) != NULL;
return 0;
}
设备数匹配 > idtable表匹配
struct i2c_msg {
__u16 addr; /* slave address */
__u16 flags; /* I2C_M_RD 读数据 0 写数据 */
__u16 len; /* msg length */
__u8 *buf; /* pointer to msg data */
};
/***********************************************************************************
*功能:i2c总线数据传输
*参数:
* @adap struct i2c_adapter *
* @msgs 消息结构体
* @num 消息结构体个数
**********************************************************************************/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
数据收发函数的封装:
[1]. 发送数据
int write_reg(struct i2c_client *client,u8 reg,u8 val)
{
int ret = 0;
u8 buf[] = {reg,val};
struct i2c_msg msgs[] = {
[0] = {
.addr = client->addr,
.flags= 0,
.len = 2,
.buf = buf,
},
};
ret = i2c_transfer(client->adapter,msgs,ARRAY_SIZE(msgs));
if(ret < 0){
return ret;
}
return 0;
}
[2]. 接受数据
int read_reg(struct i2c_client *client,u8 reg)
{
int ret = 0;
u8 val = 0;
u8 buf[] = {reg};
struct i2c_msg msgs[] = {
[0] = {
.addr = client->addr,
.flags= 0,
.len = 1,
.buf = buf,
},
[1] = {
.addr = client->addr,
.flags= I2C_M_RD,
.len = 1,
.buf = &val,
},
};
ret = i2c_transfer(client->adapter,msgs,ARRAY_SIZE(msgs));
if(ret < 0){
return ret;
}
return (unsigned int)val;
}
linux中断的更多相关文章
- linux中断与异常
看了<深入理解linux内核>的中断与异常,简单总结了下,如果有错误,望指正! 一 什么是中断和异常 异常又叫同步中断,是当指令执行时由cpu控制单元产生的,之所以称之为异常,是因为只有在 ...
- 13.linux中断处理程序
linux中断处理程序 一.中断处理流程 在linux内核代码中进入entry-armv.S目录: linux统一的入口:__irq svc. 进入了统一的入口之后,程序跳到irq_handler标号 ...
- Linux中断(interrupt)子系统
Linux中断(interrupt)子系统之一:中断系统基本原理 Linux中断(interrupt)子系统之二:arch相关的硬件封装层 Linux中断(interrupt)子系统之三:中断流控处理 ...
- 驱动: 中断【1】linux中断流程
通常情况下,当一个给定的中断处理程序正在执行时,所有其他的中断都是打开的,所以这些不同中断线上的其他中断都能被处理,但当前中断总是被禁止的. 将中断处理切为两个部分或两半.中断处理程序上半部(top ...
- Linux中断子系统:级联中断控制器驱动
Linux中断子系统 Linux中断子系统是个很大的话题,如下面的思维导图所示,包含硬件.驱动.中断上半部.中断下半部等等.本文着眼于中断控制器(PIC),特别是级联中断控制器驱动部分,对驱动的设计和 ...
- Linux中断管理
CPU和外设之间的交互,或CPU通过轮询机制查询,或外设通过中断机制主动上报. 对大部分外设中断比轮询效率高,但比如网卡驱动采取轮询比中断效率高. 这里重点关注ARM+Linux组合下中断管理,从底层 ...
- Linux中断管理 (1)Linux中断管理机制
目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...
- Linux中断管理 (2)软中断和tasklet
目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...
- Linux中断管理 (3)workqueue工作队列
目录: <Linux中断管理> <Linux中断管理 (1)Linux中断管理机制> <Linux中断管理 (2)软中断和tasklet> <Linux中断管 ...
- 全志A33 lichee 开发板 Linux中断编程原理说明
开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 本节实验目标实现按键触发中断 ...
随机推荐
- “百度杯”CTF比赛 九月场 YeserCMS
打开题目 进入后是一个cms,但肯定的是这个cms不叫yesercms 于是我们开始随便翻翻,寻找信息,后台我也看了除了一个登陆界面,就没有其他的提示信息. 最后在文档下载的评论栏里发现,这个cms的 ...
- IllegalArgumentException: Unmatched braces in the pattern.
IllegalArgumentException: Unmatched braces in the pattern. 非法参数异常. 不匹配的 吊带 在 样品 中. === 没有管. 项目一直卡在d ...
- python简单实现队列和栈push、pop操作
栈: # -*- coding: utf-8 -*- #定义序列 lst=[] def pop(): if(len(lst)==0): print"栈为空","无法出栈& ...
- spring boot学习总结(一)-- 基础入门 Hello,spring boot!
写在最前 SpringBoot是伴随着Spring4.0诞生的: 从字面理解,Boot是引导的意思,因此SpringBoot帮助开发者快速搭建Spring框架: SpringBoot帮助开发者快速启动 ...
- centos上安装elasticsearch 5.5.1 遇到的各种坑
mac玩得好好滴,一次性启动成功,结果在centos上安装时,遇坑无数,记录一下: 一.只能localhost访问的问题修改 conf\elasticsearch.yml network.host: ...
- request.getRequestDispatcher("").forward()中文乱码
即使jsp页面的编码已设为“UTF-8”,有中文的地方还是会出现乱码,但是用response.sendRedirect不会出现此问题. 解决方案一: 不使用PrintWriter out=respon ...
- sqlserver 2012 IDE中 Windows身份验证连接服务器报错 ,Login failed for user 'xxx\Administrator'. 原因: 找不到与提供的名称匹配的登录名。
问题描述: 本地装了两个实例,一个是SQLEXPRESS,可以正常操作.但是另一个开发常用的实例MSSQLSERVER却连Windows身份验证都报错,报的错误也是很奇葩,怎么会找不到Administ ...
- JS删除String里某个字符的方法
关于JS删除String里的字符的方法,一般使用replace()方法.但是这个方法只会删除一次,如果需要将string里的所以字符都删除就要用到正则. 1 2 3 4 var str = " ...
- TCP握手与socket通信细节
http://www.jianshu.com/u/5qrPPM http://www.jianshu.com/p/f86512230707
- ARM 编程平台+coresight
http://www.keil.com/product/ DS-5:http://www.cnblogs.com/njseu/p/6023081.html http://www.arm.com/pro ...