ARM中断分析之四:WinCE的OAL层的中断分析

从前面的介绍,我们知道了裸机中断处理的流程、WINCE驱动的中断处理,但是,WINCE底层是怎么处理中断的呢?这里就是介绍WinCE系统的OAL层的中断处理。它和裸机的处理总体一样,只是实现细节方面有点区别,具体流程如下:

一、在OAL层的初始化函数,在系统启动的过程中被调用,如下所示:

BOOL OALIntrInit()
{
BOOL rc = FALSE;
// Initialize interrupt mapping
OALIntrMapInit();
// First get uncached virtual addresses
g_pIntrRegs = (S3C2410X_INTR_REG*)OALPAtoVA(
S3C2410X_BASE_REG_PA_INTR, FALSE
);
g_pPortRegs = (S3C2410X_IOPORT_REG*)OALPAtoVA(
S3C2410X_BASE_REG_PA_IOPORT, FALSE
);
// Mask and clear external interrupts
OUTREG32(&g_pPortRegs->EINTMASK, 0xFFFFFFFF);
OUTREG32(&g_pPortRegs->EINTPEND, 0xFFFFFFFF);
// Mask and clear internal interrupts
OUTREG32(&g_pIntrRegs->INTMSK, 0xFFFFFFFF);
OUTREG32(&g_pIntrRegs->SRCPND, 0xFFFFFFFF);
// S3C2410X developer notice (page 4) warns against writing a 1 to any
// 0 bit field in the INTPND register. Instead we'll write the INTPND
// value itself.
OUTREG32(&g_pIntrRegs->INTPND, INREG32(&g_pIntrRegs->INTPND));
// Unmask the system tick timer interrupt
CLRREG32(&g_pIntrRegs->INTMSK, 1 << IRQ_TIMER4);
// Give BSP change to initialize subordinate controller
rc = BSPIntrInit(); // 配置某些外设的中断配置,比如以太网,但这不是必须的,也可以在以太网驱动内实现。
return rc;
}

实际上,上面这部份的初始化是超简单的,总结为完成的事情如下:
1、外设引脚功能的配置及中断触发方式,图中所示是:GPFCON、EXTINT0
2、中断mask码、优先级、模式的设定,包括子级掩码、主级掩码,图中所示是:EINTMASK、MASK、MODE、Priority。

