zoukankan      html  css  js  c++  java
  • [国嵌攻略][050][2440按键中断编程]

    程序结构优化

    1.把不同的功能放到不同的文件里面

    2.一般在bootloader中不使用MMU,所以关掉MMU

    按键初始化

    1.打开开发板的原理图,找到按键

    2.把对应的GPIO配置成中断,对中断源进行初始化

    初始化中断控制器

    1.SUBMASK和MASK必须要保证没有屏蔽中断,GPIO是不属于子中断,所以不用设置SUBMASK,MODE和Priority保存默认值即可,设置INTMSK(0x4A000008)

    2.EINT4_7对应4个中断,分开设置需要设置EINTMASK(0x560000A4)。注意,设置EINTMASK寄存器必须要在INTMASK之前设置

    3.在核心预处理时,关闭了中断,在这里需要打开中断

    中断处理

    1.当中断产生时,会跳转到中断向量表,执行ldr pc, _irq

    2.保存环境

    2.1.当前lr指向pc+8的位置,当中断返回时需要返回到lr-4的位置,算出lr的值,sub lr, lr, #4

    2.2.保存寄存器到堆栈,stmfd sp!, {r0-r12, lr}

    2.3.调用中断处理函数,handle_int

    2.4.从堆栈恢复寄存器,ldmfd sp!, {r0-r12, pc}^

    2.5.handle_int需要做:1.判断中断源 2.根据中断源,执行不同的中断处理。INTOFFSET(0x4A000014)标明了那个中断源产生了中断

    3.清除中断,在恢复环境之前先要清除SRCPND(0x4A000000)和INTPND(0x4A000010)对应位的请求,保证下次中断能被处理。如果下次中断到来,发现SRCPND和INTPND对应位为1,表示上次中断还没有被处理,忽略这次中断请求。如果用到是子中断需要清零SUBSRCPND,如果用到的是EINT4-ENT23那么要清除EINTPEND(0x560000A8)。注意,要清除中断时要往对应位上写入1

    4.注意在irq模式中设置的sp栈指针是r13_irq,而初始化栈sp指针是r13_svc。所以在初始化栈指针是要对r13_irq和r13_svc都要设置地址

    /********************************************************************
    *名称:irq
    *功能:中断处理
    *********************************************************************/
    irq:
    	//保存环境
    	sub lr, lr, #4            //三级流水线,pc指向指定的地址与当前执行指令的地址偏移+8
    	stmfd sp!, {r0-r12, lr}   //保存r0-r12和lr寄存器的值到栈中
    	
    	//处理中断
    	bl process_int
    	
    	//恢复环境
    	ldmfd sp!, {r0-r12, pc}^   //从栈中载入r0-r12和lr寄存器的值,^表示把spsr恢复到cpsr
    
    /********************************************************************
    *名称:int
    *作者:D
    *时间:2015.11.10
    *功能:中断控制器
    ********************************************************************/
    
    /********************************************************************
    *							 宏定义
    ********************************************************************/
    #define SRCPND 0X4A000000     //中断源请求寄存器
    #define INTPND 0X4A000010     //中断请求寄存器
    #define INTMSK 0x4A000008     //中断掩码寄存器
    #define EINTMASK 0x560000A4   //外部中断掩码寄存器
    #define EINTPEND 0x560000A8   //外部中断请求寄存器
    
    .text
    /********************************************************************
    *名称:init_int
    *功能:初始化中断
    *********************************************************************/
    .global init_int
    init_int:
    	//屏蔽中断
    	ldr r0, =INTMSK
    	mvn r1, #0   //屏蔽中断,设置INTMSK[31-0]:0xFFFFFFFF
    	str r1, [r0]
    	
    	//关闭中断
    	mrs r0, cpsr
    	orr r0, r0, #0x000000C0   //关闭中断,设置cpsr[7-6]:11
    	msr cpsr, r0
    	
    	mov pc, lr
    	
    /********************************************************************
    *名称:enable_int
    *功能:打开中断
    *********************************************************************/
    .global enable_int
    enable_int:
    	//使能中断
    	ldr r0, =EINTMASK
    	ldr r1, [r0]
    	bic r1, r1, #0x00000900   //使能外部中断,设置外部中断掩码EINT8:0 EINT11:0
    	str r1, [r0]
    	
    	ldr r0, =INTMSK
    	ldr r1, [r0]
    	bic r1, r1, #0x00000020   //使能中断,设置中断掩码EINT8_23:0
    	str r1, [r0]
    	
    	//打开中断
    	mrs r0, cpsr
    	bic r0, r0, #0x000000C0   //打开中断,设置cpsr[7-6]:00
    	msr cpsr, r0
    	
    	mov pc, lr
    	
    /********************************************************************
    *名称:process_int
    *功能:处理中断
    *********************************************************************/
    .global process_int
    process_int:
    	mov ip, lr   //保存链接寄存器,嵌套调用保存返回地址
    	
    	//读取中断源
    	ldr r0, =EINTPEND   //读取外部中断请求,如果中断从INTOFFSET中读取,子中断从SUBSRCPND
    	ldr r1, [r0]
    	
    	//处理中断源
    	cmp r1, #0x00000100   //如果是EINT8,调用EINT8中断处理
    	beq eint8_process
    	cmp r1, #0x00000800   //如果是EINT11,调用EINT11中断处理
    	beq eint11_process
    	b end_process_int     //如果都不是,结束中断处理
    	
    eint8_process:
    	bl on_led    //点亮led
    	b end_process_int
    	
    eint11_process:
    	bl off_led   //熄灭led
    	b end_process_int
    
    end_process_int:
    	//清除中断源
    	ldr r0, =EINTPEND
    	ldr r1, [r0]
    	str r1, [r0]              //清除外部中断请求
    	
    	ldr r0, =SRCPND
    	ldr r1, [r0]
    	orr r1, r1, #0x00000020   //清除中断源请求,设置EINT8_23:0,如果是子中断还要清除SUBSRCPND
    	str r1, [r0]
    	
    	ldr r0, =INTPND
    	ldr r1, [r0]
    	orr r1, r1, #0x00000020   //清除中断请求,设置EINT8_23:0
    	str r1, [r0]
    	
    	mov lr, ip   //恢复链接寄存器,嵌套调用恢复返回地址
    	mov pc, lr
    

    注意:在函数嵌套调用中要先把lr保存到ip中,在函数中被调用其他函数时会改变,当外部函数返回时,需要从ip中恢复lr,用于返回到外部函数被调用处

    r0-r15寄存器作用

    r0-r3

    用作传入函数参数,传出函数返回值。在子程序调用之间,可以将 r0-r3 用于任何用途。被调用函数在返回之前不必恢复 r0-r3。如果调用函数需要再次使用 r0-r3 的内容,则它必须保留这些内容。

    r4-r11

    被用来存放函数的局部变量。如果被调用函数使用了这些寄存器,它在返回之前必须恢复这些寄存器的值。

    r12

    是内部调用暂时寄存器 ip。它在过程链接胶合代码(例如,交互操作胶合代码)中用于此角色。在过程调用之间,可以将它用于任何用途。被调用函数在返回之前不必恢复 r12。

    r13

    是栈指针 sp。它不能用于任何其它用途。sp 中存放的值在退出被调用函数时必须与进入时的值相同。

    r14

    是链接寄存器 lr。如果您保存了返回地址,则可以在调用之间将 r14 用于其它用途,程序返回时要恢复

    r15

    是程序计数器 PC。它不能用于任何其它用途。

    注意:在中断程序中,所有的寄存器都必须保护,编译器会自动保护R4~R11

  • 相关阅读:
    fiddler修改请求和返回
    解决springboot在mac电脑下启动过慢的问题
    mysql中的联合查询(内联、左联、外联、右联、全联)
    servlet防止表单重复提交
    spring开发中常见错误集合,逐步添加
    spring4整合hibernate5以及出现的问题解决办法
    利用maven构建一个spring mvc的helloworld实例
    Hibernate5 入门之SessionFactory对象的创建
    OGNL表达式入门
    Template模版
  • 原文地址:https://www.cnblogs.com/d442130165/p/4955365.html
Copyright © 2011-2022 走看看