中断实验(裸奔)

 一、实验平台:开发板fs2410,采用三星s3c2410的CPU,无操作系统。

二、实现功能:主程序让D9闪烁,用K1触发中断,点亮D12

三、实验原理:

       Fs2410开发板共有56个中断源,其中有24个外部中断,中断产生后,cpu会进入中断模式,程序计数器(PC)会跳转到异常向量表(IRQ中断时跳转到ox18处),执行相应的指令,一般为跳转指令,跳转到中断处理程序,完成相应的功能。

       中断产生后,CPU会停止正在运行的程序,转去执行中断程序,处理完中断程序后再返回接着处理被打断的程序。

四、实验现象:

       按下开关K1时,D12被点亮,D9保持现有状态不变,松开开关K1时,D12熄灭。D9继续闪烁。

五、实验总结:

       1、要清楚中断的流程,如使能中断和清除中断的步骤;

       2、请入中断后,首先要保护现场(各共有寄存器的值、返回地址);

       3、中断程序完成后,要恢复现场。

六、示例代码:

@******************************************************************************
@ File:head.S
@ 功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
@******************************************************************************       

.equ        MEM_CTL_BASE,       0x48000000
.equ        SDRAM_BASE,         0x30000000

.text
.global _start
_start:
@******************************************************************************       
@ 初始化向量向量表,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@****************************************************************************** 
    b   Reset

@ 0x04: 未定义指令中止模式的向量地址
HandleUndef:
    b   HandleUndef 
 
@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
    b   HandleSWI

@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
    b   HandlePrefetchAbort

@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
    b   HandleDataAbort

@ 0x14: 保留
HandleNotUsed:
    b   HandleNotUsed

@ 0x18: 中断模式的向量地址
    b   HandleIRQ

@ 0x1c: 快中断模式的向量地址
HandleFIQ:
    b   HandleFIQ

Reset:                  


    @ 关闭WATCHDOG,否则CPU会不断重启
    @ 往WATCHDOG寄存器写0即可
    mov r1,     #0x53000000
    mov r2,     #0x0
    str r2,     [r1]
    
    @时钟初始化
pllsetup:
	ldr r0,=0x4c000000  @LOCKTIME
	ldr r1,=0x00ffffff
	str r1,[r0]
	
	ldr r0,=0x4c000014  @CLKDIVN
	ldr r1,=0x3
	str r1,[r0]
	
    @/* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
    mrc    p15, 0, r1, c1, c0, 0        @/* 读出控制寄存器 */ 
    orr    r1, r1, #0xc0000000          @/* 设置为“asynchronous bus mode” */
    mcr    p15, 0, r1, c1, c0, 0        @/* 写入控制寄存器 */
    
    ldr r0,=0x4c000004  @MPLLCON
    ldr r1,=0x5c040
    str r1,[r0]
    
    
    @ 设置存储控制器
    @ 设置存储控制器以便使用SDRAM等外设

    mov 	r1,     #MEM_CTL_BASE    @ 存储控制器的13个寄存器的开始地址
    adrl    	r2, mem_cfg_val         @ 这13个值的起始存储地址
    add r3,     r1, #52              @ 13*4 = 52
1:  
    ldr r4,     [r2], #4            @ 读取设置值,并让r2加4
    str r4,     [r1], #4            @ 将此值写入寄存器,并让r1加4
    cmp r1,     r3                  @ 判断是否设置完所有13个寄存器
    bne 1b                          @ 若没有写成,继续
    
    @搬运代码到SDRAM
    @ 将Steppingstone的4K数据全部复制到SDRAM中去
    @ Steppingstone起始地址为0x00000000,SDRAM中起始地址为0x30000000
    
    mov r1, #0
    ldr r2, =SDRAM_BASE
    mov r3, #4*1024
1:  
    ldr r4, [r1],#4     @ 从Steppingstone读取4字节的数据,并让源地址加4
    str r4, [r2],#4     @ 将此4字节的数据复制到SDRAM中,并让目地地址加4
    cmp r1, r3          @ 判断是否完成:源地址等于Steppingstone的未地址?
    bne 1b              @ 若没有复制完,继续

    ldr pc,=on_sdram    @让PC跳到SDRAM中继续执行
on_sdram:
    
    @堆栈初始化,初始化IRQ和SYSTEM模式的堆栈
