现在做第一个实验,模拟未定义模式。

未定义模式,是cpu遇到自己不能识别的指令时候做出的异常处理。

arm指令的机器码一定是按照某种规范要求的,不然你随意写一条指令,cpu不是都可以执行吗?在cpu没有定义该条指令含义的情况下,我们执行了这样未定义的指令,就会进入未定义异常。

现在我们要模拟一个未定义异常,所以我们只要写出一个cpu无法识别的指令即可。

在这之前,要明白一个道理,在内存中执行的机器码,只有0,1两个值,不同的指令被分解为不同的0,1信号的机器码。

所以,我们在运行内存中存放一个32bit的值,这个值又恰恰是上图所不能表示的指令,那么这样,就可以测试未定义异常了。我们采用.word 关键字,.word expression就是在当前位置放一个word型的值,这个值就是expression 。

.word 接收4字节的数据,放在当前地址。

现在我们仔细观察上面的那个图,找到一个未定义的机器码,把这个值放在.word的地方,当cpu运行到.word 地址时,发现这个地址的0,1数据即机器码它不能识别,就发生未定义异常。

所以我们可以使用 .word 0xf3000000来表示一条未定义指令,但大家用的比较多的是.word 0xbadc0de(很形象,表示坏代码)。

现在更改star.S:

.text
.global _start _start:
b reset /* vector : reset */
ldr pc, und_addr /* vector : und */ und_addr:
.word do_und do_und:
/* 执行到这里之前:
* . lr_und保存有被中断模式中的下一条即将执行的指令的地址
* . SPSR_und保存有被中断模式的CPSR
* . CPSR中的M4-M0被设置为11011, 进入到und模式
* . 跳到0x4的地方执行程序
*/ /* sp_und未设置, 先设置它 */
ldr sp, =0x34000000 /* 在und异常处理函数中有可能会修改r0-r12, 所以先保存 */
/* lr是异常处理完后的返回地址, 也要保存 */
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 reset:
/* 关闭看门狗 */
ldr r0, =0x53000000
ldr r1, =
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 = :: */
ldr r0, =0x4C000014
ldr r1, =0x5
str r1, [r0] /* 设置CPU工作于异步模式 */
mrc p15,,r0,c1,c0,
orr r0,r0,#0xc0000000 //R1_nF:OR:R1_iA
mcr p15,,r0,c1,c0, /* 设置MPLLCON(0x4C000004) = (<<)|(<<)|(<<)
* m = MDIV+ = +=
* p = PDIV+ = + =
* s = SDIV =
* FCLK = *m*Fin/(p*^s) = **/(*^)=400M
*/
ldr r0, =0x4C000004
ldr r1, =(<<)|(<<)|(<<)
str r1, [r0] /* 一旦设置PLL, 就会锁定lock time直到PLL输出稳定
* 然后CPU工作于新的频率FCLK
*/ /* 设置内存: sp 栈 */
/* 分辨是nor/nand启动
* 写0到0地址, 再读出来
* 如果得到0, 表示0地址上的内容被修改了, 它对应ram, 这就是nand启动
* 否则就是nor启动
*/
mov r1, #
ldr r0, [r1] /* 读出原来的值备份 */
str r1, [r1] /* ->[] */
ldr r2, [r1] /* r2=[] */
cmp r1, r2 /* r1==r2? 如果相等表示是NAND启动 */
ldr sp, =0x40000000+ /* 先假设是nor启动 */
moveq sp, # /* nand启动 */
streq r0, [r1] /* 恢复原来的值 */ bl sdram_init
//bl sdram_init2 /* 用到有初始值的数组, 不是位置无关码 */ /* 重定位text, rodata, data段整个程序 */
bl copy2sdram ldr pc, =sdram
sdram:
/* 清除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

cpu处理异常的时候,是有专门地址的,这里的未定义und异常,在地址0x4处,当发生未定义异常时,硬件让程序从地址0x4处执行。这里说明一下汇编中定义字符串:

.string  “XXXX” 表示定义的字符串包含最后的\0.

.ascii "XXXX"表示定义的字符串不包含最后的\0.

.asciiz "XXXX"表示定义的字符串包含最后的\0,z代表zero。

参考:(点击这里)

.align 4 放在.string 后面是为了使后面的指令四字节对齐,因为字符串的字节数不一定是四字节对齐的。

进入异常处理前需要保存现场,异常处理之后需要恢复现场。

现在说明下面代码段:

    ldr pc, und_addr /* vector  : und */

und_addr:
.word do_und

但是我在想,为什么韦老大说nand启动,怕访问超过4k空间,所以采取上面的操作方式,这样保证肯定无论是否超过4k,程序都可以正常运行。但是,我们的sdram已经重定位完毕了,那样sdram已经是可以访问的了,所以就算超过4k也不会有问题啊?(这个等到后面上文件系统的时候测试,我觉得这里是不存在老师说的那种情况的)。

Question:

去掉star.S中的 bl  print1

发现不会进入未定义异常了?这是为什么?

经过分析,是puts函数问题,只有调用了puts函数,才会进入未定义异常。原因。。。

我们上面忽略了一点,就是cond所占用的四个字节条件,

所以,未定义指令要忽略高4位cond条件码。

在测试过程中,我能发现是puts函数的问题,可是,puts函数是我们重定义的库函数,这和stm32 printf映射串口有一点像,具体编译器在操作puts的时候做了什么不得而知,但是可以肯定的是puts让cpsr高四位变成了无条件执行,才触发了未定义异常。现在我们把未定义指令的高四位改成1110,后面加上arm不能识别的指令,就可以进入未定义异常模式了。

