S3C2440中断进不去分析

 经常看到有人问这样的问题,自己用mini2440开发板调试中断的时候进不去中断,要了解中断,就需要了解中断机制和中断向量表。相信看这篇文章的读者肯定知道什么是中断以及中断机制了,由于中断的编程跟2440的启动方式有关系,因此我们先说下启动方式吧。

       S 3C 2440支持两种启动模式:NAND和非NAND(这里是NOR FLASH)具体取决与OM0OM1两个引脚。同时我们这里再加一种情况,就是程序在SDRAM中运行(或者说用JTAG调试的时候的情况)。我们就从这三种情况来说明中断如何实现。

       (1) 当从NAND启动时,CPU会自动从NAND flash中读取前4KB的数据放置在片内SRAM(S 3C 2440是集成到内部的叫做Steppingstone),同时把这段片内SRAM映射到nGCS0片选的空间(0x00000000)CPU是从0x00000000开始执行的,也就是NAND FLASH里面的前4KB内容。由于NAND FLASH的结构决定了NAND FLASH没有地址线,而且存取都是以页来进行的,这就是为什么CPU会自动从NAND FLASH读取前面4KB到内部SRAM里的原因。我们很快会想到一个问题,那就是4KB以后的代码如何执行。这就是程序员需要做的工作了,在前面4KB的代码中,必须含有将以后的主程序代码拷贝到SDRAM中运行,完成拷贝,以及4KB的启动代码后,跳转到SDRAM中执行其余程序。这里我就不详细介绍了,可以查看mini2440例子中的启动代码。

注意:这里必须明确的一点就是NAND地址不是线性的,程序不能直接运行,必须拷贝到线性RAM中。

        (2) 当从NOR启动时,NOR FLASH被映射到0x00000000地址(就是nGCS0,这里就不需要片内SRAM来辅助了,所以片内SRAM的起始地址还是0x40000000)。然后CPU0x00000000开始执行(也就是在Norflash中执行)。这种情况是最简单的,只要将程序的下载地址设置到0x00000000即可。

        在实际的开发中,一般可以把bootloader烧入到Norflash,程序运行可以通过串**互,进行一定的操作,比如下载,调试。这样就很可以很方便的调试你的一些代码。Norflash中的Bootloader还可以烧录内核到Norflash等等功能。

       (3) 当程序在SDRAM运行,由于SDRAM的地址是0x30000000,因此运行程序需要下载到0x30000000,当程序在内存中运行,由于发生中断时,会跳到0x00000018,因此在SDRAM运行时,要进入中断,有两种方法进行实现:一是MMU配置,使0x30000000映射到0x00000000地址,当中断发生时,跳到0x30000018的地址二是在0x00000000的内部SDRAM中存中断向量表,或者在0x00000000NAND FLASH位置放中断向量表

下面是自己在MMU开启的情况下,中断的应用实例:

文件名:head.s

@*************************************************************************
@ File
head.S
@
功能:设置SDRAM,将第二部分代码复制到SDRAM,设置页表,启动MMU
@      
 然后跳到SDRAM继续执行
@*************************************************************************  

.global PrintStr                        @************串口输出字符串函数*******************@

.include "2440addr.inc"         @************引用2440头文件************************@

.include "Memcfg.inc"

.equ ISR_BADDR , 0xB3ffff00   @**************中断映射后的地址*****************@

.equ INTOFFSET , 0x 4a 000014    @Interruot r=est source offset

.equ rINTMSK     ,0x 4a 000008   @//Interrupt mask control

@频率的设置参数定义
.equ CLKDIV_VAL , 5   @ 0=1:1:1, 1=1:1:2, 2=1:2:2, 3=1:2:4, 4=1:4:4, 5=1:4:8, 6=1:3:3, 7=1:3:6.
.equ M_MDIV   , 92   @ Fin=12.0MHz Fout=304.8MHz
.equ M_PDIV   , 1   @ 1
.equ M_SDIV   , 1   @ 2
.equ U_MDIV   , 56   @ Fin=12MHz Fout=48MHz
.equ U_PDIV   , 2
.equ U_SDIV   , 2