@init_stack:
    msr cpsr_c, #0xd2       @ 进入中断模式
    ldr sp, =0x33fffc00     @ 设置中断模式栈指针

    msr cpsr_c, #0xdf       @ 进入系统模式
    ldr sp, =0x34000000     @ 设置系统模式栈指针,
                            @ 其实复位之后,CPU就处于系统模式,

    bl  eint_init           @ 调用中断初始化函数,在init.c中
    msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断
    
    ldr lr, =halt_loop      @ 设置返回地址
    ldr pc, =main           @ 调用main函数  相等于bl main
halt_loop:
    b   halt_loop

            
   
	
HandleIRQ:
    sub lr, lr, #4                  @ 计算返回地址
    stmfd   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器
                                    @ 注意,此时的sp是中断模式的sp
                                    @ 初始值是上面设置的0x33fffc0
    
    @ldr lr, =int_return            @ 设置调用ISR即EINT_Handle函数后的返回地址  
    @ldr pc, =EINT_Handle           @ 调用中断服务函数,在interrupt.c中
    @int_return:
	
    bl light_on                     @中断处理函数
    ldmfd   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr
    



.align 4
mem_cfg_val:
    @ 存储控制器13个寄存器的设置值
    .long   0x22111120      @ BWSCON
    .long   0x00000700      @ BANKCON0
    .long   0x00000700      @ BANKCON1
    .long   0x00000700      @ BANKCON2
    .long   0x00000700      @ BANKCON3  
    .long   0x00000700      @ BANKCON4
    .long   0x00000700      @ BANKCON5
    .long   0x00018005      @ BANKCON6
    .long   0x00018005      @ BANKCON7
    .long   0x008E0459      @ REFRESH
    .long   0x000000B2      @ BANKSIZE
    .long   0x00000030      @ MRSRB6
    .long   0x00000030      @ MRSRB7



 

/*irq.c*/
#define SRCPND    (*(volatile unsigned long *)0x4a000000)
#define INTMOD    (*(volatile unsigned long *)0x4a000004)
#define INTMASK   (*(volatile unsigned long *)0x4a000008)
#define INTPND    (*(volatile unsigned long *)0x4a000010)
#define EXTINT2   (*(volatile unsigned long *)0x56000090)
#define EINTMASK  (*(volatile unsigned long *)0x560000a4)
#define EINTPEND  (*(volatile unsigned long *)0x560000a8)
#define GPECON    (*(volatile unsigned long *)0x56000040)
#define GPEDAT    (*(volatile unsigned long *)0x56000044)
#define GPFCON    (*(volatile unsigned long *)0x56000050)
#define GPFDAT    (*(volatile unsigned long *)0x56000054)
#define GPGCON    (*(volatile unsigned long *)0x56000060)

#define GPE11_out (1<<22)
#define GPF4_out  (1<<8)
#define GPF5_out  (1<<10)
#define GPF6_out  (1<<12)
#define GPF7_out  (1<<14)
#define GPG11_int (2<<22)

void eint_init(void)
{
	GPECON = GPE11_out;  //GPE11输出低电平
	GPEDAT &= ~(1<<11);

	GPGCON = GPG11_int;
	EXTINT2 |= (1<<13);  //EINT19设为下降沿触发

	EINTPEND = 0; //清除所有外部中断挂起状态
	SRCPND = 0;  //清除所有源挂起状态
	INTPND = 0;  //清除所有挂起状态
	INTMOD = 0;  //设置为IRQ模式

	EINTMASK &= ~(1<<19);  //EINT19允许响应
	INTMASK &= ~(1<<5);    //EINT8-23允许响应
}

void light_on(void)  //中断处理程序
{
	if((EINTPEND&(1<<19)) && (SRCPND&(1<<5))){  //有中断请求
		GPFDAT &= ~(1<<4);  //点亮D12
		EINTPEND |= (1<<19); //清中断,写1清0
		SRCPND |= (1<<5);
		INTPND = INTPND;  //清除响应的中断
	}
}

void wait(unsigned long dly)
{
	for(;dly>0;dly--);
}

int main(void)   //主程序,让D9闪烁
{
	GPFCON = GPF4_out|GPF5_out|GPF6_out|GPF7_out; 
	GPFDAT |= 0xf0;

	while(1){
		GPFDAT &= ~(1<<7);
		wait(200000);
		GPFDAT |= 0xf0;
		wait(200000);
	}
	
	return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值