(原创)eCos驱动分析 之 ISR是如何与硬件中断联系起来的 ---转载文章

合集下载

外部中断实验原理

外部中断实验原理

外部中断实验原理一、实验原理外部中断是计算机科学中的一个重要概念,它允许程序在特定的事件发生时被唤醒或中断。

外部中断对于实现实时计算、多任务处理、异常处理等重要功能具有关键作用。

本实验旨在深入理解外部中断的工作原理,并通过实例分析来揭示其实际应用中的关键点。

二、详细内容分析1. 中断触发机制外部中断是由特定事件触发的,例如输入输出操作完成、定时器溢出、硬件错误等。

当中断触发条件满足时,硬件会保存当前程序的状态,并将控制权转移到指定的中断处理程序。

2. 中断优先级当多个中断同时发生时,系统需要根据一定的优先级规则来确定执行哪个中断处理程序。

中断优先级的高低取决于具体应用的需求,通常可以根据重要性和实时性要求来设定。

3. 中断处理程序中断处理程序(Interrupt Service Routine, ISR)是一段特定的代码,用于在发生中断时处理事件并做出响应。

ISR通常包括保存寄存器状态、处理中断事件、恢复寄存器状态以及执行相应的操作等步骤。

4. 中断嵌套与处理器状态在多任务操作系统中,可能存在多个中断同时发生的情况。

此时,系统需要根据优先级逐一处理中断,并保存每个中断处理前的处理器状态,以便在处理完中断后恢复到原来的状态。

5. 中断屏蔽与唤醒某些情况下,系统可能需要暂时屏蔽某些中断,以避免干扰关键任务的执行。

同时,某些中断可能需要唤醒睡眠状态的进程或线程。

这些操作需要通过特定的指令或机制来实现。

三、实例分析以一个简单的例子来说明外部中断的工作流程:假设我们有一个基于Linux 系统的嵌入式系统,当某个硬件设备完成一项任务(如数据传输)时,会触发一个外部中断。

系统会保存当前的任务状态,并执行相应的中断处理程序(ISR)。

ISR会读取硬件设备的数据,并执行相应的操作(如数据处理、任务调度等)。

在ISR执行完毕后,系统会恢复之前保存的任务状态,并继续执行之前的任务。

这个例子中,我们看到了外部中断如何被用于实时处理任务、唤醒睡眠状态的进程以及调度任务等操作。

DSPBIOS总结

DSPBIOS总结

DSP/BISO线程调度DSP/BIOS使用户的应用程序可以由一个线程集合构筑起来,每一个线程执行一个模块化的功能。

通过允许高优先级的线程抢占低优先级的线程,以及允许阻塞、同步、通信等各种线程间的交互方式,使得多线程的应用程序可以在一个处理器上运行。

DSP/BIOS支持多种不同优先级的线程,每种线程类型都有不同的执行和抢占特性。

这些线程按照优先级从高到低的顺序排列如下:●硬件中断(HWI),包括CLK函数。

●软件中断(SWI),包括PRD函数。

●任务(TSK)。

●后台线程(IDL)。

在DSP/BIOS中,硬件中断有最高的优先级,然后是软件中断,软件中断可以被高优先权软件中断或硬件中断抢先。

软件中断是不能被阻塞的。

任务的优先权低于软件中断,共有15个任务优先权级别(加上TSK_idle应该16个)。

任务在等待某个资源有效时可以被阻塞。

后台线程idle_loop是优先级最低的线程。

线程优先级如下图表示:下面具体介绍各种线程。

HWI module硬件中断是用来处理应用程序响应外部异步事件时必须执行的关键操作。

在典型的DSP应用中,硬件中断是由片上的外设或者DSP外部的设备触发的。

中断发生后处理器会通过中断向量跳转到相应的ISR地址。

一个中断的跳转由一个DSP/BIOS HWI对象负责,跳转的地址可以是一个用户函数或者是通用的系统HWI调度程序(dispatcher)的入口地址。

硬件中断ISR可以使用汇编语言、C语言或者混合编写。

HWI函数通常使用汇编来提高效率。

如果要完全使用C语言编写,应该使用系统的HWI调度程序,它会在调用用户C函数的前后分别惊醒现场环境保护与恢复。

所有的硬件中断都会一直运行到结束,如果一个硬件中断在其ISR得到运行机会前被多次触发,该ISR也只运行一次。

