单片机 > 单片机程序设计 > 详情

根据韦东山修改的mini2440中断的裸机代码

发布时间:2020-08-27 发布时间:
|
这是根据韦东山的关于中断的代码改成在mini2440板子上可以运行的代码。
以下是5个文件的所有内容:
@是注释符!!
 
head.S文件内容:
 
 
@**************************************************************************
          File:head.S
          功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
@**************************************************************************
 
.extern    main
.text
.global    _start
_start:
@**************************************************************************
   中断向量,本程序中,除Reset和HandleIRQ外,其他异常都没有使用
@**************************************************************************
@0x00地址处的指令为"b Reset",在系统复位后,这条指令将跳去执行标号"Reset"开始的代码
          Reset
      
@0x04:未定义指令终止模式的向量地址
HandleUndef:
          HandleUndef
      
@0x08:管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
          HandleSWI
      
@0x0c:指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
          HandlePrefetchAbort
      
@0x10:数据访问终止导致的异常的向量地址  
HandleDataAbort:
          HandleDataAbort
      
@0x14:保留
HandleNotUsed:
          HandleNotUsed
      
@0x18:中断模式的向量地址     
          HandleIRQ
      
@0x1c:快中断模式的向量地址
HandleFIQ:
          HandleFIQ
      
Reset:
       ldr   sp,=4096              
@设置栈指针,以下都是C函数,调用前需要设好栈。栈是用   @来保存C函数的变量和返回地址
       bl    disable_watch_dog        @关闭WATCHDOG,否则CPU会不断重启
      
       msr  cpsr_c,#0xd2  @进入中断模式
       ldr   sp,=3072               @设置中断模式的栈指针,这里的sp寄存器是sp_irq
      
       msr  cpsr_c,#0xdf   @进入系统模式
       ldr   sp,=4096               @设置系统模式的栈指针,这里的sp寄存器是sp_sys
                                                        @其实复位之后,CPU就处于系统模式
                                                        @前面的"ldr  sp,=4096"完成同样的功能,此句可省略
      
       bl    init_led                 @初始化LED的GPIO管脚,在init.c中
       bl    init_irq                  @调用中断初始化函数,在init.c中
       msr  cpsr_c,#0x5f   @设置I-bit=0,开IRQ中断
      
       ldr   lr,=halt_loop   @设置返回地址
       ldr   pc,=main                                                                                      @调用main函数,main函数是个不做任何事的无限循环。当按下按键时,这个循环被打断,CPU进入
                                                                      @中断模式,执行“b HandleIRQ”的指令
halt_loop:
          halt_loop
      
HandleIRQ:                                @HandleIRQ开始的代码用于处理中断
       sub  lr,lr,#4                                        @计算中断处理完毕后的返回地址
       stmdb      sp!,{r0-r12,lr}              @保存使用到的寄存器
                                                                                           @注意,此时的sp是中断模式的sp
                                                                                           @初始值是上面设置的3072
      
       ldr   lr,=int_return                @设置调用ISR即EINT_Handle函数后的返回地址
       ldr   pc,=EINT_Handle                @调用中断服务函数,在interrupt.c中
      
int_return:
       ldmia      sp!,{r0-r12,pc}^    @中断返回,^表示将spsr的值复制到cpsr
      
 
       init.c文件内容:
 
 
 
 
 
 
 
 
#define    EINTMASK   (*(volatile unsigned long*)0x560000a4)//外部中断屏蔽寄存器
#define    INTMSK        (*(volatile unsigned long*)0x4a000008)
 
 
#define    GPBCON       (*(volatile unsigned long*)0x56000010)
#define    GPBDAT (*(volatile unsigned long*)0x56000014)
 
#define GPB5_out         (1< #define    GPB6_out             (1< #define    GPB7_out             (1< #define    GPB8_out             (1<  
 
#define    GPGCON       (*(volatile unsigned long*)0x56000060)
#define    GPGDAT (*(volatile unsigned long*)0x56000064)
 
#define    GPG0_eint                   (2<    //K1,EINT8
#define    GPG3_eint                   (2<    //K2,EINT11
#define    GPG5_eint                   (2<    //K3,EINT13
#define    GPG6_eint                   (2<    //K4,EINT14
 
 
 
