armlinux内核中ARM中断实现详解.
- 格式:doc
- 大小:82.50 KB
- 文档页数:15
Linux内核中ARM中断实现详解request_irq()、free_irq()Request_irq()调用的定义:int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname,void *dev_id);irq 是要申请的硬件中断号。
具体应是何值参见博文blog.csdn/songqqnew/article/details/6791602。
handler 是向系统注册的中断处理函数,是一个回调函数,中断发生时,系统调用这个函数,dev_id 参数将被传递给它。
即是中断服务子程序,用staticirqreturn_tadc_interrupt(intirq,void*dev_id);定义或声明。
Irqflags 是中断处理的一些属性。
若设置了IRQF_DISABLED (老版本中的SA_INTERRUPT,本版zhon 已经不支持了),则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了IRQF_SHARED (老版本中的SA_SHIRQ),则表示多个设备共享中断,若设置了IRQF_SAMPLE_RANDOM(老版本中的SA_SAMPLE_RANDOM),表示对系统熵有贡献,对系统获取随机数有好处。
(这几个flag 是可以通过或的方式同时使用的)devname 设置中断名称,在cat /proc/interrupts 中可以看到此名称。
为注册的驱动程序的设备名。
dev_id 在中断共享时会用到。
一般设置为这个设备的device 结构本身或者NULL。
中断处理程序可以用dev_id 找到相应的控制这个中断的设备,或者用irq2dev_map 找到中断对应的设备。
arm中断实验的实验报告ARM中断实验的实验报告引言:ARM中断是一种常用的处理器功能,它可以在特定条件下中断当前的程序执行,转而执行指定的中断服务程序。
本次实验旨在通过ARM中断实验,深入了解中断的原理和应用。
一、实验背景ARM中断是ARM处理器中的一种重要功能,它可以在特定条件下中断当前的程序执行,转而执行指定的中断服务程序。
中断可以分为外部中断和内部中断两种类型。
外部中断是指来自外部设备的中断请求,例如外部设备的输入信号变化;内部中断是指来自处理器内部的中断请求,例如算术溢出、指令错误等。
二、实验目的1. 了解中断的概念和原理;2. 掌握ARM中断的实现方法;3. 学习如何编写中断服务程序。
三、实验步骤1. 准备实验环境:搭建ARM开发板,连接必要的外设;2. 配置中断控制器:根据实验需求,配置中断控制器的相关寄存器,使其能够正确响应中断请求;3. 编写中断服务程序:根据实验需求,编写中断服务程序,实现中断处理的相关功能;4. 运行实验程序:将编写好的程序下载到ARM开发板上,运行程序,观察中断的触发和响应情况;5. 实验结果分析:根据实验结果,分析中断的触发条件、中断服务程序的执行情况等。
四、实验结果与分析通过实验,我们成功实现了ARM中断的功能。
在实验过程中,我们配置了外部设备的中断引脚,当引脚状态发生变化时,中断控制器会产生中断请求,处理器则会立即中断当前的程序执行,转而执行中断服务程序。
在中断服务程序中,我们可以完成一些特定的操作,例如读取外设数据、更新系统状态等。
实验结果表明,中断服务程序能够正确地响应中断请求,并完成相应的操作。
五、实验总结本次实验通过ARM中断的实验,我们深入了解了中断的原理和应用。
中断是一种重要的处理器功能,它可以在特定条件下中断当前的程序执行,转而执行指定的中断服务程序。
掌握了中断的实现方法和编写中断服务程序的技巧,我们可以在实际应用中更好地利用中断功能,提高系统的响应速度和稳定性。
Linux中断处理流程1. 中断处理流程 当中断发⽣时,Linux系统会跳转到asm_do_IRQ()函数(所有中断程序的总⼊⼝函数),并且把中断号irq传进来。
根据中断号,找到中断号对应的irq_desc结构(irq_desc结构为内核中中断的描述结构,内核中有⼀个irq_desc结构的数组irq_desc_ptrs[NR_IRQS]),然后调⽤irq_desc中的handle_irq函数,即中断⼊⼝函数。
我们编写中断的驱动,即填充并注册irq_desc结构。
2. 中断处理数据结构:irq_desc Linux内核将所有的中断统⼀编号,使⽤⼀个irq_desc[NR_IRQS]的结构体数组来描述这些中断:每个数组项对应着⼀个中断源(也可能是⼀组中断源),记录中断⼊⼝函数、中断标记,并提供了中断的底层硬件访问函数(中断清除、屏蔽、使能)。
另外通过这个结构体数组项中的action,能够找到⽤户注册的中断处理函数。
struct irq_desc {unsigned int irq;irq_flow_handler_t handle_irq;struct irq_chip *chip;struct msi_desc *msi_desc;void *handler_data;void *chip_data;struct irqaction *action; /* IRQ action list */unsigned int status; /* IRQ status */unsigned int depth; /* nested irq disables */unsigned int wake_depth; /* nested wake enables */unsigned int irq_count; /* For detecting broken IRQs */unsigned long last_unhandled; /* Aging timer for unhandled count */unsigned int irqs_unhandled;spinlock_t lock;const char *name;} ____cacheline_internodealigned_in_smp;(1)handle_irq:中断的⼊⼝函数(2)chip:包含这个中断的清除、屏蔽、使能等底层函数struct irq_chip {const char *name;unsigned int (*startup)(unsigned int irq);void (*shutdown)(unsigned int irq);void (*enable)(unsigned int irq);void (*disable)(unsigned int irq);void (*ack)(unsigned int irq);void (*mask)(unsigned int irq);void (*mask_ack)(unsigned int irq);void (*unmask)(unsigned int irq);void (*eoi)(unsigned int irq);void (*end)(unsigned int irq);void (*set_affinity)(unsigned int irq,const struct cpumask *dest);int (*retrigger)(unsigned int irq);int (*set_type)(unsigned int irq, unsigned int flow_type);int (*set_wake)(unsigned int irq, unsigned int on);/* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHODvoid (*release)(unsigned int irq, void *dev_id);#endif/** For compatibility, ->typename is copied into ->name.* Will disappear.*/const char *typename;};(3)action:记录⽤户注册的中断处理函数、中断标志等内容struct irqaction {irq_handler_t handler;unsigned long flags;cpumask_t mask;const char *name;void *dev_id;struct irqaction *next;int irq;struct proc_dir_entry *dir;};3. 中断处理流程总结(1)发⽣中断后,CPU执⾏异常向量vector_irq的代码;(2)在vector_irq⾥⾯,最终会调⽤中断处理C程序总⼊⼝函数asm_do_IRQ();(3)asm_do_IRQ()根据中断号调⽤irq_des[NR_IRQS]数组中的对应数组项中的handle_irq();(4)handle_irq()会使⽤chip的成员函数来设置硬件,例如清除中断,禁⽌中断,重新开启中断等;(5)handle_irq逐个调⽤⽤户在action链表中注册的处理函数。
cm4中断压栈
CM4(通常指的是ARM Cortex-M4微控制器)的中断处理机制是其核心功能之一,它允许微控制器在特定事件发生时暂停当前的任务,转而执行与中断相关的代码,处理完中断后再返回到原任务继续执行。
在这个过程中,中断压栈是一个非常重要的步骤,它确保了在中断处理过程中,当前的执行环境(如寄存器状态、程序计数器等)被正确保存,以便在中断处理完成后能够恢复到原来的状态。
当中断发生时,Cortex-M4会执行一系列的操作来响应这个中断。
首先,它会保存当前执行环境的上下文信息,这通常包括程序计数器(PC)、堆栈指针(SP)、链接寄存器(LR)以及一些特定的寄存器值。
这些信息被保存到一个预先定义好的中断堆栈中,这个过程就是中断压栈。
中断压栈的具体实现通常依赖于微控制器的硬件架构和编程环境。
在Cortex-M4中,中断压栈的过程是由硬件自动完成的,而不需要软件干预。
当微控制器接收到中断请求时,硬件会自动将当前的寄存器状态保存到堆栈中,并将程序计数器设置为中断处理程序(中断向量表)的入口地址。
中断处理程序通常是一个特定的函数,它负责处理中断事件。
在这个函数中,程序可以执行与中断相关的操作,如读取中断状态寄存器、清除中断标志、执行必要的任务等。
当中断处理完成后,程序需要恢复被中断的上下文,这通常是通过从堆栈中恢复寄存器状态来实现的。
这个过程被称为中断出栈。
总的来说,中断压栈是Cortex-M4微控制器中断处理机制的一个重要环节,它确保了中断处理过程中程序状态的正确保存和恢复。
这对于实现实时、可靠的嵌入式系统至关重要。
linux中断处理流程Linux中断处理流程Linux中断处理是操作系统中的一个重要组成部分,用于响应硬件设备的事件。
在Linux中,中断可以是外部中断,如硬件设备发送的中断信号,也可以是内部中断,如软件产生的异常或系统调用。
中断处理的目的是及时响应硬件设备的事件,并采取相应的措施来处理这些事件。
一、中断的触发中断是由硬件设备发送的一个信号,用于通知操作系统某个事件的发生。
这个信号可以是一个电平的变化,一个特定的数据包,或者一个指定的硬件寄存器的变化。
当硬件设备检测到某个事件发生时,它会向处理器发送一个中断信号,处理器会立即停止当前正在执行的任务,保存当前的上下文,并跳转到中断处理程序的入口点。
二、中断处理程序的执行中断处理程序是一个特殊的函数,负责处理中断事件。
当中断发生时,处理器会跳转到中断处理程序的入口点,并执行相应的代码。
中断处理程序的执行过程可以分为以下几个步骤:1. 保存上下文:在执行中断处理程序之前,处理器需要保存当前任务的上下文,包括程序计数器、寄存器和堆栈指针等。
这样可以确保在中断处理程序执行完成后,能够正确地返回到原来的任务。
2. 中断处理程序的执行:一旦保存了上下文,处理器就会执行中断处理程序的代码。
中断处理程序根据中断的类型,执行相应的操作。
例如,对于外部中断,中断处理程序可能需要读取硬件设备的状态,处理数据包或执行特定的操作。
对于内部中断,中断处理程序可能需要处理异常或系统调用。
3. 中断处理程序的结束:当中断处理程序执行完成后,处理器会恢复之前保存的上下文,并将控制权返回给原来的任务。
这样原来的任务就可以继续执行,而不会受到中断的影响。
三、中断处理的优先级在Linux中,中断处理有不同的优先级。
这是为了确保对于紧急事件的及时处理。
中断的优先级由硬件设备决定,通常是通过一个优先级编码器来实现的。
当多个中断同时发生时,处理器会按照优先级的顺序来处理中断。
高优先级的中断会立即被处理,而低优先级的中断则会被推迟到稍后处理。
第30卷 第2期2007年4月电子器件Ch inese Jou r nal Of Elect ro n DevicesVol.30 No.2Ap r.2007Implementatio n o f ARM 2μC Linux Interrupt T ech nique B ased o n the SEP32031Pr o cesso r 3ZOU Zhi 2f en g ,W A N G X ue 2x i an g ,Z H A N G Yu(N ati onal AS IC S ystem Engi neeri ng Center ,S out heas t Uni versi t y ,Nanj i n g 210096,Chi na)Abstract :Inter ruption techni que i s very i mport ant in an e mbedded syst em.Wi t h t hi s techni que ,processor and perip hery equipment s ca n work toget her and CPU can work more efficiency.It analyzes t he i nt errupt 2t ec hni que wit hi n t he a rm 2μClinux syst em f rom hardware to soft wa re ,and t he n ,i nt roduces t he inter rupt vector t able based on t he SEP3203p rocessor particul arl y .The i nit ializat io n of t he i nt errupt vector and t he net device ’s ISR regist er a re discussed.K ey w or ds :inter rupt ;ISR ;A RM 2μClinux EEACC :1265F基于SEP32031处理器的ARM 2μCl inux 中断处理技术的研究与实现3邹志烽,王学香,张 宇(东南大学国家专用集成电路系统工程技术中心,南京210096)收稿日期62623基金项目基于国内第一个RM 大学计划授权,S 33是由东南大学国家专用集成电路系统工程技术研究中心自主设计的63位R IS 微控制器作者简介邹志烽(2),女,硕士研究生,主要研究方向为嵌入式系统软件,z zf @摘 要:在现代嵌入式操作系统中,中断处理技术是一项重要的技术.通过中断技术,使得处理器能够和外设并行地工作,提高了CPU 的执行效率.首先结合了软件和硬件两个方面分析a rm 2μclinux 的中断处理技术,然后基于S EP3203微处理器介绍了中断向量表的软件实现,最后通过网络设备中断例程的注册阐述了如何实现用户中断例程的安装.关键词:中断;设备中断例程注册;ARM 2μClinux中图分类号:TP334.7 文献标识码:A 文章编号:100529490(2007)022******* 随着信息科技的不断发展,嵌入式系统(Em 2bedded Syst em s )已经遍及工业控制、消费类电子产品、通信系统、网络系统等各类产品市场.产品功能集成的越多,相应的外围控制模块与C PU 的交互也就越频繁.CPU 与外设的交互有多种方式,在现代嵌入式系统中,为了实现处理器与外设能够并行工作,常采用中断处理技术来实现CPU 与外设的交互,这可以在很大程度上提高CPU 的执行效率[2].本文研究了一种基于SEP3203处理器的μClinux 中断处理实现方案,从硬件和软件的角度介绍了中断向量表的实现以及μCLinux 下网络设备的中断处理例程的安装.1 ARM 2μClin ux 简介目前ARM 处理器已经风靡全球,32位的R ISC 嵌入式处理器已经开始成为高中端嵌入式应用和设计的主流.ARM 微控制器的低功耗、高性价比,也向传统的8位/16位微控制器提出了挑战.AR M7TDMI 是一款经典的通用32位微控制器.S EP3203是内嵌A RM7TDM I 核的16/32位R ISC 微控制器,面向低成本手持设备和其它通用嵌入式设备.μCli nux 是Micro 2Cont roll er 2Li nux 的缩写,即“针对微控制领域而设计的Linux 系统”[3].它的优势在于:开源,免费,稳定及强大的网络功能.主要应8:20000:A E P 021/2C :1979o u ho tmail.co m.用于工业控制等中低端电子产品中.与标准L INU X 的主要区别在于:不支持MMU 、默认的文件系统为只读紧凑的ro mf s 且重写了C 程序库.μClinux 对程序库采用静态连接的形式,这是由μCli nux 内存管理形式决定的.2 ARM 处理器的工作模式与异常中断操作系统需要在硬件设备上运行.A RM7TDMI 芯核提供了7种工作模式,而μClinux 操作系统只定义了用户态和内核态两种工作模式.结合μCli nux ,ARM 处理器通常只运行于3种工作模式:用户模式(U se r )、外部中断模式(IR Q )和特权模式(SVC ).Li nux 系统运行于用户态时,A RM 处理器通常工作在用户模式下.无论Linux 系统在何种工作模式下,当响应外部硬件中断时,ARM 处理器即进入IRQ 模式;特权模式是操作系统的保护模式,处理器响应软件中断时即进入特权模式.各种不同的处理器模式有对应于该模式的物理寄存器组[4].广义上来讲中断是指CPU 对系统发生的某个事件作出的一种反应:C PU 暂停正在执行的程序,保留现场后自动转去执行相应的处理程序,处理完该事件后再返回断点继续执行被"打断"的程序.在A RM 体系结构中,有两个术语对应此概念:异常和中断.虽然处理异常和处理中断的方式基本是相同的,但异常和中断是两个不同的概念.中断有向处理器主动申请的色彩.而异常主要是从处理器被动接受的角度出发,异常的产生必须考虑与处理器时钟的同步,异常往往被称为同步中断.在这个概念的基础上,A RM7TDMI 具有常规中断(IRQ )、快中断(F IQ )和软件中断(S of t ware Int errupt )三种中断方式.各种中断对应着一定的处理器模式.本文只涉及常规中断(IRQ).3 ARM 核下的多中断源处理方案A RM 核只有一个常规中断引脚nIRQ ,而在现代嵌入式系统中,中断源可能多达几十个.为此,在系统设计时,采用了二级中断的方式来实现中断控制.即由一个中断控制器来处理来自不同中断源的中断信号,经过判断后将中断信号送给A RM 内核的中断引脚.S EP3203内集成的中断控制器支持32个普通中断源,并给这32个普通中断源分配了固定的优先级每个中断源相应的可以配置为硬件中断或软件强制中断当硬件中断或软件强制中断产生的时候,都可以产生IRQ 中断信号[]基于硬件的架构,软件系统在实现中断向量的初始化时要构建2级向量表,如图1所示.第一级为AR M 核的异常向量表(普通向量表),第二级由具体CPU 中断控制器控制的异常向量表———通常第二级向量表是IRQ 异常处理向量表(特殊向量表).在μCLi nux 中,使用一组指针来指向中断例程的首地址.这些例程对应于设备的中断服务函数,同时由它负责在设备初始化时为每个设备驱动申请其请求的中断号.这组指针构成了由C PU 中断控制器控制的第二级异常向量表.图1 两级中断向量表4 SEP3203的μClinux 中断机制实现 如上所述,在SEP3203上的中断向量分为两级.对应于软件的具体实现,在start _kernel (st art _ker nel 是Linux 的C 语言的入口函数,此函数是系统的初始化主要函数)中,有关中断的初始化的有两个重要的函数:t rap_i nit ()和IRQ_init ().它们分别实现了第一级和第二级中断向量的初始化.本文接下来详细介绍这两个重要函数的具体实现.4.1 A RM 核的异常向量表初始化Trap_i ni t ()通过调用ent ry 2armv.S 中的(__t rap_i nit )函数段———由汇编语言编写的一段代码.用于在系统的0x00地址处安装AR M 的异常向量表,然后在0x200处建立各个异常(如i rq ,fi q ,data ,undefi ned 等)的分类处理路线,以建立起完整的异常处理表.中断发生时处理器的动作如下[8].①拷贝CPSR 到SPSR_<mode >;②设置适当的CPSR 位:i.改变处理器状态进入A RM 状态ii.改变处理器模式进入相应的异常模式iii.设置中断禁止位禁止相应中断③更新LR_<mode >④设置PC 到相应的异常向量具体代码实现如图无论在何种工作模式发生异常,系统都将切换到SV 模式下处理主要的响应流程为保护现场,556第2期邹志烽,王学香等:基于S EP3203处理器的AR M 2μCli nux 中断处理技术的研究与实现8..9.2.C .:图2 ARM 异常向量表的建立获得中断号(get _irqnr _a nd _ba se ),强制切换到(SV C )模式,再执行相应的处理.获得中断号的处理函数如下图3所示.图3 获得确定中断号其中IN TC_FNLS TS 是G arfield S EP3203的中断控制器中的最终状态寄存器,在linux 22.4.x \in 2cl ude\asm 2a rmnom mu\arch 2gfd\hardware.h 中定义.获得中断控制器中的最终状态寄存器的值后,采用移位判断法来确定最终的中断号.在DO _IRQ 中,根据中断号获得相应处理函数的入口指针地址,执行中断处理.中断处理完成后,进行一次调度,如果没有其它进程需要执行,则系统返回中断前的用户现场.4.2 IRQ 异常向量表的初始化ini t_IRQ ()函数实现了第二级中断向量表的初始化.此函数初始化了IRQ 的请求队列,为每一个中断号分配一个i rq_desc 结构,组成了一个数组.N R_IRQ S 代表中断数目.SEP3203的中断控制器提供有3个IRQ 中断源,因此在我们的系统中定义N R _IRQS 为3S 33的中断号和N R _IRQS 在22GFD q 中有定义.如下所图4所示.图4 中断数目和中断号的初始化4.3 中断请求队列的初始化st art _kernel 通过执行上面的两个函数来建立两级中断向量表.但第二级向量表是一堆空的数组结构,每个中断服务队列都是空的[5].虽然从中断源的硬件以及中断控制器的角度来看,似乎已经得到服务了,但是从逻辑角度、功能角度来看,他并没有执行到具体的中断服务例程,没有得到具体的中断服务.具体设备初始化时会将其中断处理程序通过reque st_i rq ()向系统"登记",调用set up _arm _i rq ()挂入某个中断请求队列,参数i rq 是中断请求号,对应于中断控制器为每个中断源配置的中断号[5].中断处理例程结束时通过f ree_irq 来释放中断.5 中断机制在网络设备驱动中的应用 我们采用了R TL8019网络控制器,接在S EP3203处理器的IN T14中断引脚,根据硬件Da 2ta Sheet ,其中断号为0x0f.本文只注册了一个网卡et h0,在网卡的初始化函数ne_probe ()中注册了网络设备的基地址和中断号,并调用系统提供的系统调用函数request _i rq ()来注册中断处理例程.如下图5,图6所示.图5 网卡设备地址和中断号的注册图6 网卡中断处理例程的注册 通过上面的网卡中断例程的注册,当物理网络设备接收到新数据时,它将发送一个硬件中断请求给x 系统[6]系统在侦察到有物理设备发出中断请求,由硬件自动将设为x 8,通过级中断向量表调用网卡的中断处理函数_来处656电 子 器 件第30卷82 2.EP 20asm a rmnom mu/arch /i r s.h linu .PC 012ei interrupt理中断请求.网络中断的处理流程如下图7所示:图7 网络中断的处理流程5 结束语本文结合软件和硬件提出了基于S EP3203处理器的ARM 2μClinux 中断处理机制,并着重分析了2级中断向量的初始化的具体实现方法.最后通过具体的网络设备的中断处理过程,实现了此中断处理机制的应用.目前此机制已应用于油库数据采集终端系统项目中,实践证明此方案稳定可靠,网络的处理速度可达2.5~3.5Mbps ,满足项目要求,也可为其他嵌入式系统的设计提供一定参考.参考文献:[1] OL AF KIR CH &T ERR Y DAWSON.Linu x Net wor k Ad 2minis trato r ’s Guide (Version 2)[S].O ’RIL L Y.[2] 蒋静,徐志伟.操作系统原理.技术编程[M ].机械工业出版社2004.1.[3] 周立功,陈明计,陈渝.A RM 嵌入式lin ux 系统构建与驱动开发范例[M].北京航空航天大学出版社.2006.1.[4] 杜春雷.ARM 体系结构与编程[M ].清华大学出版社,2003.[5] 毛德操,胡希明.Li nux 内核源代码情景分析(上册)[M ],杭州:浙江大学出版社出版,2001.[6] 潘刚.Li nux 网络设备分析[J ].微电子科学与计算机,2006年6期.[7] AL ESSANDRO RUBINI &J ONA THAN COR B E T.魏永明骆刚姜君译.L INUX 设备驱动程序(第二版)[M ],北京:中国电力出版社,2002.346~393.[8] 费浙平.基于A RM 的嵌入式系统程序开发要点(四)———异常处理机制的设计[J ].单片机与嵌入式系统应用.2003,(11):82285.[9] 东南大学国家专用集成电路系统工程技术中心东芯IVSEP3203F50用户手册[S]2006.6.(上接第653页){DWORD fJ umping ;}USB_BOOT_AC K;在传输中,这种类型的数据还起到请求数据的作用,此时,数据包是由设备端发送至主机的,定义为Data Reque st.③Dat a :此时后面的数据块为传输数据块,它是由主机发送给HPC 的.数据块的前四个字节为USB_BL OC K _H EADER ,后面为真正的传输数据,如下:USB_BL OC K _HEADERDataUSB_BL OC K _HEAD ER 的结构如下:t ype def str uct tagUSB_BLOC K _HEADER {DWORD uBlockNum ;}USB_BLOC K_H EADER ;总结如下:①设备端发送Boot Request 请求开始传输数据.②主机接受到请求后向设备端发送Boot AC K ,示意设备端数据传输开始.③设备端接受到主机回应后发送数据请求包Dat a Request ,在包内注明请求的包的ID.④主机接受到设备端的Dat a Request 后发送相应的数据包给设备.⑤重复步骤3、4直至数据发送完成.镜像在内存中存放的地址需要在软件中明确定义下载完成后,把X 55的指令指针寄存器的值定位到镜像存放的起始地址即可运行操作系统进行调试.该下载方案将速度提高到760kbyt e/s ,可以满足li nux 开发平台上传输操作系统内核镜像和文件系统镜像的需求.5 小结本文分析了U SB 设备的结构框架,在功能单元层上定义了简单的数据传输协议,并配置了PXA255的UDC 模块完成了boot loade r 下宿主机到目标机的数据传输.该下载方案已经应用于一款PMC 的开发中,传输速度达到了760kbyte/s ,方便了该产品的开发调试,对相关的嵌入式系统开发具有一定的参考意义.参考文献:[1] 毛德操胡希明.嵌入式系统-采用公开源代码和St rong 2ARM/XScal e 处理器[M ].Oct .2003.浙江大学出版社.[2] Vi ncent Sanders.Boot ing AR M Li nux [J ].May.2004.[3] 严菊明.基于A RM 嵌入式系统的通用boot loader 的设计与实现[D ].Mar.2005.[4] C o m p aq Int el Micro s oft N EC.U ni versal S erial Bus S p ecifica 2t ion [S].Sep.1998.[5] 马伟.计算机U S B 系统原理及其主/从机设计[M ].Sep.2003.北京航空航天出版社.[6] Int el C o rpo rat ion.Int el PXA255Processor Developer ’s Manu 2[S]M 3[] I I X 55D G [S]M 3756第2期邹志烽,王学香等:基于S EP3203处理器的AR M 2μCli nux 中断处理技术的研究与实现8.P A2a l .a r.200.7nt el Co rpo ra t ion.nte l P A 2Proce s so r e si gn uide .ar.200.。
ARM中断程序的原理和实现引言:中断是计算机系统中一种特殊的事件,它可以打断当前正在执行的程序,并执行一段特定的代码。
在ARM架构中,中断主要由两部分组成:中断处理程序和中断控制器。
本文将介绍ARM中断程序的原理和实现,包括中断的基本概念、中断的分类、中断的处理过程以及中断控制器的实现方式。
一、中断的基本概念中断可以看作是外部设备向CPU发送一个请求的一种方法。
当外部设备发生一些特定的事件时(如按键、时钟周期等),它会产生一个中断请求信号,通知CPU去处理相应的事件。
CPU收到中断请求信号后,会暂停当前的任务,保存现场并跳转到中断处理程序来处理中断。
二、中断的分类1.外部中断:外部中断是由外设产生的中断信号,如GPIO、串口等。
当外设产生中断请求信号时,中断控制器会将信号传递给CPU,触发相应的中断处理程序。
2.软件中断:软件中断是由软件主动触发的中断,通过软件指令可以触发中断控制器发送中断请求信号给CPU。
软件中断可以用于实现系统调用、任务切换等功能。
三、中断的处理过程1.中断请求:外部设备发生特定事件,产生中断请求信号。
中断请求信号会被中断控制器接收并传递给CPU。
2.中断响应:CPU收到中断请求信号后,会立即响应中断,并执行中断处理程序。
在响应中断之前,CPU需要保存当前的现场(包括程序计数器PC、寄存器等)。
3.中断处理:CPU跳转到中断处理程序的入口地址,开始执行中断处理程序。
中断处理程序通常用来处理中断事件,并根据需要进行中断服务例程的调用。
4.中断返回:中断处理程序执行完毕后,CPU会根据中断处理程序的返回指令返回到原来的程序中,并恢复之前保存的现场。
同时,中断控制器会清除中断请求信号,使其能够接受新的中断请求。
四、中断控制器的实现方式ARM架构中,中断控制器常用的实现方式包括级联式中断控制器和向量式中断控制器。
1.级联式中断控制器:级联式中断控制器是一种层级结构的中断控制器。
它包含多个级别的中断控制器,每个级别对应一组中断请求。
Linux设备树语法详解-中断【转】Linux内核从3.x开始引⼊设备树的概念,⽤于实现驱动代码与设备信息相分离。
在设备树出现以前,所有关于设备的具体信息都要写在驱动⾥,⼀旦外围设备变化,驱动代码就要重写。
引⼊了设备树之后,驱动代码只负责处理驱动的逻辑,⽽关于设备的具体信息存放到设备树⽂件中,这样,如果只是硬件接⼝信息的变化⽽没有驱动逻辑的变化,驱动开发者只需要修改设备树⽂件信息,不需要改写驱动代码。
⽐如在ARM Linux内,⼀个.dts(device tree source)⽂件对应⼀个ARM的machine,⼀般放置在内核的"arch/arm/boot/dts/"⽬录内,⽐如exynos4412参考板的板级设备树⽂件就是"arch/arm/boot/dts/exynos4412-origen.dts"。
这个⽂件可以通过$make dtbs命令编译成⼆进制的.dtb ⽂件供内核驱动使⽤。
基于同样的软件分层设计的思想,由于⼀个SoC可能对应多个machine,如果每个machine的设备树都写成⼀个完全独⽴的.dts⽂件,那么势必相当⼀些.dts⽂件有重复的部分,为了解决这个问题,Linux设备树⽬录把⼀个SoC公⽤的部分或者多个machine共同的部分提炼为相应的.dtsi⽂件。
这样每个.dts就只有⾃⼰差异的部分,公有的部分只需要"include"相应的.dtsi⽂件, 这样就是整个设备树的管理更加有序。
我这⾥⽤`Linux4.8.5源码⾃带的dm9000⽹卡为例来分析设备树的使⽤和移植。
这个⽹卡的设备树节点信息在"Documentation/devicetree/bindings/net/davicom-dm9000.txt"有详细说明,其⽹卡驱动源码是"drivers/net/ethernet/davicom/dm9000.c"。
ARM7内核的中断屏蔽方法ARM7内核的中断屏蔽方法是通过设置与中断相关的寄存器来实现的。
ARM7内核提供了多个中断屏蔽寄存器,可以分别对不同的中断进行屏蔽设置。
下面将对常见的中断屏蔽方法进行详细介绍,包括通过CPSR寄存器和INTCON寄存器进行中断屏蔽。
1.CPSR寄存器屏蔽中断ARM7内核的CPSR寄存器(Current Program Status Register)是一个32位寄存器,其中的第7位(I-bit)用于控制中断的屏蔽。
当I位为1时,中断被屏蔽,当I位为0时,中断不被屏蔽。
通过修改CPSR寄存器的I位,可以实现对中断的屏蔽和开启。
中断屏蔽可以通过以下方式进行设置:(1)通过修改CPSR寄存器的I位:在特权级别下,可以直接修改CPSR寄存器的I位,来控制中断的屏蔽。
(2)通过使用屏蔽和解屏函数:ARM提供了两个专门的汇编指令用于修改CPSR寄存器的I位,分别是CPSID和CPSIE。
CPSID指令用于屏蔽中断,CPSIE指令用于解除中断的屏蔽。
2.INTCON寄存器屏蔽中断ARM7内核还提供了INTCON寄存器(Interrupt Control Register)用于屏蔽和控制外部中断的响应。
INTCON寄存器是一个32位的寄存器,每个位对应一个外部中断的屏蔽位。
当一些屏蔽位为1时,对应的中断将被屏蔽,当屏蔽位为0时,对应的中断不被屏蔽。
通过修改INTCON寄存器的屏蔽位,可以实现对外部中断的屏蔽和开启。
中断屏蔽可以通过以下方式进行设置:(1)直接修改INTCON寄存器的屏蔽位:在特权级别下,可以通过直接写入INTCON寄存器来修改外部中断的屏蔽位。
(2)使用特殊函数来修改INTCON寄存器的屏蔽位:ARM提供了特殊的函数用于修改INTCON寄存器的屏蔽位。
需要注意的是,中断屏蔽方法只能屏蔽外部中断,对于内部中断(如软中断、异常中断)无法进行屏蔽。
同时,ARM7内核的中断屏蔽方法也存在优先级的问题,当多个中断同时发生时,只会响应优先级最高的中断请求。
Cortex R5 中断使能例程一、引言Cortex R5 是一款高性能的嵌入式处理器,广泛应用于汽车电子、工业控制、通信设备等领域。
在实际应用中,中断是一种常见的处理器外部事件响应机制,有效的中断处理能力是保证系统稳定运行的关键。
本文将介绍如何在 Cortex R5 处理器上实现中断使能的例程。
通过本例程,读者可以了解如何编写具体的中断处理函数,并在实际应用中加以调用,从而达到处理外部事件的目的。
二、Cortex R5 中断基本原理Cortex R5 处理器支持多种中断类型,包括外部中断、定时器中断、软件中断等。
当外部事件发生时,处理器会根据中断优先级和中断向量表中的配置进行中断向量的跳转,从而执行相应的中断处理函数。
在实现中断处理时,需要对中断进行使能和屏蔽,并且需要编写具体的中断处理函数。
通过合理配置中断优先级和中断向量表,可以实现对不同中断的灵活控制和处理。
三、Cortex R5 中断使能例程实现步骤1. 中断向量表配置首先需要在代码中定义中断向量表,并将中断处理函数位置区域填充到相应的中断向量表项中。
中断向量表通常存放在处理器的指定位置区域处,具体配置方法可以参考处理器手册。
```ctypedef void (*isr_t)(void);isr_t isr_table[] = {isr_handler0, // 中断向量0对应的处理函数isr_handler1, // 中断向量1对应的处理函数// 其他中断处理函数};```2. 中断使能和屏蔽配置在 Cortex R5 处理器中,中断使能和屏蔽通常通过 CPACR 寄存器和NVIC 相关寄存器进行配置。
具体的配置方法需要设置相应的寄存器位,以使能或屏蔽特定的中断。
3. 中断处理函数编写针对不同的中断类型,需要编写特定的中断处理函数。
在中断发生时,处理器会根据中断向量表跳转到相应的中断处理函数进行处理。
编写中断处理函数时,需要注意保存和恢复上下文信息,以确保中断处理的正确性和可靠性。
基于ARM的嵌入式linux内核的裁剪与移植前言嵌入式系统一直是计算机行业中的领域之一。
在许多应用程序中,嵌入式系统越来越流行。
嵌入式系统通常使用嵌入式芯片,如ARM芯片,并且它们通常运行Linux内核。
Linux内核是一个开放源代码的操作系统内核。
在嵌入式领域,Linux 内核可以被用于实现各种应用程序。
本文将重点介绍如何基于ARM平台的嵌入式Linux内核进行裁剪和移植。
ARM平台ARM处理器是一种RISC(Reduced Instruction Set Computer)处理器。
这种类型的处理器可用于嵌入式系统开发,因为它具有较低的功耗和高效的性能。
ARM处理器有许多版本,其中包括ARMv6和ARMv7。
ARMv6通常用于嵌入式系统,而ARMv7则用于智能手机和平板电脑等高端设备。
Linux内核的裁剪在嵌入式系统中,Linux内核需要进行裁剪,以适应嵌入式设备的需求。
与桌面计算机相比,嵌入式系统拥有更少的资源,包括RAM、闪存和存储空间。
因此,在将Linux内核移植到嵌入式系统之前,必须将内核进行裁剪。
在裁剪内核之前,您必须确定哪些内核模块是必需的。
一些模块可以从内核中移除,以减少内核的大小。
通常,将不必要的模块和其他功能从内核中移除可以使内核变得更小并具有更好的性能。
另外,裁剪内核时应确保其他组件与内核兼容。
例如,在新内核中可能需要更改驱动程序或实用程序以适应修改后的内核。
裁剪内核可能是一项比较困难的工作,需要深刻了解Linux内核的各个方面,以确保正确地裁剪内核。
移植Linux内核到ARM移植内核是将Linux内核适应新硬件的过程。
在开始移植内核之前,您必须了解嵌入式设备的硬件架构以及所需的内核组件。
移植Linux内核到ARM可以分为以下步骤:1.选择合适的ARM平台和处理器并确定所需的内核选项。
2.下载最新的内核源代码。
3.配置内核选项,并使其适应新硬件。
4.使用交叉编译器编译内核。
ARMv8 中断处理流程一、中断请求中断请求是由硬件或软件发起的异常信号,用于打断正在执行的指令序列,将控制权转移到中断处理程序。
在ARMv8 架构中,中断请求由中断控制器(如GIC)产生,并通过中断信号线传递给处理器核。
二、中断响应当处理器核接收到中断请求时,它会根据优先级和其他因素决定是否响应中断。
如果处理器核决定响应中断,它将执行一系列指令来保存当前执行环境的状态,并跳转到中断处理程序的入口点。
在ARMv8 架构中,中断处理程序的入口点由中断向量表(IVT)或异常向量表(EVT)指定。
三、保存上下文在中断响应过程中,处理器核需要保存当前执行环境的状态,以便在中断处理程序执行完毕后能够恢复原来的执行环境。
在ARMv8 架构中,上下文保存的操作包括:1. 保存寄存器状态寄存器(xPSR)的值;2. 保存当前指令指针(PC)的值;3. 保存堆栈指针(SP)和链接寄存器(LR)的值;4. 如果当前执行环境是异常或中断处理程序,则保存相应的程序计数器(PC)和链接寄存器(LR)的值。
四、执行异常处理程序中断处理程序的入口点通常是指向异常向量表(EVT)或中断向量表(IVT)的一个跳转指令。
当处理器核跳转到这个地址时,它会执行该地址处的指令,即异常处理程序的入口点。
在执行异常处理程序时,处理器核会根据具体的异常类型和上下文信息执行相应的操作,如执行设备驱动程序或系统调用等。
五、恢复上下文在异常处理程序执行完毕后,处理器核需要恢复原来的执行环境。
在ARMv8 架构中,上下文恢复的操作包括:1. 恢复寄存器状态寄存器(xPSR)的值;2. 恢复当前指令指针(PC)的值;3. 恢复堆栈指针(SP)和链接寄存器(LR)的值;4. 如果当前执行环境是异常或中断处理程序,则恢复相应的程序计数器(PC)和链接寄存器(LR)的值。
六、中断返回在恢复上下文后,处理器核会执行一条返回指令,将控制权从异常处理程序返回给原来的执行环境。
linux-2.6.26内核中ARM中断实现详解(1)作者:刘洪涛,华清远见嵌入式学院金牌讲师,ARM ATC授权培训讲师。
看了一些网络上关于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~0x0000001CV=1 ~ 0xffff0000~0xffff00 1Carch/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_startstubs_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中也是这样定义的。
三、中断处理过程这一节将以S3C2410为例,描述linux-2.6.26内核中,从中断开始,中断是如何一步一步执行到我们注册函数的。
3.1 中断向量表 arch\arm\kernel\entry-armv.S__vectors_start:swi SYS_ERROR0b vector_und + stubs_offsetldr pc, .LCvswi + stubs_offsetb vector_pabt + stubs_offsetb vector_dabt + stubs_offsetb vector_addrexcptn + stubs_offsetb vector_irq + stubs_offsetb vector_fiq + stubs_offset.globl __vectors_end__vectors_end:中断发生后,跳转到b vector_irq + stubs_offset的位置执行。
注意现在的向量表的初始位置是0xffff0000。
3.2 中断跳转的入口位置 arch\arm\kernel\entry-armv.S.globl __stubs_start__stubs_start:/** Interrupt dispatcher*/vector_stub irq, IRQ_MODE, 4 @IRQ_MODE 在include\asm\ptrace.h中定义:0x12.long __irq_usr @ 0 (USR_26 / USR_32).long __irq_invalid @ 1 (FIQ_26 /FIQ_32).long __irq_invalid @ 2 (IRQ_26 / IRQ_32).long __irq_svc @ 3 (SVC_26 / SVC_32).long __irq_invalid @ 4.long __irq_invalid @ 5.long __irq_invalid @ 6.long __irq_invalid @ 7.long __irq_invalid @ 8.long __irq_invalid @ 9.long __irq_invalid @ a.long __irq_invalid @ b.long __irq_invalid @ c.long __irq_invalid @ d.long __irq_invalid @ e.long __irq_invalid @ f上面代码中vector_stub宏的定义为:.macro vector_stub, name, mode, correction=0.align 5vector_\name:.if \correctionsub lr, lr, #\correction.endif@@ Save r0, lr_<exception> (parent PC) and spsr_<exception>@ (parent CPSR)@stmia sp, {r0, lr} @ save r0, lrmrs lr, spsrstr lr, [sp, #8] @ save spsr@@ Prepare for SVC32 mode. IRQs remain disabled.@mrs r0, cpsreor r0, r0, #(\mode ^ SVC_MODE)msr spsr_cxsf, r0 @为后面进入svc模式做准备@@ the branch table must immediately follow this code@and lr, lr, #0x0f @进入中断前的mode的后4位@#define USR_MODE 0x00000010@#define FIQ_MODE 0x00000011@#define IRQ_MODE 0x00000012@#define SVC_MODE 0x00000013@#define ABT_MODE 0x00000017@#define UND_MODE 0x0000001b@#define SYSTEM_MODE 0x0000001fmov r0, spldr lr, [pc, lr, lsl #2] @如果进入中断前是usr,则取出PC+4*0的内容,即__irq_usr @如果进入中断前是svc,则取出PC+4*3的内容,即__irq_svcmovs pc, lr @ 当指令的目标寄存器是PC,且指令以S结束,则它会把@ spsr的值恢复给cpsr branch to handler in SVC mode.endm.globl __stubs_start__stubs_start:/** Interrupt dispatcher*/vector_stub irq, IRQ_MODE, 4.long __irq_usr @ 0 (USR_26 / USR_32).long __irq_invalid @ 1 (FIQ_26 / FIQ_32).long __irq_invalid @ 2 (IRQ_26 / IRQ_32).long __irq_svc @ 3 (SVC_26 / SVC_32)用“irq, IRQ_MODE, 4”代替宏vector_stub中的“name, mode, correction”,找到了我们中断处理的入口位置为vector_irq(宏里面的vector_\name)。