二、中断服务程序,它会在硬件IRQ产生时被调用
中断服务程序是IRQ中断的入口点,代码如下所示:
ULONG OEMInterruptHandler(ULONG ra)
{
UINT32 sysIntr = SYSINTR_NOP;
UINT32 irq, irq2 = OAL_INTR_IRQ_UNDEFINED, mask;
fInterruptFlag = TRUE; // Signal OemIdle to come out of idle.
// Get pending interrupt(s)
irq = INREG32(&g_pIntrRegs->INTOFFSET);
// System timer interrupt? 系统时间中断?
if (irq == IRQ_TIMER4) {
// Clear the interrupt
OUTREG32(&g_pIntrRegs->SRCPND, 1 << IRQ_TIMER4);
OUTREG32(&g_pIntrRegs->INTPND, 1 << IRQ_TIMER4);
// Rest is on timer interrupt handler
sysIntr = OALTimerIntrHandler();
}
// Profiling timer interrupt?
else if (irq == IRQ_TIMER2)
{
// Mask and clear the interrupt.
mask = 1 << irq;
SETREG32(&g_pIntrRegs->INTMSK, mask);
OUTREG32(&g_pIntrRegs->SRCPND, mask);
OUTREG32(&g_pIntrRegs->INTPND, mask);
// The rest is up to the profiling interrupt handler (if profiling
// is enabled).
//
if (g_pProfilerISR)
{
sysIntr = g_pProfilerISR(ra);
}
}
else
{
if (irq == IRQ_EINT4_7 || irq == IRQ_EINT8_23) {
// Find external interrupt number
mask = INREG32(&g_pPortRegs->EINTPEND);
mask &= ~INREG32(&g_pPortRegs->EINTMASK); // Find the effect interrupt number
/*
// g_i[i], g_i[i] ^(g_i[i]-1), g_i[i]^(g_i[i]-1)) >> 5
1: 1 : 0
2: 3 : 0
4: 7 : 0
8: 15 : 0
16: 31 : 0
32: 63 : 1
64: 127 : 3
128: 255 : 7
256: 511 : 15
512: 1023 : 31
1024: 2047 : 63
*/
mask = (mask ^ (mask - 1)) >> 5;
irq2 = IRQ_EINT4;
while (mask != 0) {
mask >>= 1;
irq2++;
}
// Mask and clear interrupt
mask = 1 << (irq2 - IRQ_EINT4 + 4);
SETREG32(&g_pPortRegs->EINTMASK, mask);
OUTREG32(&g_pPortRegs->EINTPEND, mask);
// calculate mask for primary interrupt
mask = 1 << irq;
// update irq
irq = irq2;
} else {
// Mask the interrupt
mask = 1 << irq;
SETREG32(&g_pIntrRegs->INTMSK, mask);
}
// clear primary interrupt
OUTREG32(&g_pIntrRegs->SRCPND, mask);
OUTREG32(&g_pIntrRegs->INTPND, mask);
// First find if IRQ is claimed by chain
sysIntr = NKCallIntChain((UCHAR)irq);
if (sysIntr == SYSINTR_CHAIN || !NKIsSysIntrValid(sysIntr)) {
// IRQ wasn't claimed, use static mapping
sysIntr = OALIntrTranslateIrq(irq);
}
// unmask interrupts in case it's NOP or invalid
if (SYSINTR_NOP == sysIntr) {
if (OAL_INTR_IRQ_UNDEFINED == irq2) {
// Unmask the primary interrupt
CLRREG32(&g_pIntrRegs->INTMSK, mask);
} else {
// Unmask the external interrupt
mask = 1 << (irq2 - IRQ_EINT4 + 4);
CLRREG32(&g_pPortRegs->EINTMASK, mask);
}
}
}
return sysIntr;
}
从上面代码总结出,中断服务程序主要做的事情是:
1、从INTPND得知主级中断中的中断号。
2、从EINTPEND得知次级中断中的中断号。
3、置位或者清零中断控制器的寄存器
·置位次级的mask
·置位主级的mask
·清理次级中断PND,图中所示为:EINTPEND
·清理主级中断PND,图中所示为:SRCPND
4、最后返回一个中断号sysIntr,这个是逻辑上面的中断号,和WINCE驱动的逻辑中断号相对应。

三、OALIntrDoneIrqs函数
WinCE驱动在处理中断完毕后,会调用InterruptDone函数,此函数会调用OALIntrDoneIrqs函数,OALIntrDoneIrqs函数内容如下:
VOID OALIntrDoneIrqs(UINT32 count, const UINT32 *pIrqs)
{
UINT32 i, mask, irq;
for (i = 0; i < count; i++) {
// Depending on IRQ number use internal or external mask register
if (irq <= IRQ_ADC) {
// Use internal interrupt mask register
mask = 1 << irq;
CLRREG32(&g_pIntrRegs->INTMSK, mask);
} else if (irq <= IRQ_EINT23) {
// Use external mask register
mask = 1 << (irq - IRQ_EINT4 + 4);
CLRREG32(&g_pPortRegs->EINTMASK, mask);
}
}
}
从上面的代码可知,OALIntrDoneIrqs所做的事情是在中断处理完毕之后的清零主级的mask或者清零次级的mask。

现在回顾一下整理,在OEMInterruptHandler函数内清零PND,这样做是有好处的。不然,在驱动内实现的话,就要严格按照步骤来清零,即:先清零PND,然后再清零外设PND。为什么要先清零PND,然后再清零外设PND,可以参考我写的另一篇文章“应该怎么样清理中断的PND位?”。

结论是,WinCE在默认情况下,适合边缘触发的中断,如果需要处理电平触发的话,需要同时修改OEMInterruptHandler函数和OALIntrDoneIrqs函数,在OEMInterruptHandler函数内不要清零PND而在OALIntrDoneIrqs内清零PND,这样才能避免重复处理同一个中断。

总之,WINCE的OAL层和中断相关的函数是:
ULONG OEMInterruptHandler(ULONG ra); //中断服务函数

void OEMInterruptDone( DWORD idInt ); //中断处理完毕的函数
void OEMInterruptDisable( DWORD idInt ); //禁用中断的函数
BOOL OEMInterruptEnable( DWORD idInt, LPVOID pvData, DWORD cbData ); //启用中断的函数
当然,还有中断初始化函数,但那是非OEM函数,即自己定义。以上几个函数的源码,可以参考相应的BSP包。

