wince -- 中断篇

[复制链接]
6009|6
 楼主| 驱动开发版 发表于 2007-9-25 09:42 | 显示全部楼层 |阅读模式
Exception&nbsp;Process&nbsp;in&nbsp;wince&arm<br />作者:Walzer<br />日期:2005.3.11<br /><br />我被INTEL的Application&nbsp;Engineer特地纠正了“中断向量表”的说法,应该叫Exception&nbsp;Vector.按我理解,应该只有IRQ和FIQ算做interrupt吧,像reset和几个abort叫做exception的确更合适些。<br /><br />一般而言,&nbsp;硬件的异常产生后,CPU将跳转到0x00000000地址访问中断向量表(normal&nbsp;exception&nbsp;vectors),&nbsp;&nbsp;但ARM920T&nbsp;/&nbsp;ARM9&nbsp;/&nbsp;ARM10&nbsp;系列的CPU支持把中断向量表放到高地址0xFFFF0000(high&nbsp;exception&nbsp;vectors).&nbsp;该跳转地址的决定因素为协处理器的CP15:BI13.&nbsp;即CP15:BIT13&nbsp;=&nbsp;0时,&nbsp;跳转到低地址;&nbsp;CP15:BIT13&nbsp;=&nbsp;1时,&nbsp;跳转到高地址.&nbsp;根据INTEL应用工程师的回答,该地址在MMU使能之前为physical&nbsp;address,&nbsp;使能之后为virtual&nbsp;address,&nbsp;该点有待确认.<br /><br />由于WinCE在编译nk.nb0或xboot.nb0时,&nbsp;和其他application使用了同一个Linker的缘故,&nbsp;从0x00000000~0x00001000这段是reserved的,留作给application的PE头(Portable&nbsp;Executable&nbsp;&nbsp;header,&nbsp;什么用的我还没搞懂,&nbsp;MSDN上有详细说明).&nbsp;而我们的代码从0x00001000这行开始放起.但在0x00000000有句跳转指令&quot;b&nbsp;1000&quot;.&nbsp;其实这中间还有几行代码,&nbsp;但不知道干什么用的,反正被跳过去不执行就是了.<br /><br />因为上述缘故,&nbsp;WinCE里就不能把exception&nbsp;vectors放在normal的低地址了,&nbsp;只能选用高地址放置.<br /><br />在WINCE500PRIVATEWINCEOSCOREOSNKKERNELARMarmtrap.s&nbsp;中,&nbsp;下面这段VectorInsturctions代码将被复制到0xFFFF0000位置,&nbsp;占据8*4=32bit的长度.&nbsp;我们最经常使用的IRQ中断在0xFFFF0018的位置.&nbsp;其中0x14是保留给以后扩展的,目前并没有用到.按照ARM体系,&nbsp;应该有7种中断.&nbsp;而实际上只有IRQ和FIQ会跳到OEMInterruptHandler里面(后者是OEMInterruptHandlerFIQ).<br />VectorInstructions<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;reset<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;undefined&nbsp;instruction<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;SVC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;Prefetch&nbsp;abort<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;data&nbsp;abort<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;unused&nbsp;vector&nbsp;location<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;IRQ<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pc,&nbsp;[pc,&nbsp;#0x3E0-8]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;FIQ<br />这只是第一次跳转,&nbsp;跳转到0xFFFF03E0后,这里才是中断向量表(vector&nbsp;table).&nbsp;这个vector&nbsp;table并不在armtrap.s里,而是在同目录的exvector.s里单独定义,&nbsp;这里就是各Interrupt&nbsp;Service&nbsp;Routine的入口地址了.<br />VectorTable<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;reset<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;UndefException&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;undefined&nbsp;instruction<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SWIHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;SVC<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PrefetchAbort&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;Prefetch&nbsp;abort<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DataAbortHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;data&nbsp;abort<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;unused&nbsp;vector<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IRQHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;IRQ<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DCD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FIQHandler&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;FIQ<br /><br />实际上不论是ExceptionVectors或者VectorTable,&nbsp;一开始都是放置在ROM里面的,这就需要在系统startup的时候把它们搬运到指定的位置,下面这段代码应该就是干的这事.<br />;&nbsp;Setup&nbsp;the&nbsp;vector&nbsp;area.<br />;<br />;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(r8)&nbsp;=&nbsp;ptr&nbsp;to&nbsp;exception&nbsp;vectors<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r7,&nbsp;pc,&nbsp;#VectorInstructions&nbsp;-&nbsp;(.+8)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldmia&nbsp;&nbsp;&nbsp;r7!,&nbsp;{r0-r3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;load&nbsp;4&nbsp;instructions<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stmia&nbsp;&nbsp;&nbsp;r8!,&nbsp;{r0-r3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;store&nbsp;the&nbsp;4&nbsp;vector&nbsp;instructions<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldmia&nbsp;&nbsp;&nbsp;r7!,&nbsp;{r0-r3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;load&nbsp;4&nbsp;instructions<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stmia&nbsp;&nbsp;&nbsp;r8!,&nbsp;{r0-r3}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;store&nbsp;the&nbsp;4&nbsp;vector&nbsp;instructions<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;convert&nbsp;VectorTable&nbsp;to&nbsp;Physical&nbsp;Address<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,&nbsp;=VectorTable&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;(r0)&nbsp;=&nbsp;VA&nbsp;of&nbsp;VectorTable<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r1,&nbsp;r11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;(r1)&nbsp;=&nbsp;&OEMAddressTable[0]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;bl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PaFromVa<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r7,&nbsp;r0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;(r7)&nbsp;=&nbsp;PA&nbsp;of&nbsp;VectorTable<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r8,&nbsp;r8,&nbsp;#0x3E0-(8*4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;;&nbsp;(r8)&nbsp;=&nbsp;target&nbsp;location&nbsp;of&nbsp;&nbsp;the&nbsp;vector&nbsp;table<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldmia&nbsp;&nbsp;&nbsp;r7!,&nbsp;{r0-r3}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stmia&nbsp;&nbsp;&nbsp;r8!,&nbsp;{r0-r3}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ldmia&nbsp;&nbsp;&nbsp;r7!,&nbsp;{r0-r3}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stmia&nbsp;&nbsp;&nbsp;r8!,&nbsp;{r0-r3}<br /><br />OK了,运行到这步后,各种不同的exception就要分别进入其ISR了.&nbsp;这些ISR仍然是在armtrap.s里面的.&nbsp;以IRQHandler为例.&nbsp;从0xFFFF03F8跳转到ISR入口处:&nbsp;NESTED_ENTRY&nbsp;IRQHandler,&nbsp;后面好长一段汇编,&nbsp;算了一下145行,&nbsp;晕倒,&nbsp;看不懂.&nbsp;这些都是WINCE做好的不需要OEM再去修改。其实我们暂时先看懂一个标识符就OK了:&nbsp;CALL<br /><br />第一次CALL了这个函数CeLogInterrupt,&nbsp;它位于wince500privatewinceoscoreos
kkernellogger.c里面,&nbsp;实质性工作就是一个interrupt&nbsp;counter,把一个计算中断数量的全局变量加一.<br /><br />接下来CALL了我们亲切的&quot;OEMInterruptHandler&quot;.&nbsp;在INTEL的BSP里提供了intr.c,&nbsp;里头实现了这个OEMInterruptHandler函数.&nbsp;这个函数都做些什么呢?&nbsp;首先通过OEMAddressTalbe把CPU上的Interrupt&nbsp;Controller&nbsp;Registers影射到virtual&nbsp;address,&nbsp;其实我们只关心这里面的一个地方:&nbsp;ICHP[IRQ],&nbsp;这里指示了IRQ&nbsp;Highest&nbsp;Priority&nbsp;Field,所以我们只要把这5个BIT取出来判断就可以了.&nbsp;当然从这里取得的只是硬件的physical&nbsp;IRQ号(有的地方翻译成设备中断号),&nbsp;得通过OALIntrTranslateIrq<br />转换成能够在系统里使用的logical&nbsp;SysIntr号(调度中断号).&nbsp;<br /><br />IRQ号可以在BSP里找到定义(Bxxxxx_intr.h),&nbsp;而SysIntr则分为三类:&nbsp;WINCE规定好的&nbsp;/&nbsp;OEM自行分配&nbsp;/&nbsp;&nbsp;DRIVER运行时动态获取.&nbsp;WINCE在publiccommonoakinc
kintr.h中规定一些较为核心的SYSINTR,如SYSINTR_NOP,&nbsp;RESCHED,&nbsp;BREAK,&nbsp;CHAIN,&nbsp;还有TIMEING,&nbsp;RTC_ALARM等,&nbsp;而在BSP里bsp_cfg.h则定义了外围设备的SYSINTR,&nbsp;如OHCI,&nbsp;UART,&nbsp;KEYPAD等.&nbsp;前面这两种情况的SYSINTR,&nbsp;在注册表platform.reg里也必须写值,&nbsp;并且得和程序里定义的一样.&nbsp;第三种是运行时动态获取的SYSINTR,&nbsp;我还没碰到过,&nbsp;不是很清楚.<br /><br />从OEMInterruptHandler中返回了一个该IRQ所对应的SysIntr号,&nbsp;放置在R0里.<br /><br />接下来,&nbsp;call了这个函数指针&quot;pfnOEMIntrOccurs&quot;,&nbsp;到private里追踪,&nbsp;该指针在schedule.c里指向了函数FakedOEMIntrOccurs,&nbsp;而这个函数就在该赋值语句的上面几行,具体操作为:return&nbsp;dwSysIntr.&nbsp;哈被耍了,&nbsp;人家函数名就叫Fake,&nbsp;自己要去追的,&nbsp;活该.<br /><br />再往下走,&nbsp;&quot;cmp&nbsp;&nbsp;r0,&nbsp;#SYSINTR_RESCHED&quot;,&nbsp;轮询的时间片已经用完了,&nbsp;只好进行调度了,PendEvents,&nbsp;等下个时间片再来解决了.具体做法十分严谨,不过我还不太看得懂这堆ARM汇编,&nbsp;望洋兴叹了.<br /><br />这样汇编里的ISR就走完了。<br /><br />现在从最高层面上的device&nbsp;driver往下走.<br />device&nbsp;drvier在initialize过程中,肯定有个初始化中断的过程.&nbsp;典型的做法是首先调用GetISRInfo函数从注册表里把IRQ和SysIntr读出来(当然同时还读了InterfaceType,&nbsp;BusNumber等其他东东),&nbsp;然后前面会声明个m_hISTEvent的handler,&nbsp;在这里就CreatEvent,&nbsp;建立IST事件.&nbsp;如果EVENT建立成功,&nbsp;下面就InterruptInitialize(SysIntr,&nbsp;m_hISTEvent),把这个调度中断号和ISTEVENT关联起来.&nbsp;具体在WINCE&nbsp;HELP里面可以查到InterruptInitialize这个API的用法.&nbsp;&nbsp;&nbsp;<br /><br />关于这个InterruptInitialize,&nbsp;可以在wince500privatewinceoscoreoscoredllCoredll.def里面Ln1355找到这么一行:<br />InterruptInitialize=xxx_InterruptInitialize&nbsp;@627<br /><br />也就是InterruptInitialize实际上属于Coredll.dll的,并且被调用时实际上是去运行&nbsp;xxx_InterruptInitialize函数&nbsp;(&nbsp;前三个字估计是MS程序员写什么政治敏感词汇,&nbsp;结果提交代码时被系统屏蔽成xxx了,哈哈)&nbsp;&nbsp;这个xxx函数是看不到源代码的,不过我们可以跟踪抓出它的汇编<br />xxx_InterruptInitialize:<br />03F70744&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r12,&nbsp;sp<br />03F70748&nbsp;&nbsp;&nbsp;&nbsp;stmdb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp!,&nbsp;{r0&nbsp;-&nbsp;r3}<br />03F7074C&nbsp;&nbsp;&nbsp;&nbsp;stmdb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp!,&nbsp;{r4,&nbsp;r12,&nbsp;lr}<br />03F70750&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp,&nbsp;sp,&nbsp;#0x14<br />$M20120:<br />03F70754&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;#0<br />03F70758&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;r3,&nbsp;#0xE,&nbsp;22<br />03F7075C&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[r3]<br />03F70760&nbsp;&nbsp;&nbsp;&nbsp;sub&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;r3,&nbsp;#0x14<br />03F70764&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[r3]<br />03F70768&nbsp;&nbsp;&nbsp;&nbsp;tst&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;#1<br />03F7076C&nbsp;&nbsp;&nbsp;&nbsp;beq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|$M20120+44h&nbsp;(03f70798)|<br />03F70770&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[pc,&nbsp;#0x74]<br />03F70774&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[r3]<br />03F70778&nbsp;&nbsp;&nbsp;&nbsp;cmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;#0<br />03F7077C&nbsp;&nbsp;&nbsp;&nbsp;beq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|$M20120+44h&nbsp;(03f70798)|<br />03F70780&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[pc,&nbsp;#0x64]<br />03F70784&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[r3]<br />03F70788&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;r3,&nbsp;#0x69,&nbsp;30<br />03F7078C&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[r3]<br />03F70790&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#0xC]<br />03F70794&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|$M20120+4Ch&nbsp;(03f707a0)|<br />03F70798&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[pc,&nbsp;#0x48]<br />03F7079C&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#0xC]<br />03F707A0&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;cbData<br />03F707A4&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r2,&nbsp;pvData<br />03F707A8&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r1,&nbsp;hEvent<br />03F707AC&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,&nbsp;idInt<br />03F707B0&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r4,&nbsp;[sp,&nbsp;#0xC]<br />03F707B4&nbsp;&nbsp;&nbsp;&nbsp;mov&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lr,&nbsp;pc<br />03F707B8&nbsp;&nbsp;&nbsp;&nbsp;bx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r4<br />03F707BC&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,&nbsp;[sp,&nbsp;#0x10]<br />03F707C0&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#0x10]<br />03F707C4&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#4]<br />03F707C8&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,&nbsp;sp,&nbsp;#0<br />03F707CC&nbsp;&nbsp;&nbsp;&nbsp;bl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|KillThreadIfNeeded_t::~KillThreadIfNeeded_t&nbsp;(03f60928)|<br />03F707D0&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#4]<br />03F707D4&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r3,&nbsp;[sp,&nbsp;#8]<br />03F707D8&nbsp;&nbsp;&nbsp;&nbsp;ldr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r0,&nbsp;[sp,&nbsp;#8]<br />03F707DC&nbsp;&nbsp;&nbsp;&nbsp;add&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp,&nbsp;sp,&nbsp;#0x14<br />03F707E0&nbsp;&nbsp;&nbsp;&nbsp;ldmia&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sp,&nbsp;{r4,&nbsp;sp,&nbsp;lr}<br />03F707E4&nbsp;&nbsp;&nbsp;&nbsp;bx&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lr<br />@_@&nbsp;&nbsp;看不懂.&nbsp;期待高人指点<br /><br />另外wince500publiccommonoakincMkfuncs.h里面Ln579看到&nbsp;<br />BOOL&nbsp;xxx_InterruptInitialize(DWORD&nbsp;idInt,&nbsp;HANDLE&nbsp;hEvent,&nbsp;LPVOID&nbsp;pvData,&nbsp;DWORD&nbsp;cbData);<br />#define&nbsp;InterruptInitialize&nbsp;xxx_InterruptInitialize<br />这个是头文件的include路径是&nbsp;mkfuncs.h&nbsp;-&gt&nbsp;kfuncs.h&nbsp;-&gt&nbsp;winbase.h&nbsp;-&gt&nbsp;windows.h.&nbsp;可能还有其他支路,但一般要调用的话,include&nbsp;&ltwindows.h&gt就行了<br /><br />然后简单说一下主要的调用层次关系 xxx_InteeruptInitialize&nbsp;-&gt&nbsp;SC_InterruptInitialize&nbsp;(wince500privatewinceoscoreos
kkernelintrapi.c)&nbsp;-&gt&nbsp;DoInterruptEnable&nbsp;(同上intrapi.c)&nbsp;-&gt&nbsp;OEMInterruptEnable&nbsp;(wince500platformcommonintrcommonoem.c)&nbsp;-&gt&nbsp;OALIntrEnableIrqs&nbsp;(wince500platformcommonintrpxa27xintr.c)<br /><br />这么长的三段主要就是为了说明,中断并不是在整个系统boot起来后就一口气全部ENABLE的,&nbsp;而是根据当前加载的模块,&nbsp;在调用InterruptInitialize的时候才进行Enable,&nbsp;这可以是去对INTR&nbsp;MASK&nbsp;REGISTER里面对应的BIT进行UNMASK,&nbsp;或者是把GPIO&nbsp;EDGE&nbsp;DETECT&nbsp;ENABLE,&nbsp;取决于中断实现的硬件途径.<br /><br />接上面话题,驱动中在InterruptInitialize后,最后在CeSetPriority把THREAD的优先级设一下就OK了.&nbsp;现在跳到driver的IST去看看,开始的地方一般就是个大的WHILE,里面有个WaitForSingleObject(m_hISTEvent,&nbsp;INFINITE),<br /><br />OK,那么在设备初始化完成后,Interrupt&nbsp;Service&nbsp;Thread就保持一个SUSPEND状态,保持WaitForSingleObject.&nbsp;&nbsp;中断发生后,在OEMInterruptHandler中会把这个IRQ转换成SYSINTR并通知系统(&nbsp;这个就是想当然的了,我没有看到具体怎样通知系统的,&nbsp;估计这段代码MS没有公开),&nbsp;则由于前面已经将SYSINTR和ISTEVENT相关联,&nbsp;所以系统收到这个SYSINTR后,就把SET相关的EVENT.&nbsp;从而IST从WaitForSingleObject里跳出往下继续执行,进而读取自己模块的Interrupt&nbsp;Status&nbsp;Register进行判断,操作其他register控制硬件,&nbsp;完成后调用InterruptDone函数告知系统,然后又回到WaitForSinigleObject里去傻等了.<br /><br />现在整个中断处理过程中,只剩下一块的代码没有看到/找到。那就是转换成SysIntr后,如何告知系统,并且把相关的模块的中断处理事件SetEvent.&nbsp;我估计是在private里面。如果要深究的话,可以从上面提到的xxx_InterruptXXXXXX系列函数入手。<br /><br />-------------------------------------------------------<br /><br />下面举个实际的例子,我在已有的代码中开启一个STUART的中断让APPLICATION使用(intel&nbsp;pxa270平台),步骤如下<br /><br />1.首先在platformwindowtvsrccommonpxa27xinculverde_intr.h中检查是否定义了IRQ_STUART,&nbsp;所定义的中断号是否和pxa27x&nbsp;manual上面的一样.&nbsp;如果没有就自己添加进去。<br /><br />2.在&nbsp;platformwindowtvsrccommonintrpxa27xintr.c&nbsp;中的g_InPriorties数组里,&nbsp;加入IRQ_STUART.&nbsp;该数组在OALIntrInit()中初始化Interrupt&nbsp;Priority&nbsp;Registers的时候会用到<br /><br />3.在platformwindowtvsrcincsp_cfg,h中添加系统中断号SYSINTR_STUART.&nbsp;这里要用define也行.<br /><br />4.platformwindowtvsrckerneloalintr.c中,&nbsp;函数BSPIntrInit()里添加软硬件中断号的关联&nbsp;OALIntrStaticTranslate(SYSINTR_STUART,&nbsp;IRQ_STUART);<br /><br />最后在驱动程序里建立一个事件,然后用InterruptInitialize(sysintr,&nbsp;istevent,&nbsp;0,&nbsp;0)把系统中断号和事件关联,&nbsp;那么硬件中断就能够进到系统中断进而设置事件.&nbsp;驱动程序得到了事件,&nbsp;就爱干嘛干嘛吧……<br /><br /><br />-----The&nbsp;End-----<br />Copyright&nbsp;@&nbsp;Walzer&nbsp;2005
 楼主| 驱动开发版 发表于 2007-9-25 11:20 | 显示全部楼层

