44b0中断

前段时间,刚用LPC2214做了一款测试仪器,最近又由于项目需求,开始转手用44B0进行开发,发现两款同属arm7的片子还是有很大区别 的。因为我以前就是搞单片机的,所以入手lpc系列时感觉很上手,没遇到什么难度,再加上ZLG的服务态度也不错,所以很快就把产品搞出来了。可是当接触 到44B0的时候,感觉就不一样了,单从启动这一块好像就要比lpc的复杂多了,要相系统运行稳定必须得分散加载程序,先得加载bios。头大!

转载一篇bios注释吧:

44b0引导过程详解(综合多篇资料和自己的理解,不当之处敬请指正--原创)

----枫之家

; *******************************************************
; * NAME    : 44BINIT.S     *
; * Version : 10.JAn.2003    *
; * Description:     *
; * C start up codes    *
; * Configure memory, Initialize ISR ,stacks *
; * Initialize C-variables    *
; * Fill zeros into zero-initialized C-variables *
; *******************************************************
;   说明:  为了学习方便,参考多篇资料对44B0的引导代码重新编辑、注释  
; *******************************************************
 ;输入文件和外部变量;
; *******************************************************
   GET ../inc/option.s
   GET ../inc/memcfg.s
  
;bootloader要将RW段复制到ram中并将ZI段清零编译器使用下列段来记录各段的起始和结束地址
; |Image$$RO$$Base| ; RO段起始地址
; |Image$$RO$$Limit| ; RO段结束地址加1
; |Image$$RW$$Base| ; RW段起始地址
; |Image$$RW$$Limit| ; RW段结束地址加1
; |Image$$ZI$$Base| ; ZI段起始地址
; |Image$$ZI$$Limit| ; ZI段结束地址加1

    IMPORT |Image$$RO$$Limit|  ; End of ROM code (=start of ROM data)
    IMPORT |Image$$RW$$Base|   ; Base of RAM to initialise
    IMPORT |Image$$ZI$$Base|   ; Base and limit of area
    IMPORT |Image$$ZI$$Limit|  ; to zero initialise

    IMPORT  Main    ; The main entry of mon program
 ; *******************************************************
 ;定义引导过程中需要设置的控制寄存器,仅针对44B0,44B0寄存器在44B0.H里有定义,但此时无法调用,需要自己定义
 ; *******************************************************
;Interrupt Control
INTPND     EQU 0x01e00004
INTMOD     EQU 0x01e00008
INTMSK     EQU 0x01e0000c
I_ISPR     EQU 0x01e00020
I_CMST     EQU 0x01e0001c

;Watchdog timer
WTCON     EQU 0x01d30000

;Clock Controller
PLLCON     EQU 0x01d80000
CLKCON     EQU 0x01d80004
LOCKTIME    EQU 0x01d8000c
 
;Memory Controller
REFRESH     EQU 0x01c80024
 ; *******************************************************
 ;定义系统常量,主要是ARM工作模式,应该是针对所有ARM7,为CPSR的[0,4]所决定,主要是为了便于操作
 ; *******************************************************
USERMODE EQU 0x10 ;0b10000用户模式
FIQMODE EQU 0x11 ;0b10001FIQ模式
IRQMODE EQU 0x12 ;0b10010IRQ模式
SVCMODE EQU 0x13 ;0b10011管理模式
ABORTMODE EQU 0x17 ;0b10111中止模式
UNDEFMODE EQU 0x1b ;0b11011未定义
MODEMASK EQU 0x1f ;0b11111系统模式
NOINT EQU 0x80 ;  原来设置为C0,即: NOINT EQU 0xc0 ;但考虑到一些安全因素,暂时设置为80,尽量保证初始化时在ARM状态并关闭中断。  

; *******************************************************
 ;定义系统变量,arm处理器有两种工作状态 1.arm:32位这种工作状态下执行字对准的arm指令 2.Thumb:16位这种工作状态执行半字对准的Thumb指令
;因为处理器分为16位 32位两种工作状态程序的编译器也是分16位和32两种编译方式所以下面的程序用于根据处理器工作状态确定编译器编译方式
;code16伪指令指示汇编编译器后面的指令为16位的thumb指令
;code32伪指令指示汇编编译器后面的指令为32位的arm指令
;这段是为了统一目前的处理器工作状态和软件编译方式(16位编译环境使用tasm.exe编译),应该是统一为32位,该部分代码实际无多大意义,无法实现预期目的,修改如下
;影响如何,需要进一步验证
 ; *******************************************************

    GBLL    THUMBCODE
   ; [ {CONFIG} = 16 
;THUMBCODE SETL {TRUE}
 ;   CODE32
  ;  |  
;THUMBCODE SETL {FALSE}
 ;   ]

  ;  [ THUMBCODE
  ;  CODE32   ;for start-up code for Thumb mode
  ;  ]
   CODE32    ;32位
  ; *******************************************************
 ;宏定义,负责向量中断函数的加载,与C语言中宏的定义和使用类似
 ;下面包含的HandlerXXX HANDLER HandleXXX将都被下面这段程序展开 ,
;本初始化程序定义了一个数据区(在文件最后),34个字空间,存放相应中断服务程序的首地址。每个字空间都有一个标号,以Handle***命名。
;在向量中断模式下使用“加载程序”来执行中断服务程序。
;向量中断模式和非向量中断模式的概念
;向量中断模式是当cpu读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址
;函数中节省了中断处理时间提高了中断处理速度标 例如 ADC中断的向量地址为0xC0,则在0xC0处放如下代码:ldr PC,=HandlerADC 当ADC中断产生的时候系统会
;自动跳转到HandlerADC函数中
;非向量中断模式处理方式是一种传统的中断处理方法,当系统产生中断的时候,系统将interrupt pending寄存器中对应标志位置位然后跳转到位于0x18处的统一中断
;函数中 该函数通过读取interrupt pending寄存器中对应标志位来判断中断源并根据优先级关系再跳到对应中断源的处理代码中
 ; *******************************************************  
  
     MACRO