因此,用户必须尽量和减少HWI执行的代码量。

如果GIE位被使能,一个硬件中断可能被任何其他的被使能的中断抢占。

硬件中断没有优先级的区分;线程调度结果首先取决于该类就绪线程是被使能还是被禁止的。

浅谈linux性能调优之十七:进程绑定与中断绑定

浅谈linux性能调优之十七:进程绑定与中断绑定

浅谈linux性能调优之十七:进程绑定与中断绑定1.使用taskset设置CPU亲和性taskset搜索并设定运行进程的CPU亲和性(根据进程ID)。

它还可用于启动给定CPU亲和性的进程,这样就可将指定的进程与指定的CPU或者一组CPU捆绑CPU 亲和性使用位掩码表示。

最低位对应第一个逻辑 CPU,且最高位对应最后一个逻辑CPU。

这些掩码通常是十六进制,因此0x00000001 代表处理器 1,0x00000003 代表处理器 3 。

要设定运行进程的 CPU 亲和性,请执行以下命令,使用处理器或者您要捆绑到的处理器掩码替换 mask,使用您要更改亲和性的进程的进程 ID 替换 pid。

# taskset -p mask pid要启动给定亲和性的进程,请运行以下命令,使用处理器或者您要捆绑的处理器的掩码替换 mask,使用程序、选项以及您要运行的程序参数替换 program。

# taskset mask -- program与其将处理器指定为位码,您还可以使用 -c 选项提供逗号分开的独立处理器,或者一组处理器列表,类似如下:# taskset -c 0,5,7-9 -- myprogram有关 taskset 的详情请参考 man page:man taskset。

2.硬件中断发生频繁,是件很消耗 CPU 资源的事情,在多核 CPU 条件下如果有办法把大量硬件中断分配给不同的 CPU (core) 处理显然能很好的平衡性能。

现在的服务器上动不动就是多 CPU 多核、多网卡、多硬盘,如果能让网卡中断独占1个 CPU (core)、磁盘 IO 中断独占1个 CPU 的话将会大大减轻单一 CPU 的负担、提高整体处理效率。

中断请求(IRQ)是用于服务的请求,在硬件层发出。

可使用专用硬件线路或者跨硬件总线的信息数据包(消息信号中断,MSI)发出中断。

启用中断后,接收IRQ 后会提示切换到中断上下文。

内核中断调度代码会搜索 IRQ 号码机器关联的注册中断服务路由(ISR)列表,并按顺序调用 ISR。

中断实例

中断实例

.sect “.pvecs”
PVECTORS B B B B B B B PHANTOM PHANTOM PHANTOM PHANTOM PHANTOM PHANTOM PHANTOM
;定义各外设子向量段
;子向量的地址偏移为0000h 子向量的地址偏移为 ;子向量的地址偏移为0001h 子向量的地址偏移为 ;子向量的地址偏移为0002h 子向量的地址偏移为 ;子向量的地址偏移为0003h 子向量的地址偏移为 ;子向量的地址偏移为0004h 子向量的地址偏移为 ;子向量的地址偏移为0005h 子向量的地址偏移为 ;子向量的地址偏移为0006h 子向量的地址偏移为
INT5 B INT6 B
PHANTOM ;PMA Int level 5 8 PHANTOM ;PMC Int level 6 9 PHANTOM ;PM10 User S/W int- - PHANTOM ;PM12 User S/W int- - PHANTOM ;PM14 User S/W int- - PHANTOM ;PM16 User S/W in存器PIVR中 CPU获取被装载 中断向量)被装载到外设中断向量寄存器PIVR中,CPU获取被装载 PIVR 到PIVR中的值之后,用这个值来判断是哪一个外设引起的中断,接 PIVR中的值之后,用这个值来判断是哪一个外设引起的中断, 中的值之后 着转移到相应的SISR。 转移到相应的SISR。 SISR 将PIVR中的值装载入累加器时需先左移,再加上一个固定的偏 PIVR中的值装载入累加器时需先左移, 加上一个固定的偏 中的值装载入累加器时需先左移 移量,然后程序转到累加器指定的地址入口,这个地址将指向SISR, 移量,然后程序转到累加器指定的地址入口,这个地址将指向SISR, SISR 从而执行XINT1的中断服务子程序。 从而执行XINT1的中断服务子程序。 XINT1的中断服务子程序 例如: 例如: LACC PIVR,1;读外设中断向量寄存器(PIVR),并左移 位 ),并左移 ;读外设中断向量寄存器( ),并左移1位 ADD #PVECTTORS;加上外设中断入口地址, ;加上外设中断入口地址, BACC ;跳到相应的中断服务子程序入口 T1PINT_ISR:LDP #DP_EVA;通用定时器 中断服务;子程序入 中断服务; : ;通用定时器1中断服务 口