#define   WTCON         (*(volatile unsigned long*)0x53000000)
 
void disable_watch_dog(void)
{
       WTCON=0;   
}
 
void init_led(void)
{
       GPBCON=GPB5_out|GPB6_out|GPB7_out|GPB8_out;     
       GPBDAT|=(0x0f<<5);          //所有LED熄灭,如果没有这一句,LED灯默认是全亮的
}
 
 
 
void init_irq()
{
       GPGCON=GPG0_eint|GPG3_eint|GPG5_eint|GPG6_eint; 
      
       //对于EINT8,EINT11,EINT13,EINT14,需要在EINTMASK寄存器使能它们
       EINTMASK&=(~(1<<8))&(~(1<<11))&(~(1<<13))&(~(1<<14));
       //这4个外部中断的优先级是相同的,EINT8_23都接仲裁器的REQ1引脚
       //所以不用像韦东山程序里那样再设置优先级了
      
       //EINT8,EINT11,EINT13,EINT14使能
       INTMSK&=(~(1<<5));
}
 
 
 
interrupt.c文件内容:
 
 
#define    GPBDAT                      (*(volatile unsigned long*)0x56000014)
#define INTOFFSET         (*(volatile unsigned long*)0x4A000014)
#define    EINTPEND                  (*(volatile unsigned long*)0x560000a8)
#define    SRCPND                      (*(volatile unsigned long*)0x4a000000)
#define    INTPND                      (*(volatile unsigned long*)0x4a000010)
 
void EINT_Handle()
{
       unsigned long oft=INTOFFSET;
       unsigned long val;
      
 
       GPBDAT|=(0x0f<<5);          //所有LED熄灭,如果没有这一句,那么会出现一个结果,就是将程序下到板子里运行时,
                                                                                    //4个LED灯都是灭的,因为在init.c函数里设置它为全灭。然后你按下K1,LED1亮了,
                                                                                    //再按下K2,LED2亮了,但是LED1却没熄灭,知道你按到K4,4个LED全亮,再按就没变化了
                                                                                    //加上这一句就不一样了,每按一个键,只亮相应的灯,这也说明中断的执行情况
       val=EINTPEND;    //EINT寄存器,它的位x为1时,表示EINT已经发生(x为4——23)。                                                                  
       if(val&(1<<8))                           //K1被按下,LED1被点亮
              GPBDAT&=~(1<<5);
             
       if(val&(1<<11))                          //K2被按下,LED2被点亮
              GPBDAT&=~(1<<6);
             
       if(val&(1<<13))                          //K3被按下,LED3被点亮
              GPBDAT&=~(1<<7);
             
       if(val&(1<<14))                          //K4被按下,LED4被点亮
              GPBDAT&=~(1<<8);
              //清除中断
       if(oft==5)
              EINTPEND=(1<<8)|(1<<11)|(1<<13)|(1<<14);   //清除EINTPEND寄存器,往某位写入1即可清楚此位
       SRCPND=1<                                           //清除SRCPND寄存器,往某位写入1即可清楚此位
       INTPND=1<                                     //清除INTPND寄存器,往某位写入1即可清楚此位
       //注意:清除顺序很重要:先是EINTPEND,然后是SRCPND,最后是INTPND
          
 
 
 
main.c文件内容:
 
 
 
int main()
{
       while(1);
       return      0;   
}
 
Makfile文件内容:
 
objs:=head.o   init.o       interrupt.o      main.o
 
int.bin:$(objs)
       arm-linux-ld   -Ttext      0x00000000    -o    int_elf     $^
       arm-linux-objcopy  -O   binary     -S    int_elf     $@
       arm-linux-objdump       -D   -m   arm  int_elf     > int.dis
      
%.o:%.c
       arm-linux-gcc -Wall      -O2  -c    -o    $@  $<
      
%.o:%.S
       arm-linux-gcc -Wall      -O2  -c    -o    $@  $<
      
clean:
       rm   -f int.bin int_elf     int.dis     *.o
关键字:mini2440  中断  裸机代码 

『本文转载自网络,版权归原作者所有,如有侵权请联系删除』

热门文章 更多
PIC单片机基础知识之二