S3C2440A中的中断控制器可以从60个中断源接收中断请求。这些中断源由内部外设提供,如表所列:
在前面我们使用
定时器定时报警,现在我们学会使用定时器中断方式实现定时报警。
► S3C2440的中断特性 32个中断请求优先级逻辑包括基于仲裁器的7个反转,6个一级仲裁器和一个2级仲裁器,如图所示。
每个仲裁器居于一个位仲裁器模式控制(ARB_MODE)和选择控制信号(ARB_SEL)的两位来处理6个中断请求。
ARB_MODE位控制优先级模式,为0固定优先级;为1翻转方式。
ARB_SEL的2个位设置如下:
● ARB_SEL位是00b,优先级是REQ0、REQ1、REQ2、REQ3、REQ4、REQ5。
● ARB_SEL位是01b,优先级是REQ0、REQ2、REQ3、REQ4、REQ1、REQ5。
● ARB_SEL位是10b,优先级是REQ0、REQ3、REQ4、REQ1、REQ2、REQ5。
● ARB_SEL位是11b,优先级是REQ0、REQ4、REQ1、REQ2、REQ3、REQ5。
注意:仲裁器的REQ0总是有最高优先级,REQ5总是有最低优先级。此外通过改变ARB_SEL位,我们可以反转REQ1到REQ4的优先级。
♥ 中断处理过程: ● 中断控制器汇集各类外设发出的中断信号,然后通知CPU;
● CPU保存程序的运行
环境(保存相应
寄存器的值),
调用中断服务程序(ISR)来处理这些中断;
● 在ISR中通过读取中断控制器,外设的相关寄存器来识别这个是那个中断,并进行相应的处理;
● 清楚中断: 通过读写中断控制器和外设的相关寄存器来实现;
● 最后恢复被中断程序的运行环境(即上面保存的各个寄存器等),继续执行。
► S3C2440的中断寄存器 中断源的所有中断请求首先都是在中断源未决寄存器中,基于中断模式寄存器中断请求分为两组包括快速中断请求(FIQ)和中断请求(IRQ)。对于多个IRQ的仲裁过程是基于优先级寄存器。
在S3C2440中断控制器中有5个控制寄存器:
♥ 中断源未决寄存器(SRCPND) SRCPND寄存器包括32位,每位与一个中断源相关。如果相应的中断源产生中断请求且等待中断服务,则相应位置1(具体中断源表查看说明书),因此这个寄存器指出哪个中断源在等待中断服务。
注意:SRCPND的每个位都由中断源自动置位,不管INTMASK寄存器的屏蔽位,并不受中断控制器的优先级逻辑的映像。
可以通过写
数据到这个寄存器来清除SRCPND寄存器的某个位,向相应位置1来清除相应位。如果写0,则该位的数值保持不变。
♥ 中断模式寄存器(INTMOD) 该寄存器包括32位,每位与一个中断源相关,如果某位置1,相应的中断将在FIQ模式下处理。否则在IRQ模式下操作。
注意:仅有一个中断源能够在FIR模式下服务,也就是说,INTMOD仅有一个位可以被置1。
♥ 屏蔽寄存器(INTMSK) 该寄存器包括32位,每位与一个中断源相关,如果某位置1,则CPU不会服务相应中断源的中断请求。如果屏蔽位为0,中断请求可以被服务。
注意:被屏蔽的中断源,如果有中断产生,在SRCPND的相应位还是会被置1。
♥ 优先级寄存器(PRIORITY)中断优先级寄存器用于配置IRQ中断优先级,配置仲裁器组优先级翻转(ARB_MODE)使能,默认值为1(优先级翻转使能);仲裁器组优先级顺序(ARB_SEL),默认值为00(REQ=0-1-2-3-4-5)。
♥ 中断未决寄存器(INTPND)中断未决寄存器的32位显示是否相应的中断请求有最高优先级,其中断请求未屏蔽且在等待中断服务。因为INTPND寄存器位于优先级逻辑之后,仅1位可以被置1,且中断请求生成对CPU的IRQ。在对于IRQ的中断服务程序中,我们可以读取寄存器决定那个中断源被服务。
该寄存器每一位指出请求的状态:0,中断源没有被请求;1,中断源已经申请中断请求。向相应位置1来清除相应位。如果写0,则该位的数值保持不变。
► S3C2440定时器中断代码
- /********************************************************************
- * 名称:Timer1_ISR()
- * 功能:定时器1中断服务程序
- * 入口参数:
- ********************************************************************/
- void __irq Timer1_ISR(void)
- {
- static int count;
- count ++;
- rSRCPND = rSRCPND | (0x1<<11);
- rINTPND = rINTPND | (0x1<<11);
- //每隔为1秒蜂鸣器响一次,持续时间为0.5秒
- if (count % 1000 ==0)
- rGPADAT |= (1<<16); //蜂鸣器响
- else if (count % 1000 ==500)
- rGPADAT &= ~(1<<16); //蜂鸣器不响
- }
复制代码
- /********************************************************************
- * 名称:Timer1_init()
- * 功能:定时器1初始化
- * 入口参数:
- ********************************************************************/
- void Timer1_init(void)
- {
- U32 time_val;
- rTCFG0 = 3; //配置定时器0,1的预分频值
- rTCFG1 = 0<<4; //配置定时器1分频值
- time_val = PCLK/ (3+1) / 2 / 1000 - 1; // 1ms = PCLK / prescaler / divider / 1000
-
- rSRCPND = rSRCPND | (0x1<<11); //清除中断源未决寄存器相应位
- rINTPND = rINTPND | (0x1<<11); //
- rINTMSK = ~(0x1<<11); //打开定时器1中断
-
- rTCNTB1 = time_val; //计数缓存寄存器
- rTCMPB1 = time_val>>1; // 50%
-
- rTCON &= ~(0xf<<8); //手动更新位且配置反相器位(开/关)(手动更行位将TCNTBn和TCMPBn的值分别给TCNTn和TCMPn寄存器)
- rTCON |= 0xb<<8; //定时器使能并自动重载
- rTCON &= ~(2<<8); //clear manual update bit
-
- pISR_TIMER1 = (U32)Timer1_ISR;
- }
复制代码 ► 定时器报警实验 ♥ 实验设备 硬件: PC机 一台
YX-AIO
嵌入式综合创新设计平台 一台
ARM9核心板 一块
软件: Windows操作系统,ADS1.2集成开发环境,H-JTAG下载环境
♥ 实验内容 使用定时器中断方式控制YX-AIO嵌入式综合创新设计平台上的蜂鸣器报警。
♥ 实验步骤 ① 在ADS开发环境中使用ARM9_S3C2440工程模版创建一个工程,并将程序代码添加到该工程;
② 在ADS开发环境中编译
链接并生成目标文件;
③ 将JTAG下载器连接YX-AIO嵌入式综合创新设计平台,并将该平台通电;
④ 开启H-JTAG软件检测
处理器与NOR-Flash;
⑤ 使用H-JTAG软件将目标文件(.bin)下载到YX-AIO嵌入式综合创新设计平台上;
⑥ 复位平台。
主程序代码:
- /********************************************************************
- ** 文件名:main()
-
- ** 文件名: main.c
-
- ** 修改时间: 2009-6-2
- ** 描述:
- ********************************************************************/
- void Main(void)
- {
- //----------------添加自己的代码-------------------
- rGPACON &= ~(1<<16);
- Timer1_init();
- while (1);
- }