S3C2440的七种模式之——未定义模式(去掉bl print1 bug解决)的更多相关文章

  1. 情景剧:C/C++中的未定义行为(undefined behavior)

    写在前面 本文尝试以情景剧的方式,轻松.直观地解释C/C++中未定义行为(undefined behavior)的概念.设计动机.优缺点等内容1,希望读者能够通过阅读本文,对undefined beh ...

  2. ARM微处理器的七种运行模式

    ARM微处理器的七种运行模式: 用户模式(usr):正常的程序执行状态 快速中断模式(fiq):用于处理快速中断,对高速数据传输或通道处理. 中断模式(irq):对一般情况下的中断进行处理. 管理模式 ...

  3. (转)深度分析Linux下双网卡绑定七种模式

    现在一般的企业都会 使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多.而一般企业都会使用linux操作系统下自带的网卡绑定模式,当然现在 网卡产商也会出一些针对window ...

  4. linux bond配置步骤,七种bond模式说明

    一.网卡绑定: 第一步:创建一个ifcfg-bondX # vi /etc/sysconfig/network-scripts/ifcfg-bond0 DEVICE=bond0 BONDING_OPT ...

  5. 深度分析Linux下双网卡绑定七种模式 多网卡的7种bond模式原理

    http://blog.csdn.net/abc_ii/article/details/9991845多网卡的7种bond模式原理 Linux网卡绑定mode共有七种(~) bond0.bond1.b ...

  6. 深度分析Linux下双网卡绑定七种模式

    现在一般的企业都会使用双网卡接入,这样既能添加网络带宽,同时又能做相应的冗余,可以说是好处多多.而一般企业都会使用linux操作系统下自带的网卡绑定模式,当然现在网卡产商也会出一些针对windows操 ...

  7. 《JAVASCRIPT高级程序设计》创建对象的七种模式

    细看javascript创建对象模式的诞生,具体的脉络为:不使用任何模式——工厂模式——构造函数模式——原型模式——组合使用构造函数模式——动态原型模式——寄生构造函数模式——稳妥构造函数模式.每一种 ...

  8. 七种bond模式说明

    第一种模式:mod=0 ,即:(balance-rr) Round-robin policy(平衡抡循环策略) 特点:传输数据包顺序是依次传输(即:第1个包走eth0,下一个包就走eth1….一直循环 ...

  9. MySQL逻辑架构、SQL加载执行顺序、七种JOIN模式图解

    逻辑架构   存储引擎 查看当前安装的mysql提供的存储引擎 查看当前mysql默认的存储引擎 MyISAM和InnoDB SQL加载执行顺序 sql书写顺序 mysql解析器执行的顺序  考点:m ...

随机推荐

  1. 蓝牙进阶之路 (002) - HC-05与HC-06的AT指令的区别(转)

    蓝牙HC-05与HC-06对比指令集 高电平->AT命令响应工作状态     低电平->蓝牙常规工作状态 <重新上电表示完成复位> HC-05 可以主从切换模式,但是HC-06 ...

  2. numpy 数组迭代Iterating over arrays

    在numpy 1.6中引入的迭代器对象nditer提供了许多灵活的方式来以系统的方式访问一个或多个数组的所有元素. 1 单数组迭代 该部分位于numpy-ref-1.14.5第1.15 部分Singl ...

  3. 【转载并整理】AJAX XmlHttpRequest对象详解

    一. XMLHttpRequest由来及原生介绍 XMLHttpRequest(XHR)是一个API对象,其中的方法可以用来在浏览器和服务器端传输数据.这个对象是浏览器的js环境提供的.从XHR获取数 ...

  4. Android Studio主题设置、颜色背景配置

    打开http://color-themes.com/有很多样式可供选择 导入方式 下载主题—xxx.jar 注意:如果我们下载下来的jar名字如果有空格,一定要把空格去掉,同时文件路径中不要含有中文 ...

  5. Android studio的一些常用快捷键

    Alt+回车 导入包,自动修正 Ctrl+N 查找类 Ctrl+Shift+N 查找文件 Ctrl+Alt+L 格式化代码 Ctrl+Alt+O 优化导入的类和包 Alt+Insert 生成代码(如g ...

  6. JPA之@GeneratedValue注解(转)

    JPA的@GeneratedValue注解,在JPA中,@GeneratedValue注解存在的意义主要就是为一个实体生成一个唯一标识的主键(JPA要求每一个实体Entity,必须有且只有一个主键), ...

  7. Maven 使用国内镜像

    1 修改maven 的配置文件 settings.xml,添加阿里云的一个中央仓库. 2 找到maven 的配置文件,一般在 maven 安装目录 apache-maven-3.5.0\conf 文件 ...

  8. windows如何查看某个端口被谁占用

    我们在启动应用的时候经常发现我们需要使用的端口被别的程序占用,但是我们又不知道是被谁占用,这时候我们需要找出“真凶”,如何做到呢? cmd命令中 输入命令:netstat -ano,列出所有端口的情况 ...

  9. 搭建Dubbo+Myeclipse2015+Maven3.3.1的过程遇到问题集锦

    1. 找不到dubbo2.8.4包的问题 在编译Maven工程的过程中,出现如下问题: Description Resource Path Location Type ArtifactDescript ...

  10. Ubuntu中开启和关闭防火墙-摘自网络

    1.关闭ubuntu的防火墙 ufw disable开启防火墙ufw enable 2.卸载了iptablesapt-get remove iptables3.关闭ubuntu中的防火墙的其余命令ip ...