前言
ARM的中断和51单片机的中断有不少不同的地方,这里梳理一下ARM外部中断的实现过程。
环境
- ARM单片机:公司设计的EM537单片机
- ARM指令集型号:V7-A
正文
一、ARM中断类型
首先参考《ARM体系结构与编程》第九章异常中断处理章节中的内容。
ARM中断可以分为以下几种类型:
ARM中断向量的地址和优先级表格
ARM共有8种类型的中断,中断的数目可以扩展。
EM537中通过TZIC模块,将IRQ中断数目扩展至128。
FIQ的中断,优先级高,延迟低。常用于DMA类型的中断。
我们平时使用最多的还是IRQ外部中断。
二、中断触发-处理中断的过程(以外部中断为例)
2.1 中断的配置
不同平台配置寄存器不同
- 打开想使用的中断允许位
- 配置中断优先级
- 打开总中断
2.2 中断的触发
满足中断触发条件后,由硬件进行触发。
作为开发者不需要关心硬件触发过程。
2.3 中断的执行
首先参考一下EM537的中断向量表:
@vectable.s
@--------------------------------
@ vector table
@--------------------------------
.global _start
.global UNDEF_HLDR
.global SWI_HLDR
.global PREFETCH_HLDR
.global ABORT_HLDR
.global IRQ_HLDR
.global FIQ_HLDR
.global JUMP_CS0
.global JUMP_COMMON
.arm
VECTORS:
.ifdef BOOT_DENALI
ldr pc, =JUMP_COMMON
.else
.ifdef ARM_EMBEDDED_MODE
ldr pc, =_start
.else
ldr pc, =JUMP_CS0
.endif
.endif
ldr pc, =UNDEF_HLDR
ldr pc, =SWI_HLDR
ldr pc, =PREFETCH_HLDR
ldr pc, =ABORT_HLDR
nop
ldr pc, =IRQ_HLDR
ldr pc, =FIQ_HLDR
nop
nop
首先定义的是复位异常中断,此中断跳转地址是正常程序的起始地址_start。
然后按顺序定义其他的中断跳转地址。
硬件触发外部中断后,ARM会跳转到IRQ_HLDR。
然后来看看 IRQ_HLDR的汇编。
@crt0.s的部分内容
IRQ_HLDR:
stmfd sp!, {r0-r12,lr}
ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending register
ldr r0,[r0]
mov r2, #0x0
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending register
ldr r0,[r0]
mov r2, #32
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending register
ldr r0,[r0]
mov r2, #64
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending register
ldr r0,[r0]
mov r2, #96
cmp r0, #0
bne FIND_NUMBER
FIND_NUMBER:
mov r0, r0, lsr #1
cmp r0, #0
beq FOUND_NUMBER
add r2, r2, #0x1
b FIND_NUMBER
FOUND_NUMBER:
mov r2, r2, lsl #2
mov r0, r2
ldr lr,=INTERRUPT_0
ldr r0,[lr,r0]
mov lr,pc
bx r0
mrs r0, cpsr
bic r1, r0, #0x100
msr cpsr_cxsf, r1
ldmfd sp!, {r0-r12,lr}
subs pc,lr,#4
首先stmfd 压栈, 保护CPU状态。
接下来是4段比较相似的程序,用于查询触发的外部中断号。
TZIC 实现了128个外部中断,使用前需要先对TZIC进行配置。
设置相应中断的中断号。如果此中断触发,就可以在HIPND(0-3) interrupt pending register这四个寄存器中查到。
然后解析一下其中一段程序的内容:
@将中断挂起寄存器0的地址,保存到r0
ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending register
@寄存器间接寻址,将r0寄存器的值看作地址,然后将地址对应的值传给r0
ldr r0,[r0]
@r2 = 0
mov r2, #0x0
@比较r0和0的大小,如果r0!=0,则跳转FIND_NUMBER
cmp r0, #0
bne FIND_NUMBER
@回顾这段代码,功能是检查中断挂起寄存器的值,如果全零就检查下一个,否则跳转FIND_NUMBER计算相应的中断号
FIND_NUMBER通过移位找出中断号,然后保存在r2中。
FOUND_NUMBER首先左移2,相当于*4,是为了计算相应的偏移地址。然后保存在r0中。
ldr lr,=INTERRUPT_0
ldr r0,[lr,r0]
这两句是相对寻址,最后r0=INTERRUPT_0的地址+r0。
结合下面的汇编代码,更容易理解
然后就可以跳转到对应的外部中断处理程序。
@int_table.s的部分
.global INTERRUPT_0
.global ESDHC1_INT_ROUTINE
.global ESDHC2_INT_ROUTINE
.global ESDHC3_INT_ROUTINE
.global ESDHC4_INT_ROUTINE
.global DAP_INT_ROUTINE
.global SDMA_INT_ROUTINE
.global IOMUX_INT_ROUTINE
.global EMI1_INT_ROUTINE
.global VPU1_INT_ROUTINE
.global IPU_ERR_INT_ROUTINE
.global IPU_FUNC_INT_ROUTINE
.global GPU1_INT_ROUTINE
.global UART4_ANDED_INT_ROUTINE
.global USB_UH1_INT_ROUTINE
.global EMI2_INT_ROUTINE
.global USB_UH2_INT_ROUTINE
.global USB_UH3_INT_ROUTINE
.global USB_UOTG_INT_ROUTINE
.global SAHARA_INT1_ROUTINE
.global SAHARA_INT2_ROUTINE
.global SCC_SMON_INT_ROUTINE
.global SCC_SCTL_INT_ROUTINE
.global SCC_SCTL_NS_INT_ROUTINE
.global SRTC_INT_ROUTINE
.global SRTC_SEC_INT_ROUTINE
.global RTIC_INT_ROUTINE
.global CSU_INT_ROUTINE
.global SATA_INT_ROUTINE
.global SSI1_INT_ROUTINE
.global SSI2_INT_ROUTINE
.global UART1_ANDED_INT_ROUTINE
.global UART2_ANDED_INT_ROUTINE
.global UART3_ANDED_INT_ROUTINE
2.4 代码中调用中断(动态设置中断函数)
首先引用一下,参考文献1,2关于global的说明
.global 修饰标号为全局的,用法 .global xxx 这个符号可以被当前源文件以外的其他文件使用也可以被连接脚本(连接器)使用,xxx仅仅是一个标号对应一个地址并不是C中的一个变量。
无法对他取地址,因为他本身代表一个地址,仅仅是一个对应到一个编译过程中的值的别名,类似C代码中的define 定义的一样,只是在链接时他的值是由连接器自动处理的。
汇编代码使用仅能使用ldr,Rx,=xxx;而不能使用ldr,Rx,xxx.global关键字用来让一个符号对链接器可见,可以供其他链接对象模块使用。
.global _start 让_start符号成为可见的标示符,这样链接器就知道跳转到程序中的什么地方并开始执行。linux寻找这个 _start标签作为程序的默认进入点。
在汇编和C混合编程中,在GNU ARM编译环境下,汇编程序中要使用.global伪操作声明汇编程序为全局的函数,意即可被外部函数调用,同时C程序中要使用extern声明要调用的汇编语言程序。
所以ini_table.s中的
只是声明了一个符号,并没有相应的程序。.global UART1_ANDED_INT_ROUTINE
在interrupt.h文件中
使用extern关键字声明,以便在c里面进行调用。extern void ( *UART1_ANDED_INT_ROUTINE )(void);
这里声明的
是一个函数指针。UART1_ANDED_INT_ROUTINE
这里引用参考文献4中的介绍:
因此可以通过更改
中断函数指针指向的函数,实现动态更改中断函数。UART1_ANDED_INT_ROUTINE
EM537中使用下面里例子进行设置:
#define CAPTURE_INTERRUPT(handle,routine) handle = (void (*)(void)) routine
__irq(intr_routin1)
#pragma interrupt intr_routin1
void intr_routin1(void);
void intr_routin1(void){
//用户自定义函数内容
}
void main(){
CAPTURE INTERRUPT(UART1_ANDED_INT_ROUTINE, intr_routin1);
}
三、ARM初始化配置
想要正确的执行中断,还需要对ARM寄存器进行上电初始化。
初始化的主要功能是:
- 初始化Rn等常用寄存器的值为0;(理论上要使用的内存区域都要初始化,避免硬件初始化值不同造成错误。)
- 初始化各种处理器模式下的堆栈指针,否则堆栈指针可能会覆盖内存中的值,造成程序错误。
- 进入SPVR 模式 打开程序状态寄存器(CPSR)中的IRQ和FIQ中断标志位。
附件2 crt0.s是初始化相关的汇编代码。
附件
1. interrupt.h
// These interrupts MUST be defined in the correct order.
// IRQ INTERRUPT
extern void ( *INTERRUPT_0 )(void); //RESERVED
extern void ( *ESDHC1_INT_ROUTINE )(void);
extern void ( *ESDHC2_INT_ROUTINE )(void);
extern void ( *ESDHC3_INT_ROUTINE )(void);
extern void ( *ESDHC4_INT_ROUTINE )(void);
extern void ( *DAP_INT_ROUTINE )(void);
extern void ( *SDMA_INT_ROUTINE )(void);
extern void ( *IOMUX_INT_ROUTINE )(void);
extern void ( *EMI1_INT_ROUTINE )(void);
extern void ( *VPU1_INT_ROUTINE )(void);
extern void ( *IPU_ERR_INT_ROUTINE )(void);
extern void ( *IPU_FUNC_INT_ROUTINE )(void);
extern void ( *GPU1_INT_ROUTINE )(void);
extern void ( *UART4_ANDED_INT_ROUTINE )(void);
extern void ( *USB_UH1_INT_ROUTINE )(void);
extern void ( *EMI2_INT_ROUTINE )(void);
extern void ( *USB_UH2_INT_ROUTINE )(void);
extern void ( *USB_UH3_INT_ROUTINE )(void);
extern void ( *USB_UOTG_INT_ROUTINE )(void);
extern void ( *SAHARA_INT1_ROUTINE )(void);
extern void ( *SAHARA_INT2_ROUTINE )(void);
extern void ( *SCC_SMON_INT_ROUTINE )(void);
extern void ( *SCC_SCTL_INT_ROUTINE )(void);
extern void ( *SCC_SCTL_NS_INT_ROUTINE )(void);
extern void ( *SRTC_INT_ROUTINE )(void);
extern void ( *SRTC_SEC_INT_ROUTINE )(void);
extern void ( *RTIC_INT_ROUTINE )(void);
extern void ( *CSU_INT_ROUTINE )(void);
extern void ( *SATA_INT_ROUTINE )(void);
extern void ( *SSI1_INT_ROUTINE )(void);
extern void ( *SSI2_INT_ROUTINE )(void);
extern void ( *UART1_ANDED_INT_ROUTINE )(void);
extern void ( *UART2_ANDED_INT_ROUTINE )(void);
extern void ( *UART3_ANDED_INT_ROUTINE )(void);
extern void ( *RTC_INT_ROUTINE )(void);
extern void ( *PTP_INT_ROUTINE )(void);
extern void ( *ECSPI1_INT_ROUTINE )(void);
extern void ( *ECSPI2_INT_ROUTINE )(void);
extern void ( *CSPI_INT_ROUTINE )(void);
extern void ( *GPT_INT_ROUTINE )(void);
extern void ( *EPIT1_INT_ROUTINE )(void);
extern void ( *EPIT2_INT_ROUTINE )(void);
extern void ( *GPIO1_INT7_ROUTINE )(void);
extern void ( *GPIO1_INT6_ROUTINE )(void);
extern void ( *GPIO1_INT5_ROUTINE )(void);
extern void ( *GPIO1_INT4_ROUTINE )(void);
extern void ( *GPIO1_INT3_ROUTINE )(void);
extern void ( *GPIO1_INT2_ROUTINE )(void);
extern void ( *GPIO1_INT1_ROUTINE )(void);
extern void ( *GPIO1_INT0_ROUTINE )(void);
extern void ( *GPIO1_INT15_0_ROUTINE )(void);
extern void ( *GPIO1_INT31_16_ROUTINE )(void);
extern void ( *GPIO2_INT15_0_ROUTINE )(void);
extern void ( *GPIO2_INT31_16_ROUTINE )(void);
extern void ( *GPIO3_INT15_0_ROUTINE )(void);
extern void ( *GPIO3_INT31_16_ROUTINE )(void);
extern void ( *GPIO4_INT15_0_ROUTINE )(void);
extern void ( *GPIO4_INT31_16_ROUTINE )(void);
extern void ( *WDOG1_INT_ROUTINE )(void);
extern void ( *WDOG2_INT_ROUTINE )(void);
extern void ( *KPP_INT_ROUTINE )(void);
extern void ( *PWM1_INT_ROUTINE )(void);
extern void ( *I2C1_INT_ROUTINE )(void);
extern void ( *I2C2_INT_ROUTINE )(void);
extern void ( *I2C3_INT_ROUTINE )(void);
extern void ( *MLB_INT_ROUTINE )(void);
extern void ( *ASRC_INT_ROUTINE )(void);
extern void ( *SPDIF_INT_ROUTINE )(void);
extern void ( *INTERRUPT_68 )(void); //RESERVED
extern void ( *IIM_INT_ROUTINE )(void);
extern void ( *PATA_INT_ROUTINE )(void);
extern void ( *CCM_INT1_ROUTINE )(void);
extern void ( *CCM_INT2_ROUTINE )(void);
extern void ( *GPC_INT1_ROUTINE )(void);
extern void ( *GPC_INT2_ROUTINE )(void);
extern void ( *SRC_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K_NM_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K_PMU_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K_CTI_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K1_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K2_INT_ROUTINE )(void);
extern void ( *ESAI1_INT_ROUTINE )(void);
extern void ( *CAN1_INT_ROUTINE )(void);
extern void ( *CAN2_INT_ROUTINE )(void);
extern void ( *GPU2D_IRQ_INT_ROUTINE )(void);
extern void ( *GPU2D_BUSY_INT_ROUTINE )(void);
extern void ( *UART5_ANDED_INT_ROUTINE )(void);
extern void ( *FEC_INT_ROUTINE )(void);
extern void ( *OWIRE_INT_ROUTINE )(void);
extern void ( *TIGERP_PLATFORM_NE_32K_256K3_INT_ROUTINE )(void);
extern void ( *SJC_INT_ROUTINE )(void);
extern void ( *INTERRUPT_91 )(void); //RESERVED
extern void ( *TVOUT_INT_ROUTINE )(void);
extern void ( *FIRI_INT_ROUTINE )(void);
extern void ( *PWM2_INT_ROUTINE )(void);
extern void ( *INTERRUPT_95 )(void); //RESERVED
extern void ( *SSI3_INT_ROUTINE )(void);
extern void ( *INTERRUPT_97 )(void); //RESERVED
extern void ( *TIGERP_PLATFORM_NE_32K_256K4_INT_ROUTINE )(void);
extern void ( *INTERRUPT_99 )(void); //RESERVED
extern void ( *VPU2_INT_ROUTINE )(void);
extern void ( *EMI_PROG_INT_ROUTINE )(void);
extern void ( *GPU2_INT_ROUTINE )(void);
extern void ( *GPIO5_INT15_0_ROUTINE )(void);
extern void ( *GPIO5_INT31_16_ROUTINE )(void);
extern void ( *GPIO6_INT15_0_ROUTINE )(void);
extern void ( *GPIO6_INT31_16_ROUTINE )(void);
extern void ( *GPIO7_INT15_0_ROUTINE )(void);
extern void ( *GPIO7_INT31_16_ROUTINE )(void);
extern void ( *INTERRUPT_109_128 )(void); //RESERVED
// IRQ TZIC INTERRUPT NUMBER
#define INTERRUPT_0_NUM 0 //RESERVED
#define ESDHC1_INT_NUM 1
#define ESDHC2_INT_NUM 2
#define ESDHC3_INT_NUM 3
#define ESDHC4_INT_NUM 4
#define DAP_INT_NUM 5
#define SDMA_INT_NUM 6
#define IOMUX_INT_NUM 7
#define EMI1_INT_NUM 8
#define VPU1_INT_NUM 9
#define IPU_ERR_INT_NUM 10
#define IPU_FUNC_INT_NUM 11
#define GPU1_INT_NUM 12
#define UART4_ANDED_INT_NUM 13
#define USB_UH1_INT_NUM 14
#define EMI2_INT_NUM 15
#define USB_UH2_INT_NUM 16
#define USB_UH3_INT_NUM 17
#define USB_UOTG_INT_NUM 18
#define SAHARA_INT1_NUM 19
#define SAHARA_INT2_NUM 20
#define SCC_SMON_INT_NUM 21
#define SCC_SCTL_INT_NUM 22
#define SCC_SCTL_NS_INT_NUM 23
#define SRTC_INT_NUM 24
#define SRTC_SEC_INT_NUM 25
#define RTIC_INT_NUM 26
#define CSU_INT_NUM 27
#define SATA_INT_NUM 28
#define SSI1_INT_NUM 29
#define SSI2_INT_NUM 30
#define UART1_ANDED_INT_NUM 31
#define UART2_ANDED_INT_NUM 32
#define UART3_ANDED_INT_NUM 33
#define RTC_INT_NUM 34
#define PTP_INT_NUM 35
#define ECSPI1_INT_NUM 36
#define ECSPI2_INT_NUM 37
#define CSPI_INT_NUM 38
#define GPT_INT_NUM 39
#define EPIT1_INT_NUM 40
#define EPIT2_INT_NUM 41
#define GPIO1_INT7_NUM 42
#define GPIO1_INT6_NUM 43
#define GPIO1_INT5_NUM 44
#define GPIO1_INT4_NUM 45
#define GPIO1_INT3_NUM 46
#define GPIO1_INT2_NUM 47
#define GPIO1_INT1_NUM 48
#define GPIO1_INT0_NUM 49
#define GPIO1_INT15_0_NUM 50
#define GPIO1_INT31_16_NUM 51
#define GPIO2_INT15_0_NUM 52
#define GPIO2_INT31_16_NUM 53
#define GPIO3_INT15_0_NUM 54
#define GPIO3_INT31_16_NUM 55
#define GPIO4_INT15_0_NUM 56
#define GPIO4_INT31_16_NUM 57
#define WDOG1_INT_NUM 58
#define WDOG2_INT_NUM 59
#define KPP_INT_NUM 60
#define PWM1_INT_NUM 61
#define I2C1_INT_NUM 62
#define I2C2_INT_NUM 63
#define I2C3_INT_NUM 64
#define MLB_INT_NUM 65
#define ASRC_INT_NUM 66
#define SPDIF_INT_NUM 67
#define INTERRUPT_68_NUM 68 //RESERVED
#define IIM_INT_NUM 69
#define PATA_INT_NUM 70
#define CCM_INT1_NUM 71
#define CCM_INT2_NUM 72
#define GPC_INT1_NUM 73
#define GPC_INT2_NUM 74
#define SRC_INT_NUM 75
#define TIGERP_PLATFORM_NE_32K_256K_NM_INT_NUM 76
#define TIGERP_PLATFORM_NE_32K_256K_PMU_INT_NUM 77
#define TIGERP_PLATFORM_NE_32K_256K_CTI_INT_NUM 78
#define TIGERP_PLATFORM_NE_32K_256K1_INT_NUM 79
#define TIGERP_PLATFORM_NE_32K_256K2_INT_NUM 80
#define ESAI1_INT_NUM 81
#define CAN1_INT_NUM 82
#define CAN2_INT_NUM 83
#define GPU2D_IRQ_INT_NUM 84
#define GPU2D_BUSY_INT_NUM 85
#define UART5_ANDED_INT_NUM 86
#define FEC_INT_NUM 87
#define OWIRE_INT_NUM 88
#define TIGERP_PLATFORM_NE_32K_256K3_INT_NUM 89
#define SJC_INT_NUM 90
#define INTERRUPT_91_NUM 91 //RESERVED
#define TVOUT_INT_NUM 92
#define FIRI_INT_NUM 93
#define PWM2_INT_NUM 94
#define INTERRUPT_95_NUM 95 //RESERVED
#define SSI3_INT_NUM 96
#define INTERRUPT_97_NUM 97 //RESERVED
#define TIGERP_PLATFORM_NE_32K_256K4_INT_NUM 98
#define INTERRUPT_99_NUM 99 //RESERVED
#define VPU2_INT_NUM 100
#define EMI_PROG_INT_NUM 101
#define GPU2_INT_NUM 102
#define GPIO5_INT15_0_NUM 103
#define GPIO5_INT31_16_NUM 104
#define GPIO6_INT15_0_NUM 105
#define GPIO6_INT31_16_NUM 106
#define GPIO7_INT15_0_NUM 107
#define GPIO7_INT31_16_NUM 108
#define INTERRUPT_109_128_NUM 109 //RESERVED
#ifdef ROC_TEST
#define ROC_ABORT_INTERRUPT 127 //abort interrupt for ROC test only!!! (shayg)
#endif //ROC_TEST
// FIQ INTERRUPT
extern void ( *FIQ_INTERRUPT_0 )(void); //RESERVED
extern void ( *FIQ_ESDHC1_INT_ROUTINE )(void);
extern void ( *FIQ_ESDHC2_INT_ROUTINE )(void);
extern void ( *FIQ_ESDHC3_INT_ROUTINE )(void);
extern void ( *FIQ_ESDHC4_INT_ROUTINE )(void);
extern void ( *FIQ_DAP_INT_ROUTINE )(void);
extern void ( *FIQ_SDMA_INT_ROUTINE )(void);
extern void ( *FIQ_IOMUX_INT_ROUTINE )(void);
extern void ( *FIQ_EMI1_INT_ROUTINE )(void);
extern void ( *FIQ_VPU1_INT_ROUTINE )(void);
extern void ( *FIQ_IPU_ERR_INT_ROUTINE )(void);
extern void ( *FIQ_IPU_FUNC_INT_ROUTINE )(void);
extern void ( *FIQ_GPU1_INT_ROUTINE )(void);
extern void ( *FIQ_UART4_ANDED_INT_ROUTINE )(void);
extern void ( *FIQ_USB_UH1_INT_ROUTINE )(void);
extern void ( *FIQ_EMI2_INT_ROUTINE )(void);
extern void ( *FIQ_USB_UH2_INT_ROUTINE )(void);
extern void ( *FIQ_USB_UH3_INT_ROUTINE )(void);
extern void ( *FIQ_USB_UOTG_INT_ROUTINE )(void);
extern void ( *FIQ_SAHARA_INT1_ROUTINE )(void);
extern void ( *FIQ_SAHARA_INT2_ROUTINE )(void);
extern void ( *FIQ_SCC_SMON_INT_ROUTINE )(void);
extern void ( *FIQ_SCC_SCTL_INT_ROUTINE )(void);
extern void ( *FIQ_SCC_SCTL_NS_INT_ROUTINE )(void);
extern void ( *FIQ_SRTC_INT_ROUTINE )(void);
extern void ( *FIQ_SRTC_SEC_INT_ROUTINE )(void);
extern void ( *FIQ_RTIC_INT_ROUTINE )(void);
extern void ( *FIQ_CSU_INT_ROUTINE )(void);
extern void ( *FIQ_SATA_INT_ROUTINE )(void);
extern void ( *FIQ_SSI1_INT_ROUTINE )(void);
extern void ( *FIQ_SSI2_INT_ROUTINE )(void);
extern void ( *FIQ_UART1_ANDED_INT_ROUTINE )(void);
extern void ( *FIQ_UART2_ANDED_INT_ROUTINE )(void);
extern void ( *FIQ_UART3_ANDED_INT_ROUTINE )(void);
extern void ( *FIQ_RTC_INT_ROUTINE )(void);
extern void ( *FIQ_PTP_INT_ROUTINE )(void);
extern void ( *FIQ_ECSPI1_INT_ROUTINE )(void);
extern void ( *FIQ_ECSPI2_INT_ROUTINE )(void);
extern void ( *FIQ_CSPI_INT_ROUTINE )(void);
extern void ( *FIQ_GPT_INT_ROUTINE )(void);
extern void ( *FIQ_EPIT1_INT_ROUTINE )(void);
extern void ( *FIQ_EPIT2_INT_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT7_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT6_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT5_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT4_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT3_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT2_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT1_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT0_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO1_INT31_16_ROUTINE )(void);
extern void ( *FIQ_GPIO2_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO2_INT31_16_ROUTINE )(void);
extern void ( *FIQ_GPIO3_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO3_INT31_16_ROUTINE )(void);
extern void ( *FIQ_GPIO4_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO4_INT31_16_ROUTINE )(void);
extern void ( *FIQ_WDOG1_INT_ROUTINE )(void);
extern void ( *FIQ_WDOG2_INT_ROUTINE )(void);
extern void ( *FIQ_KPP_INT_ROUTINE )(void);
extern void ( *FIQ_PWM1_INT_ROUTINE )(void);
extern void ( *FIQ_I2C1_INT_ROUTINE )(void);
extern void ( *FIQ_I2C2_INT_ROUTINE )(void);
extern void ( *FIQ_I2C3_INT_ROUTINE )(void);
extern void ( *FIQ_MLB_INT_ROUTINE )(void);
extern void ( *FIQ_ASRC_INT_ROUTINE )(void);
extern void ( *FIQ_SPDIF_INT_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_68 )(void); //RESERVED
extern void ( *FIQ_IIM_INT_ROUTINE )(void);
extern void ( *FIQ_PATA_INT_ROUTINE )(void);
extern void ( *FIQ_CCM_INT1_ROUTINE )(void);
extern void ( *FIQ_CCM_INT2_ROUTINE )(void);
extern void ( *FIQ_GPC_INT1_ROUTINE )(void);
extern void ( *FIQ_GPC_INT2_ROUTINE )(void);
extern void ( *FIQ_SRC_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K_NM_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K_PMU_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K_CTI_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K1_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K2_INT_ROUTINE )(void);
extern void ( *FIQ_ESAI1_INT_ROUTINE )(void);
extern void ( *FIQ_CAN1_INT_ROUTINE )(void);
extern void ( *FIQ_CAN2_INT_ROUTINE )(void);
extern void ( *FIQ_GPU2D_IRQ_INT_ROUTINE )(void);
extern void ( *FIQ_GPU2D_BUSY_INT_ROUTINE )(void);
extern void ( *FIQ_UART5_ANDED_INT_ROUTINE )(void);
extern void ( *FIQ_FEC_INT_ROUTINE )(void);
extern void ( *FIQ_OWIRE_INT_ROUTINE )(void);
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K3_INT_ROUTINE )(void);
extern void ( *FIQ_SJC_INT_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_91 )(void); //RESERVED
extern void ( *FIQ_TVOUT_INT_ROUTINE )(void);
extern void ( *FIQ_FIRI_INT_ROUTINE )(void);
extern void ( *FIQ_PWM2_INT_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_95 )(void); //RESERVED
extern void ( *FIQ_SSI3_INT_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_97 )(void); //RESERVED
extern void ( *FIQ_TIGERP_PLATFORM_NE_32K_256K4_INT_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_99 )(void); //RESERVED
extern void ( *FIQ_VPU2_INT_ROUTINE )(void);
extern void ( *FIQ_EMI_PROG_INT_ROUTINE )(void);
extern void ( *FIQ_GPU2_INT_ROUTINE )(void);
extern void ( *FIQ_GPIO5_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO5_INT31_16_ROUTINE )(void);
extern void ( *FIQ_GPIO6_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO6_INT31_16_ROUTINE )(void);
extern void ( *FIQ_GPIO7_INT15_0_ROUTINE )(void);
extern void ( *FIQ_GPIO7_INT31_16_ROUTINE )(void);
extern void ( *FIQ_INTERRUPT_109_128 )(void); //RESERVED
// FIQ TZIC INTERRUPT NUMBER
#define FIQ_INTERRUPT_0_NUM 0 //RESERVED
#define FIQ_ESDHC1_INT_NUM 1
#define FIQ_ESDHC2_INT_NUM 2
#define FIQ_ESDHC3_INT_NUM 3
#define FIQ_ESDHC4_INT_NUM 4
#define FIQ_DAP_INT_NUM 5
#define FIQ_SDMA_INT_NUM 6
#define FIQ_IOMUX_INT_NUM 7
#define FIQ_EMI1_INT_NUM 8
#define FIQ_VPU1_INT_NUM 9
#define FIQ_IPU_ERR_INT_NUM 10
#define FIQ_IPU_FUNC_INT_NUM 11
#define FIQ_GPU1_INT_NUM 12
#define FIQ_UART4_ANDED_INT_NUM 13
#define FIQ_USB_UH1_INT_NUM 14
#define FIQ_EMI2_INT_NUM 15
#define FIQ_USB_UH2_INT_NUM 16
#define FIQ_USB_UH3_INT_NUM 17
#define FIQ_USB_UOTG_INT_NUM 18
#define FIQ_SAHARA_INT1_NUM 19
#define FIQ_SAHARA_INT2_NUM 20
#define FIQ_SCC_SMON_INT_NUM 21
#define FIQ_SCC_SCTL_INT_NUM 22
#define FIQ_SCC_SCTL_NS_INT_NUM 23
#define FIQ_SRTC_INT_NUM 24
#define FIQ_SRTC_SEC_INT_NUM 25
#define FIQ_RTIC_INT_NUM 26
#define FIQ_CSU_INT_NUM 27
#define FIQ_SATA_INT_NUM 28
#define FIQ_SSI1_INT_NUM 29
#define FIQ_SSI2_INT_NUM 30
#define FIQ_UART1_ANDED_INT_NUM 31
#define FIQ_UART2_ANDED_INT_NUM 32
#define FIQ_UART3_ANDED_INT_NUM 33
#define FIQ_RTC_INT_NUM 34
#define FIQ_PTP_INT_NUM 35
#define FIQ_ECSPI1_INT_NUM 36
#define FIQ_ECSPI2_INT_NUM 37
#define FIQ_CSPI_INT_NUM 38
#define FIQ_GPT_INT_NUM 39
#define FIQ_EPIT1_INT_NUM 40
#define FIQ_EPIT2_INT_NUM 41
#define FIQ_GPIO1_INT7_NUM 42
#define FIQ_GPIO1_INT6_NUM 43
#define FIQ_GPIO1_INT5_NUM 44
#define FIQ_GPIO1_INT4_NUM 45
#define FIQ_GPIO1_INT3_NUM 46
#define FIQ_GPIO1_INT2_NUM 47
#define FIQ_GPIO1_INT1_NUM 48
#define FIQ_GPIO1_INT0_NUM 49
#define FIQ_GPIO1_INT15_0_NUM 50
#define FIQ_GPIO1_INT31_16_NUM 51
#define FIQ_GPIO2_INT15_0_NUM 52
#define FIQ_GPIO2_INT31_16_NUM 53
#define FIQ_GPIO3_INT15_0_NUM 54
#define FIQ_GPIO3_INT31_16_NUM 55
#define FIQ_GPIO4_INT15_0_NUM 56
#define FIQ_GPIO4_INT31_16_NUM 57
#define FIQ_WDOG1_INT_NUM 58
#define FIQ_WDOG2_INT_NUM 59
#define FIQ_KPP_INT_NUM 60
#define FIQ_PWM1_INT_NUM 61
#define FIQ_I2C1_INT_NUM 62
#define FIQ_I2C2_INT_NUM 63
#define FIQ_I2C3_INT_NUM 64
#define FIQ_MLB_INT_NUM 65
#define FIQ_ASRC_INT_NUM 66
#define FIQ_SPDIF_INT_NUM 67
#define FIQ_INTERRUPT_68_NUM 68 //RESERVED
#define FIQ_IIM_INT_NUM 69
#define FIQ_PATA_INT_NUM 70
#define FIQ_CCM_INT1_NUM 71
#define FIQ_CCM_INT2_NUM 72
#define FIQ_GPC_INT1_NUM 73
#define FIQ_GPC_INT2_NUM 74
#define FIQ_SRC_INT_NUM 75
#define FIQ_TIGERP_PLATFORM_NE_32K_256K_NM_INT_NUM 76
#define FIQ_TIGERP_PLATFORM_NE_32K_256K_PMU_INT_NUM 77
#define FIQ_TIGERP_PLATFORM_NE_32K_256K_CTI_INT_NUM 78
#define FIQ_TIGERP_PLATFORM_NE_32K_256K1_INT_NUM 79
#define FIQ_TIGERP_PLATFORM_NE_32K_256K2_INT_NUM 80
#define FIQ_ESAI1_INT_NUM 81
#define FIQ_CAN1_INT_NUM 82
#define FIQ_CAN2_INT_NUM 83
#define FIQ_GPU2D_IRQ_INT_NUM 84
#define FIQ_GPU2D_BUSY_INT_NUM 85
#define FIQ_UART5_ANDED_INT_NUM 86
#define FIQ_FEC_INT_NUM 87
#define FIQ_OWIRE_INT_NUM 88
#define FIQ_TIGERP_PLATFORM_NE_32K_256K3_INT_NUM 89
#define FIQ_SJC_INT_NUM 90
#define FIQ_INTERRUPT_91_NUM 91 //RESERVED
#define FIQ_TVOUT_INT_NUM 92
#define FIQ_FIRI_INT_NUM 93
#define FIQ_PWM2_INT_NUM 94
#define FIQ_INTERRUPT_95_NUM 95 //RESERVED
#define FIQ_SSI3_INT_NUM 96
#define FIQ_INTERRUPT_97_NUM 97
#define FIQ_TIGERP_PLATFORM_NE_32K_256K4_INT_NUM 98
#define FIQ_INTERRUPT_99_NUM 99 //RESERVED
#define FIQ_VPU2_INT_NUM 100
#define FIQ_EMI_PROG_INT_NUM 101
#define FIQ_GPU2_INT_NUM 102
#define FIQ_GPIO5_INT15_0_NUM 103
#define FIQ_GPIO5_INT31_16_NUM 104
#define FIQ_GPIO6_INT15_0_NUM 105
#define FIQ_GPIO6_INT31_16_NUM 106
#define FIQ_GPIO7_INT15_0_NUM 107
#define FIQ_GPIO7_INT31_16_NUM 108
#define FIQ_INTERRUPT_109_128_NUM 109 //RESERVED
2. crt0.s
.global RESET_HLDR
.global UNDEF_HLDR
.global SWI_HLDR
.global PREFETCH_HLDR
.global ABORT_HLDR
.global IRQ_HLDR
.global FIQ_HLDR
.global SMI_HLDR
.extern __init_main
.extern main
.extern main_section
.extern SMI_RANDOM
.global _start
.global undef_hdler
.global swi_hdler
.global prefetch_hdler
.global abort_hdler
.global irq_hdler
.global fiq_hdler
.global smi_hdler
.extern rompatch_tbl_ptr
.extern c_main
.extern UNDEF_HLDR_EXCEPT
.extern SWI_HLDR_EXCEPT
.extern PREFETCH_HLDR_EXCEPT
.extern ABORT_HLDR_EXCEPT
.extern IRQ_HLDR_EXCEPT
.extern FIQ_HLDR_EXCEPT
.extern SMI_HLDR_EXCEPT
.align 4
.arm
.section .start
.macro write_reg addr, val
ldr r0, =\addr
ldr r1, =\val
str r1, [r0]
.endm
.macro read_reg addr, reg
ldr r0, =\addr
ldr \reg, [r0]
.endm
.equ TZIC_BASE_ADDR, 0x0FFFC000
.equ IRAM_BASE_ADDR, 0xF8000000
.equ RAM_TEST_CODE_ADDR, IRAM_BASE_ADDR+0x1000 @; F800_1000 - F800_FFFF (EFFF) Test code
_start:
nop
CRT0_START:
@;@@@@@@@@@@@@@@@@@NORMAL@@@@@@@@@@@@@
@; initialize registers in USER mode
mov r0,#0
mov r1,#0
mov r2,#0
mov r3,#0
mov r4,#0
mov r5,#0
mov r6,#0
mov r7,#0
mov r8,#0
mov r9,#0
mov r10,#0
mov r11,#0
mov r12,#0
@; ARM_EMBEDDED_MODE
mrs r7,CPSR
bic r7,r7,#0x0f @; clear mode bits
add r6,r7,#0x01
msr CPSR,r6 @; goto FIQ mode
@; initialize registers in FIQ mode
mov r8,#0
mov r9,#0
mov r10,#0
mov r11,#0
mov r12,#0
ldr sp,=__SP_FIQ
mov lr,#0
add r6,r7,#0x02
msr CPSR,r6 @; goto IRQ mode
@; initialize registers in IRQ mode
ldr sp,=__SP_IRQ
mov lr,#0
add r6,r7,#0x03
msr CPSR,r6 @; goto SVC mode
@; initialize registers in SVC mode
@; Read Secure or Nonsecure Vector Base Address Register
mrc p15,0,r5,c12,c0,1
ldr r5,=vects1_start
@; Write Secure or Nonsecure Vector Base Address Register
mcr p15,0,r5,c12,c0,1
ldr sp,=__SP_SVC
mov lr,#0
add r6,r7,#0x06
msr CPSR,r6 @;go to MON mode
@;initialize registers in monitor mode
ldr sp,=__SP_MON
mov lr,#0
add r6,r7,#0x07
msr CPSR,r6 @; goto ABORT mode
@; initialize registers in ABORT mode
ldr sp,=__SP_ABORT
mov lr,#0
add r6,r7,#0x0b
msr CPSR,r6 @; goto UNDEF mode
@; initialize registers in UNDEF mode
ldr sp,=__SP_UNDEF
mov lr,#0
add r6,r7,#0x0f
msr CPSR,r6 @; goto SYSTEM mode
mrs r0, cpsr
bic r1,r0, #0x100 @;@ try to clear the A bit
msr cpsr_cxsf, r1
mrs r0, cpsr
@; initialize registers in SYSTEM mode
@;
@; Note: SYSTEM mode does not share r13 and r14 (i.e. sp and lr) with USER mode
ldr sp,=__SP_SYSTEM
mov lr,#0
@; Enable exceptions
@; clean up and call the C 'main' function
mrs r6,CPSR
bic r7,r6,#0xc0 @; enable exceptions
msr CPSR,r7
@; enable the coprocessors
ldr r0,=0xffffffff
mcr p15,0,r0,c1,c0,2
@; ensure the return stack does not have x's which can cause core to hang
BL rs_label0
rs_label0:
BL rs_label1
rs_label1:
BL rs_label2
rs_label2:
BL rs_label3
rs_label3:
BL rs_label4
rs_label4:
BL rs_label5
rs_label5:
BL rs_label6
rs_label6:
BL rs_label7
rs_label7:
@;; edof 27.8
@;; MOV to spvr mode so test will start in SPVR mode with SP_svc and LR_svc
mrs r0,CPSR @;; Read CPSR
bic r0,r0,#0x1f @;; Clear Mode bits
orr r0,r0,#0x13 @;; Set the Mode bits to SPVR mode
msr CPSR_c,r0 @;; Update the control bits in the CPSR , now in SPVR mode
@; Mapping the special handler UNDEF_HLDR,SWI_HLDR,PREFECH_HLDR,ABORT_HLDR,IRQ_HLDR,FIQ_HLDR.
@; look in $DESIGN_DIR/project_settings/testbench/arm_gnu/src/vectable.s for the HDLR order
LDR r5, = 0x00000004
LDR r6, = 0xE59FF014 @;op.code -> jump to the address in pc+0x1C
LDR r1, = IRAM_BASE_ADDR+0x1FFBC @;; RAM address,the ARM jump to this address when UNDEF occur.
str r6, [r1]
add r1,r1,r5 @; RAM address,the ARM jump to this address when SWI occur.
str r6, [r1]
add r1,r1,r5 @; RAM address,the ARM jump to this address when PREFECH occur.
str r6, [r1]
add r1,r1,r5 @; RAM address,the ARM jump to this address when ABORT occur.
str r6, [r1]
add r1,r1,r5 @; NOP - empty
str r6, [r1]
add r1,r1,r5 @; RAM address,the ARM jump to this address when IRQ occur.
str r6, [r1]
add r1,r1,r5 @; RAM address,the ARM jump to this address when FIQ occur.
str r6, [r1]
LDR r6, = RAM_TEST_CODE_ADDR @;;UNDEF_HLDR place when running from RAM
add r1,r1,r5
str r6, [r1] @;;UNDEF_HLDR place
add r1,r1,r5
ldr r2,= 0x1c
add r6,r6,r2 @; addr=base+0x1c
str r6, [r1] @;;SWI_HLDR place
add r1,r1,r5
ldr r2,= 0x38
add r6,r6,r2 @; addr=base+0x54
str r6, [r1] @;;PREFECH_HLDR place
add r1,r1,r5
ldr r2,= 0x1c
add r6,r6,r2 @; addr=base+0x70
str r6, [r1] @;;ABORT_HLDR place
add r1,r1,r5
ldr r2,= 0x00
add r6,r6,r2 @;
str r6, [r1] @;;NOP place
add r1,r1,r5
ldr r2,= 0x3c
add r6,r6,r2 @; addr=base+0xac
str r6, [r1] @;;IRQ_HLDR place
add r1,r1,r5
ldr r2,= 0x94
add r6,r6,r2 @; addr=base+0x140
str r6, [r1] @;;FIQ_HLDR place
ldr r6,= 0x00001fff
add r1,r1,r5
str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFF4)
add r1,r1,r5
str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFF8)
add r1,r1,r5
str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFFC)
b c_main
UNDEF_HLDR:
stmfd sp!, {r0,lr} @; push our temp reg, R0, since C seems to feel free to bash it anyway
ldr lr,=undef_hdler @; load address of pointer to undef handler function using LR temporarily
ldr r0,[lr] @; load the undef handler function pointer into R0
mov lr,pc @; preserve PC in LR so that called code can return.
bx r0 @; this way of doing the call allows Thumb code to be called
ldmfd sp!, {r0,lr} @; then, pull back preserved R0.
movs pc,lr @; return from the interrupt to wherever LR points.
SWI_HLDR:
stmfd sp!, {r0-r1,lr} @; push register onto SWI stack
mrs r0, spsr @; get saved status register
tst r0, #0x20 @; check if call was in THUMB mode
ldrneh r0, [lr,#-2] @; yes: load opcode half-word and
bicne r0, r0, #0xff00 @; yes: extract THUMB comment
ldreq r0, [lr,#-4] @; no: load opcode word and
biceq r0, r0, #0xff000000 @; no: extract ARM comment
@; now r0 has comment field
ldr lr,=swi_hdler @; >= 16: pointer to standard SWI
ldr r1,[lr] @; handler
mov lr,pc @; >= 16: set link register
bx r1 @; >= 16: jump to standard SWI
@; handler
ldmfd sp!, {r0-r1,pc}^
.ltorg
PREFETCH_HLDR:
stmfd sp!, {r0,lr} @; see UNDEF_HLDR for commentary
@; as this only differs in return mechanism
ldr lr,=prefetch_hdler
ldr r0,[lr]
mov lr,pc
bx r0
ldmfd sp!, {r0,lr}
subs pc,lr,#4
ABORT_HLDR:
stmfd sp!, {r0-r2,lr} @; see UNDEF_HLDR for commentary
@; as this only differs in return mechanism
ldr lr,=abort_hdler
ldr r0,[lr]
mov lr,pc
bx r0
mrc p15,0,r0,c5,c0,0
ldr r1,=0x40f
and r0,r0,r1
ldr r2,=0x406
cmp r0,r2
bne NOT_IMPRECISE_ABORT
ldmfd sp!, {r0-r2,lr}
subs pc,lr,#8
NOT_IMPRECISE_ABORT :
ldmfd sp!, {r0-r2,lr}
subs pc,lr,#4
IRQ_HLDR:
stmfd sp!, {r0-r12,lr}
ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending register
ldr r0,[r0]
mov r2, #0x0
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending register
ldr r0,[r0]
mov r2, #32
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending register
ldr r0,[r0]
mov r2, #64
cmp r0, #0
bne FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending register
ldr r0,[r0]
mov r2, #96
cmp r0, #0
bne FIND_NUMBER
FIND_NUMBER:
mov r0, r0, lsr #1
cmp r0, #0
beq FOUND_NUMBER
add r2, r2, #0x1
b FIND_NUMBER
FOUND_NUMBER:
mov r2, r2, lsl #2
mov r0, r2
ldr lr,=INTERRUPT_0
ldr r0,[lr,r0]
mov lr,pc
bx r0
mrs r0, cpsr
bic r1, r0, #0x100
msr cpsr_cxsf, r1
ldmfd sp!, {r0-r12,lr}
subs pc,lr,#4
FIQ_HLDR:
stmfd sp!, {r0-r12,lr}
ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending register
ldr r0,[r0]
mov r2, #0x0
cmp r0, #0
bne FIQ_FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending register
ldr r0,[r0]
mov r2, #32
cmp r0, #0
bne FIQ_FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending register
ldr r0,[r0]
mov r2, #64
cmp r0, #0
bne FIQ_FIND_NUMBER
ldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending register
ldr r0,[r0]
mov r2, #96
cmp r0, #0
bne FIQ_FIND_NUMBER
FIQ_FIND_NUMBER:
mov r0, r0, lsr #1
cmp r0, #0
beq FIQ_FOUND_NUMBER
add r2, r2, #0x1
b FIQ_FIND_NUMBER
FIQ_FOUND_NUMBER:
mov r2, r2, lsl #2
mov r0, r2
ldr lr,=FIQ_INTERRUPT_0
ldr r0,[lr,r0]
mov lr,pc
bx r0
mrs r0, cpsr
bic r1, r0, #0x100
msr cpsr_cxsf, r1
ldmfd sp!, {r0-r12,lr}
subs pc,lr,#4
@;MODIFIED 26-May(IDC)
.align 5
vects1_start:
nop @; offset 0x00
nop @; offset 0x04
ldr pc, =SMI_HLDR @; offset 0x08
nop @; offset 0x0c
nop @; offset 0x10
nop @; offset 0x14
nop @; offset 0x18
ldr pc, =FIQ_HLDR @; offset 0x1c
nop @; offset 0x20
nop @; offset 0x24
nop @; offset 0x28
nop @; offset 0x2c
nop @; offset 0x30
nop @; offset 0x34
nop @; offset 0x38
nop @; offset 0x3c
nop @; offset 0x40
nop @; offset 0x44
nop @; offset 0x48
nop @; offset 0x4c
nop @; offset 0x50
nop @; offset 0x54
nop @; offset 0x58
nop @; offset 0x5c
nop @; offset 0x60
nop @; offset 0x64
nop @; offset 0x68
nop @; offset 0x6c
nop @; offset 0x70
nop @; offset 0x74
nop @; offset 0x78
nop @; offset 0x7c
nop @; offset 0x80
nop @; offset 0x84
nop @; offset 0x88
ldr pc, =SMI_HLDR @; offset 0x8c
@;MODIFIED 11-May(IDC)
SMI_HLDR:
stmfd sp!, {r0-r1,lr} @; push register onto SMI stack
ldr r1,=smi_hdler @; >= 16: pointer to standard SMI
ldr r0,[r1] @; handler
mov lr,pc @; >= 16: set link register
bx r0 @; >= 16: jump to standard SMI
@; handler
ldmfd sp!, {r0-r1,pc}^
@;Following is Exception Table
undef_hdler:
.long UNDEF_HLDR_EXCEPT
swi_hdler:
.long SWI_HLDR_EXCEPT
prefetch_hdler:
.long PREFETCH_HLDR_EXCEPT
abort_hdler:
.long ABORT_HLDR_EXCEPT
irq_hdler:
.long IRQ_HLDR_EXCEPT
fiq_hdler:
.long FIQ_HLDR_EXCEPT
smi_hdler:
.long SMI_HLDR_EXCEPT
CRT0_END:
.ltorg @; literal dump
3. 链接脚本
MEMORY
{
rom : org = 0x00000000, len = 0x00008000
ram : org = 0xf8000000, len = 0x00020000
}
/*********************************************************
** Define memory regions for secure ROM and BOOT
*********************************************************/
__SEC_ROM_START = 0x00000000;
__NORM_ROM_START = 0x00000000;
SECTIONS
{
.rom : { vectors.o (.vectors); } > rom
.rom : { crt0.o(.start) *(.text); } > rom
.rom : { * (.text); *(.rodata); } > rom
.ram : { *(.glue_7) *(.glue_7t) ; } > ram
.data : { *(.data) ; } > ram
.bss : { *(.bss) *(.sbss) ; } > ram
.stack : { . += 0x1000; } > ram
.mmu : { *(.mmu) ; } > ram
.vfp11_veneer : { *(.vfp11_veneer) ; } > ram
}
/* ------------------------------------------------------------------------- */
/* Definitions of identifiers used by sbrk.c, init.c, and the different */
/* crt0.s files. Their purpose is to control initialization and memory */
/* allocation. */
/* */
/* __HEAP_START : Start of memory used by malloc() etc. */
/* __HEAP_END : End of heap memory */
/* __SP_INIT : Initial address of stack pointer */
/* __SP_END : Only used when stack probing */
/* __DATA_ROM : Address of initialized data in ROM */
/* __DATA_RAM : Address of initialized data in RAM */
/* __DATA_END : End of allocated initialized data */
/* __BSS_START : Start of uninitialized data */
/* __BSS_END : End of data to be cleared */
/* ------------------------------------------------------------------------- */
__HEAP_START = ADDR(.bss)+SIZEOF(.bss);
__SP_UNDEF = ADDR(.stack)+SIZEOF(.stack);
__SP_ABORT = __SP_UNDEF - 0x0200;
__SP_SVC = __SP_UNDEF - 0x0400;
__SP_IRQ = __SP_UNDEF - 0x0600;
__SP_FIQ = __SP_UNDEF - 0x0800;
__SP_SYSTEM = __SP_UNDEF - 0x0a00;
__SP_MON = __SP_UNDEF - 0x0c00;
__HEAP_END = __SP_UNDEF - 0x8000;
__SP_END = __HEAP_END;
__DATA_ROM = ADDR(.data);
__DATA_RAM = ADDR(.data);
__DATA_END = ADDR(.data)+SIZEOF(.data);
__BSS_START = ADDR(.bss);
__BSS_END = ADDR(.bss)+SIZEOF(.bss);
/* ------------------------------------------------------------------------- */
/* Some targets use an extra underscore in front of identifiers */
/* ------------------------------------------------------------------------- */
___HEAP_START = __HEAP_START;
___HEAP_END = __HEAP_END;
___SP_INIT = __SP_SYSTEM;
___SP_END = __SP_END;
___DATA_ROM = __DATA_ROM;
___DATA_RAM = __DATA_RAM;
___DATA_END = __DATA_END;
___BSS_START = __BSS_START;
___BSS_END = __BSS_END;