嵌入式Linux之und异常处理

嵌入式Linux之und异常处理

加入一条未定义指令:
.word 0xdeadc0de
如发生异常,则程序强制跳至0x4的地址执行程序。

und异常处理函数

do_und:
	ldr sp,=0x34000000      //首先重新设置栈
	
	stmdb sp!,{r0-r12,lr}   //保存现场

	mrs r0,cpsr
	ldr r1,=und_string
	bl printException       //处理und异常
	
	ldmia sp!,{r0-r12,pc}^ //恢复现场,会把spsr的值恢复到cpsr里
  • ld_und保存有被中断模式中的下一条指令的地址
  • SPSR_und保存有被中断模式的CPSR
  • CPSR中的M4-M0被设置为10011进入svc模式
  • 跳到0x4的地址执行程序

打印字符串函数

und_string:
	.string "undefined instruction exception"
	.align 4

注:在字符串之后,加入.align 4后面的函数以四字节对齐,否则程序将错乱。

由于printException函数中需要打印字符串,故在此之前需要先初始化串口!

完整的start.S:

.text
.global _start

_start:
	b reset
	b do_und

do_und:
	ldr sp,=0x34000000   //设置栈
	
	//保存现场
	stmdb sp!,{r0-r12,lr}
	
	//处理und异常
	mrs r0,cpsr
	ldr r1,=und_string
	bl printException

	//恢复现场
	ldmia sp!,{r0-r12,pc}^ //会把spsr的值恢复到cpsr里
und_string:
	.string "undefined instruction exception"
	.align 4
reset:
	/* 关闭看门狗 */
	ldr r0, =0x53000000
	ldr r1, =0
	str r1, [r0]

	/* 设置MPLL, FCLK : HCLK : PCLK = 400m : 100m : 50m */
	/* LOCKTIME(0x4C000000) = 0xFFFFFFFF */
	ldr r0, =0x4C000000
	ldr r1, =0xFFFFFFFF
	str r1, [r0]

	/* CLKDIVN(0x4C000014) = 0X5, tFCLK:tHCLK:tPCLK = 1:4:8  */
	ldr r0, =0x4C000014
	ldr r1, =0x5
	str r1, [r0]

	/* 设置CPU工作于异步模式 */
	mrc p15,0,r0,c1,c0,0
	orr r0,r0,#0xc0000000   //R1_nF:OR:R1_iA
	mcr p15,0,r0,c1,c0,0

	/* 设置MPLLCON(0x4C000004) = (92<<12)|(1<<4)|(1<<0) 
	 *  m = MDIV+8 = 92+8=100
	 *  p = PDIV+2 = 1+2 = 3
	 *  s = SDIV = 1
	 *  FCLK = 2*m*Fin/(p*2^s) = 2*100*12/(3*2^1)=400M
	 */
	ldr r0, =0x4C000004
	ldr r1, =(92<<12)|(1<<4)|(1<<0)
	str r1, [r0]

	/* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
	 * 然后CPU工作于新的频率FCLK
	 */
	
	

	/* 设置内存: sp 栈 */
	/* 分辨是nor/nand启动
	 * 写0到0地址, 再读出来
	 * 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
	 * 否则就是nor启动
	 */
	mov r1, #0
	ldr r0, [r1] /* 读出原来的值备份 */
	str r1, [r1] /* 0->[0] */ 
	ldr r2, [r1] /* r2=[0] */
	cmp r1, r2   /* r1==r2? 如果相等表示是NAND启动 */
	ldr sp, =0x40000000+4096 /* 先假设是nor启动 */
	moveq sp, #4096  /* nand启动 */
	streq r0, [r1]   /* 恢复原来的值 */

	bl sdram_init

	/* 重定位text, rodata, data段整个程序 */
	bl copy2sdram
	
	/* 清除BSS段 */
	bl clean_bss

	bl uart0_init

	bl print1
	//故意加入一条未定义指令
und_code:
	.word 0xdeadc0de

	bl print2
	//bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */
	ldr pc, =main  /* 绝对跳转, 跳到SDRAM */


halt:
	b halt
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值