ARM 外部中断的过程
前言
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
.armVECTORS:
.ifdef BOOT_DENALIldr pc, =JUMP_COMMON
.else.ifdef ARM_EMBEDDED_MODEldr pc, =_start.else ldr pc, =JUMP_CS0.endif
.endifldr pc, =UNDEF_HLDRldr pc, =SWI_HLDRldr pc, =PREFETCH_HLDRldr pc, =ABORT_HLDRnopldr pc, =IRQ_HLDRldr pc, =FIQ_HLDRnopnop
首先定义的是复位异常中断,此中断跳转地址是正常程序的起始地址**_start**。
然后按顺序定义其他的中断跳转地址。
硬件触发外部中断后,ARM会跳转到IRQ_HLDR。
然后来看看 IRQ_HLDR的汇编。
@crt0.s的部分内容
IRQ_HLDR:stmfd sp!, {r0-r12,lr}ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending registerldr r0,[r0]mov r2, #0x0cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending registerldr r0,[r0]mov r2, #32cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending registerldr r0,[r0]mov r2, #64cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending registerldr r0,[r0]mov r2, #96cmp r0, #0bne FIND_NUMBERFIND_NUMBER:mov r0, r0, lsr #1cmp r0, #0beq FOUND_NUMBERadd r2, r2, #0x1b FIND_NUMBERFOUND_NUMBER:mov r2, r2, lsl #2mov r0, r2ldr lr,=INTERRUPT_0ldr r0,[lr,r0]mov lr,pcbx r0mrs r0, cpsrbic r1, r0, #0x100msr cpsr_cxsf, r1ldmfd sp!, {r0-r12,lr}subs pc,lr,#4
首先stmfd 压栈, 保护CPU状态。
接下来是4段比较相似的程序,用于查询触发的外部中断号。
TZIC 实现了128个外部中断,使用前需要先对TZIC进行配置。
设置相应中断的中断号。如果此中断触发,就可以在HIPND(0-3) interrupt pending register这四个寄存器中查到。
然后解析一下其中一段程序的内容:
@将中断挂起寄存器0的地址,保存到r0ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending register@寄存器间接寻址,将r0寄存器的值看作地址,然后将地址对应的值传给r0ldr r0,[r0]@r2 = 0mov r2, #0x0@比较r0和0的大小,如果r0!=0,则跳转FIND_NUMBERcmp r0, #0bne 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 void ( *UART1_ANDED_INT_ROUTINE )(void);使用extern关键字声明,以便在c里面进行调用。
这里声明的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, valldr r0, =\addrldr r1, =\valstr r1, [r0]
.endm.macro read_reg addr, regldr r0, =\addrldr \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 modemov r0,#0mov r1,#0mov r2,#0mov r3,#0mov r4,#0mov r5,#0mov r6,#0mov r7,#0mov r8,#0mov r9,#0mov r10,#0mov r11,#0mov r12,#0@; ARM_EMBEDDED_MODEmrs r7,CPSRbic r7,r7,#0x0f @; clear mode bitsadd r6,r7,#0x01msr CPSR,r6 @; goto FIQ mode@; initialize registers in FIQ modemov r8,#0mov r9,#0mov r10,#0mov r11,#0mov r12,#0ldr sp,=__SP_FIQmov lr,#0add r6,r7,#0x02msr CPSR,r6 @; goto IRQ mode@; initialize registers in IRQ modeldr sp,=__SP_IRQmov lr,#0add r6,r7,#0x03msr CPSR,r6 @; goto SVC mode@; initialize registers in SVC mode@; Read Secure or Nonsecure Vector Base Address Registermrc p15,0,r5,c12,c0,1ldr r5,=vects1_start
@; Write Secure or Nonsecure Vector Base Address Registermcr p15,0,r5,c12,c0,1ldr sp,=__SP_SVCmov lr,#0add r6,r7,#0x06msr CPSR,r6 @;go to MON mode@;initialize registers in monitor modeldr sp,=__SP_MONmov lr,#0add r6,r7,#0x07msr CPSR,r6 @; goto ABORT mode@; initialize registers in ABORT modeldr sp,=__SP_ABORTmov lr,#0add r6,r7,#0x0bmsr CPSR,r6 @; goto UNDEF mode@; initialize registers in UNDEF modeldr sp,=__SP_UNDEFmov lr,#0add r6,r7,#0x0fmsr CPSR,r6 @; goto SYSTEM modemrs r0, cpsrbic r1,r0, #0x100 @;@ try to clear the A bitmsr cpsr_cxsf, r1mrs r0, cpsr@; initialize registers in SYSTEM mode
@;
@; Note: SYSTEM mode does not share r13 and r14 (i.e. sp and lr) with USER modeldr sp,=__SP_SYSTEMmov lr,#0@; Enable exceptions@; clean up and call the C 'main' functionmrs r6,CPSRbic r7,r6,#0xc0 @; enable exceptionsmsr CPSR,r7@; enable the coprocessorsldr r0,=0xffffffffmcr p15,0,r0,c1,c0,2@; ensure the return stack does not have x's which can cause core to hangBL 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_svcmrs r0,CPSR @;; Read CPSRbic r0,r0,#0x1f @;; Clear Mode bitsorr r0,r0,#0x13 @;; Set the Mode bits to SPVR modemsr 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 orderLDR r5, = 0x00000004LDR r6, = 0xE59FF014 @;op.code -> jump to the address in pc+0x1CLDR 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 - emptystr 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 RAMadd r1,r1,r5str r6, [r1] @;;UNDEF_HLDR placeadd r1,r1,r5ldr r2,= 0x1cadd r6,r6,r2 @; addr=base+0x1cstr r6, [r1] @;;SWI_HLDR placeadd r1,r1,r5ldr r2,= 0x38add r6,r6,r2 @; addr=base+0x54str r6, [r1] @;;PREFECH_HLDR placeadd r1,r1,r5ldr r2,= 0x1cadd r6,r6,r2 @; addr=base+0x70str r6, [r1] @;;ABORT_HLDR placeadd r1,r1,r5ldr r2,= 0x00add r6,r6,r2 @;str r6, [r1] @;;NOP placeadd r1,r1,r5ldr r2,= 0x3cadd r6,r6,r2 @; addr=base+0xacstr r6, [r1] @;;IRQ_HLDR placeadd r1,r1,r5ldr r2,= 0x94add r6,r6,r2 @; addr=base+0x140str r6, [r1] @;;FIQ_HLDR placeldr r6,= 0x00001fffadd r1,r1,r5str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFF4)add r1,r1,r5str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFF8)add r1,r1,r5str r6, [r1] @; Data so we will not read xxxx (r1=SCC_RAM_BASE_ADDR+0x1FFFC)b c_mainUNDEF_HLDR:stmfd sp!, {r0,lr} @; push our temp reg, R0, since C seems to feel free to bash it anywayldr lr,=undef_hdler @; load address of pointer to undef handler function using LR temporarilyldr r0,[lr] @; load the undef handler function pointer into R0mov 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 calledldmfd 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 stackmrs r0, spsr @; get saved status registertst r0, #0x20 @; check if call was in THUMB modeldrneh r0, [lr,#-2] @; yes: load opcode half-word andbicne r0, r0, #0xff00 @; yes: extract THUMB commentldreq r0, [lr,#-4] @; no: load opcode word andbiceq r0, r0, #0xff000000 @; no: extract ARM comment@; now r0 has comment fieldldr lr,=swi_hdler @; >= 16: pointer to standard SWIldr r1,[lr] @; handlermov lr,pc @; >= 16: set link registerbx r1 @; >= 16: jump to standard SWI@; handlerldmfd sp!, {r0-r1,pc}^.ltorgPREFETCH_HLDR:stmfd sp!, {r0,lr} @; see UNDEF_HLDR for commentary@; as this only differs in return mechanismldr lr,=prefetch_hdlerldr r0,[lr]mov lr,pcbx r0ldmfd sp!, {r0,lr}subs pc,lr,#4ABORT_HLDR:stmfd sp!, {r0-r2,lr} @; see UNDEF_HLDR for commentary@; as this only differs in return mechanismldr lr,=abort_hdlerldr r0,[lr]mov lr,pcbx r0mrc p15,0,r0,c5,c0,0ldr r1,=0x40fand r0,r0,r1ldr r2,=0x406cmp r0,r2bne NOT_IMPRECISE_ABORTldmfd sp!, {r0-r2,lr}subs pc,lr,#8
NOT_IMPRECISE_ABORT :ldmfd sp!, {r0-r2,lr}subs pc,lr,#4IRQ_HLDR:stmfd sp!, {r0-r12,lr}ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending registerldr r0,[r0]mov r2, #0x0cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending registerldr r0,[r0]mov r2, #32cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending registerldr r0,[r0]mov r2, #64cmp r0, #0bne FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending registerldr r0,[r0]mov r2, #96cmp r0, #0bne FIND_NUMBERFIND_NUMBER:mov r0, r0, lsr #1cmp r0, #0beq FOUND_NUMBERadd r2, r2, #0x1b FIND_NUMBERFOUND_NUMBER:mov r2, r2, lsl #2mov r0, r2ldr lr,=INTERRUPT_0ldr r0,[lr,r0]mov lr,pcbx r0mrs r0, cpsrbic r1, r0, #0x100msr cpsr_cxsf, r1ldmfd sp!, {r0-r12,lr}subs pc,lr,#4FIQ_HLDR:stmfd sp!, {r0-r12,lr}ldr r0,= TZIC_BASE_ADDR+0xD80 @; HIPND0 interrupt pending registerldr r0,[r0]mov r2, #0x0cmp r0, #0bne FIQ_FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD84 @; HIPND1 interrupt pending registerldr r0,[r0]mov r2, #32cmp r0, #0bne FIQ_FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD88 @; HIPND2 interrupt pending registerldr r0,[r0]mov r2, #64cmp r0, #0bne FIQ_FIND_NUMBERldr r0,= TZIC_BASE_ADDR+0xD8C @; HIPND3 interrupt pending registerldr r0,[r0]mov r2, #96cmp r0, #0bne FIQ_FIND_NUMBERFIQ_FIND_NUMBER:mov r0, r0, lsr #1cmp r0, #0beq FIQ_FOUND_NUMBERadd r2, r2, #0x1b FIQ_FIND_NUMBERFIQ_FOUND_NUMBER:mov r2, r2, lsl #2mov r0, r2ldr lr,=FIQ_INTERRUPT_0ldr r0,[lr,r0]mov lr,pcbx r0mrs r0, cpsrbic r1, r0, #0x100msr cpsr_cxsf, r1ldmfd sp!, {r0-r12,lr}subs pc,lr,#4@;MODIFIED 26-May(IDC)
.align 5
vects1_start:nop @; offset 0x00nop @; offset 0x04ldr pc, =SMI_HLDR @; offset 0x08nop @; offset 0x0cnop @; offset 0x10nop @; offset 0x14nop @; offset 0x18ldr pc, =FIQ_HLDR @; offset 0x1cnop @; offset 0x20nop @; offset 0x24nop @; offset 0x28nop @; offset 0x2cnop @; offset 0x30nop @; offset 0x34nop @; offset 0x38nop @; offset 0x3cnop @; offset 0x40nop @; offset 0x44nop @; offset 0x48nop @; offset 0x4cnop @; offset 0x50nop @; offset 0x54nop @; offset 0x58nop @; offset 0x5cnop @; offset 0x60nop @; offset 0x64nop @; offset 0x68nop @; offset 0x6cnop @; offset 0x70nop @; offset 0x74nop @; offset 0x78nop @; offset 0x7cnop @; offset 0x80nop @; offset 0x84nop @; offset 0x88ldr pc, =SMI_HLDR @; offset 0x8c@;MODIFIED 11-May(IDC)SMI_HLDR:stmfd sp!, {r0-r1,lr} @; push register onto SMI stackldr r1,=smi_hdler @; >= 16: pointer to standard SMIldr r0,[r1] @; handlermov lr,pc @; >= 16: set link registerbx r0 @; >= 16: jump to standard SMI@; handlerldmfd 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_EXCEPTCRT0_END:.ltorg @; literal dump
3. 链接脚本
MEMORY
{rom : org = 0x00000000, len = 0x00008000ram : 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;
参考文献
- ARM汇编–汇编中符号和变量
- ARM汇编.global和.extern
- ARM中C和汇编混合编程及示例
- 函数指针和指针函数用法和区别
- 《ARM体系与结构编程》
- ARM嵌入式系统开发软件设计与优化
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
