<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM啟動代碼分析-philips的LPC2xxx系列

          ARM啟動代碼分析-philips的LPC2xxx系列

          作者: 時間:2016-11-10 來源:網(wǎng)絡(luò) 收藏
          **********************************************************************************************
          *File: startup.s
          *Author: Embest w.h.xie 2005.02.21
          *Desc: lpc22xxlpc212xlpc211xlpc210x startup code
          *History:
          * note modify: cui jian jie 2006-4-25
          *comment:
          **********************************************************************************************/
          # 處理器的七種工作方式的常量定義
          .EQU Mode_USR, 0x10 #用戶模式
          .EQU Mode_FIQ, 0x11 #FIQ模式
          .EQU Mode_IRQ, 0x12 #IRQ模式
          .EQU Mode_SVC, 0x13 #超級用戶模式
          .EQU Mode_ABT, 0x17 #終止模式
          .EQU Mode_UND, 0x1B #未定義模式
          .EQU Mode_SYS, 0x1F #系統(tǒng)模式

          # 中斷屏蔽位
          .EQU I_Bit, 0x80 //IRQ中斷控制位,當(dāng)被置位時,IRQ中斷被禁止
          .EQU F_Bit, 0x40 //FIQ中斷控制位,當(dāng)被置位時,F(xiàn)IQ中斷被禁止

          # 狀態(tài)屏蔽位
          .EQU T_bit, 0x20 //T位,置位時在Thumb模式下運行,清零時在ARM下運行

          # 定義程序入口點
          .globl _start
          .code 32

          .TEXT

          _start:

          # 中斷向量表

          Vectors:
          LDR PC, Reset_Addr //把Reset_Addr地址處的內(nèi)容放入PC中
          LDR PC, Undef_Addr
          LDR PC, SWI_Addr
          LDR PC, PAbt_Addr
          LDR PC, DAbt_Addr
          .long 0xb9205f80 @ keep interrupt vectors sum is 0
          LDR PC, [PC, #-0xff0] //當(dāng)前PC值減去0xFF0等于IRQ中斷入口地址
          LDR PC, FIQ_Addr
          #地址表
          Reset_Addr: #該地址標(biāo)號存放Reset_Handler程序段的入口地址
          .long Reset_Handler
          Undef_Addr: #該地址標(biāo)號存放Undef_Handler程序段的入口地址
          .long Undef_Handler
          SWI_Addr: #該地址標(biāo)號存放SWI_Handler程序段的入口地址
          .long SWI_Handler
          PAbt_Addr: #該地址標(biāo)號存放PAbt_Handler程序段的入口地址
          .long PAbt_Handler
          DAbt_Addr:
          .long DAbt_Handler
          .long 0
          IRQ_Addr: #地址標(biāo)號處存放一個無效的數(shù)據(jù)
          .long 0
          FIQ_Addr: #該地址標(biāo)號存放FIQ_Handler程序段的入口地址
          .long FIQ_Handler


          Undef_Handler:
          B Undef_Handler
          PAbt_Handler:
          B PAbt_Handler
          DAbt_Handler:
          B DAbt_Handler

          #軟中斷的中斷服務(wù)子程序入口地址
          SWI_Handler:
          STMFD sp!, {r0-r3, r12, lr} //入棧,現(xiàn)場數(shù)據(jù)保護(hù)
          MOV r1, sp //把堆棧指針SP存入R1中
          MRS r0, spsr //把SPSR值存入R0,SPSR值為產(chǎn)生軟中斷時的CPSR
          TST r0, #T_bit //判斷R0(SPSR)的T位是否為0
          #SPSR的T位不為0,工作在Thumb模式下
          LDRNEH r0, [lr,#-2] //SPSR的T位不為0,則[lr-2]-〉r0
          BICNE r0, r0, #0xFF00 // SPSR的T位不為0,清除r0的Bit8~Bit15位
          # SPSR的T位為0,工作在ARM模式下
          LDREQ r0, [lr,#-4] // SPSR的T位為0,則[lr-4] -〉r0
          BICEQ r0, r0, #0xFF000000 // SPSR的T位為0,清除r0的Bit24~Bit131位

          # R0 is interrupt number //R0是中斷號
          # R1 is stack point //R1是堆棧指針

          BL SWI_Exception //進(jìn)入軟中斷處理程序
          LDMFD sp!, {r0-r3, r12, pc}^ //出棧,現(xiàn)場數(shù)據(jù)恢復(fù)


          # 快速響應(yīng)中斷的中斷服務(wù)自程序的入口地址
          FIQ_Handler:
          STMFD SP!, {R0-R3, LR} //入棧的現(xiàn)場保護(hù)
          # BL FIQ_Exception //進(jìn)入FIQ的中斷處理程序
          LDMFD SP!, {R0-R3, LR} //出棧,恢復(fù)現(xiàn)場
          SUBS PC, LR, #4 //返回到主程序

          # 復(fù)位后程序處理的入口地址
          Reset_Handler:
          BL RemapSRAM //進(jìn)行存儲器映射的操作
          #下面幾行代碼用來判斷當(dāng)前的工作模式
          MRS R0, CPSR //讀CPSR到寄存器R0
          AND R0, R0, #0x1F //R0 = R0 AND 0x1F
          CMP R0, #Mode_USR //比較R0 和 #Mode_USR,二者相減
          //如果相等則說明當(dāng)前處在用戶模式下,需要通過產(chǎn)生11號軟中斷進(jìn)入系統(tǒng)模式。因為下面的初始化堆棧
          //需要在不同的工作模式下切換,而在用戶模式下不能直接切換,只有系統(tǒng)模式可以,所以要通過產(chǎn)生11
          //號軟中斷切換到用戶模式。
          SWIEQ #11

          BL InitStack //進(jìn)行堆棧初始化工作

          ARM啟動代碼分析-philips的LPC2xxx系列32006-7-24 14:33:00
          #------------------------------------------------------------------------------
          #- 初始化C變量
          #------------------------
          #- 下表由連接器自動產(chǎn)生
          #- RO: 只讀=代碼區(qū)。
          #- RW: 可讀可寫=預(yù)先初始化的數(shù)據(jù)(初始化的全局變量)和預(yù)先被清零的數(shù)據(jù)(未初始化的全局變量)。.
          #- ZI: 預(yù)先被清零的數(shù)據(jù)區(qū)(未初始化的全局變量)
          #- 預(yù)先被初始化的數(shù)據(jù)區(qū)定位在代碼區(qū)之后。
          #- 預(yù)先被清零的數(shù)據(jù)區(qū)定位在預(yù)先被初始化的數(shù)據(jù)區(qū)之后。
          #- 注意數(shù)據(jù)區(qū)的位置 :
          #- I如果用 ARM SDT, 當(dāng)鏈接器選擇no -rw-base時, 數(shù)據(jù)區(qū)被映射在代碼區(qū)之后
          #- 你可以把數(shù)據(jù)區(qū)房子內(nèi)部的SRAM( -rw-base=0x40 or 0x34)中
          #- 或者放在外部的SRAM( -rw-base=0x2000000 )中。
          #- 注意:為了提高代碼的密度,預(yù)先被初始化的數(shù)據(jù)必須盡可能的少。
          #------------------------------------------------------------------------------
          #該部分程序功能:先判斷當(dāng)前是在RAM中運行還是在FLASH中運行,如果在FLASH中運行,先把FLASH
          #中的預(yù)先賦值的RW段數(shù)據(jù)和未賦值的ZI段數(shù)據(jù)都搬移到RAM區(qū)中,再把ZI段數(shù)據(jù)全部清零;如果程#序就是在RAM中運行,則直接把ZI段數(shù)據(jù)清零。
          .extern Image_RO_Limit /* ROM區(qū)中數(shù)據(jù)段的起始地址*/
          .extern Image_RW_Base /* RW段起始地址 */
          .extern Image_ZI_Base /* ZI段的起始地址*/
          .extern Image_ZI_Limit /* ZI段的結(jié)束地址加1 */

          ldr r0, =Image_RO_Limit /* 取ROM區(qū)中數(shù)據(jù)段的首地址 */
          ldr r1, =Image_RW_Base /* 取RAM區(qū)中RW段的目標(biāo)首地址*/
          ldr r3, =Image_ZI_Base /*取RAM區(qū)中ZI段的首地址 */
          cmp r0, r1 /* 比較ROM區(qū)中數(shù)據(jù)段首地址和RAM區(qū)中RW段目標(biāo)首地址 */
          beq NoRW /*相等代表當(dāng)前是在RAM中運行*/
          LoopRw: cmp r1, r3 /*不相等則和RAM區(qū)中ZI段的目標(biāo)地址比較*/
          ldrcc r2, [r0], #4 /*如果r1 strcc r2, [r1], #4 /*如果r1 bcc LoopRw /*如果r1NoRW: ldr r1, =Image_ZI_Limit /* 取ZI段的結(jié)束地址 */
          mov r2, #0 /*將r2賦0*/
          LoopZI: cmp r3, r1 /* 將ZI段清零*/
          strcc r2, [r3], #4 /*如果r3 bcc LoopZI /*如果r3
          .extern Main /*聲明外部變量*/
          B Main /*t跳轉(zhuǎn)到用戶的主程序入口*/
          # 為每一種模式建立堆棧,ARM堆棧指針向下生長
          InitStack:
          MOV R1, LR //把該子程序返回地址保留在R1中

          LDR R0, =Top_Stack //取棧定地址到R0中
          #進(jìn)入未定義模式,并禁止FIQ中斷和IRQ中斷
          MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
          #設(shè)置未定義模式下堆棧的棧頂指針
          MOV SP, R0
          SUB R0, R0, #UND_Stack_Size #未定義模式下堆棧深度

          #進(jìn)入終止模式,并禁止禁止FIQ中斷和IRQ中斷
          MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
          #緊接著未定義模式下的堆棧,設(shè)置終止模式下棧頂指針
          MOV SP, R0
          SUB R0, R0, #ABT_Stack_Size #終止模式下堆棧深度

          #進(jìn)入FIQ模式,并禁止FIQ中斷和IRQ中斷
          MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
          #緊接著終止模式下的堆棧,設(shè)置下FIQ模式下棧頂指針
          MOV SP, R0
          SUB R0, R0, #FIQ_Stack_Size #FIQ模式下的堆棧深度

          #進(jìn)入IRQ模式,并禁止FIQ中斷和IRQ中斷
          MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
          #緊接著FIQ模式下的堆棧,設(shè)置IRQ模式下的棧頂指針
          MOV SP, R0
          SUB R0, R0, #IRQ_Stack_Size #IRQ模式下的堆棧深度

          #進(jìn)入超級用戶模式,并禁止FIQ中斷和IRQ中斷
          MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
          #緊接著IRQ模式下的堆棧,設(shè)置超級用戶下的棧頂指針
          MOV SP, R0
          SUB R0, R0, #SVC_Stack_Size #超級用戶下的堆棧深度

          #設(shè)置進(jìn)入用戶模式
          MSR CPSR_c, #Mode_USR
          #緊接著超級用戶模式下的堆棧,設(shè)置用戶模式下的棧頂指針,剩余的空間都開辟為堆棧
          MOV SP, R0

          MOV PC, R1 #堆棧初始化子程序返回
          # 重映射SRAM區(qū)
          RemapSRAM:

          MOV R0, #0x40000000 //RAM區(qū)首地址
          LDR R1, =Vectors //向量表首地址
          #下面一段程序是把從0x00000000開始的64個字節(jié)(FLASH中的中斷向量表和地址表)搬移到以
          #0x40000000為首地址的RAM區(qū)中
          LDMIA R1!, {R2-R9} //把以[R1]為首地址的32個字節(jié)數(shù)據(jù)裝載到R2-R9中
          STMIA R0!, {R2-R9} //把R2-R9中的數(shù)據(jù)存入以[R0]為首地址的單元中
          LDMIA R1!, {R2-R9} //把以[R1]為首地址的32個字節(jié)數(shù)據(jù)裝載到R2-R9中
          STMIA R0!, {R2-R9} ////把R2-R9中的數(shù)據(jù)存入以[R0]為首地址的單元中
          #下面幾行代碼設(shè)置存儲器映射控制寄存器
          LDR R0, =MEMMAP //取MEMMAP地址到R0
          MOV R1, #0x02
          STR R1, [R0] //給MEMMAP賦值為0x02,設(shè)置中斷向量從RAM區(qū)從新映射

          mov pc, lr //跳轉(zhuǎn)到主程序

          #下面一段程序代碼是進(jìn)入軟中斷來切換系統(tǒng)的工作模式,當(dāng)希望從一種模式切換入另一種模式時,可以通
          #過調(diào)用下面對應(yīng)標(biāo)號的程序段進(jìn)入軟中斷。在軟中斷處理程序中會根據(jù)所給定的中斷號處理,執(zhí)行SWI #num后軟中斷號被存入R0中。
          .globl disable_IRQ
          .globl restore_IRQ
          .globl ToSys
          .globl ToUser

          # 禁止IRQ

          disable_IRQ:
          STMFD SP!, {LR} //把LR值壓入堆棧
          swi #0 //產(chǎn)生0號軟中斷, 0 -〉R0
          LDMFD SP!, {pc} //恢復(fù)PC值,返回

          # 恢復(fù)IRQ

          restore_IRQ:
          STMFD SP!, {LR} //把LR值壓入堆棧
          swi #1 //產(chǎn)生1號軟中斷,1 –〉R0
          LDMFD SP!, {pc} //恢復(fù)PC值,返回

          #進(jìn)入系統(tǒng)工作模式

          ToSys:
          STMFD SP!, {LR} //把LR值壓入堆棧
          swi #11 //產(chǎn)生11號軟中斷,11 –〉R0
          LDMFD SP!, {pc} //恢復(fù)PC值,返回

          # 進(jìn)入用戶工作模式

          ToUser:
          STMFD SP!, {LR} //把LR值壓入堆棧
          swi #12 //產(chǎn)生12號軟中斷,11 –〉R0
          LDMFD SP!, {pc} //恢復(fù)PC值,返回


          關(guān)鍵詞: ARM啟動代碼LPC2xxx系

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();