基于S3C2410,Windows CE4.2,BSP是smdk2410。

WinCE的中断处理是三个映射关系:<br /><br />ISQ&nbsp;--&gt&nbsp;Interrupt&nbsp;ID(逻辑中断号)&nbsp;&nbsp;--&gt&nbsp;Event对象。<br /><br />当中断发生时,ISR(中断服务例程)返回该中断号对应的逻辑中断号,然后尽可能快地返回;随后CE就set该逻辑中断号对应的Event对象(如果有的话),以唤醒在该Event等待的IST(中断服务线程),大部分工作都是由IST来完成。一般来说IST是存在驱动程序里,单其实放在普通的应用程序里也可以,尤其是对应只有一个应用程序使用的特殊硬件更方便。因为对应CE来说其实驱动程序也只是一个普通的DLL,也是运行在用户空间。<br /><br />为了简单起见我们就直接修改BSP包的ISR部分,IST也直接在应用程序里实现,步骤如下:<br /><br />1、在BSP的oalintr.h里定义自定义中断的逻辑中断值,如:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;#define&nbsp;SYSINTR_MYINTR&nbsp;&nbsp;(SYSINTR_FIRMWARE&nbsp;+&nbsp;10)<br /><br />2、修改KERNELHALcfw.c中的以下三个函数,增加对自定义中断的启用禁用代码:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;OEMInterruptEnable(),&nbsp;OEMInterruptDisable(),&nbsp;OEMInterruptDone()<br /><br />3、修改KERNELHALARMarmint.c中的OEMInterruptHandler(),对irq返回逻辑中断号,如:<br />&nbsp;else&nbsp;if&nbsp;(IntPendVal&nbsp;==&nbsp;INTSRC_EINT2)&nbsp;//&nbsp;EINT2<br />&nbsp;&nbsp;&nbsp;&nbsp;return(SYSINTR_MYINTR);<br /><br />4、在PlatformBuilder中重新生成nk.bin,下载运行。<br /><br />现在,内核已经支持我们的自定义中断SYSINTR_MYINT了,我们在应用程序中就可以把这个SYSINTR_MYINT与一个Event对象关联起来,然后在一个线程里等待这个Event就ok了,这个线程就是IST。<br /><br />5、在IST里用InterruptInitialize()将自定义中断和Event关联起来,并WaitForSingleObject()。注意下面的代码是在一个线程里(即IST):<br />&nbsp;hEvent&nbsp;=&nbsp;CreateEvent(NULL,&nbsp;FALSE,&nbsp;FALSE,&nbsp;NULL));<br />&nbsp;InterruptInitialize(SYSINTR_MYINTR,&nbsp;hEvent,&nbsp;NULL,&nbsp;0));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//若没有修改OEMInterruptEnable(),这个调用就会失败<br />&nbsp;while&nbsp;(&nbsp;TRUE&nbsp;)<br />&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;WaitForSingleObject(hEvent,&nbsp;INFINITE);<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;do&nbsp;some&nbsp;process...<br />}
 楼主| 驱动开发版 发表于 2007-9-25 11:30 | 显示全部楼层

pb5 和 pb4.2的略有不同

pb5的OEMInterruptHandler()是在csp里面intr.c<br /><br />而OEMInterruptEnable()...等函数是在oal里面的intr.c交由OALIntrEnableIrqs()处理.
HWM 发表于 2007-9-29 07:58 | 显示全部楼层

顶!

  
huangqi412 发表于 2007-10-6 09:17 | 显示全部楼层

学习

  
cecwxf 发表于 2011-5-25 17:57 | 显示全部楼层
此贴解我疑惑  谢谢
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

22

帖子

0

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