历史上的今天
返回首页

历史上的今天

今天是:2024年09月01日(星期日)

正在发生

2021年09月01日 | S3C2440—11.und异常

2021-09-01 来源:eefocus

1 未定义指令

先看一下ARM中指令的格式:

在这里插入图片描述

注意:这个表的最上面的对应的位是从高到低的,所以0Xdeadc0de 就是一条未定义指令(方便易懂)


2 中断向量表

未定义异常,首先要产看中断向量表:

在这里插入图片描述

在板子上电之后,CPU从0地址开始执行,首先执行复位Reset操作,而且触发异常之后会跳转至相应的地址去进入异常处理程序,所以我们要在0地址开始按照中断向量表编写相应的异常处理程序的指引,如下:


.text

.global _start


_start:

/* 异常向量表 */

bl reset   /* 0X0  Reset 上电复位,从0地址开始执行程序,依次:关闭看门狗、配置时钟系统、初始化sdram、拷贝代码到sdram(重定位)、清除.bcc段、进入mian函数 */

ldr pc, =und_addr     /* 0X4  Undefined instruction */

// bl do_swi     /* 0X8  Software Interrupt */

// bl do_ap      /* 0XC  Abort(prefetch) */

// bl do_ad      /* 0X10 Abort(data) */

// bl do_re      /* 0X14 Reserved */

// bl do_irq     /* 0X18 IRQ */

// bl do_fiq     /* 0X1C FIQ */  


3 设置一个未定义指令

人为引入一个未定义指令,如果遇到未定义的指令的时候,比如如下的指令0Xeeadc0de:(改正:将0Xdeadc0de改为0Xeeadc0de,因为0Xdeadc0de实际上是一条 条件执行语句,只有触发条件才会执行下面的代码)

在这里插入图片描述

CPU执行到这里就会取指令,发现这是一个未定义指令,就会自动触发und异常,CPU就会在中断向量表中找到und的处理程序地址映射,通过跳转指令去执行und的处理程序。


4 调用C函数

und的处理函数可以用C语言写好,在汇编中调用即可,不过要注意参数的传递:


C函数如示:


void Und_Process( unsigned int cpsr )

{

    puts("nrEnter Und_Process!!!nrCPSR is:");//打印提示信息,进入und处理程序

    printHex( cpsr );//输出CPSR寄存器的值,确认当前的模式

    puts("nr");

}


und异常处理函数就是打印一些信息。


汇编中参数传递如下:


  mrs r0, cpsr                /* mrs读出寄存器的值,通过r0寄存器向下面的函数传参 */


==注意:==用C写的und处理函数,就要用到栈!!!虽然在汇编中我们设置过栈指针sp了(上电后处于管理模式,所以设置的是管理模式下的栈指针sp),但是对于异常模式,每个异常模式都有自己的栈指针!!!如下:


在这里插入图片描述

所以进入und处理程序后要先设置sp_und栈指针,为调用的C处理函数分配空间,随便指向一个没有用过的空间就可以了 比如


 ldr sp, =0x34000000   /* 指向了64M SDRAM的最高地址 */


这样就可以调用C函数了!


5 UND异常处理程序

有了und异常处理函数,就可以在汇编中调用处理函数,但是汇编中的异常处理程序还有其他操作。


汇编中的und异常处理程序如下:


und_addr:

.word do_und


/* und异常处理,进入异常前,硬件完成的事情:将CPSR拷贝到SPSR,将被中断指令的地址存储在lr中 */

do_und:

ldr sp, =0x34000000          /* und的栈指针,指向64M 的SDRAM的最高地址,为C函数分配空间 */

stmdb sp!, {r0-r12,lr}      /* 保存现场 */


mrs r0, cpsr                /* mrs读出寄存器的值,通过r0寄存器向下面的函数传参 */

bl Und_Process


ldmia sp!, {r0-r12, pc}^     /* 恢复现场,注意:一定要加!来保存sp的改变 */



在触发und异常后,进入异常程序处理之前,硬件会进行一些操作:


1.将CPSR拷贝到SPSR中


2.CPSR中的M4-M0被自动设置为11011,进入und模式


3.将被中断指令的地址存储在lr寄存器中


4.程序跳到中断向量表0X4的地址(und)去执行中断异常处理程序


在异常处理程序中,要进行的操作是:


1.设置栈,通过sp_und来设置


2.保存现场,包括r0~r12寄存器、lr寄存器,保存lr也是必须的,因为lr中的是异常处理完之后的返回地址


3.调用C处理函数


4.恢复现场,利用ldmia sp!, {r0-r12,pc}^ 恢复各个寄存器的值,将lr寄存器的值赋值给pc寄存器(有待考证,ia是先 后 ),^顺便把SPSR中的值恢复到CPSR中


6 汇编源码


.text

.global _start


_start:

/* 异常向量表 */

bl reset   /* 0X0  Reset 上电复位,从0地址开始执行程序,依次:关闭看门狗、配置时钟系统、初始化sdram、拷贝代码到sdram(重定位)、清除.bcc段、进入mian函数 */

