jz2440裸机开发与分析:S3c2440ARM异常与中断体系详解6---按键中断程序示例概述与初始

在前面的视频里我们举了一个例子,母亲看书被声音打断,远处的声音来源有多种多样,声音传入耳朵,再由耳朵传入大脑,整个过程涉及声音来源耳朵大脑,为了确保这个母亲看书的过程能够被声音打断,我们必须保证声音来源可以发出声音,耳朵没有聋,脑袋没有傻。

中断处理流程
1、中断初始化:

①我们需要设置中断源,让它能够发出中断
②设置中断控制器,让它能发出中断给CPU
③设置CPU,CPSR有I位,是总开关

2、处理完之后清理中断

3、处理时,要分辨中断源,对于不同的中断源要执行不同的处理函数
下面开始写代码

打开start.S 先做初始化工作,先做第 3 设置CPU,CPSR有I位,是总开关

我们需要把CPSR寄存器 bit7给清零,这是中断的总开关,如果bit7设置为1,CPU无法响应任何中断
在这里插入图片描述

    /* 清除BSS段 */
    bl clean_bss

    /* 复位之后, cpu处于svc模式
     * 现在, 切换到usr模式
     */
    mrs r0, cpsr         /* 读出cpsr */
    bic r0, r0, #0xf     /* 修改M4-M0为0b10000, 进入usr模式 */

/*1
把bit7这一位清零
*/
    bic r0, r0, #(1<<7)  /* 清除I位, 使能中断 */
    msr cpsr, r0

    /* 设置 sp_usr */
    ldr sp, =0x33f00000

    ldr pc, =sdram
sdram:
    bl uart0_init

    bl print1
    /* 故意加入一条未定义指令 */
und_code:
    .word 0xdeadc0de  /* 未定义指令 */
    bl print2

    swi 0x123  /* 执行此命令, 触发SWI异常, 进入0x8执行 */

/*2 调用两个中断 */
    bl interrupt_init /*初始化中断控制器*/
    bl eint_init /*初始化按键,设为中断源*/

/*需要初始化上面这两个函数*/
    //bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
    ldr pc, =main  /* 绝对跳转, 跳到SDRAM */

halt:
    b halt

添加一个 interrupt.c文件,这个程序稍微有些复杂,我们先画个流程图

在这里插入图片描述
我们想达到按下按键灯亮松开按键灯灭,把下面四个按键全部配置为外部中断按键
在这里插入图片描述
打开芯片手册找到第九章 IO ports,直接搜索“’EINT0号中断和EINT2号中断”’,找配置寄存器 GPFCON

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述为了简单操作

/* 1、初始化按键,设置为中断源 */ 

