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 本节实验目标实现按键触发中断 ...
随机推荐
- 循序渐进学.Net Core Web Api开发系列【2】:利用Swagger调试WebApi
系列目录 循序渐进学.Net Core Web Api开发系列目录 本系列涉及到的源码下载地址:https://github.com/seabluescn/Blog_WebApi 一.概述 既然前后端 ...
- asp.net core 中的SignalR与web前端进行实时通信
一.介绍 SignalR是.net 开源库,用于构建需要实时进行用户交互和数据更新的web应用,如在线聊天,游戏,天气等实时应用程序,且简化了构建实时应用的过程,包括服务端库和js端库,继承了数种常见 ...
- 网页图表Highcharts实践教程标之添加题副标题版权信息
网页图表Highcharts实践教程标之添加题副标题版权信息 Highcharts辅助元素 辅助元素图表的非必要元素,如标题.版权信息.标签.载入动态.它们不和图表数据发生关联,只是额外说明一些基本信 ...
- ArduinoYun教程之通过网络为Arduino Yun编程
ArduinoYun教程之通过网络为Arduino Yun编程 Arduino Yun的软件部分 通过第一章的介绍后读者就明白了Arduino Yun除了是一个类似其他Arduino的单片机之外,它的 ...
- 8.4 正睿暑期集训营 Day1
目录 2018.8.4 正睿暑期集训营 Day1 A 数对子 B 逆序对 C 盖房子 考试代码 A B C 2018.8.4 正睿暑期集训营 Day1 时间:4.5h(实际) 期望得分:30+50+3 ...
- zoj 3644 记忆化搜索
题目:给出一个有向图,从1到n,每个结点有个权值,每走一步,分值为结点权值的LCM,而且每一步的LCM都要有变化,问到达N的时候分值恰好为K的路径有多少条 记忆化搜索,虽然做过很多了,但是一直比较慢, ...
- 工具使用-----Jmeter-脚本的录制
//转载 http://www.cnblogs.com/fnng/archive/2011/08/20/2147082.html 以下是我自己录制的关于这篇文章的视频,有兴趣的可以下载哦 https ...
- AIM Tech Round 3 (Div. 1) B. Recover the String 构造
B. Recover the String 题目连接: http://www.codeforces.com/contest/708/problem/B Description For each str ...
- Java Web c3p0 pool池泄漏优化与日志分析
问题跟踪: 近期在整合SSH(spring.springmvc.hibernate)项目,提供给第三方服务.每当调用内存池达到上限之后,外界调用服务直接失败,提示[cannot open connec ...
- JVM7、8参数详解及优化
1. JVM堆内存划分 这两天看到下面这篇文章的图不错. 一图读懂JVM架构解析 1.1 JDK7及以前的版本 其中最上一层是Nursery内存,一个对象被创建以后首先被放到Nursery中的Eden ...