1 嵌入式结构
名称
说明
应用程序
app
库
libc.so.6、libstdc++.so、libjpeg.so、…
GUI
QT(C++)、Android(Java)、Mini-GUI(C)、GTK()
文件系统
Filesystem
内核
Linux、Android
bootloader
uboot、myboot
板卡
SOC+DDR+NAND(EMMC)+LCD+SOUND+NET…
SOC
CPU(arm)+总线+控制器
Arm公司只设计处理器架构,Arm1 Arm2 …. Arm6
版本
内核
芯片
v4
arm7TDMI
S3C44B0
arm920T
S3C2440(火,资料多)
v5
arm10
v6
arm1176
S3C6410
arm11MP
v7
arm-cortex-a,针对以应用为主(消费电子、高端的嵌入式设备)
a8
S5PV210(单核)
a9
Exynos4412(4核)、Imax6.Q/D、Omap4460(TI)
a15
Exynos5210(a15以上才支持硬件除法)
arm-cortex-r
r4/r6
arm-cortex-m(m系列都支持硬件除法)
m3
STM32F10xxx(ST)
m4
STM32F40xxx
m7
STM32F7xxx
v8
arm-cortex-a50(都是64位)
a53(消费电子、高端的嵌入式设备)
a57(服务器)
arm-cortex-a72
除arm外的芯片
名称
说明
mips
网络设备(路由)
ppc
航空航天,高端路由
51
仪器仪表
2 ARM架构
2.1 结构
SOC=CPU(arm)+总线+控制器
i5--PIC-E--桥(芯片组)
ARM=arm_core 执行arm指令,哈弗结构
cache 高速缓存
I-cache 缓存代码
D-cache 缓存数据
TCM 要求访问速度高的,可以存在这里
I-tcm 存代码
D-tccm 存数据
2.2 协处理器
名称
说明
CP15
cache、tcm、指令分支预测等的开关,处理器的大小端、MMU的开关、页表
CP14
调试
CP10
NENO
CP11
VFP
2.3 寄存器
r13~r15不要随便用,所有函数按1、2、3的顺序执行,保证调用函数之后能够正确返回
1、LR->SP
2、SP->LR
3、PC=LR
名称
说明
CPSR
当前程序状态寄存器
SPSR
保存程序状态寄存器
r0~r12
写程序时随便用
r13
SP stack pointer(指向在栈中的地址)
r14
LR link register(函数返回时的指向)
r15
PC process counter(指向程序执行地方)
2.4 指令集
arm-cortex-m 只支持thumb thumb2
名称
位数
说明
arm指令
32位
高效,占空间比较大
thumb指令
16位
比arm低效,占空间比较小
thumb2指令
32/16位混合
2.5 七种工作模式
名称
位数
user
用户模式,执行用户程序
system
系统模式
svc
管理模式,执行boot kernel
abort
模式,处理非法访问地址
irq
中断模式
fiq
快速中断
unde
未定义模式,处理未定义指令
普通模式:user 只能修改NZCVQ 特权模式:system,svc,unde,abort,irq,fiq 异常模式:svc,unde,abort,irq,fiq 每个异常模式都有自己的r13,r14,SPSR
模式切换:CPSR[NZCVQ EAIFT M[4:0]]
N 负操作1,否则0
Z 零操作1,否则0
C 加法,如果有进位1,否则0 减法,如果有借位0,否则1
V 有溢出1,否则0
Q 有饱和1,否则0
E 如果小端0,否则1
A 中止禁止位,如果为1则禁止了中止异常
I 中断禁止位
F 快速禁止位
T 如果执行的thumb指令则位2,否则为0
M[4:0] 只有特权模式可以写
3 ARM汇编,在C中嵌套汇编
int main(void ){
int a = 100 ;
int b = 30 ;
int c = 50 ;
__asm__ __volatile__(
"mov %0,#20\n"
"mov r0,#123\n"
"mov %1,r0\n"
"mov r1,%2\n"
"mov %0,r1\n"
:"=&r" (a),"=&r" (b) /**
* 声明输出变量(只能写不能读)和输入输出变量,第一个声明的是%0,
* 第二个是%1,=是输出变量,+是可读可写变量,&是独占寄存器,r代表是寄存器,
* =后记住加&
*/
:"r" (c)
:"r0" ,"r1"
);
printf("hello asm %d %d %d\n" ,a,b,c);
/**
* out = in_out;
* in_out = in;
*/
int in_out = 200 ;
int out;
int in = 52 ;
asm volatile (
"mov %0,%1\n"
"mov %1,%2\n"
:"=&r" (out),"+r" (in_out)
:"r" (in)
:
)
printf("hello asm out=%d in_out=%d\n" ,out,in_out);
int d,f,e;
asm volatile (
"mov %[d],#1\n"
"mov %[f],#2\n"
:[d]"=&r" (d),[e]"=&r" (e),[f]"=&r" (f)
:
:
)
printf("hello asm d=%d f=%d\n" ,d,f);
int g,h,i;
asm volatile (
"mov r0,#9\n"
"mov r1,#8\n"
"sub %0,r0,r1\n"
:"=&r" (g)
:
:"r0" ,"r1"
);
printf("hello asm sub g=%d\n" ,g);
/**
* 32位处理器上进行64位减法,I存高位,H存低位
* 0x33333333 00000004
* 0x11111111 00000005
* 0x22222221 ffffffff
*/
asm volatile (
"mov r0,#4\n"
"mov r1,#5\n"
"subs %0,r0,r1\n"
"ldr r0,=0x33333333"
"ldr r1,=0x11111111"
"sbc %1,r0,r1\n"
:"=&r" (h),"=&r" (i)
:
:"r0" ,"r1"
);
printf("sub = %#x%08X\n" ,i,h);
int mul;
asm volatile (
"mov r0,#3\n"
"mov r1,#4\n"
"mul %0,r0,r1\n"
:"=&r" (mul)
:
:"r0" ,"r1"
);
printf("hello asm mul=%d\n" ,mul);
asm volatile (
"mov r0,#3\n"
"mov r1,#4\n"
"mov r2,#5\n"
"mla %0,r0,r1,r2\n"
:"=&r" (mul)
:
:"r0" ,"r1" ,"r2"
);
printf("hello asm mul=%d\n" ,mul);
/**
* 条件执行,大多数的arm指令都支持
* thumb指令只有跳转指令才支持
* 大于gt,小于lt,等于eq,不等于ne,小于等于le,大于等于ge
*/
int k=5 ,m=6 ,l;
asm volatile (
"subs r0,%1,%2\n"
"movgt %0,#1\n"
"moveq %0,#2\n"
"movlt %0,#3\n"
:"=&r" (l)
:"r" (k),"r" (m)
:"r0"
);
printf("hello asm l=%d\n" ,l);
asm volatile (
"mov r0,#4\n"
"mov r1,#5\n"
"cmp r0,r1\n"
"movgt %0,#1\n"
"moveq %0,#2\n"
"movlt %0,#3\n"
:"=&r" (l)
:
:"r0" ,"r1"
);
printf("hello asm l=%d\n" ,l);
asm volatile (
"mov r0,#4\n"
"mov r1,#5\n"
"teq r0,r1\n"
"moveq %0,#1\n"
"movne %0,#2\n"
:"=&r" (l)
:
:"r0" ,"r1"
);
printf("hello asm l=%d\n" ,l);
asm volatile (
"mov r0,#0xf0\n"
"tst r0,#(1<<4)\n"
"moveq %0,#0\n"
"movne %0,#1\n"
:"=&r" (l)
:
:"r0"
);
/**
* 逻辑运算
* and 两个是1才是1,其余都是0
* orr 有1个是1都是1
* eor 不同为1,相同为0
* bic
*
* mvn r0,#0xff 按位取反
* r0 = ~0x000000ff = 0xffffff00
*
* 移位运算符<<向左移,>>向右移
* 需要移位的数字 << 移位的次数
* 例如: 3 << 2,则是将数字3左移2位
* 首先把3转换为二进制数字0000 0000 0000 0000 0000 0000 0000 0011,然后把该数字高位(左侧)的两个零移出
* 其他的数字都朝左平移2位
* 最后在低位(右侧)的两个空位补零。则得到的最终结果是0000 0000 0000 0000 0000 0000 0000 1100
* 则转换为十进制是12。不溢出的情况下
* 相当于3*2的2次方
* 3*(2^2) = 12
*/
int and,orr,eor,bic;
asm volatile (
"mov r0,#5\n"
"mov r1,#6\n"
"and %0,r0,r1\n"
"orr %1,r0,r1\n"
"eor %2,r0,r1\n"
"mov r0,#0xff"
"bic %3,r0,#4\n"
:"=&r" (and),"=&r" (orr),"=&r" (eor),"=&r" (bic)
:
:"r0" ,"r1"
);
printf("hello asm and=%d orr=%d eor=%d bic=%x\n" ,and,orr,eor,bic);
/**
* lsl逻辑左移,lsr逻辑右移
* asr算术右移,ror循环右移
*/
int lsl,lsr,asr,ror;
asm volatile (
"mov r0,#20\n"
"mov %0,r0,lsl #1\n"
"mov %0,r0,lsr #1\n"
"mov r0,#-20\n"
"mov %2,r0,lsr #1\n"
"mov %3,r0,asr #1\n"
"mov r0,#0#ff\n"
"mov %4,r0,ror #4\n"
:"=&r" (lsl),"=&r" (lsr),"=&r" (asr),"=&r" (ror)
:
:"r0" ,
);
printf("hello asm lsl=%d lsr=%d asr=%d ror=%x\n" ,lsl,lsr,asr,ror);
int n;
asm volatile (
"mrs %0,cpsr\n"
:"=&r" (n)
:
:
);
printf("cpsr = %#x\n" ,n);
asm volatile (
"mrs r0,cpsr\n"
"orr r0,r0,#(1<<7)\n"
"msr cprs,r0\n"
:
:
:"r0"
);
return 0 ;
}
4 syscall
int main(void )
{
char *s = "hell syscall\n" ;
int ret;
write(1 ,s,strlen (s));
syscall(4 ,1 ,s,strlen (s));
asm volatile (
"mov r0,#1\n"
"mov r1,%1\n"
"mov r2,#14\n"
"swi 0x900004\n"
"mov %0,r0\n"
:"=&r" (ret)
:"r" (s)
:"r0" ,"r1" ,"r2"
);
printf ("ret =%d\n,ret" );
return 0 ;
}