基于eCos操作系统的FLASH驱动程序分析与移植

基于eCos操作系统的FLASH驱动程序分析与移植

基于eCos操作系统的FLASH驱动程序分析与移植0 引言嵌入式系统需要支持的外部设备种类繁多,如何构造运行良好的嵌入式设备的驱动程序,对嵌入式操作系统的实际应用有重要意义。

eCos是一种源代码公开的实时嵌人式操作系统,对嵌入式应用具有良好的支持,内核专门设计了便于设备驱动管理和开发的I/O包和DEV包,开发人员可以方便地将自己开发的驱动程序加入其中,与别的系统组件一起进行配置。

1 系统目标板简介硬件目标板是为无人机系统设计的系统开发板,它是从Arca系统测试板经过功能简化设计而来的满足无人机系统要求的目标板。

硬件目标板如图1所示。

GT2000支持SRAM,FLASH,ROM,VLIO(静态段支持可变等待时间I/O设备)和SDRAM(同步动态RAM)等外部扩展存储器。

GT2000的外部地址空间是按体(bank)划分的,有四个体属于静态存储器区域,由引脚CS0~CS3选择,在将FLASH,SRA M,VLIO(用作其他外设接口)等静态I/O设备地址分别设计在CS0~CS2区域内,由GT2000内部的外部内存访问接口(EMI)控制器中的静态内存访问控制寄存器(SMCR)进行访问控制,分配地址访问接口。

系统目标板选用两片Intel公司的TE28F320的FLASH(16位)并联获得32位总线宽度。

Intel公司的TE28F320是32 Mb(2 M×16 b)多功能FLASH,2.7~3.6 V单电源供电,读取时间为70 ns,封装格式为48-Pin TSoP(12 mm×20 mm)或48-Ball TFB-GA,可被擦写10 000次。

方舟的JTAG仿真器支持TE28F320 FLASH,可以通过JTAG接口进行在线读写和擦除,这给调试程序和硬件提供了方便。

FLASH的电路原理图以及GT2000的引脚“DACK[2..1]/MD_MEM[1..0]”设置如图2所示。

2 eCos驱动程序的体系结构与驱动程序设计模式eCos操作系统的设备驱动程序通常包含以下内容:提供一些底层函数,负责完成设备初始化与配置、注册设备,从设备收发数据、控制设备、处理设备中断等,并进行设备管理。

CE中断详解

CE中断详解

CE中断详解CE中断详解WINCE驱动开发之中断的使用中断的使用1、wince中断简介1: ISR的概念首先搞清楚两个名词意义,IRQ:硬件中断号;SYSINTR_xx:系统中断或者称逻辑中断号。

ISR(interrupt service routine)是处理IRQs(interrupt request line)的程序。

Windows CE用一个ISR来处理所有的IRQ (硬件中断号)请求。

当一个中断发生时,内核的异常处理程序先调用内核ISR,内核ISR禁用所有具有相同优先级和较低优先级的中断,然后调用已经注册的OAL ISR程序,一般ISR有下列特征:1) 执行最小的中断处理,最小的中断处理指能够检验、答复产生中断的硬件,而把更多的处理工作留给IST(interrupt service thread)。

2) 当ISR完成时返回中断ID(逻辑中断,或者说是系统中断,就是SYSINTR_xx)(这个中断ID大部分是预定义的)。

ISR是在OAL层中实现的运行于内核态的程序。

根据执行效率要高和嵌入式实时性的要求,ISR多用汇编或者C语言实现,主要任务就是根据硬件中断返回一个逻辑中断号。

根据CPU是单个中断入口还是多个中断入口,ISR分为单ISR模型和多ISR模型:(1)单ISR模型:CPU只有一个硬件中断IRQ入口(如ARM和XScale处理器),所有的中断只有一个ISR入口,在OAL层中有一个统一的函数名:OEMInterruptHandler,在此函数中识别中断源并返回一个逻辑中断号SYSINTR_ID。

