坏块处理
8192块
64页
每一页
main区
spare区
0块
0(0)
1(1)
2
3
4
…
63
1块
0(64)
1(65)
2
3
4
…
63
2块
0(128)
1(129)
2
3
4
…
63
读第0页,第2048个字节(spare区的第一个字节)
如果不是0xFF,坏块
如果是0xFF
读第1页,第2048个字节(spare区的第一个字节)
如果不是0xFF,坏块
如果是0xFF,好块
好块:
第0页,2048,0xFF
第1页,2048,0xFF
坏块:
第0页,2048,不是0xFF
第0页,2048,是0xFF
第1页,2048,不是0xFF
思考:
Linux的Image烧写有坏块处
依然正常启动
Shell#
Badblock 0x000000EA 234 0x01d40000 234x64x2048
Badblock 0x000000EC 236 0x01d80000
Badblock 0x000000F4 244 0x01e80000
Badblock 0x000000F6 246
Badblock 0x000010A8 4264
Badblock 0x00001938 6456
Badblock 0x0000193A 6458
ARM体系结构:
精简指令集(RISC)
复杂指令集(CISC)
ARM编程模型
1.工作模式:
管理模式SVC:复位,执行SWI指令
快速中断:发生高优先级的中断
中断:发生低优先级的中断
中止:访问存储器发生非法情况
未定义:执行的指令,不能识别
系统:
用户:多数应用程序和系统任务运行在模式
2.工作模式的分类:
(1)异常,非异常
异常模式:管理模式,快速中断,中断,中止,未定义
非异常模式:系统,用户
(2)特权,非特权
特权模式:其余6种都是特权模式
非特权模式:用户
3.工作模式之间是否能够切换,如何切换?
工作模式之间是可以切换
切换的方式有两种:
1.处理器自动切换:发生异常时,处理器会自动进入对应的异常模式
2.指令切换:
切换的原则:
1.特权模式之间可以随意切换
2.可以从特权模式进入用户模式,不能从用户模式切换到特权模式
3.如果用户模式要进入特权模式,可以通过调用SWI指令来完成。
4.ARM的运行状态
1.ARM状态
执行ARM指令32bit
指令地址是4字节对齐,最后两bit为0
0 0000
4 0100
8 1000
C 1100
2.Thumb状态
执行Thumb指令16bit
指令地址是2字节对齐,最后1bit为0
0 0000
2 0010
4 0100
6 0110
8 1000
a 1010
c 1100
e 1110
5.运行状态的切换
1.处理器自动切换
2.用指令切换
6.寄存器
在Cortex-a8核心里面
所有的寄存器是没有地址,如果使用,直接使用
寄存器都是32bit
r0-r12:通用寄存器
r13(sp):存放栈顶地址,栈就是内存的一个区域
异常模式下,都有自己的栈
发生异常时,CPU会自动切换到异常模式,先保护现场,将上一模式使用的寄存器入栈保护,等到异常处理器完毕,返回上一模式时,再将栈中保存的值依次出栈到对应的寄存器
r14(LR):存放返回地址
r15(PC):存放取指的指令地址
cpsr
spsr
执行一条指令,分三个阶段:
(1)取指
(2)解码
(3)执行
这三个阶段,分了三个不同的硬件来完成
push
add
sub
取指 解码 执行
push
add push
sub add push
--------------------->
正在执行的指令的地址:0x20008000
正在取指的指令的地址:0x20008008
PC= 0x20008008
执行指令的地址=PC-8
CPSR程序状态寄存器
mode[4:0]:模式位,存放当前CPU的工作模式
T[5]:状态位:存放当前CPU处于的运行状态
0:ARM状态
1:Thumb状态
F[6]:FIQ禁止位
0:开启FIQ
1:禁止FIQ
I[7]:IRQ禁止位
0:开启IRQ
1:禁止IRQ
NZCV条件标志位
ARM支持的数据存储类型
Byte字节8位(一个字节)
HalfWord半字16位(两个字节)
Word字32位(四个字节)
DoubleWord双字64位(8个字节)
0x12345678(4个字节)
(高地址)小端模式 大端模式
0x20008003 0x12 0x78
0x20008002 0x34 0x56
0x20008001 0x56 0x34
0x20008000 0x78 0x12
(低地址)
ARM指令集
跳转指令:
分支指令B
带链接的分支指令BL
带状态切换的分支指令BX
ARMv5以后支持:BLX
BL
跳转指令B
b{cond} <target_label>
跳转范围:PC(new)=PC(当前)±32MB
B和BL共用
L:1 BL
L:0 B
cond:条件码
24bit:表示偏移量
1bit符号位
23bit 8M 223= 23X 220
bl delay
2000804c: eb00000a PC=0x2000807C
执行bl,PC(当前)=0x2000804c + 8 = 0x20008054
通过bl指令的机器码,得到偏移量:0xax 4 = 0x28 = 40
PC(new)= PC(当前)+偏移量
=0x20008054 + 0x28
=0x2000807C
start:
cmp r0, r1
beq not_copy
mov r0, r1
not_copy:
b.
带链接的分支指令:BL
指令格式:
BL{cond}<target_address>
START:
MOV R0,#1 //R0=1
MOV R1,#2 //R1=2
BL DoAdd //在执行该指令时
//CPU会自动将下一条指令的地址保存到LR,
//然后再跳
B.
…
DoAdd:
ADD R0, R0, R1 //R0=R0+R1
MOVPC, LR //PC=LR
…
带状态切换的跳转指令
指令格式
BX{cond} <Rm>
跳转范围限制
绝对地址、4G范围
ARM状态
Thumb状态
.CODE 32
ARM_code:
ADR R0,THUMB_code + 1 //R0= THUMB_code + 1
BX R0
//1.CPSR[5]=R0[0],改变当前的状态为Thumb
//2.PC= R0 & 0xFFFFFFFE
……
.CODE 16
THUMB_code:
ADR R0, ARM_code //R0= ARM_code
BX R0
…… //1.CPSR[5]=R0[0]
//2.PC = R0 & 0xFFFFFFFE
B:相对跳转PC(跳转)=PC(当前)+/-偏移量(32M),无返回
BL:相对跳转PC(跳转)=PC(当前)+/-偏移量(32M)
CPU会自动将BL指令的下一条指令的地址保存的LR,然后跳转,当执行完代码后,手动通过指令返回到BL指令的下一条指令继续执行MOV PC,LR
BX:绝对跳转,跳转范围4G
1.Rm[0]给CPSR的T位,改变当前的运行状态
2.PC=Rm& 0xFFFFFFFE
BLX:
1.保存下一条指令的地址到LR
2.Rm[0]给CPSR的T位,改变当前的运行状态
3.PC=Rm& 0xFFFFFFFE
1.编写sub.s
2.安装4.4.1版本的交叉编译器
arm-linux-gdb
将ftp://arm/armgcc编译器/arm-2009q3.tar.bz2拷贝到共享目录下
cd /home/tarena
mkdir opt
cd opt
sudo tar jxf /mnt/hgfs/1409/arm-2009q3.tar.bz2
cd /home/tarena/opt/arm-2009q3/bin
3.配置环境变量
cd /home/tarena
vi .bashrc
source .bashrc
arm-linux-gcc -v
gccversion 4.4.1 (Sourcery G++ Lite 2009q3-67)
4.安装qemu软件包
将ftp://arm/day07/qemu.rar拷贝到共享目录
直接在XP下解压
cd /mnt/hgfs/1409/qemu/qemu
sudo dpkg -i *
运行环境搭建完毕
5.编译sub.s
arm-linux-as -g -o sub.o sub.s
arm-linux-ld -e do_sub -o sub sub.o
qemu-arm -g 1234 sub
6.重新打开一个标签页
arm-linux-gdb sub
(gdb)target remote localhost:1234
(gdb)s
(gdb)s
(gdb)s
(gdb)info r
//查看寄存器
main:
stmfd sp!, {r14}入栈
bl func1
ldmfd sp!, {pc}出栈
func1:
bl func2
mov pc, lr
func2:
mov pc, lr