当前位置: 首页 > news >正文

linux-2.6.26内核中ARM中断实现详解(1)

看了一些网络上关于linux中断实现的文章,感觉有一些写的非常好,在这里首先感谢他们的无私付出,然后也想再补充自己对一些问题的理解。先从函数注册引出问题吧。

一、中断注册方法

在linux内核中用于申请中断的函数是request_irq(),函数原型在Kernel/irq/manage.c中定义:

int request_irq(unsigned int irq, irq_handler_t handler,
unsigned long irqflags, const char *devname, void *dev_id)

irq是要申请的硬件中断号。

handler是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id参数将被传递给它。

irqflags是中断处理的属性,若设置了IRQF_DISABLED (老版本中的SA_INTERRUPT,本版zhon已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。(这几个flag是可以通过或的方式同时使用的)

dev_id在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。

devname设置中断名称,在cat /proc/interrupts中可以看到此名称。

request_irq()返回0表示成功,返回-INVAL表示中断号无效或处理函数指针为NULL,返回-EBUSY表示中断已经被占用且不能共享。

关于中断注册的例子,大家可在内核中搜索下request_irq。

在编写驱动的过程中,比较容易产生疑惑的地方是:

1、中断向量表在什么位置?是如何建立的?
2、从中断开始,系统是怎样执行到我自己注册的函数的?
3、中断号是如何确定的?对于硬件上有子中断的中断号如何确定?
4、中断共享是怎么回事,dev_id的作用是?

本文以2.6.26内核和S3C2410处理器为例,为大家讲解这几个问题。

二、异常向量表的建立

在ARM V4及V4T以后的大部分处理器中,中断向量表的位置可以有两个位置:一个是0,另一个是0xffff0000。可以通过CP15协处理器c1寄存器中V位(bit[13])控制。V和中断向量表的对应关系如下:

V=0 ~ 0x00000000~0x0000001C
V=1 ~ 0xffff0000~0xffff001C

arch/arm/mm/proc-arm920.S中

.section ".text.init", #alloc, #execinstr
__arm920_setup:
…… orr r0, r0, #0x2100 @ ..1. ...1 ..11 ...1

//bit13=1 中断向量表基址为0xFFFF0000。R0的值将被付给CP15的C1.

在linux中,向量表建立的函数为:

init/main.c->start_kernel()->trap_init()

void __init trap_init(void)
{
unsigned long vectors = CONFIG_VECTORS_BASE;
……
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
....
}

在2.6.26内核中CONFIG_VECTORS_BASE最初是在各个平台的配置文件中设定的,如:

arch/arm/configs/s3c2410_defconfig中

CONFIG_VECTORS_BASE=0xffff0000

__vectors_end 至 __vectors_start之间为异常向量表。

位于arch/arm/kernel/entry-armv.S

.globl __vectors_start
__vectors_start:
swi SYS_ERROR0:
b vector_und + stubs_offset //复位异常:
ldr pc, .LCvswi + stubs_offset //未定义指令异常:
b vector_pabt + stubs_offset //软件中断异常:
b vector_dabt + stubs_offset //数据异常:
b vector_addrexcptn + stubs_offset //保留:
b vector_irq + stubs_offset //普通中断异常:
b vector_fiq + stubs_offset //快速中断异常:
.globl __vectors_end:
__vectors_end:

__stubs_end 至 __stubs_start之间是异常处理的位置。也位于文件arch/arm/kernel/entry-armv.S中。vector_und、vector_pabt、vector_irq、vector_fiq都在它们中间。

stubs_offset值如下:

.equ stubs_offset, __vectors_start + 0x200 - __stubs_start

stubs_offset是如何确定的呢?(引用网络上的一段比较详细的解释)

当汇编器看到B指令后会把要跳转的标签转化为相对于当前PC的偏移量(±32M)写入指令码。从上面的代码可以看到中断向量表和stubs都发生了代码搬移,所以如果中断向量表中仍然写成b vector_irq,那么实际执行的时候就无法跳转到搬移后的vector_irq处,因为指令码里写的是原来的偏移量,所以需要把指令码中的偏移量写成搬移后的。我们把搬移前的中断向量表中的irq入口地址记irq_PC,它在中断向量表的偏移量就是irq_PC-vectors_start, vector_irq在stubs中的偏移量是vector_irq-stubs_start,这两个偏移量在搬移前后是不变的。搬移后 vectors_start在0xffff0000处,而stubs_start在0xffff0200处,所以搬移后的vector_irq相对于中断 向量中的中断入口地址的偏移量就是,200+vector_irq在stubs中的偏移量再减去中断入口在向量表中的偏移量,即200+ vector_irq-stubs_start-irq_PC+vectors_start = (vector_irq-irq_PC) + vectors_start+200-stubs_start,对于括号内的值实际上就是中断向量表中写的vector_irq,减去irq_PC是由汇编器完成的,而后面的 vectors_start+200-stubs_start就应该是stubs_offset,实际上在entry-armv.S中也是这样定义的。(作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM ATC授权培训讲师。

相关文章:

  • 创建Azure scheduler完成日常任务
  • (TipsTricks)用客户端模板精简JavaScript代码
  • eclipse 生成发布的apk (signed zipalign过程)
  • 使用黄金分割比值计算斐波那契数列
  • 遭遇飞信“中奖” 之 图文全攻略
  • Swift 3 实现拍照功能
  • 我们欠了地球什么?
  • Iphone 消息通知(APNS)的3种方式 -- C# 和 nodejs
  • 创建Azure Function
  • 金旭亮博客之“桌面应用程序开发技术”资源主页
  • Javascript MV framework 对比
  • 基于LWUIT实现全局按键控制(快捷键)
  • azure 架构选择
  • Swift 3 点击屏幕任意位置隐藏键盘
  • 成为优秀的程序员真不简单
  • 【Amaple教程】5. 插件
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • docker容器内的网络抓包
  • Flannel解读
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • js继承的实现方法
  • PHP那些事儿
  • Rancher如何对接Ceph-RBD块存储
  • SpringBoot 实战 (三) | 配置文件详解
  • Spring框架之我见(三)——IOC、AOP
  • Spring思维导图,让Spring不再难懂(mvc篇)
  • Webpack 4x 之路 ( 四 )
  • webpack项目中使用grunt监听文件变动自动打包编译
  • Web标准制定过程
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 利用DataURL技术在网页上显示图片
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 每天10道Java面试题,跟我走,offer有!
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 在electron中实现跨域请求,无需更改服务器端设置
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​直流电和交流电有什么区别为什么这个时候又要变成直流电呢?交流转换到直流(整流器)直流变交流(逆变器)​
  • !!Dom4j 学习笔记
  • (+3)1.3敏捷宣言与敏捷过程的特点
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (Matlab)基于蝙蝠算法实现电力系统经济调度
  • (第61天)多租户架构(CDB/PDB)
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)spring boot建达集团公司平台 毕业设计 141538
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (一)Dubbo快速入门、介绍、使用
  • (一)Linux+Windows下安装ffmpeg
  • (转) ns2/nam与nam实现相关的文件
  • (转)Sql Server 保留几位小数的两种做法
  • .NET Core 2.1路线图
  • .net core Swagger 过滤部分Api
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径