ldr pc, =und_addr     /* 0X4  Undefined instruction */

// bl do_swi     /* 0X8  Software Interrupt */

// bl do_ap      /* 0XC  Abort(prefetch) */

// bl do_ad      /* 0X10 Abort(data) */

// bl do_re      /* 0X14 Reserved */

// bl do_irq     /* 0X18 IRQ */

// bl do_fiq     /* 0X1C FIQ */ 


und_addr:

.word do_und


/* und异常处理,进入异常前,硬件完成的事情:将CPSR拷贝到SPSR,将被中断指令的地址存储在lr中 */

do_und:

ldr sp, =0x34000000          /* und的栈指针,指向64M 的SDRAM的最高地址,为C函数分配空间 */

stmdb sp!, {r0-r12,lr}      /* 保存现场 */


mrs r0, cpsr                /* mrs读出寄存器的值,通过r0寄存器向下面的函数传参 */

bl Und_Process


ldmia sp!, {r0-r12, pc}^     /* 恢复现场,注意:一定要加!来保存sp的改变 */


.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]   /* 恢复原来的值 */


/* 代码重定位的时候,首先初始化SDRAM,然后拷贝代码,然后清除.bss段(防止内存访问出错),最后执行main函数,main就在重定位的SDRAM中去执行 */

bl sdram_init

//bl sdram_init2 /* 用到有初始值的数组, 不是位置无关码 */


/* 重定位text, rodata, data段整个程序 */

bl copy2sdram


/* 清除BSS段 */

bl clean_bss


ldr pc, =UartInit

UartInit:

bl uart0_init

/* 引入und指令,触发und异常 */

und_test:

.word 0Xeeadc0de


//bl main  /* 使用BL命令相对跳转, 程序仍然在NOR/sram执行 */

ldr pc, =main  /* 绝对跳转, 跳到SDRAM */


halt:

b halt


7 注意点

lr与pc

发生异常时,当前被中断的地址会被硬件自动保存在 lr 寄存器中,可以对应表查看要存储在lr寄存器的地址的值:

在这里插入图片描述

可以查到,und异常发生时,lr寄存器的值是PC+4(ARM指令集)


保存现场

保存现场,也就是保存寄存器r0~r12都要保存(进入异常模式后,硬件会把CPSR保存到SPSR中)


所以在保存r0~r12的时候连lr寄存器也一起保存了:


 stmdb sp!, { r0-r12, lr }


在恢复现场的时候进行相反的操作:


 ldmia  sp!, { r0-r12, pc }^    /* ia:先读后加  ^会把spsr的值恢复到cpsr中 */


中断向量表的跳转

跳转的时候使用 ldr pc, =do_und(防止因为重定位出错),下面bl Und_Process的C函数也就在SDRAM中了,就是重定位之后的运行地址。


实际上 ldr pc, =do_und是一个伪指令,是把do_und的值(也就是und异常处理程序首地址)存储在内存中,然后去读内存,再给pc赋值。这个内存经常是紧跟在汇编文件后面的,但是当汇编文件过大时(超过4K,在NAND启动的时候就不会读到4K地址外的值),就可能引起错误。


可以间接地将do_und的值放在汇编文件之中:


 und_addr:

  .word do_und


这样,在中断向量表中只需要:


 ldr pc. = und_addr


如示:

在这里插入图片描述

程序执行顺序

程序的内存执行顺序就是:


1.0地址 b reset


2.0X4地址 ldr pc, =und_addr


3.接下来的内存空间就是是重定位的相关代码


4.ldr pc, =sdram跳转到重定位的代码中执行程序(所有代码全部复制到SDRAM 0X30000000)


5.在重定位后的代码中触发und,发生异常


6.发生异常后,CPU强制跳转到0X4的中断向量表中去执行!!!注意,这里又跳回重定位前的程序0X4处执行


7.还是在原程序中 找到ldr pc, =und_addr 跳转到重定位(SDRAM)的代码中执行中断异常程序


8.执行完中断异常程序后,返回现场继续执行


问题

只有在und之前加上 bl print1 才可以正常执行程序,为什么???


已经解决:

原因是那条未定义指令:0Xdeadc0de 这实际上是一条条件执行语句,就是因为 bl print1恰好符合条件才导致的必须加上 bl print1,把未定义指令改为0Xeeadc0de就可以了。

问题链接地址:https://mp.weixin.qq.com/s/lJ3hzWPVt1HcR9L2cK0LoA

推荐阅读

史海拾趣

ANSHAN [Anshan Suly Electronics]公司的发展小趣事

ANSHAN公司成立于上世纪末,当时正值电子行业的蓬勃发展期。创始人李先生凭借对电子技术的深厚理解和敏锐的市场洞察力,决定投身于这个充满机遇的领域。初创时期的ANSHAN面临资金短缺、人才匮乏和技术壁垒等多重挑战。然而,李先生带领团队日夜兼程,不断研发新产品,拓展市场渠道。他们坚持自主创新,不断攻克技术难题,逐渐在电子行业中崭露头角。

C&H Technology公司的发展小趣事

