start.S源碼:
.globl _start
_start:
// 0 地址
b reset // 復位時,cpu跳到0地址 其實復位之后,CPU就處于管理模式(svc)
ldr pc, =undefined_instruction //cpu遇到不能識別的指令時 ,地址4,該指令到內存處讀取un..的鏈接地址
ldr pc, _vector_swi // 當執行swi指令時, 進入swi模 式 ,地址8,該指令直接讀取_vector_swi當前地址
b halt @ldr pc, _prefetch_abort // 預取中止異常
b halt @ldr pc, _data_abort // 數據訪問異常
b halt @ldr pc, _not_used // 沒用到
ldr pc, _irq // 0x18 中斷異常
b halt @ldr pc, _fiq // 快中斷異常
_irq :
.word vector_irq
_vector_swi:
.word vector_swi
vector_swi:
// 1. 保存現場
ldr sp, =0x56000000 //sp是svc模式自己的r13,要從新設置
stmdb sp!, {r0-r12, lr} // lr就是swi的下一條指令地址
// 2. 處理異常
mrs r0, cpsr
ldr r1, =swi_str
bl print_cpsr
// 3. 恢復現場
ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢復到cpsr
swi_str:
.word 0x00697773 // swi
undefined_instruction:
// 1. 保存現場
ldr sp, =0x55000000
stmdb sp!, {r0-r12, lr}
// 2. 處理異常
mrs r0, cpsr
ldr r1, =und_str
bl print_cpsr
// 3. 恢復現場
ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢復到cpsr
und_str:
.word 0x00646e75 // und
usr_str:
.word 0x00727375 // usr
vector_irq:
// 1. 保存現場
ldr sp, =0x54000000
sub lr, lr, #4
stmdb sp!, {r0-r12, lr} // lr就是swi的下一條指令地址
// 2. 處理異常
// 2.1 分辨是哪個中斷
// 2.2 調用它的處理函數
// 3. 恢復現場
ldmia sp!, {r0-r12, pc}^ // ^表示把spsr恢復到cpsr
reset:
// 硬件相關的設置
// Peri port setup
ldr r0, =0x70000000
orr r0, r0, #0x13
mcr p15,0,r0,c15,c2,4 @ 256M(0x70000000-0x7fffffff)
// 關看門狗
// 往WTCON(0x7E004000)寫0
ldr r0, =0x7E004000
mov r1, #0
str r1, [r0]
// 設置棧
ldr sp, =8*1024
// 設置時鐘
bl clock_init
bl ddr_init
bl init_uart
// 把程序的代碼段、數據段復制到它的鏈接地址去
adr r0, _start // 獲得_start指令當前所在的地址 : 0
ldr r1, =_start // _start的鏈接地址 0x51000000
ldr r2, =bss_start // bss段的起始鏈接地址
sub r2, r2, r1
cmp r0,r1
beq clean_bss
bl copy2ddr
cmp r0, #0
bne halt
// 清BSS
// 把BSS段對應的內存清零
clean_bss:
ldr r0, =bss_start
ldr r1, =bss_end
mov r3, #0
cmp r0, r1
ldreq pc, =on_ddr
clean_loop:
str r3, [r0], #4
cmp r0, r1
bne clean_loop
ldr pc, =on_ddr //跳到DDR中運行
on_ddr:
mrs r0, cpsr //把狀態寄存器的值讀到r0中
bic r0,r0,#0x1f //清掉后5位
orr r0,r0,#0x10 //把第四位置1
msr cpsr,r0 // 進入user mode ,把r0的值賦給程序狀態寄存器
ldr sp, =0x57000000 //用戶模式下的sp
ldr r1, =usr_str
bl print_cpsr
swi 0
// cpu進入svc模式
// 把之前的cpsr保存到spsr_svc
// 切換到r13_svc, r14_svc
// 把swi的下一條指令(bl hello)的地址存到r14(lr)_svc
// 跳到地址8
bl hello
undef: //執行完hello函數以后會執行該條未定義指令,從而進入未定義指令中斷
.word 0xff000000
// cpu進入Undefined模式
// 把之前的cpsr保存到spsr_und
// 切換到r13_und, r14_und
// 把下一條指令存的地址到r14(lr)_und
// 跳到地址4
swi_ret:
bl main
halt:
b halt
====================================================================
說明:
①上面代碼上電復位后CPU就處于管理模式(svc),執行0地址處的b reset跳轉到reset:處繼續運行,把相關硬件初始化以后會清掉cpsr后5位并把第四位置1,進入user mode設置棧后運行于用戶態(usr),即處理器啟動時首先進入管理員模式(svc),此后進入除用戶模式之外的其他模式,主要完成各模式的堆棧設置,最后進入用戶模式,運行用戶程序;當發生swi軟中斷以后cpu進入svc模式。
②swi軟中斷主要用于usr模式(應用程序通常運行于usr模式)切換到svc模式下。在arm的7種模式當中(已經不止7種了)usr模式是唯一一個非特權模式,其他都是特權模式,比如fiq、und等都是特權模式,他們之間的切換直接更改cpsr寄存器的低5位的模式位或者真的發生fiq、und等異常的時候就可以達到切換的目的;而usr模式不是特權模式沒有辦法更改cpsr寄存器的低5位進行切換,想切換到特權模式只能調用swi指令,swi指令會幫助它進入到svc模式。
③如果原來是svc模式,發生未定義指令異常后進入und(Undefined)模式,這時候要重新設置sp棧指針;如果執行swi指令的時候已經處于svc模式,那么發生swi的軟中斷之后仍然還是svc模式,這個時候就不用再去設置sp棧指針了(在tiny4412異常實驗中因為運行的uboot,已經處于svc模式,故要注意sp指針)。
④只有處理swi和und異常的時候lr指向下一條指令,其他的異常發生的時候lr都是指向下兩條指令;ARM上的每條指令長度都是32位即4個字節;swi指令也是32位且其后面跟的value值占該指令的低24位,所以在程序里可以得到swi指令的value值,具體如下:
unsigned long *pdo_swi = 0x75000000;
*pdo_swi = do_swi; //先把中斷處理函數do_swi地址放在0x75000000
在發生swi異常的時候程序會自動跳到異常向量入口:"b swi\n"
接著跳轉到swi處執行:
"swi:\n"
"stmfd sp!, {r0-r12, lr}\n"
//保護現場,把usr模式下的相關寄存器入棧,
//存放順序是先存放lr、r12....r0,最終sp指向r0的地址
"mov r0, sp\n" //把上一步中指向usr模式下r0地址的sp傳給r0寄存器
"mov r3, #0x75000000\n"
"ldr r3, [r3]\n"
"blx r3\n" //調用中斷處理函數do_swi,參數放在r0中
//regs[0] == r0
//regs[1] == r1
//.....
//regs[12] == r12
//regs[13] == lr
void do_swi(unsigned long regs[]) //regs指向usr模式下r0地址
{
//按照入棧順序regs[13]為usr模式下lr值,即發生swi異常時下一條指令的地址
//regs[13] - 4 = lr - 4 ; 即上一條指令的地址也就是swi異常的地址
unsigned long *instr = regs[13] - 4;
//根據ARM指令是32位的,swi指令也是32位且其后面跟的value值占該指令的低24位得到value值
printf("swi: 0x%x\n", *instr & 0xffffff);
}
====================================================================
注意異常在操作系統里的用法:
①SWI異常中斷的用處是:應用程序運行于用戶態(usr),當應用程序調用open/read/write函數的時候要調用內核的函數,要怎么進入內核呢?其實open/read/write函數就是一條SWI #VAL指令,帶有不同的參數,一執行這條指令CPU就會發生異常,cpu會進入svc模式,跳到固定的地址,在地址里面就放有內核代碼,在內核代碼里面就判斷SWI指令帶進來的#VAL參數值,如果是open函數就調用sys_open函數等等。
②未定義指令異常用處:調試用,程序在執行的時候想打一個斷點怎么打?程序在運行的時候在想打斷點的地方把指令取出來,并且保存,替換為一條未定義的指令,程序在運行的時候跑到該指令處就會發生未定義指令異常,進入到未定義指令異常處理函數,在處理函數里面就可以放一些代碼,比如等待用戶輸入其他指示,用戶要查看某些寄存器,查看某些內存,就可以查看寄存器內存并把結果返回,當要繼續運行的時候就把替換的指令恢復回去,讓程序從這里重新運行。
入棧順序
上一篇:ARM工作模式和大端小端存儲模式
下一篇:OK6410裸機之NAND Flash操作更新固件
推薦閱讀
史海拾趣
隨著市場需求的不斷變化,Degson意識到只有不斷創新和升級產品,才能在激烈的市場競爭中保持領先地位。因此,公司投入大量資金用于研發,并在技術上取得了重大突破。Degson成功研發出了一系列新型接線端子和精密模具,不僅提高了產品的性能和質量,還降低了生產成本。這些新產品迅速在市場上獲得了廣泛應用,進一步鞏固了Degson在電子連接器領域的領先地位。
在追求商業成功的同時,Codeco也積極履行企業社會責任。他們注重環保和可持續發展,在生產過程中采用環保材料和技術,減少對環境的影響。此外,Codeco還積極參與公益事業,為社會做出貢獻。這些舉措不僅提升了公司的社會形象,也贏得了員工和消費者的尊重與認可。
您可以根據這個框架,結合您對電子行業和Codeco Corporation Of Vermont的了解,撰寫具體的故事內容。請注意,這些故事應基于事實或合理的推測,避免涉及未經證實的信息或夸大其詞的描述。
人才是企業發展的核心競爭力。E Connector Solutions公司高度重視人才培養和團隊建設。公司建立了完善的人才培養機制,通過內部培訓、外部引進等方式不斷提升員工的專業技能和綜合素質。同時,公司還注重團隊建設,鼓勵員工之間的協作與交流,營造積極向上的工作氛圍。這種注重人才培養和團隊建設的做法為公司的發展提供了堅實的人才保障。
請注意,以上故事均為虛構,旨在為您提供一個關于電子連接器解決方案公司發展起來的故事框架。如果您需要了解特定公司的具體發展情況,建議您查閱相關公司的官方網站或行業報告。
CMOS Sensor Inc公司起源于硅谷,由一群熱衷于光電圖像采集技術的工程師創立。他們看到了光電圖像采集技術在多個領域的巨大潛力,于是決定投身于這一行業。在創立初期,公司面臨著資金短缺、市場競爭激烈等諸多挑戰。然而,憑借著對技術的執著和不懈努力,CMOS Sensor Inc公司逐漸在市場中站穩了腳跟。
在1924年,大金工業株式會社成功合成了碳氟化合物,并在隨后的18年里,這項技術逐漸成熟并開始批量生產。這一突破性的技術不僅為大金在化學領域奠定了堅實的基礎,也為公司后續在家用空調市場的進軍提供了技術支持。
Antiference公司最初以生產電磁屏蔽材料起家,但隨著電子設備的普及和電磁干擾問題的日益嚴重,公司意識到單純的材料生產已無法滿足市場需求。于是,Antiference投入巨資研發新型電磁干擾抑制技術,成功開發出了一款能夠顯著降低電磁干擾的芯片。這款芯片迅速在市場上獲得了廣泛認可,Antiference也因此成為了電磁干擾抑制領域的領軍企業。
平臺 6410+CE6.0 用DM9000A網絡可以正常NK,用DM9000C不可以,提示如下信息: DM9000 ID is 0x90000a46 INFO: Probe: DM9000 is detected. DM9000: MAC Address: 0:11:22:33:44:55 System ready! Preparing for download... INFO: *** Devic ...… 查看全部問答∨ |
聽說wince5.0出了最新版本,wince5.0_dublin,有沒有哪位仁兄知道哪里可以下載呢? 據說這個版本對藍牙有了比較全面的支持,不知道它目前都支持了哪些bluetooth profile?… 查看全部問答∨ |
if(FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED))) return FALSE; HRESULT hr; CLSI ...… 查看全部問答∨ |
請問有什么辦法可以不讓拔通的GPRS隨時都在線呢,我現在用dup方式連接了gprs的DNS服務器,連接也是成功的,最后往它發一些數據,(沒有數據返回)但我也不要求有返回的數據,只是想讓信道上有定時的有些數據流量,以此來保持狀態.但是過45分鐘后,GPRS還是斷 ...… 查看全部問答∨ |
請問smdk6400開機停在starting kernel...地問題 各位大大好 小弟想請教一下個問題 我在complier完load進smdk6400主板 但系統一開機執行到Starting kernel... 就當掉哩~~~ 有什麼方向可以去追緃嗎 謝謝~~~… 查看全部問答∨ |
EVC4.0中,提示'TextOut' : is not a member of 'CClientDC' 代碼如下: char buff[10]; CClientDC dc(this); sprintf(buff,\"[%o3d,%03d]\",point.x,point.y); dc.Tex ...… 查看全部問答∨ |