如:在BSP的oalintr.h里定义自定义中断的逻辑中断值#define SYSINTR_MYINTR (SYSINTR_FIRMWARE + 10)在armint.c的OEMInterruptHandler()中OEMInterruptHandler(){…………….else if (IntPendVal == INTSRC_EINT2) // EINT2return(SYSINTR_MYINTR);}(2)多ISR模型:即ISR链(IISR)。

ECos系统驱动程序的编写

ECos系统驱动程序的编写

ECos系统驱动程序的编写介绍Ecos的驱动程序分为两个部分:1./dev目录下,该部分程序同硬件相关2./io目录下,该部分程序同系统相关在IO包中的元件,可以增加当一个驱动程序被认为是静止的时候,她们必须通过一个透明的“handle”来访问。

每一个设备都有一个独特的名字,函数cyg_io_lookup()被用来寻找设备名字和设备号的对应。

而且,cyg_io_lookup()函数为设备驱动程序在使用该设备时进行设备的初始化提供了方便。

所有设备都有一个名字,如:/dev/console、/dev/serial0,等等所有的驱动程序,在Ecos中都是有c写成的设备驱动程序的基本功能是提供对设备的接收和发送数据。

而详细的实现方法有设备类自己实现。

例如:向块设备读写数据同向串口读写数据不同附加的函数为操作设备或硬件设备的状态提供了接口。

不同的设备有不同的附加函数。

Ecos的设备模块支持分层(layering),也就是说,一个设备驱动程序可以创建在另一个设备驱动程序上。

例如:tty就建立在简单的串口驱动上。

上层模块相对底层模块而言,有更好的可塑性,可以增加更多的功能和特征。

如tty设备驱动还提供了队列缓冲和编辑。

有些设备驱动还提供了它们所依赖的下一级驱动的特性。

Tty设备允许通过get/set config 调用来操作实际串口的的信息,并下达到实际串口。

用户API所有相关函数,除了cyg_io_lookup()以外,都需要io句柄。

所有函数都返回一个Cyg_ErrNo值。

若一个错误发生时,该值为负数,且其绝对值代表相应的错误号。

该值在cyg/error/codes.h有定义。

正确返回ENOERR。

任何的函数参数都为指针。

它允许驱动传递效率高。

最应引起注意的是参数length,他将传递给读写函数。

他包含有一个期待返回的数据长度而返回实际长度。

Cyg_ErrNo cyg_io_lookup( const char *name, cyg_io_handle_t *handle )上述函数将设备名字转换成句柄。

中断处理可以分为两部分中断服务b例程bISR

中断处理可以分为两部分中断服务b例程bISR

中断在系统设计中的应用非常广泛,可以说,硬件中断、软件中断无处不在,在WINCE下驱动开发更是如此,比如:按键中断、触摸屏中断、AUDIO中断、DMA中断.....等等,几乎含概每个模块。

因此,了解中断的处理过程对驱动开发极其重要,下面对WINCE下的中断处理过程做一个简单介绍。

中断处理可以分为两部分:中断服务例程-ISR、中断服务线程-IST。

系统在处理中断异常的时候,应该要尽可能快的完成,因此,我们应该ISR中做简短的处理,把中断标识返回给中断处理器,越快越好。

那么就要把大部分的处理留给IST来处理。

我们可以简单的认为,ISR的任务就是完成把硬件中断也就是物理中断转为系统中断并返回。

下面再来了解一下IST,IST就是一个线程,在驱动初始化的时候创建并等待一个事件,当然,在这之前要先创建一个事件,并与中断相关联起来,当中断产生以后该事件触发IST,IST里通常是用户的处理程序。

IST的实现必须先实现两个过程:IST的中断必须和一个事件相关联,IST必须通过WaitForSingleObject来等待这个事件的唤醒,IST的最后要调用INTERRUPTDONE来对注销中断,否则该中断只能用一次,一般我们在驱动的XXX_INIT函数中实现。

IST在BSP/COMMON/INTR/intr.c中,这里面的内容包括init、enable、disable、oeminterrupthandler等函数,主要是对中断的初始化、使能、处理等,其中最关键的是oeminterrupthandler。

