08_I.MX6ULL汇编编写中断向量表

汇编源码

使用汇编编写中断向量表,复位中断服务函数,以及IRQ中断服务函数。

.global _start  		/* 全局标号 */



/*

 * 描述:	_start函数,程序从此函数开始执行,此函数主要功能是设置C

 *		 运行环境。

 */

_start:

	/*中断向量表*/ 

	ldr pc, =Reset_Handler  	/*复位中断函数*/

	ldr pc, =Undefined_Handler  /*未定义指令中断*/ 

	ldr pc, =SVC_Handler    	/*SVC*/

	ldr pc, =PreAbort_Handler   /*预取终止中断*/

	ldr pc, =DataAbort_Handler  /*数据终止中断 */ 

	ldr pc, =NotUsed_Handler    /*未使用*/

	ldr pc, =IRQ_Handler 	    /*IRQ中断*/ 

	ldr pc, =FIQ_Handler        /*FIQ中断*/



/*复位中断服务函数*/

Reset_Handler:



	cpsid i      		/*关闭IRQ中断 */



	/*关闭I,D Cache和MMU */

	/*修改SCTLR寄存器,采用读-改写的方式 */

	MRC p15, 0, r0, c1, c0, 0 	/*读取SCTLR寄存器的数据到r0寄存器里面 */

	bic r0, r0, #(1 << 12)    	/*关闭I Cache bic是对某位置0*/

	bic r0, r0, #(1 << 11)    	/*关闭分支预测 */

	bic r0, r0, #(1 << 2) 		/*关闭D Cache */

	bic r0, r0, #(1 << 1)		/*关闭对齐*/

	bic r0, r0, #(1 << 0)		/*关闭MMU */

	MCR p15, 0, r0, c1, c0, 0	/* 将r0寄存器数据写入SCTLR寄存器里*/



	/*设置中断向量偏移 */

	ldr r0, =0x87800000  

	/*指令同步数据同步 */ 

	dsb

	isb

	MCR p15, 0, r0, c12, c0, 0 /*设置VBAR寄存器=0x87800000 */

	/*指令同步数据同步 */ 

	dsb

	isb



	/*进入IRQ模式设置sp指针 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4*/

	orr r0, r0, #0x12 	/* r0或上0x12,表示使用IRQ模式*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中*/

	ldr sp,=0X80600000	/* 设置IRQ模式下栈首地址为0X80600000,大小为2MB*/



	/*进入SYS模式设置sp指针 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4*/

	orr r0, r0, #0x1f 	/* r0或上0x12,表示使用IRQ模式*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中*/

	ldr sp,=0X80400000	/* 设置SYS模式下栈首地址为0X80400000,大小为2MB*/



	/*进入SVC模式*/

	/* 设置栈指针,

	 * 注意:IMX6UL的堆栈是向下增长的!

	 * 堆栈指针地址一定要是4字节地址对齐的!!!

	 * DDR范围:0X80000000~0X9FFFFFFF

	 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4*/

	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中*/

	ldr sp,=0X80200000	/* 设置SVC模式下栈首地址为0X80200000,大小为2MB*/



	cpsie i				/*打开IRQ中断使能 */



	b main				/* 跳转到main函数 */







/*未定义指令中断服务函数*/

Undefined_Handler:

	/*死循环 */

	ldr r0, =Undefined_Handler

	bx r0



/*SVC中断服务函数*/

SVC_Handler:

	/*死循环 */

	ldr r0, =SVC_Handler

	bx r0



/*预取终止中断服务函数*/

PreAbort_Handler:

	/*死循环 */

	ldr r0, =PreAbort_Handler

	bx r0



/*数据终止中断服务函数*/

DataAbort_Handler:

	/*死循环 */

	ldr r0, =DataAbort_Handler

	bx r0



/*未使用*/

NotUsed_Handler:

	/*死循环 */

	ldr r0, =NotUsed_Handler

	bx r0



/*IRQ中断服务函数*/

IRQ_Handler:



	push {lr}					/* 保存lr地址 */

	push {r0-r3, r12}			/* 保存r0-r3,r12寄存器 */



	mrs r0, spsr				/* 读取spsr寄存器 */

	push {r0}					/* 保存spsr寄存器 */



	mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中*/	

							

														

	add r1, r1, #0X2000			/* GIC基地址加0X2000,也就是GIC的CPU接口端基地址 */

	ldr r0, [r1, #0XC]			/* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器,

								 * GICC_IAR寄存器保存这当前发生中断的中断号,我们要根据

								 * 这个中断号来绝对调用哪个中断服务函数

								 */

	push {r0, r1}				/* 保存r0,r1 */

	

	cps #0x13					/* 进入SVC模式,允许其他中断再次进去 */

	

	push {lr}					/* 保存SVC模式的lr寄存器 */

	ldr r2, =system_irqhandler	/* 加载C语言中断处理函数到r2寄存器中*/

	blx r2						/* 运行C语言中断处理函数,带有一个参数,保存在R0寄存器中 */



	pop {lr}					/* 执行完C语言中断服务函数,lr出栈 */

	cps #0x12					/* 进入IRQ模式 */

	pop {r0, r1}				

	str r0, [r1, #0X10]			/* 中断执行完成,写EOIR */



	pop {r0}						

	msr spsr_cxsf, r0			/* 恢复spsr */



	pop {r0-r3, r12}			/* r0-r3,r12出栈 */

	pop {lr}					/* lr出栈 */

	subs pc, lr, #4				/* 将lr-4赋给pc */

	

	



/*FIQ中断服务函数*/

FIQ_Handler:

	/*死循环 */

	ldr r0, =FIQ_Handler

	bx r0













	





你可能感兴趣的:(ARM(IMX6U)裸机,汇编,嵌入式硬件,I.MX6ULL,linux,物联网)