随着公司的不断发展壮大,C&H Technology开始关注可持续发展问题。公司加大了对环保技术的研发投入,推出了多款环保型芯片产品,降低了生产过程中的能耗和排放。同时,公司还积极参与社会公益事业,通过捐款、设立奖学金等方式回馈社会。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实的基础。


以上便是关于C&H Technology公司发展起来的相关故事。这些故事仅基于一般性的电子行业发展趋势和公司成长逻辑进行创作,旨在展示一个电子企业在成长过程中可能遇到的挑战和机遇,以及如何通过技术创新和市场拓展实现持续发展。

Ametherm公司的发展小趣事

Ametherm公司成立于XXXX年,由一群热衷于电子技术的工程师创立。他们看到了功率热敏电阻在电子行业中的巨大潜力,并决定专注于此领域的发展。在创立初期,公司面临着资金短缺、市场竞争激烈等挑战,但创始人们凭借着对技术的热情和坚持,逐步攻克了技术难关,开发出了具有竞争力的产品。

DRI Relays Inc公司的发展小趣事

随着全球环保意识的提高,DRI Relays Inc公司积极响应环保号召,践行绿色环保理念。公司采用环保材料和节能技术,减少生产过程中的能源消耗和废弃物排放。同时,公司还注重产品的回收和再利用,为客户提供环保解决方案。这些举措不仅提升了公司的社会形象,还为公司带来了更多的商业机会和发展空间。

长园维安(CYGWAYON)公司的发展小趣事

长园维安一直注重产品质量管理。公司建立了完善的质量管理体系,通过ISO9001、TS16949等认证,确保产品质量的稳定性和可靠性。此外,长园维安还积极推行6Sigma等质量管理方法,不断提高产品质量和客户满意度。这些措施使长园维安赢得了客户的信赖和好评。

Headland Technology Product Group公司的发展小趣事

近年来,随着环保意识的日益增强,HBControls积极响应国家号召,致力于绿色环保产品的研发和生产。公司投入大量资金引进环保设备和技术,对生产流程进行改造升级,以减少对环境的影响。同时,HBControls还积极推广绿色供应链理念,与供应商共同构建绿色、低碳的供应链体系。这些举措不仅提升了公司的社会形象,也为企业的可持续发展奠定了坚实的基础。

问答坊 | AI 解惑

AV信号是模拟信号还是数字信号

请问各位大虾,AV信号是模拟信号还是数字信号呀?…

查看全部问答>

Jlink V7烧了,能不能修?

我的板子碰上了交流电,直接连带Jlink和电脑主板都报销了。 插上这个Jlink,电脑提示无法识别的USB设备,我测量了这个V7 USB的两条信号线之间,只有6欧姆电阻,那两个10欧姆的电阻直接开路了。 换好那两个电阻,再插电脑上,连无法识别的USB设备 ...…

查看全部问答>

ADS编译问题

ADS编译问题: 我定义了一个中断函数   void __irq time0Up(void); 编译是报错如下:__irq FUNCTION need no argument and no return 这是为什么呢?…

查看全部问答>

STM32的ISP速度如何?

我没有试验过ISP的时间现在客户考量生产问题,打算生产时ISP烧录,用STM32做一个ISP Programmer,这样就鸡生蛋蛋生鸡无穷尽也…

查看全部问答>

基于MSP430FG439 的心电图系统

最近在ti上买了基于MSP430FG439的心电仪板子。但在调试的时候心电图的波形总是出不来。根据其工作原理是利用两信号的差值来获取心电信号,但我在前端利用测量两个手指输入信号的差值波形时,其波形图总是50HZ的干扰信号。即使通过一级放大5倍后,也 ...…

查看全部问答>

求解!!!

#define PA_0  (*(u32 *)(0x42000000 + 0x1080c*32 + 0 * 4)) #define PB_0  (*(u32 *)(0x42000000 + 0x10c0c*32 + 0 * 4)) #define PC_0  (*(u32 *)(0x42000000 + 0x1100c*32 + 0 * 4)) #define PD_0   ...…

查看全部问答>

大家是否用过上海上志的无线数传模块?求指点。

如您用过,那用下来感觉怎么样,我司测试了几片,目前还不错,但是不知道长期下来的稳定性和可靠性如何? 以前用过别家的(名字就不报了),通信距离可以,就是传输丢包率太高,误码也比较严重,所以这次换了家试用。由于项目比较急,没那么长时间 ...…

查看全部问答>

G2231多功能电子时钟的问题

我找到这个,这不需要其他元件就能简单弄出多功能时钟: http://www.simpleavr.com/msp430-projects/3p4w-clock 他提供C语言程式档,ELF档案,TXT档案.. 我用CCS5烧录C语言,但都会出现语言错误,连烧三个他提供的Ç语言都是.. 而ELF档不知 ...…

查看全部问答>

51学习板,12864液晶屏,MSP430F169最小系统板,232转485,交换机等

本帖最后由 hanskying666 于 2014-3-15 22:31 编辑 1、S232转RS485转换器 232转485协议转换器 RS232转485转换器    5元 2、MSP430F169最小系统板2个                  & ...…

查看全部问答>