ARM中異常模式的跳轉(zhuǎn)
(詳細(xì)內(nèi)容請(qǐng)參考 ARM架構(gòu)參考手冊(cè)第二章41頁(yè))
本文引用地址:http://m.butianyuan.cn/article/201611/317864.htm對(duì)應(yīng)的中文詳細(xì)模式如下:
今天主要對(duì)ARM的 undefined模式來(lái)認(rèn)識(shí)ARM中處理異常的機(jī)制,在A(yíng)RM中,如果遇到異常情況,首先會(huì)找異常向量表,如下圖(詳細(xì)請(qǐng)參考ARM架構(gòu)手冊(cè)54頁(yè))
例如,有以下代碼。在板子運(yùn)行的時(shí)候就會(huì)發(fā)生異常。對(duì)應(yīng)的,由于.word這是undifined異常,對(duì)應(yīng)異常向量表,就會(huì)在04這個(gè)位子來(lái)尋求解決異常的辦法.......
1 #include《stdio.h》2 3 int main()4 {5 6 __asm__ __volatile__(7 ".word 0x77n"8 );9 10 11 12 }
但是。。。。不巧的是在A(yíng)RM中地址00到10地址是ROM,ROM是只可讀,不可寫(xiě)的。所以,這就是MMU存在的意義之所在了,來(lái)一個(gè)“隔山打牛”把內(nèi)存04這個(gè)地址映射到其他可以寫(xiě)入的地方,以后操作04這個(gè)地址就是在操作其他地址了。
順便回顧上一次MMU的代碼。詳細(xì)請(qǐng)參考上一篇筆記
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 %xn",*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此時(shí)將是小頁(yè)模式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:初始化頁(yè)表53 54 unsigned long mmu = 1 (1 << 1) (1 << 8);55 //將MMU的第0,1,8位置156 __asm__ __volatile__(57 "mov r0, #3n"58 "MCR p15, 0, r0, c3, c0, 0n"http://manager59 "MCR p15, 0, %0, c2, c0, 0n"http://addr 60 "MCR p15, 0, %1, c1, c0, 0n"http:// enable mmu61 :62 : "r" (addr), "r" (mmu)63 : "r0"64 );65 printf("MMU is enable!n");66 }67
在代碼中,首先,在0x 31的地址中存入了數(shù)據(jù)0x11.然后,將0x30地址映射到了0x50的地址中,最后,打印0x51地址里的值,就是打印0x31的地址里的值。
以下是對(duì)于處理異常模式跳轉(zhuǎn)的代碼:
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 //發(fā)生異常時(shí)會(huì)進(jìn)入異常模式跳轉(zhuǎn)到0 4地址處理異常事件 12 unsigned long source_addr=volitale_init();13 //異常事件處理函數(shù)14 printf("souce addr is %xn",source_addr);15 //將異常處理地址的值放到0x6416 memcopy(0x64,source_addr,0x100);17 18 enable_mmu();19 //內(nèi)存映射將0x04映射到0x6004 20 __asm__ __volatile__(21 ".word 0x77n"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此時(shí)將是小頁(yè)模式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:初始化頁(yè)表116 117 unsigned long mmu = 1 (1 << 1) (1 << 8);118 //將MMU的第0,1,8位置1119 __asm__ __volatile__(120 "mov r0, #3n"121 "MCR p15, 0, r0, c3, c0, 0n"http://manager122 "MCR p15, 0, %0, c2, c0, 0n"http://addr 123 "MCR p15, 0, %1, c1, c0, 0n"http:// enable mmu124 :125 : "r" (addr), "r" (mmu)126 : "r0"127 );128 printf("MMU is enable!n");129 }
在程序中,
volitale_init()函數(shù)的作用就是獲得處理異常函數(shù)的地址,存到變量source中并返回.
voctor_start匯編函數(shù)主要就是實(shí)現(xiàn)了從SVR模式跳入到UND模式,在UND模式中打印了一句話(huà)
hello undefined并且跳出來(lái)在代碼中,跳轉(zhuǎn)模式主要有三步,而跳出模式也有兩步,代碼中沒(méi)給出,就是/1:將CPSR保存在SPSR中2:將PC保存到新模式下的lr中;。
memcopy()函數(shù)的作用是:將source_addr里的數(shù)據(jù)拷貝到0x64地址,一共拷貝len個(gè)地址
實(shí)際上就是將處理異常函數(shù)的地址存到可以讀寫(xiě)的地址。下次到0x04地址找處理函數(shù)的時(shí)候久直接調(diào)用到了處理異常函數(shù)。
接下來(lái)是enable_mmu()函數(shù),用法與上一個(gè)一樣。但是,此時(shí)在制表函數(shù)init_ttb()中。新把
從00-10的地址映射到了60--70 地址
對(duì)于匯編部分,對(duì)于不太了解的沒(méi)關(guān)系,主要了解實(shí)現(xiàn)功能是什么。掌握主要流程, 到最后再作
統(tǒng)一總結(jié)。
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
評(píng)論