void key_eint_int()
{
	/* 配置GPF0 GPF2 GPG3 GPG11中断引脚 */
	GPFCON  &= ~((3<<0) | (3<<4));
	GPFCON  |= ((2<<0) | (2<<4)); /* S2,S3被配置为中断引脚 */
	GPGCON  &= ~((3<<22) | (3<<6));
	GPGCON  |= ((2<<22) | (2<<6)); /* S4,S5被配置为中断引脚 */ 
	
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

/* 1、初始化按键,设置为中断源 */ 

void key_eint_int()
{
	/* 1、配置GPF0 GPF2 GPG3 GPG11中断引脚 */

	GPFCON  &= ~((3<<0) | (3<<4));
	GPFCON  |= ((2<<0) | (2<<4)); /* S2,S3被配置为中断引脚 */
	GPGCON  &= ~((3<<22) | (3<<6));
	GPGCON  |= ((2<<22) | (2<<6)); /* S4,S5被配置为中断引脚 */ 
	
	/* 2、设置中断触发方式: (按下松开,从低电源变为高电源,或者从)双边沿触发 */
	/*    设置<code>EINT0 EINT2</code>为双边沿触发                                   */
	EXTINT0 |= ((7<<0) | (7<<8)) /* S2,S3 */
	EXTINT1 |= (7<<12)           /* S4    */
	EXTINT2 |= (7<<12)           /* S5    */
}

外部中断屏蔽寄存器EINTMASK,设置为1的话就禁止向外部发出中断信号,只有EINTMASK相应的位设置为0外部中断才能给中断控制器发信号

我们需要设置这个寄存器
在这里插入图片描述
把EINT11设置为0 把EINT19设置为0对于EINT0 和EINT2显示为保留,默认时使能的,可以直接发送给中断控制器,无需设置
在这里插入图片描述
设置EINTMASK使能eint11,19
EINTMASK &= ~((1<<11) | (1<<19));

读EINTPEND分辨哪个EINT产生(eint4~23)(并且要清除它)
清除中断时, 写EINTPEND的相应位
在这里插入图片描述
我们接下来需要阅读‘第14章 Interrupt Controller章节设置中断控制器我们只需要按照下面这张流程图设置就可以了
在这里插入图片描述
MASK 屏蔽寄存器
INTPND 等待处理,我们可以读这个寄存器,确定是那个中断产生了
SRCPND不同的中断类型不可以直接到达这里执行

我们来看一下外部中断属于哪一种

打开芯片手册,从上往下读

在这里插入图片描述
由上图可得 EINT4_7 EINT8_23合用一条中断线ARB1

也就是可以直接到达SRCPND不需要设置SUBSRCPND和SUBMASK这两个寄存器

我们使用的外部中断源只需要设置SRCPND MASK INTPND这三个就可以
在这里插入图片描述
SRCPND表明中断请求状态标志位
SRCPND寄存器由32位组成,每一位都与中断源相关。如果相应的中断源生成中断请求并等待相应的中断服务,则将每个位设置为1,该寄存器指示哪个中断源正在等待服务请求。注意,SRCPND寄存器的每个位都是由中断源自动设置的,而不管INTMASK寄存器中的maskina位是什么。此外,SRCPND寄存器不受中断控制器优先级逻辑的影响。
在这里插入图片描述

 /* SRCPND 用来显示哪个中断产生了, 需要清除对应位,我们只需要关心
  * bit0对应eint0
  * bit2对应eint2
  * bit5对应eint8_23(表明bit5等于1的时候 eint8_23中的某一个已经产生,我们需要继续分辨
  * 读EINTPEND分辨率哪个EINT产生)
  */

INTMOD寄存器 ,模式选择,默认值为IRQ模式即可,不需要设置
在这里插入图片描述
INTMASK寄存器 ,决定哪个中断被屏蔽,需要设置为0
在这里插入图片描述

 /* INTMSK 用来屏蔽中断, 1对应masked屏蔽中断,我们需要设置相应位设置为0
  * bit0-eint0
  * bit2-eint2
  * bit5-eint8_23
  */

同时可能有多个中断产生,这么多个中断经过优先级以后,只会有一个通知CPU,是哪一个中断优先级最高,可以读INTPAD就能知道当前处理的唯 一 一个中断是那一个
INTPAD寄存器中的32位中的每一位都显示了对应的中断请求是否被解除屏蔽,并等待中断被服务。拥有最高优先级。由于INTPND register位于优先级逻辑之后,因此只能将一个位设置为1 ,而中断请求将生成IRQ到CPU。在中断服务程序为IRQ。您可以读取这个寄存器来确定在32个中断源中哪个中断源得到了服务。
在这里插入图片描述
1 表示这个中断已经产生,需要配置相应的位
INTPND 用来显示当前优先级最高的、正在发生的中断, 需要清除对应位
bit0-eint0
bit2-eint2
bit5-eint8_23

INTOFFSET寄存器 是用来显示INTPND寄存器中哪一位正在等待处理
在这里插入图片描述
INTPND中bit0等于0的话INTOFFSET就等于0
INTPND中bit1等于1的话INTOFFSET值就等于1
INTOFFSET : 用来显示INTPND中哪一位被设置为1

SUBSRCPND我们用不到
在这里插入图片描述
在这里插入图片描述
某一位等于1时INT_UART0它的来源可能有多个,这是串口0的中断,串口0的中断产生时有可能是接收到了数据(INT_RXD0),有可能是发送了数据(INT_TXD0),也有可能是产生了错误,那么到底是哪一个呢?

需要去读取SUBSRCPND下一级的源寄存器

我们只需要设置INTMSK寄存器 这个寄存器

SRCPND和INTPND 只有发生中断才需要设置

/* 初始化中断控制器 */
void interrupt_init(void)
{
    //1是屏蔽我们需要清零,外部中断0 外部中断2 外部中8_23里面还有外部中断11到19
    INTMSK &= ~((1<<0) | (1<<2) | (1<<5));

}

修改start.S
删除
bl interrupt_init /* 初始化中断控制器 /
bl key_eint_init /
初始化按键, 设为中断源 */

能使用c语言就使用C语言,在main.c文件中添加调用C函数

int main(void)
{
/************1/
    interrupt_init();  /* 初始化中断控制器 */
    key_eint_init();   /* 初始化按键, 设为中断源 */
*******/    
    puts("\n\rg_A = ");
    printHex(g_A);
    puts("\n\r");

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值