[ZLG-ARM] WINCE4.2到5.0中断服务差异

[复制链接]
 楼主| xamic 发表于 2009-6-3 13:45 | 显示全部楼层 |阅读模式
共同的内核函数:<br />OEMInterruptHandler():中断服务例程ISR<br />OEMInterruptEnable():<br />OEMInterruptDisable():<br />OEMInterruptDone():顾名思意,应用层在调用InterruptEnable、InterruptDisable、InterruptDone函数时会调用这几个内核函数<br />4.2下的OEMInterruptHandler()函数会跟据转进来的硬件IRQ中断号返回对应的SYSINTR逻辑中断号,也就是说如果需要修改两个中断号对应关系,可以直接在这个函数中修改,这里的这种对应、映射关系称之为静态映射。OEMInterruptEnable()...三个函数传进来的参数是SYSINTR逻辑中断号,可以根据OEMInterruptHandler()函数中的映射关系,对硬件中断IRQ来进行相应的操作。这几个函数分别位于platformspkernelhalcfw.c与bspkernelhalarmarmint.c文件中。换句话说4.2下的中断可以称之为静态映射,也就是不能在运行时的应用/驱动层将硬件与逻辑IRQ进行映射。<br />5.0下的OEMIntrruptHandler()函数位于:platformcommonsrcarmsamsungs3c2410xintrintr.c中。注意,他不像4.2中的该函直接将参数传递进来的硬件IRQ送出对应的逻辑SYSIRQ,而是调用OALIntrTranslateIrq()函数进行映射。OALIntrTranslateIrq()函数位于platformcommonsrccommonintrasemap.c文件中。这个函数只是简单的将以Irq参数为下标的数组中找出SYSIRQ,然后返回:<br />UINT32&nbsp;OALIntrTranslateIrq(UINT32&nbsp;irq)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;UINT32&nbsp;sysIntr&nbsp;=&nbsp;SYSINTR_UNDEFINED;<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(irq&gt=OAL_INTR_IRQ_MAXIMUM)&nbsp;goto&nbsp;cleanUp;<br />&nbsp;&nbsp;&nbsp;&nbsp;sysIntr&nbsp;=&nbsp;g_oalIrq2SysIntr[irq];<br />&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;sysintr;<br />&nbsp;&nbsp;&nbsp;&nbsp;...<br />}<br />看这里的g_oalIrq2SysIntr数组,还有一个与之对应的g_oalSysIntr2Irq数组,从名字上可以看出功能。这两个数组也定义在map.c文件中,是通过OALIntrMapInit()函数进行初始化的。这里也可以进行静态映射,使用OALIntrStaticTranslate这个函数,它的实现过程就是填充数组:<br />OALIntrStaticTranslate(UINT32&nbsp;sysIntr,&nbsp;UINT32&nbsp;irq)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;...<br />&nbsp;&nbsp;&nbsp;&nbsp;g_oalSysIntr2Irq[sysIntr]&nbsp;=&nbsp;irq;<br />&nbsp;&nbsp;&nbsp;&nbsp;g_oalIrq2SysIntr[irq]&nbsp;=&nbsp;sysIntr;<br />&nbsp;&nbsp;&nbsp;&nbsp;...<br />}<br />看一下流程:OEMInit()=&gtOALIntrInit()=&gtOALIntrMapInit()这个就是对两个数组进行初始化=&gtBSPIntrInit()可以在这个函数里用OALIntrStaticTranslate()函数进行静态映射。<br />5.0下的OEMInterruptEnable()...这三个函数位于platformcommonsrccommonINTRcommonoem.c文件小,大致流程是这样的:<br />OEMInterruptEnable()=&gtOALIntrTranslateSysIntr()这个函数是在将逻辑中断号转换成硬件的系统中断号,与OALIntrTranslateIrq()函数功相反,位于同一个文件中。=&gtOALIntrEnableIrq()这个函数先调用BSPIntrEnableIrq()使得BSP有机会先做处理,这个函数与OEMIntrruptHandler()位于同一个文件中,在platformcommonsrcarmsamsungs3c241xintrintr.c文件中。<br />OEMInterruptEnable()=&gtOALIntrTranslateSysIntr()=&gtOALIntrEnableIrqs()=&gtBSPIntrEnableIrq()<br />OEMInterruptDisable()=&gtOALIntrTranslateSysIntr()=&gtOALIntrDisableIrqs()=&gtBSPIntrDisableIrq()<br />OEMInterruptDone()=&gtOALIntrTranslateSysIntr()=&gtOALIntrDoneIrqs()=&gtBSPIntrDoneIrq()<br />总结:<br />&nbsp;&nbsp;&nbsp;&nbsp;跟4.2的区别,实际上主要是5.0可以/是在应用/驱动层使用OALIntrRequestSysIntr()动态请求/映射,而4.2好像不可以,至少我没找到。4.2的方法更简单明了,5.0的好处更明显,更改驱动等代码时无须动内核函数。<br />&nbsp;&nbsp;&nbsp;&nbsp;上面5.0使用到的几个函数分别位于下面的文件中:<br />&nbsp;&nbsp;&nbsp;&nbsp;platformcommonsrcarmsamsungs3c241xintrintr.c<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrDisableIrqs()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrDoneIrqs()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrEnableIrqs()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrInit()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrRequestIrqs()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OEMInterruptHandler()<br />&nbsp;&nbsp;&nbsp;&nbsp;platformsmdk410srckerneloalinit.c<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OEMInit()<br />&nbsp;&nbsp;&nbsp;&nbsp;platformsmdk2410srckerneloalintr.c<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrActiveIrq()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrDisableIrq()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrDoneIrq()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrEnableIrq()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrInit()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BSPIntrRequestIrqs()<br />&nbsp;&nbsp;&nbsp;&nbsp;platformcommonsrccommonintrasemap.c<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrMapInit()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrReleaseSysIntr()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrRequestSysIntr()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrStaticTranslate()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrTranslateIrq()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OALIntrTranslateSysIntr()<br />贴两个网上找到的资料,都是5.0的:<br />WinCE有两种私有的中断表,一种是物理中断——中断请求(IRQs),另一种是逻辑中断——SYSINTR值。WinCE必须将一个物理中断和一个逻辑中断关联起来。<br />物理中断号定义在platformc8090pubiccsparmintelpxa27xincBulverde_intr.h。<br />逻辑中断号定义在platformc8090platformmainstoneiisrc/incBsp_cfg.h。<br />两个中断表定义在platformc8090platformsrccommonintrasemap.c<br />static&nbsp;UINT32&nbsp;g_oalSysIntr2Irq[SYSINTR_MAXIMUM];<br />static&nbsp;UINT32&nbsp;g_oalIrq2SysIntr[OAL_INTR_IRQ_MAXIMUM];<br />OAL_INTR_IRQ_MAXIMUM定义在platformc8090commonsrcincoal_intr.h,<br />#define&nbsp;OAL_INTR_IRQ_MAXIMUM&nbsp;64<br />该值表示物理中断——IRQs的最大值,现在最大只支持到64。<br />SYSINTR_MAXIMUM定义在wm522publiccommonoakinc<br />kintr.h<br />#define&nbsp;SYSINTR_DEVICES&nbsp;8<br />#define&nbsp;SYSINTR_MAX_DEVICES&nbsp;64<br />#define&nbsp;SYSINTR_MAXIMUM&nbsp;(SYSINTR_DEVICES+SYSINTR_MAX_DEVICES)<br />OEM&nbsp;Adaptation&nbsp;Layer——OAL初始化函数是OEMInit(),它是WinCE的OAL层初始化函数,在基本初始化完成之后,由内核调用,定义在:<br />platformc8090platformmainstoneiisrckerneloalinit.c。<br />在这里调用中断初始化函数:OALIntrInit(),该函数定义在:<br />platformc8090platformcommonsrcarmintelpxa27xintrintr.c中,该函数首先调用函数OALIntrMapInit(),初始化前面提到的两个数组表g_oalSysIntr2Irq和goalIrq2SysIntr。该函数定义在platformc8090platformcommonsrccommonintrasemap.c,源码如下:<br />for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt&nbsp;SYSINTR_MAXIMUM;&nbsp;i++)&nbsp;{<br />g_oalSysIntr2Irq&nbsp;=&nbsp;OAL_INTR_IRQ_UNDEFINED;<br />}<br />for&nbsp;(i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt&nbsp;OAL_INTR_IRQ_MAXIMUM;&nbsp;i++)&nbsp;{<br />g_oalIrq2SysIntr&nbsp;=&nbsp;SYSINTR_UNDEFINED;<br />}<br />然后调用函数BSPIntrInit()将物理中断和逻辑中断关联起来,该函数定义在:<br />platformc8090platformmainstoneiisrckerneloalintr.c中。<br />关联代码例子如下:<br />OALIntrStaticTranslate(SYSINTR_PMIC,&nbsp;IRQ_GPIO0);<br />OALIntrStaticTranslate(SYSINTR_OHCI,&nbsp;IRQ_USBOHCI);<br />OALIntrStaticTranslate(SYSINTR_TOUCH,&nbsp;IRQ_GPIOXX_WM9712);<br />OALIntrStaticTranslate(SYSINTR_TOUCH_CHANGED,&nbsp;IRQ_OSMR1);<br />OALIntrStaticTranslate(SYSINTR_KEYPAD,&nbsp;IRQ_KEYPAD);<br />前面都是逻辑中断,后面是物理中断。OALIntrStaticTranslate函数定义在:<br />platformc8090platformcommonsrccommonintrasemap.c,源码如下:<br />if&nbsp;(irq&nbsp;&lt&nbsp;OAL_INTR_IRQ_MAXIMUM&nbsp;&&&nbsp;sysIntr&nbsp;&lt&nbsp;SYSINTR_MAXIMUM)&nbsp;{<br />g_oalSysIntr2Irq[sysIntr]&nbsp;=&nbsp;irq;<br />g_oalIrq2SysIntr[irq]&nbsp;=&nbsp;sysIntr;<br />}<br />OAL是位于WindowsCE内核与目标设备硬件之间的一个代码层,用于实现windowCE与目标设备硬件之间的通信。为了实现内核与硬件之间最基本的通信功能,OEM必须实现一些必要的功能,同时为了适合不同的硬件配置与操作系统功能,OEM有必要的选择实现一些其他的功能。<br />在OAL开发过程中,OEM需要实现下列主要功能或函数:<br />.Startup函数;<br />.调试串口;<br />.OEMInit函数;<br />.系统计时器;<br />.中断处理;<br />.内核的输入/输出(ioctl);<br />.KITL。<br />下面给出微软公司提供的各个功能的函数。<br />/***************************中断处理****************************/<br />./platform/Common/src/common/intr/base/map.c<br />The&nbsp;file&nbsp;implement&nbsp;simple&nbsp;table/array&nbsp;based&nbsp;mapping&nbsp;between&nbsp;IRQ&nbsp;and&nbsp;SYSINTR<br />which&nbsp;is&nbsp;suitable&nbsp;for&nbsp;most&nbsp;OAL&nbsp;implementations.<br />这个文件主要是用来定义IRQ和SYSIRQ的映射关系。<br />主要函数如下:<br />OALIntrMapInit();//此函数由OALInterruptInit调用来初始化IRQ和SYSIRQ的映射,只是简单的映射数组的初始化;初始化为未定义类型。<br />VOID&nbsp;OALIntrStaticTranslate(UINT32&nbsp;sysIntr,&nbsp;UINT32&nbsp;irq);&nbsp;//此函数建立IRQ和SYSINTR的静态映射,大多数情况下都不可能用到,只有在SYSINTR_RTC_ALARM和过时的设备驱动的时候会用到。<br />BOOL&nbsp;OALIntrTranslateSysIntr(UINT32&nbsp;sysIntr,&nbsp;UINT32&nbsp;*pCount,&nbsp;const&nbsp;UINT32&nbsp;**ppIrqs);//此函数将SYSINTR映射为它相应的IRQ,主要用在OEMInterruptXXX中对于给定SYSINTR得到其IRQs。<br />UINT32&nbsp;OALIntrTranslateIrq(UINT32&nbsp;irq);//此函数将IRQ映射为相应的SYSINTR。<br />UINT32&nbsp;OALIntrRequestSysIntr(UINT32&nbsp;count,&nbsp;const&nbsp;UINT32&nbsp;*pIrqs,&nbsp;UINT32&nbsp;flags);//此函数为给定的IRQ分配一个新的SYSINTR,如果此IRQ没有静态映射,就创建一个。<br />BOOL&nbsp;OALIntrReleaseSysIntr(UINT32&nbsp;sysIntr);//此函数释放一个SYSINTR,并且消除存在的静态映射。<br />问题:<br />SYSINTR于IRQ的映射关系是不是一对一?BOOL&nbsp;OALIntrTranslateSysIntr(UINT32&nbsp;sysIntr,&nbsp;UINT32&nbsp;*pCount,&nbsp;const&nbsp;UINT32&nbsp;**ppIrqs)使用的是地址来进行映射,而UINT32&nbsp;OALIntrTranslateIrq(UINT32&nbsp;irq)使用值来进行映射,目前我认为应该是一对一的关系来映射的。<br />感想:<br />微软的程序写的很缜密,设计的很合理,能让我学到不少编程的方法。映射关系的编程可以参考微软的中断映射表<br />&nbsp;<br /> &nbsp;&nbsp;<br />
lpczcy 发表于 2009-6-3 14:03 | 显示全部楼层

解释的很详细,辛苦了,大侠

  
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

38

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部