仅管OEMInterruptDone和OEMInterruptEnable,在功能上都是把指定IRQ的MASK给清零,但是OEMInterruptEnable需要多做一件事情,它需要把前一级的相应的PND寄存器给清零,意思是:清除以前发生的中断,现在开始处理新的中断。

OEMInterruptDone会调用OALIntrDoneIrqs,OALIntrDoneIrqs调用BSPIntrDoneIrq,主要的功能处理都在OALIntrDoneIrqs函数内实现。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/435555.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【转】TinyXML2 入门教程

转自&#xff1a;TinyXML2 入门教程_恋喵大鲤鱼的博客-CSDN博客_tinyxml2中文指南 代码编译运行环境&#xff1a;Linux 64bits Debug g -m64&#xff08;-m 表示生成 64bits 的程序&#xff09; 文章目录 1.TinyXML2 概述2. TinyXML1 与 TinyXML2 对比3. TinyXML2 用法用例…

解决“A problem has been encountered while loading the setup components. Canceling setup.”的问题...

近来因为需要开发C的程序&#xff0c;所以要在Visual Studio 2008中添加C的开发组件&#xff0c;但是在添加组件的时候&#xff0c;弹出“A problem has been encountered while loading the setup components. Canceling setup.”的提示。无奈之下&#xff0c;只好卸载&#x…

【转】linux 查看动态库和可执行程序依赖库

转自&#xff1a;linux 查看动态库和可执行程序依赖库_帅的没朋友~的博客-CSDN博客_linux 查看动态库 目录 一:objdump二:readelf三:ldd四:进程是否依赖指定一:objdump # 查看依赖的库 objdump -x xxx.so | grep NEEDED# 查看可执行程序依赖的库 objdump -x ./testTime | gr…

WinCE下的GPIO中断的处理

在我所负责的音频驱动部分代码中,采用了PXA270的GPIO34来检测Headphone的插入与拔出.原驱动部分有个BUG,即当耳机插入以后,耳机和喇叭同时在响,很明显没有对耳机插入事件做出响应.所以我开始采用了检测GPIO信号拉高或者拉低和检测耳机的插入事件,但是这样做有个问题,就是会有延…

xvhfeng的工作回忆总结(第二年)阅读手记

xvhfeng 工作回忆总结&#xff08;第二年&#xff09; 上接工作第一年回忆总结,时间来到了工作第二年&#xff0c;我在PM的帮助下拿到了令自己满意的工资&#xff0c;又开始加入公司正常的工作。 上文说到有一个外省市&#xff08;以下称为A市&#xff09;的项目在做&#xff…

【转】详解JS的四种异步解决方案:回调函数、Promise、Generator、async/await

转自&#xff1a;详解JS的四种异步解决方案&#xff1a;回调函数、Promise、Generator、async/await 同步&异步的概念 在讲这四种异步方案之前&#xff0c;我们先来明确一下同步和异步的概念&#xff1a; 所谓同步(synchronization)&#xff0c;简单来说&#xff0c;就是…

S3C2440中断解析和基于WINCE操作系统的中断分析(整理于网络,用于按键中断使用)

在调试CAN总线的时候&#xff0c;遇到了操作系统的中断&#xff0c;为了彻底的弄清楚中断是怎么回事&#xff1f;我先从底层的中断开始研究&#xff0c;在这里我们只讨论外部中断&#xff0c;下面就结合S3C2440TEST测试程序来分析一下中断是怎么执行的&#xff1a;我们研究的是…

修改 MrBayes 3.2 源码解决不能恢复断点的问题

当数据量较大时&#xff0c;用MrBayes进行计算通常是旷日持久的事情&#xff0c;几天甚至几个月。中间如果断电死机什么的发生就很令人发狂了。于是 MrBayes 3.2 svn 版增加了一个断点保存的功能&#xff0c;死机后可以从保存的断点处继续计算。只要在mcmc命令中加入checkfreqn…

【转】ubuntu下为APT设置代理

转自&#xff1a;https://blog.csdn.net/lwbeyond/article/details/8431927 Ubuntu下为APT设置代理一.最简单的方法 图形界面方法&#xff1a;新立得软件包管理器-->设置-->首选项-->网络。 进行设置代理就可以了。二.编辑命令 方法1&#xff1a;验证通过 如果您 希望…