以下是我在该函数中对EINT的简单处理部分代码:if (irq == IRQ_EINT4_7 || irq == IRQ_EINT8_23) { // 4 or 5// Find external interrupt numbermask = INREG32(&g_pPortRegs->EINTPEND);mask &= ~INREG32(&g_pPortRegs->EINTMASK);mask = (mask ^ (mask - 1)) >> 5;irq2 = IRQ_EINT4;while (mask != 0) {mask >>= 1;irq2++;}// Mask and clear interruptmask = 1 << (irq2 - IRQ_EINT4 + 4);SETREG32(&g_pPortRegs->EINTMASK, mask);OUTREG32(&g_pPortRegs->EINTPEND, mask);// Clear primary interruptmask = 1 << irq;OUTREG32(&g_pIntrRegs->SRCPND, mask);OUTREG32(&g_pIntrRegs->INTPND, mask);// From now we care about this irqirq = irq2;else {// Mask and clear interruptmask = 1 << irq;SETREG32(&g_pIntrRegs->INTMSK, mask);OUTREG32(&g_pIntrRegs->SRCPND, mask);OUTREG32(&g_pIntrRegs->INTPND, mask);}// First find if IRQ is claimed by chainsysIntr = NKCallIntChain((UCHAR)irq);if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {// IRQ wasn't claimed, use static mappingsysIntr = OALIntrTranslateIrq(irq);}而IST的具体实现过程可以参照下面的步骤:1、创建一个事件。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

(原创)eCos驱动分析之ISR是如何与硬件中断联系起来的---转载文章要想知道ecos的中断ISR是怎么与硬件中断向量联系起来的,是怎么被调用的?那就要看下面这两个关键的函数:cyg_drv_interrupt_create()cyg_drv_interrupt_attach()这两个函数都声明在cyg/kernel/kapi.h中,其形式如下:void cyg_interrupt_create( cyg_vector_t vector, /* Vector to attach to */ cyg_priority_t priority, /* Queue priority */ cyg_addrword_t data, /* Data pointer*/ cyg_ISR_t *isr, /* Interrupt Service Routine */ cyg_DSR_t *dsr, /* Deferred Service Routine */ cyg_handle_t *handle, /* returned handle */ cyg_interrupt *intr /* put interrupt here */) __THROW;void cyg_interrupt_attach( cyg_handle_t interrupt )__THROW;(注: __THROW是在C++中用的,是用来抛出异常的,详见我的博文/blog/static/888807432011611193510/ 这里可以视而不见.)其中文意义对照如下:cyg_interrupt_create( 中断号, 中断优先级, 传递的中断参数, ISR函数,DSR函数, 被返回的中断句柄, 存放与此中断相关的内核数据的变量空间);cyg_interrupt_attach(中断句柄);这样实际上去研究一下cyg_interrupt_create函数的定义内容,应该就能搞明白我们的问题了!由于其函数声明在kapi.h中,很自然的就想到其定义应在kapi.c文件中,找到....\ecos\ecos-current\packages\kernel\current\src\common\kapi.cxx文件,找到这两个函数的定义如下:/*---------------------------------------------------------------------------*//* Interrupt handling*/externC void cyg_interrupt_create( cyg_vector_t vector, /* Vector to attach to */ cyg_priority_t priority, /* Queue priority*/ cyg_addrword_t data, /* Data pointer */ cyg_ISR_t*isr, /* Interrupt Service Routine */ cyg_DSR_t *dsr, /* Deferred Service Routine */ cyg_handle_t *handle,/* returned handle */ cyg_interrupt *intr /* put interrupt here */) __THROW{ CYG_ASSERT_SIZES( cyg_interrupt,Cyg_Interrupt );Cyg_Interrupt *t = new((void *)intr) Cyg_Interrupt( (cyg_vector)vector, (cyg_priority)priority, (CYG_ADDRWORD)data, (cyg_ISR *)isr,(cyg_DSR *)dsr ); t=t;CYG_CHECK_DATA_PTR( handle, "Bad handle pointer" ); *handle = (cyg_handle_t)intr;}voidcyg_interrupt_attach( cyg_handle_t interrupt )__THROW{ ((Cyg_Interrupt *)interrupt)-&gt;attach();}函数内容比想象中的简单,所有的操作又都传给了Cyg_Interrupt这个类来完成,那就来对Cyg_Interrupt探个究竟吧:(注意Cyg_Interrupt是个C++类, 可不要找成了struct cyg_interrupt,注意哟,cyg_interrupt_create函数的最后一个参数就是这个cyg_interrupt struct类型的,在cyg/kernel/kapidata.h中有个struct cyg_interrupt定义,虽然名字和内容都很相似,但实际上不是.)真正的class Cyg_Interrupt定义在cyg/kernel/intr.hxx中,这个头文件没干别的,就是声明这个class了,可见这是一个很大的class,如下:// -------------------------------------------------------------------------// Interrupt class. This both represents each interrupt and provides a static// interface for controlling the interrupt hardware.class Cyg_Interrupt{friend class Cyg_Scheduler; friend voidinterrupt_end( cyg_uint32,Cyg_Interrupt *,HAL_SavedRegisters *); friend voidcyg_interrupt_post_dsr( CYG_ADDRWORD intr_obj );friend void cyg_interrupt_call_pending_DSRs( void );cyg_vector vector; // Interrupt vector cyg_priority priority; // Queuing priority cyg_ISR *isr; // Pointer to ISR cyg_DSR *dsr; // Pointer to DSRCYG_ADDRWORD data; // Data pointer // DSR handling interface called by the scheduler// Check for pending DSRs static cyg_bool DSRs_pending();// Call anypending DSRs static void call_pending_DSRs(); static void call_pending_DSRs_inner();// DSR handling interface called by the scheduler and HAL // interrupt arbiters.void post_dsr(); // Post the DSR for this interrupt // Data structures for handling DSR calls. We implement two DSR // handling mechanisms, a list based one and a table based // one. The list based mechanism is safe with respect to temporary // overloads and will not run out of resource. However it requires // extra data per interrupt object, and interrupts must be turned // off briefly when delivering the DSR. The table based mechanism // does not need unnecessary interrupt switching, but may be prone // to overflow on overload. However, since a correctly programmed // real time application should not experience such a condition, // the table based mechanism is more efficient for real use. The // list based mechainsm is enabled by default since it is safer to// use during development.#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_TABLE static Cyg_Interrupt *dsr_table[CYGNUM_KERNEL_CPU_MAX][CYGNUM_KERNEL_INTERRUPTS_DSRS_TABLE_SIZE] CYGBLD_ANNOTATE_VARIABLE_INTR;static cyg_ucount32dsr_table_head[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;static volatile cyg_ucount32dsr_table_tail[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LIST // Number of DSR posts made volatilecyg_ucount32 dsr_countCYGBLD_ANNOTATE_VARIABLE_INTR;// next DSR in list Cyg_Interrupt* volatile next_dsr CYGBLD_ANNOTATE_VARIABLE_INTR;// static list of pending DSRs static Cyg_Interrupt* volatile dsr_list[CYGNUM_KERNEL_CPU_MAX]CYGBLD_ANNOTATE_VARIABLE_INTR;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAIN// The default mechanism for handling interrupts is to attach just // one Interrupt object to each vector. In some cases, and on some // hardware, this is not possible, and each vector must carry a chain // ofinterrupts.Cyg_Interrupt *next; // Next Interrupt in list// Chaining ISR inserted in HAL vector staticcyg_uint32 chain_isr(cyg_vector vector, CYG_ADDRWORD data);// Table of interrupt chains static Cyg_Interrupt*chain_list[CYGNUM_HAL_ISR_TABLE_SIZE];#endif// Interrupt disable data. Interrupt disable can be nested. On // each CPU this is controlled bydisable_counter[cpu]. When the // counter is first incremented from zero to one, the //interrupt_disable_spinlock is claimed using spin_intsave(), the // original interrupt enable state being saved in// interrupt_disable_state[cpu]. When the counter is decremented // back to zero the spinlock is cleared using clear_intsave().// The spinlock is necessary in SMP systems since a thread // accessing data shared with an ISR may be scheduled on a // different CPU to the one that handles the interrupt. So, merely // blocking local interrupts would be ineffective. SMP aware // device drivers shouldeither use their own spinlocks to protect // data, or use the API supported by this class, via //cyg_drv_isr_lock()/_unlock(). Note that it now becomes// essential that ISRs do this if they are to be SMP-compatible.// In a single CPU system, this mechanism reduces to just // disabling/enabling interrupts.// Disable level counter. This counts the number of times // interrupts have been disabled. static volatile cyg_int32 disable_counter[CYGNUM_KERNEL_CPU_MAX] CYGBLD_ANNOTATE_VARIABLE_INTR;// Interrupt disable spinlock. This is claimed by any CPU that has // disabled interrupts via the Cyg_Interrupt API. static Cyg_SpinLock interrupt_disable_spinlockCYGBLD_ANNOTATE_VARIABLE_INTR;// Saved interrupt state. When each CPU first disables interrupts // the original state of the interrupts are saved here to be // restored later. staticCYG_INTERRUPT_STATEinterrupt_disable_state[CYGNUM_KERNEL_CPU_MAX] CYGBLD_ANNOTATE_VARIABLE_INTR;public:Cyg_Interrupt // Initialize interrupt ( cyg_vector vector, // Vector to attach to cyg_priority priority,// Queue priority CYG_ADDRWORD data,// Data pointer cyg_ISR *isr,// Interrupt Service Routine cyg_DSR *dsr // Deferred Service Routine );~Cyg_Interrupt(); // ISR return values enum { HANDLED = 1, // Interrupt was handled CALL_DSR = 2// Schedule DSR };// Interrupt management void attach();// Attach to vector void detach();// Detach from vector // Static Interrupt management functions// Get the current service routine static voidget_vsr(cyg_vector vector, cyg_VSR **vsr);// Install a vector service routine static voidset_vsr( cyg_vector vector, // hardware vector to replace cyg_VSR *vsr,// my new service routine cyg_VSR **old = NULL// pointer to old vsr, if required ); // Staticinterrupt masking functions// Disable interrupts at the CPU static voiddisable_interrupts();// Re-enable CPU interrupts static voidenable_interrupts();// Are interrupts enabled at the CPU? static inline cyg_bool interrupts_enabled() { return (0 == disable_counter[CYG_KERNEL_CPU_THIS()]); } // Get the vector for the following calls inline cyg_vectorget_vector() { return vector; } // Static PIC control functions // Mask a specific interrupt in a PIC static void mask_interrupt(cyg_vector vector); // The same but not interrupt safe static voidmask_interrupt_intunsafe(cyg_vector vector);// Clear PIC mask static voidunmask_interrupt(cyg_vector vector); // The same but not interrupt safe static voidunmask_interrupt_intunsafe(cyg_vector vector);// Acknowledge interrupt at PIC static void acknowledge_interrupt(cyg_vector vector);// Change interrupt detection at PIC static void configure_interrupt( cyg_vector vector,// vector to control cyg_bool level,// level or edge triggered cyg_bool up// hi/lo level, rising/falling edge );#ifdef CYGPKG_KERNEL_SMP_SUPPORT// SMP support for associating an interrupt with a specific CPU. static void set_cpu( cyg_vector,HAL_SMP_CPU_TYPE cpu ); static HAL_SMP_CPU_TYPE get_cpu( cyg_vector );#endif };这只是声明了这个class,这个class的构造/析构函数和成员函数的实现,还要找cyg/kernel/intr.hxx头文件相对应的C文件,在这里....\packages\kernel\current\src\intr\intr.cxx 找到了intr.cxx文件,因为cyg_interrupt_create函数实际上调用了classCyg_Interrupt的构造函数,我们就来看看这个构造函数: Cyg_Interrupt::Cyg_Interrupt( cyg_vector vec,// Vector to attach to cyg_priority pri,// Queue priority CYG_ADDRWORD d,// Data pointer cyg_ISR *ir,// Interrupt Service Routine cyg_DSR *dr// Deferred ServiceRoutine ){ CYG_REPORT_FUNCTION();CYG_REPORT_FUNCARG5("vector=%d, priority=%d,data=%08x, isr=%08x, ""dsr=%08x", vec, pri, d, ir, dr); vector = vec; priority = pri; isr = ir; dsr = dr; data = d;#ifdef CYGIMP_KERNEL_INTERRUPTS_DSRS_LISTdsr_count = 0; next_dsr = NULL;#endif#ifdef CYGIMP_KERNEL_INTERRUPTS_CHAINnext = NULL;#endifCYG_REPORT_RETURN();};也就是分配了一下成员变量,把cyg_interrupt_create函数传进来的中断号、ISR、DSR等分配给类的成员变量,好像也没什么特别的。

相关文档
最新文档