(具体内容请参阅 ARM架构参阅手册第二章41页)
对应的中文具体形式如下:
今日首要对ARM的 undefined形式来知道ARM中处理反常的机制,在ARM中,假如遇到反常情况,首要会找反常向量表,如下图(具体请参阅ARM架构手册54页)
例如,有以下代码。在板子运转的时分就会产生反常。对应的,因为.word这是undifined反常,对应反常向量表,就会在04这个位子来寻求处理反常的方法…….
1 #include《stdio.h》2 3 int main()4 {5 6 __asm__ __volatile__(7 ".word 0x77\n"8 );9 10 11 12 }
可是。。。。不巧的是在ARM中地址00到10地址是ROM,ROM是只可读,不可写的。所以,这便是MMU存在的含义之地点了,来一个“隔山打牛”把内存04这个地址映射到其他能够写入的当地,今后操作04这个地址便是在操作其他地址了。
趁便回忆上一次MMU的代码。具体请参阅上一篇笔记
1 2 int (*printf)(char *, ...) = 0xc3e114d8;3 4 void init_ttb(unsigned long *addr);5 void enable_mmu(void);6 7 int main()8 {9 10 printf("hello mmu!\n");11 //3040 -> 500-60012 unsigned long *pp=0x51;13 *pp= 0x;14 printf("*pp is%x \n",*pp);15 16 enable_mmu();17 18 unsigned long *pv=0x31;19 printf("*pv is %x\n",*pv);20 }21 22 void init_ttb(unsigned long *addr)23 {24 unsigned long va = 0;//界说虚拟地址25 unsigned long pa = 0;//界说物理地址26 27 //40-80 ==== 408028 for(va=0x40; va<=0x80; va+=0x100){29 pa = va;30 addr[va >> 20] = pa 2;31 //2的意图是将0-2方位为10此刻将是小页形式4K32 }33 34 //10-14 ==== 101435 for(va=0x10; va<=0x14; va+=0x100){36 pa = va;37 addr[va >> 20] = pa 2;38 }39 40 //30-40 ==== 506041 for(va=0x30; va<0x40; va+=0x100){42 pa = va + 0x20;43 addr[va >> 20] = pa 2;44 }45 }46 47 void enable_mmu(void)48 49 {50 unsigned long addr = 0x60;51 init_ttb(addr);52 //step:初始化页表53 54 unsigned long mmu = 1 (1 << 1) (1 << 8);55 //将MMU的第0,1,8方位156 __asm__ __volatile__(57 "mov r0, #3\n"58 "MCR p15, 0, r0, c3, c0, 0\n"//manager59 "MCR p15, 0, %0, c2, c0, 0\n"//addr 60 "MCR p15, 0, %1, c1, c0, 0\n"// enable mmu61 :62 : "r" (addr), "r" (mmu)63 : "r0"64 );65 printf("MMU is enable!\n");66 }67
在代码中,首要,在0x 31的地址中存入了数据0x11.然后,将0x30地址映射到了0x50的地址中,最终,打印0x51地址里的值,便是打印0x31的地址里的值。
以下是关于处理反常形式跳转的代码:
1 2 int (*printf)(char *, ...) = 0xc3e114d8;3 4 void init_ttb(unsigned long *addr);5 void enable_mmu(void);6 unsigned long volitale_init();7 void memcopy(unsigned long* dest,unsigned long* source,int len);8 9 int main()10 {11 //产生反常时会进入反常形式跳转到0 4地址处理反常事情 12 unsigned long source_addr=volitale_init();13 //反常事情处理函数14 printf("souce addr is %x\n",source_addr);15 //将反常处理地址的值放到0x6416 memcopy(0x64,source_addr,0x100);17 18 enable_mmu();19 //内存映射将0x04映射到0x6004 20 __asm__ __volatile__(21 ".word 0x77\n"22 );23 printf("welcome back! \n");24 25 26 }27 28 void memcopy(unsigned long* dest,unsigned long* source,int len)29 {30 int i=0;;31 for(i=0;i> 20] = pa 2;88 //2的意图是将0-2方位为10此刻将是小页形式4K89 }90 91 //00-10 ==== 607092 for(va=0x00; va<=0x10; va+=0x100){93 pa = va+0x60;94 addr[va >> 20] = pa 2;95 }96 97 //10-14 ==== 101498 for(va=0x10; va<=0x14; va+=0x100){99 pa = va;100 addr[va >> 20] = pa 2;101 }102 103 //30-40 ==== 5060104 for(va=0x30; va<0x40; va+=0x100){105 pa = va + 0x20;106 addr[va >> 20] = pa 2;107 }108 }109 110 void enable_mmu(void)112 {113 unsigned long addr = 0x70;114 init_ttb(addr);115 //step:初始化页表116 117 unsigned long mmu = 1 (1 << 1) (1 << 8);118 //将MMU的第0,1,8方位1119 __asm__ __volatile__(120 "mov r0, #3\n"121 "MCR p15, 0, r0, c3, c0, 0\n"//manager122 "MCR p15, 0, %0, c2, c0, 0\n"//addr 123 "MCR p15, 0, %1, c1, c0, 0\n"// enable mmu124 :125 : "r" (addr), "r" (mmu)126 : "r0"127 );128 printf("MMU is enable!\n");129 }
在程序中,
volitale_init()函数的效果便是取得处理反常函数的地址,存到变量source中并回来.
voctor_start汇编函数首要便是完成了从SVR形式跳入到UND形式,在UND形式中打印了一句话
hello undefined而且跳出来在代码中,跳转形式首要有三步,而跳出形式也有两步,代码中没给出,便是/1:将CPSR保存在SPSR中2:将PC保存到新形式下的lr中;。
memcopy()函数的效果是:将source_addr里的数据复制到0x64地址,总共复制len个地址
实际上便是将处理反常函数的地址存到能够读写的地址。下次到0x04地址找处理函数的时分久直接调用到了处理反常函数。
接下来是enable_mmu()函数,用法与上一个相同。可是,此刻在制表函数init_ttb()中。新把
从00-10的地址映射到了60--70 地址
关于汇编部分,关于不太了解的不要紧,首要了解完成功用是什么。把握首要流程, 到最终再作
一致总结。
Makefile:
1 2 all:3 arm-none-linux-gnueabi-gcc -c mmu.c -o mmu.o4 arm-none-linux-gnueabi-ld -Ttext=0x41 mmu.o -o mmu 5 arm-none-linux-gnueabi-objcopy -Ielf32-littlearm -Obinary mmu mmu.bin6 7 clean:8 rm -rf mmu mmu.o mmu.bin9 10 11
在PC终端make
在minicom板子上dnw到41地址go41