/*********************************************************************
sub sp,sp,#4 ; 计算返回地址
//进入中断后,它的返回地址该怎么计算呢,可以这样来理解,因为它的指令流水线是3级的,
//即执行进入中断函数时,PC已经指向欲取值的指令即当前执行的地址+8;当已进入中断时,
LR里面装的是PC,所以要想中断返回到正确的地址处,就必须把LR-4。
【galaxy9229 发表于www.21ic 2008-9-25 16:51 ARM程序分析与设计】
/**********************************************************************/
IRQ_Entry
sub sp,sp,#4 ;//保留PC值//; 计算返回地址//SP=SP-4;
stmfd sp!,{r8-r9} ;//将R8~R9 入栈。满递减堆栈。
ldr r9,=INTOFFSET
ldr r9,[r9]
ldr r8,=HandleEINT0 ;读入中断偏移码
add r8,r8,r9,lsl #2 ;二级跳转表的首地址
ldr r8,[r8]
str r8,[sp,#8] ;//中断入口地址送进SP(第一个代码留出的4字节空间)
ldmfd sp!,{r8-r9,pc} ;//数据出栈,放入R8~R9,PC 寄存器。满递减堆栈。
ENDIF
Reset_Addr DCD Reset_Handler ;定义中断的入口地址
Undef_Addr DCD Undef_Handler ;//DCD 用于分配一段字内存单元,并用伪指令中的expr 初始化
SWI_Addr DCD SWI_Handler
PAbt_Addr DCD PAbt_Handler
DAbt_Addr DCD DAbt_Handler
DCD 0 ;//保留地址
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
Undef_Handler B Undef_Handler ;中断处理程序的入口地址//B为跳转指令|| ??自己跳转到自己??
SWI_Handler B SWI_Handler
PAbt_Handler B PAbt_Handler
DAbt_Handler B DAbt_Handler
IF IntVT_SETUP <> 1
IRQ_Handler B IRQ_Handler
ENDIF
IF IntVT_SETUP <> 0
IRQ_Handler B IRQ_Entry
ENDIF
FIQ_Handler B FIQ_Handler
;//存储控制器配制
IF MC_SETUP <> 0
MC_CFG
DCD BWSCON_Val
DCD BANKCON0_Val
DCD BANKCON1_Val
DCD BANKCON2_Val
DCD BANKCON3_Val
DCD BANKCON4_Val
DCD BANKCON5_Val
DCD BANKCON6_Val
DCD BANKCON7_Val
DCD REFRESH_Val
DCD BANKSIZE_Val
DCD MRSRB6_Val
DCD MRSRB7_Val
ENDIF
;//时钟管理配置
IF CLOCK_SETUP <> 0
CLK_CFG
DCD LOCKTIME_Val
DCD CLKDIVN_Val
DCD UPLLCON_Val
DCD MPLLCON_Val
DCD CLKSLOW_Val
DCD CLKCON_Val
DCD CAMDIVN_Val
ENDIF
;//I/O 配置
IF PIO_SETUP <> 0
PIOA_CFG
DCD PCONA_Val
PIOB_CFG DCD PCONB_Val
DCD PUPB_Val
PIOC_CFG DCD PCONC_Val
DCD PUPC_Val
PIOD_CFG DCD PCOND_Val
DCD PUPD_Val
PIOE_CFG DCD PCONE_Val
DCD PUPE_Val
PIOF_CFG DCD PCONF_Val
DCD PUPF_Val
PIOG_CFG DCD PCONG_Val
DCD PUPG_Val
PIOH_CFG DCD PCONH_Val
DCD PUPH_Val
PIOJ_CFG DCD PCONJ_Val
DCD PUPJ_Val
ENDIF
; //复位处理模块
;//下面是重起时的中断处理函数
EXPORT Reset_Handler ;//定义一个全局函数名变量
Reset_Handler
IF WT_SETUP <> 0 ;//看门狗处理;若WT_SETUP为1,则执行下一个语句
LDR R0, =WT_BASE ;//ldr r0,0x12345678 是将内存0x12345678地址中存储的数据搬到r0寄存器中
LDR R1, =WTCON_Val ;//ldr r0,=0x12345678 可以理解为:将立即数0x12345678放到r0寄存器中
LDR R2, =WTDAT_Val
STR R2, [R0, #WTCNT_OFS] ;//将R2 的数据存储到R0+WTCNT_OFS 存储单元,R0 值不变
STR R2, [R0, #WTDAT_OFS]
STR R1, [R0, #WTCON_OFS] ;//看门狗禁止
ENDIF
IF CLOCK_SETUP <> 0 ;//时钟处理;若CLOCK_SETUP为1,则执行下一个语句
LDR R0, =CLK_BASE
ADR R8, CLK_CFG ;//将CLK_CFG 的地址放入R8
LDMIA R8, {R1-R7} ;//将CLK_CFG起始地址的8地址装载到R1-R7
STR R1, [R0, #LOCKTIME_OFS]
STR R2, [R0, #CLKDIVN_OFS]
STR R3, [R0, #UPLLCON_OFS]
nop
nop
nop
nop
nop
nop
nop
STR R4, [R0, #MPLLCON_OFS]
STR R5, [R0, #CLKSLOW_OFS]
STR R6, [R0, #CLKCON_OFS]
STR R7, [R0, #CAMDIVN_OFS]
ENDIF
IF MC_SETUP <> 0 ;//存储控制器处理;若MC_SETUP为1,则执行下一个语句
ADR R13, MC_CFG
LDMIA R13, {R0-R12}
LDR R13, =MC_BASE
STMIA R13, {R0-R12} ;//将R0-R12中的地址的数据装载到MC_BASE起始的13个寄存器。
ENDIF
IF PIO_SETUP <> 0 ;//IO处理;若PIO_SETUP为1,则执行下一个语句
LDR R13, =PIO_BASE
IF PIOA_SETUP <> 0 ;//端口A处理;若PIOA_SETUP为1,则执行下一个语句
ADR R0, PIOA_CFG
STR R0, [R13, #PCONA_OFS]
ENDIF
IF PIOB_SETUP <> 0 ;//端口B处理
ADR R0, PIOB_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONB_OFS]
STR R1, [R13, #PUPB_OFS]
ENDIF
IF PIOC_SETUP <> 0 ;//端口C处理
ADR R0, PIOC_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONC_OFS]
STR R1, [R13, #PUPC_OFS]
ENDIF
IF PIOD_SETUP <> 0 ;//端口D处理
ADR R0, PIOD_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCOND_OFS]
STR R1, [R13, #PUPD_OFS]
ENDIF
IF PIOE_SETUP <> 0 ;//端口E处理
ADR R0, PIOE_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONE_OFS]
STR R1, [R13, #PUPE_OFS]
ENDIF
IF PIOF_SETUP <> 0 ;//端口F处理
ADR R0, PIOF_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONF_OFS]
STR R1, [R13, #PUPF_OFS]
ENDIF
IF PIOG_SETUP <> 0 ;//端口G处理
ADR R0, PIOG_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONG_OFS]
STR R1, [R13, #PUPG_OFS]
ENDIF
IF PIOH_SETUP <> 0 ;//端口H处理
ADR R0, PIOH_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONH_OFS]
STR R1, [R13, #PUPH_OFS]
ENDIF
IF PIOJ_SETUP <> 0 ;//端口J处理
ADR R0, PIOJ_CFG
LDR R1, [R0,#4]
STR R0, [R13, #PCONJ_OFS]
STR R1, [R13, #PUPJ_OFS]
ENDIF
ENDIF |