$HandlerLabel HANDLER $HandleLabel

$HandlerLabel
    sub     sp,sp,#4     ;decrement sp(to store jump address)
    stmfd   sp!,{r0}     ;PUSH the work register to stack(lr does't push because it return to original address)
    ldr     r0,=$HandleLabel;load the address of HandleXXX to r0
    ldr     r0,[r0]     ;load the contents(service routine start address) of HandleXXX
    str     r0,[sp,#4]     ;store the contents(ISR) of HandleXXX to stack
    ldmfd   sp!,{r0,pc}     ;POP the work register and pc(jump to ISR)
    MEND
   
   
   
   
   
; *******************************************************
 ;程序启动代码,程序入口地址,不妨看作C语言中的 MAIN()入口,上面的代码看作MAIN之前的外部变量引用,全局常量、变量和宏定义
 ; *******************************************************


    AREA    Init,CODE,READONLY

    ENTRY
    b ResetHandler  ;0x0   复位,特权模式,优先级1
    b HandlerUndef  ;0X4   未定义指令中断模式,异常模式    6
    b HandlerSWI    ;0X8   软件中断,特权模式,,6
    b HandlerPabort ;0X0C  指令预取指中止,中止模式,5
    b HandlerDabort ;0X10  数据访问中止,中止模式,2
    b .      ;    0X14,未使用,保留
    b HandlerIRQ     ;0X18,外部中断,4,总入口,不同的中断还有不同的分入口地址,采用矢量中断模式时,不同中断源的地址入口固定,这也为系统自动计算中断服务程序入口地址提供了条件
    b HandlerFIQ     ;0X1C,快速中断,3,总入口,不同的中断还有不同的分入口地址
 ;***IMPORTANT NOTE***
 ;如果使用向量中断处理模式,上面两行的代码应该用下面两行代码代替
 ; subs pc,lr,#4 ;0X18,外部中断,4
 ; subs pc,lr,#4 ;0X1C,快速中断,3
 ; 这是因为当采用矢量中断模式时,一旦一个或多个中断发生,44B0通过硬件逻辑首先确定应该响应的中断,并计算出该中断的中断服务程序地址,该地址通过
 ;参数lr传递到下一条将要执行的指令即:subs pc,lr,#4;该指令存储在外部/快速中断的中断响应地址(0X18/0X1C)上,所以可直接跳转到相应中断源头的服务程序上
 ;中断发生--->(硬件计算服务程序地址,程序不参与)--->跳转到0X18或0X1C--->跳转到相应服务程序
 ;注意;上面的LR肯定已经不是中断发生时的指令地址,而是系统根据中断源类型生成的地址,中断发生时的地址保存在哪里,哈哈,我也不清楚,再找找了

VECTOR_BRANCH 
    ;0X20-0XC0,30个中断源的向量表
    ldr pc,=HandlerEINT0    ;mGA    H/W interrupt vector table
    ldr pc,=HandlerEINT1    ; 
......     

 ldr pc,=EnterPWDN
;下面是具体的中断处理函数跳转的宏,通过上面的$HandlerLabel的宏定义展开后跳转到对应的中断处理函数(对于向量中断)
    LTORG 

HandlerFIQ HANDLER HandleFIQ
.......
HandlerEINT0 HANDLER HandleEINT0

;
;One of the following two routines can be used for non-vectored interrupt.
;这段是没有使用装断向量模式下如何装载中断子程序,因为44B0有30个中断源,所以需要程序处理以确定调用那个中断程序
;0,1是局部标号,%B是向后搜索局部标号, %F是向前搜索局部标号。都是伪操作
;I_ISPR寄存器各位表明发生了应该调用那个中断子程序。只能1位置位,其它位为0,比如说串口1发送中断发生,这时I_ISPR的
;值为0X04,ldr r9,=I_ISPR
;ldr r9,[r9] 两条指令后,r9的内容为0X4 ,
;movs r9,r9,lsr #1 r9内容右移一位
;bcs %F1 判断是否把置位是否转移到C位,
;add r8,r8,#4 如果没有的R8加4
;如果r9内容为0x04 需要右移3次 ,之后r8的内容为8 然后HandleADC的地址加上r8的值就是串口1发送中断的地址,这个地址的内容是中断子程序的地址

IsrIRQ ;using I_ISPR register.
    sub     sp,sp,#4       ;reserved for PC
    stmfd   sp!,{r8-r9}  

 ;IMPORTANT CAUTION
 ;if I_ISPC isn't used properly, I_ISPR can be 0 in this routine.

    ldr     r9,=I_ISPR
    ldr     r9,[r9]
    mov     r8,#0x0
0
    movs    r9,r9,lsr #1
    bcs     %F1
    add     r8,r8,#4
    b     %B0

1
    ldr     r9,=HandleADC
    add     r9,r9,r8
    ldr     r9,[r9]
    str     r9,[sp,#8]
    ldmfd   sp!,{r8-r9,pc}
;****************************************************
;到此处为止,44B0的启动框架已经完毕,后面的代码均可以看做是中断服务程序,程序的嵌套调用或者子程序
;* START START *
;****************************************************

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值