@宏定义 定义HANDLER
.macro HANDLER $HandleLabel
        sub sp,sp,#4
        stmfd sp!,{r0}
        ldr r0,=/$HandleLabel
        ldr r0,[r0]
        str r0,[sp,#4]
        ldmfd sp!,{r0,pc}
.endm

@@@@@@****************程序入口********************@@@@@@@@

.code 32
.text
.align 4
.global _start
_start:
                b ResetHandle
HandlerUndef:
                b HandlerUndef        @@@
未定义指令中止模式的向量地址
HandlerSWI:
                b HandlerSWI            @@@
管理模式的向量地址,通过SWI指令进入此模式
HandlerPabort:
                b HandlerPabort      @@@
指令预取终止导致的异常的向量地址
HandlerDabort:
                b HandlerDabort      @@@
数据访问终止导致的异常的向量地址
                 b .
                ldr pc, =HandlerIRQ @@@
中断模式的向量地址
                ldr pc, =HandlerFIQ @@@
快中断模式的向量地址
                b .

HandlerFIQ:   HANDLER HandleFIQ

HandlerIRQ:   HANDLER HandleIRQ

@@@@@@@中断二级表,在这里区别是什么中断,然后跳入相应的中断进行处理

ISR_IRQ:

       sub   lr, lr, #4      @ compute the return address
       stmfd sp!,{r0-r12,lr}     @ save r8, r9, lr
       adr     r0,Say_Hello
       bl      PrintStr
       ldr   r9,=INTOFFSET
       ldr   r9,[r9]
       @ldr   r8,=HandleEINT0
       ldr    r8,=0xB3ffff20//
这里用的是虚拟地址,因为映射后HandleEINT0==0xB3ffff20
        add   r8,r8,r9,lsl #2
       ldr   r8,[r8]
       mov   lr, pc       @ the pc is the address ofIRQ_return
       mov   pc, r8
       ldmia sp!, {r0-r12,pc}^    @ restore the r8,r9,pc(lr)

@@@@@@@RESET

ResetHandle:
       ldr sp, =4096                       @
设置栈指针,以下都是C函数,调用前需要设好栈
       bl disable_watch_dog               @
关闭WATCHDOG,否则CPU会不断重启

       ldr     r0,=INTMSK
       ldr     r1,=0xffffffff      @all interrupt disable
不使能中断
       str     r1,[r0]

      ldr     r0,=SRCPND
       str     r1,[r0]

       ldr     r0,=INTPND
       str     r1,[r0]

       ldr     r0,=INTSUBMSK
       ldr     r1,=0x7fff    @all sub interrupt disable, 2002/04/10
       str     r1,[r0]

      @@@设置频率
      mov r1, #CLK_CTL_BASE
      ldr r2, clock_locktime
      str r2, [r1, #oLOCKTIME]

      mov r1, #CLK_CTL_BASE
      ldr r2, clkdivn_value
      str r2, [r1, #oCLKDIVN]

      mrc p15, 0, r1, c1, c0, 0 @ read ctrl register
      orr r1, r1, #0xc0000000 @ Asynchronous
      mcr p15, 0, r1, c1, c0, 0 @ write ctrl register

      mov r1, #CLK_CTL_BASE
      ldr r2, mpll_value   @ clock default
      str r2, [r1, #oMPLLCON]
@@@@
初始化串口
      InitUART:
      @set GPIO for UART
      mov r1, #GPIO_CTL_BASE
      add r1, r1, #oGPIO_H
      ldr r2, gpio_con_uart
      str r2, [r1, #oGPIO_CON]
      ldr r2, gpio_up_uart
      str r2, [r1, #oGPIO_UP]

      ldr r1, SerBase
      mov r2, #0x0
      str r2, [r1, #oUFCON]
      str r2, [r1, #oUMCON]
      mov r2, #0x3
      str r2, [r1, #oULCON]
      ldr r2, =0x245
      str r2, [r1, #oUCON]
.equ UART_BRD , ((UART_PCLK / (UART_BAUD_RATE*16)) - 1)
      mov r2, #UART_BRD
      str r2, [r1, #oUBRDIV]

      mov r3, #100
InitUART1:
     subs r3, r3, #0x1
      bne InitUART1

@@@@@@@@@@@@@@进入中断模式,并设置堆栈指针@@@@@@@@@@
     mrs r0,cpsr
     orr r1,r0,#0xd2
     msr cpsr_c,r1
    ldr sp,=3072

     msr cpsr_c, #0xdf @进入系统模式
     ldr r0,=rINTMSK
     mov r1,#0xfffffbff@@@
允许中断
     str r1,[r0]
     ldr sp,=4096
     msr cpsr_c, #0x 5f @
设置I-bit=0,开IRQ中断

     ldr r0,=0x33ffff18
      ldr r1,=ISR_IRQ              @ if there isnt "subs pc,lr,#4" at 0x18, 0x 1c
     str r1,[r0]

     bl memsetup                        @ 设置存储控制器以使用SDRAM
     bl copy_2th_to_sdram              @
将第二部分代码复制到SDRAM
     bl create_page_table               @
设置页表

     bl mmu_init                        @ 启动MMU

     ldr sp, =0xB2000000        @ 重设栈指针,指向SDRAM顶端(使用虚拟地址)

     ldr pc,=0xB0004000         @ 跳到SDRAM中继续执行第二部分代码

halt_loop:
     b   halt_loop

PrintChar:
     mov     r1, #UART0_CTL_BASE
PrintChar1:
     ldr     r2, [r1, #oUTRSTAT]
     tst     r2, #UTRSTAT_TX_EMPTY
     beq     PrintChar1
     str     r0, [r1, #oUTXHL]
     mov     pc, lr

PrintStr:
     stmfd sp!, {r4, lr}

     movs r4, r0
     ldmeqfd sp!, {r4, pc}
    
PrintStr1:
     ldrb r0, [r4], #1
     cmp r0, #0
    ldmeqfd sp!, {r4, pc}

bl PrintChar
b   PrintStr1
Say_Hello:
    .asciz "Welcome To Used TMSG_GUI./r/n"  
clock_locktime:
    .word vLOCKTIME
mpll_value:
    .word (M_MDIV<<12)+(M_PDIV<<4)+(M_SDIV)
clkdivn_value:
     .word vCLKDIVN
gpio_con_uart:
    .word vGPHCON
gpio_up_uart:
    .word vGPHUP
SerBase:
    .word UART0_CTL_BASE

@ @@@@@@@@@@@@@@@@@@@@@@@@@@

.equ HandleReset, (ISR_BADDR+4*0)
.equ HandleUndef, (ISR_BADDR+4*1)
.equ HandleSWI,   (ISR_BADDR+4*2)
.equ HandlePabort, (ISR_BADDR+4*3)
.equ HandleDabort, (ISR_BADDR+4*4)
.equ HandleReserved, (ISR_BADDR+4*5)
.equ HandleIRQ,   (ISR_BADDR+4*6)
.equ HandleFIQ,   (ISR_BADDR+4*7)

.equ HandleEINT0,   (ISR_BADDR+4*8)
.equ HandleEINT1,   (ISR_BADDR+4*9)
.equ HandleEINT2,   (ISR_BADDR+4*10)
.equ HandleEINT3,   (ISR_BADDR+4*11)
.equ HandleEINT4_7,   (ISR_BADDR+4*12)
.equ HandleEINT8_23,   (ISR_BADDR+4*13)
.equ HandleRSV6,    (ISR_BADDR+4*14)
.equ HandleBATFLT,   (ISR_BADDR+4*15)
.equ HandleTICK,    (ISR_BADDR+4*16)
.equ HandleWDT,    (ISR_BADDR+4*17)
.equ HandleTIMER0,   (ISR_BADDR+4*18)
.equ HandleTIMER1,   (ISR_BADDR+4*19)
.equ HandleTIMER2,   (ISR_BADDR+4*20)
.equ HandleTIMER3,   (ISR_BADDR+4*21)
.equ HandleTIMER4,   (ISR_BADDR+4*22)
.equ HandleUART2,   (ISR_BADDR+4*23)
.equ HandleLCD,    (ISR_BADDR+4*24)
.equ HandleDMA0,    (ISR_BADDR+4*25)
.equ HandleDMA1,    (ISR_BADDR+4*26)
.equ HandleDMA2,    (ISR_BADDR+4*27)
.equ HandleDMA3,    (ISR_BADDR+4*28)
.equ HandleMMC,    (ISR_BADDR+4*29)
.equ HandleSPI0,    (ISR_BADDR+4*30)
.equ HandleUART1,   (ISR_BADDR+4*31)
.equ HandleRSV24,   (ISR_BADDR+4*32)
.equ HandleUSBD,    (ISR_BADDR+4*33)
.equ HandleUSBH,    (ISR_BADDR+4*34)
.equ HandleIIC,    (ISR_BADDR+4*35)
.equ HandleUART0 ,   (ISR_BADDR+4*36)
.equ HandleSPI1,    (ISR_BADDR+4*37)
.equ HandleRTC,    (ISR_BADDR+4*38)
.equ HandleADC,    (ISR_BADDR+4*39)

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值