wince6.0 s5pv210 中断

1. 在smdkv210\src\oal\oallib\ksarm.h头文件里可以看到wince的中断定义。 设备中断的起始编号即wince预定义的设备中断ID的基值 SYSINTR_DEVICES EQU 8 一共支持64个设备中断 SYSINTR_MAX_DEVICES EQU 64 可用的设备…

Regular Expression

Reference: 正则表达式三十分钟入门&#xff1a; http://deerchao.net/tutorials/regex/regex.htm 在线测试工具&#xff1a; regexlib&#xff08;http://regexlib.com/default.aspx&#xff09; 吐血推荐&#xff0c;比较狠的一个工具&#xff1a; Expresso &…

【转】vsftp配置实例-虚拟用户锁定目录

转自&#xff1a; vsftp配置实例-虚拟用户锁定目录_jasonyang69的博客-CSDN博客_vsftpd锁定用户目录 快速解决 vsftpd nologin 虚拟用户 拒绝访问 无法登录_小飞飞飞鱼的博客-CSDN博客_vsftpd 拒绝访问 一、实验步骤 0、启用 nologin shell #vim /etc/shells /bin/sh /bi…

顺丰快递,果然不一般!

2010-06-03 18:27:03快件到达北京集散点 2010-06-03 19:15:41快件离开北京集散点 发往北京集散中心 2010-06-03 21:05:34快件到达北京集散中心 2010-06-03 21:06:12快件离开北京集散中心 发往深圳集散中心 2010-06-04 02:56:29快件到达深圳集散中心 2010-06-04 02:57:04快件离开…

windowsCE异常和中断服务程序初探(-)

1。中断/异常相量的装入和执行方式。 中断和异常都是异步发生的事件&#xff0c;当该事件发生&#xff0c;系统将停止目前正在执行的代码转而执行事件响应的服务程序。而事件服务程序的入口点就是中断/异常向量所在的位置。arm的中断向量可以是0x0开始的低地址向…

windowsCE异常和中断服务程序初探(=)

继续上次的内容&#xff0c;在上次的分析中我们已经对SWI,FIQ,IRQ的流程有了一个大概的认识&#xff0c;下面继续对DataAbort和PrefetchAbort以及公共分发程序CommonHandler进行一下认识&#xff0c;完整异常处理的流程。 2-4 DataAbort服务程序 由数据异常触发&…

【转】Linux中tty、pty和pts概念及区别

转自&#xff1a;Linux中tty、pty和pts概念及区别 - 知乎 基本概念 ①tty(终端设备的统称): tty一词源于Teletypes&#xff0c;或者teletypewriters&#xff0c;原来指的是电传打字机&#xff0c;是一种通过串行线连接键盘和打印机进行发送、阅读信息的设备&#xff0c;后来…

Microsoft Jet SQL 参考在线手册

http://www.weste.net/book/sql/转载于:https://www.cnblogs.com/cwfsoft/archive/2010/06/19/1760961.html

Windows CE下驱动程序开发基础

我想即使读者看过微软的关于驱动开发的培训教材和CE帮助文档中的驱动部分&#xff0c;头脑中仍然一片茫然。要想真正了解驱动程序必须结合一些驱动程序源码&#xff0c;在此我以串口驱动程序&#xff08;COM16550&#xff09;中初始化过程为线索简单讲一讲驱动开发的基础知识。…

【转】高端球管使用了哪些高科技?

转自&#xff1a;高端球管使用了哪些高科技&#xff1f; 本文来源&#xff1a;第三方维修平台 本文作者&#xff1a;RepairCT 随着人类发现X射线&#xff0c;这项技术不断应用到医学领域&#xff0c;比如X光机、DR、CT、乳腺钼靶等医疗设备&#xff0c;它们的主要核心均是利用…

关于代码组织的一些看法(上)

今天看了一个篇关于架构的文章&#xff0c;略有所感&#xff0c;记录一下。 软件的架构基本是从一个原始需求出发&#xff0c;逐步构建可维护、更灵活的开发框架的过程&#xff0c;在这个构建过程中可能会逐渐的增加代码的复杂度来满足灵活性的要求&#xff0c;从这个层面来讲&…