在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<menu id="6qfwx"><li id="6qfwx"></li></menu>
    1. <menu id="6qfwx"><dl id="6qfwx"></dl></menu>

      <label id="6qfwx"><ol id="6qfwx"></ol></label><menu id="6qfwx"></menu><object id="6qfwx"><strike id="6qfwx"><noscript id="6qfwx"></noscript></strike></object>
        1. <center id="6qfwx"><dl id="6qfwx"></dl></center>

            新聞中心

            EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 周立功lpc21xx/lpc22xx系列ARM7啟動代碼分析

            周立功lpc21xx/lpc22xx系列ARM7啟動代碼分析

            作者: 時間:2016-11-10 來源:網絡 收藏
            網上已經有人做了一個周立功lpc2000(ARM7TDMI)啟動代碼分析的文章, 我本來想做一個s3c2410(ARM920T)的啟動代碼分析的, 但是看來了一下2410的啟動代碼,發(fā)現有些東西還不是理解的很清楚, 我ARM9的經驗比較少.

            所以還是做一個ARM7的啟動代碼分析吧, 網上那一份相比,我這個主要關注startup.s文件.網上那個startup.s幾乎是一筆帶過的.

            本文引用地址:http://www.biyoush.com/article/201611/317260.htm

            紅色標記的是源碼.

            SVC_STACK_LEGTH EQU 0

            FIQ_STACK_LEGTH EQU 0

            IRQ_STACK_LEGTH EQU 256

            ABT_STACK_LEGTH EQU 0

            UND_STACK_LEGTH EQU 0

            NoInt EQU 0x80

            USR32Mode EQU 0x10

            SVC32Mode EQU 0x13

            SYS32Mode EQU 0x1f

            IRQ32Mode EQU 0x12

            FIQ32Mode EQU 0x11

            上面幾行代碼,不用過多分析, 定義幾個符號而已, 把EQU想像成C中的#define就可以了. 具體定義的數值,下面的代碼用到我再解釋.

            IMPORT __use_no_semihosting_swi

            上面這一句的作用是在代碼中禁用 semihosting 機制. 到底什么是semihostiong這里不多說, 網上有很多. 這里只說明Semihosting主要用來調試, 在release版本的代碼中一般是要禁用的.

            IMPORT FIQ_Exception

            IMPORT __main

            IMPORT TargetResetInit

            上面三行是把要引入的外部標號聲明一下,以便下面使用.

            EXPORT bottom_of_heap

            EXPORT StackUsr

            EXPORT Reset

            EXPORT __user_initial_stackheap

            上面四行是把要給其它文件使用的標號聲明

            AREA vectors,CODE,READONLY

            ENTRY

            上面這一行聲明匯編文件的入口, 整個文件是從這里開始執(zhí)行的.

            Reset

            LDR PC, ResetAddr

            LDR PC, UndefinedAddr

            LDR PC, SWI_Addr

            LDR PC, PrefetchAddr

            LDR PC, DataAbortAddr

            DCD 0xb9205f80

            LDR PC, [PC, #-0xff0]

            LDR PC, FIQ_Addr

            上面幾行是配置中斷向量表. 中斷向量表的順序是不能變的,因為這是ARM7規(guī)定的,可以參考相關書籍. 這里有幾個問題要說明一下.

            第一, 關于DCD 0xb9205f80, 按照ARM7的中斷向量表分布圖, 這個位置是個保留位. 但是究竟為什么要用0xb9205f80這個數值呢.

            根據周立功的說法, nxp系列的lpc21xx,lpc22xx片子要求"中斷向量表中所有數據32位累加和為0,否則程序不能脫機運行", 我在AXD反匯編了一下(如下圖),把中斷向量表中的8個機器碼累加了一下:0xe59ff018*6+0xe51ffff0+0xb9205f80,沒錯, 結果是零. 但是我遇到一個問題, 就是我在實驗中,把0xb9205f80這個數值改成任何值,程序運行都沒問題. 頭大了, 這個問題待解決中……(希望高手看到了可以指點一二).

            第二,關于LDR PC, [PC, #-0xff0].這里本應該放IRQ中斷的, 為什么是這么一句話. 其實在我blog的其中一篇文章里有提到過這一點.

            ARM7的三級流水線結構導致了PC指向的是當前指令的后8個字節(jié). 本來IRQ是應該放在0x00000018處的. LDR PC, [PC, #-0xff0]這條語句執(zhí)行后, PC的當前值就是0x00000018+8-0xff0. 很容易計算出它的結果是0xfffff030. 看一下lpc22xx的手冊就知道. 這個地址就是VICVectAddr. 也就是說本來這個地址是應該放IRQ服務程序的入口地址的,但是這個地址被放在了VICVectAddr 這個寄存器里. 英文手冊里有一段對VICVectAddr 描述. 看了之后就容易明白是怎么回事了: Vector Address Register. When an IRQ interrupt occurs, the IRQ service routine can read this register and jump to the value read

            ResetAddr DCD ResetInit

            UndefinedAddr DCD Undefined

            SWI_Addr DCD SoftwareInterrupt

            PrefetchAddr DCD PrefetchAbort

            DataAbortAddr DCD DataAbort

            Nouse DCD 0

            IRQ_Addr DCD 0

            FIQ_Addr DCD FIQ_Handler

            這幾行是為上面中斷向量表中的中斷標號分配內存空間, 也就是它們的執(zhí)行地址. 一開始我有個疑問, 為什么不直接用LDR PC, ResetInit,還要用DCD中轉一下, 后來上網查了一下,才恍然大悟, ldr指令中的地址必須為當前指令地址是4KB范圍內, 用DCD中轉一下就可以在整個程序空間尋址.

            Undefined

            B Undefined

            SoftwareInterrupt

            B SoftwareInterrupt

            PrefetchAbort

            B PrefetchAbort

            DataAbort

            B DataAbort

            FIQ_Handler

            STMFD SP!, {R0-R3, LR}

            BL FIQ_Exception

            LDMFD SP!, {R0-R3, LR}

            SUBS PC, LR, #4

            這幾行不用過多解釋, 只是說明上面幾個異常如何執(zhí)行.

            InitStack

            MOV R0, LR

            ;設置管理模式堆棧

            MSR CPSR_c, #0xd3

            LDR SP, StackSvc

            ;設置中斷模式堆棧

            MSR CPSR_c, #0xd2

            LDR SP, StackIrq

            ;設置快速中斷模式堆棧

            MSR CPSR_c, #0xd1

            LDR SP, StackFiq

            ;設置中止模式堆棧

            MSR CPSR_c, #0xd7

            LDR SP, StackAbt

            ;設置未定義模式堆棧

            MSR CPSR_c, #0xdb

            LDR SP, StackUnd

            ;設置系統(tǒng)模式堆棧

            MSR CPSR_c, #0xdf

            LDR SP, =StackUsr

            MOV PC, R0

            上面是一個子函數, 函數名為InitStack. 顧名思意, 這個函數設置ARM七種工作模式下的堆棧. 關于這一段代碼有三點要說.

            第一,MSR CPSR_c, #0xdf, 這一句把ARM的工作模式設置為系統(tǒng)模式,或者也可以說是用戶模式, 因為系統(tǒng)模式與用戶模式是共享相同的寄存器組. 用0xdf對CPSR寄存器賦值,就把IRQ中斷關閉了(可以查一下CRSR的詳細說明), 代碼正常執(zhí)行時處理器是處在用戶模式的,所以IRQ中斷是不會執(zhí)行的. 所以,如果用周立功的這個啟動代碼,當你的程序中需要中斷時,要把0xdf改成0x5f. 之前看到很多人在網上說用周立功的ADS工程模板,進不了中斷,很多情況下是這個原因.

            第二, 并不是每一種模式下的堆棧都用設置的, 比如說如果你的程序中不會用到FIQ,就可以不用設置快速中斷下的堆棧.

            第三, 注意LDR SP, =StackUsr這個語句, 其它都是沒有=號的, 為什么這個要用等號呢? 這就是LDR偽指令與LDR指令的區(qū)別了,LDR SP, =StackUsr是把StackUsr表示的地址裝載到sp,LDR SP, StackUnd是把StackUnd表示地址的內容裝載到sp,注意下面幾句

            StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4

            StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4

            StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4

            StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4

            StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4

            可以看到,沒有”=”的標號都已經用DCD初始化了, 而StackUsr到底是什么呢, 它是由下面的語句決定的

            (startup.s文件)

            AREA Stacks, DATA, NOINIT

            StackUsr

            (分散加載文件)

            STACKS 0x40002000 UNINIT

            {

            Startup.o (Stacks)

            }

            這樣就明白了, StackUsr肯定是0x40000000~0x400020000之間的某個數. 用戶模式下的堆??臻g就是它了.

            ResetInit

            BL InitStack

            BL TargetResetInit

            B __main

            處理器上電復位后通過中斷向量表進入該函數,__main函數主要工作是初始化C的庫函數, 并由它進入C的main函數.

            __user_initial_stackheap

            LDR r0,=bottom_of_heap

            ; LDR r1,=StackUsr

            MOV pc,lr

            __user_initial_stackheap函數是ADS的一個庫函數, 如果程序中用到的分散加載文件, 這個函數必須要被實現. 應用程序的棧和heap是在C庫函數初始化過程中建立起來的??梢酝ㄟ^重定向對應的子程序來改變堆棧和heap的位置. 堆棧的地址在分散加載文件里已經指定好,本函數不應該修改它們的值. 用r0,r1分別返回heap和stack的基址. 關于ADS的存儲器機制大家可以去網上查更詳細的資料.

            StackSvc DCD SvcStackSpace + (SVC_STACK_LEGTH - 1)* 4

            StackIrq DCD IrqStackSpace + (IRQ_STACK_LEGTH - 1)* 4

            StackFiq DCD FiqStackSpace + (FIQ_STACK_LEGTH - 1)* 4

            StackAbt DCD AbtStackSpace + (ABT_STACK_LEGTH - 1)* 4

            StackUnd DCD UndtStackSpace + (UND_STACK_LEGTH - 1)* 4

            AREA MyStacks, DATA, NOINIT, ALIGN=2

            SvcStackSpace SPACE SVC_STACK_LEGTH * 4 ;Stack spaces for Administration Mode

            IrqStackSpace SPACE IRQ_STACK_LEGTH * 4 ;Stack spaces for Interrupt ReQuest Mode

            FiqStackSpace SPACE FIQ_STACK_LEGTH * 4 ;Stack spaces for Fast Interrupt reQuest Mode

            AbtStackSpace SPACE ABT_STACK_LEGTH * 4 ;Stack spaces for Suspend Mode

            UndtStackSpace SPACE UND_STACK_LEGTH * 4 ;Stack spaces for Undefined Mode

            上面幾行代碼是為各個模式下的堆棧分配空間. 其中MyStacksA的位置會在分散加載文件中指定.

            IF :DEF: EN_CRP

            IF . >= 0x1fc

            INFO 1,"nThe data at 0x000001fc must be 0x87654321.nPlease delete some source before this line."

            ENDIF

            CrpData

            WHILE . < 0x1fc

            NOP

            WEND

            CrpData1

            DCD 0x87654321 ;/*When the Data is 為0x87654321,user code be protected. 當此數為0x87654321時,用戶程序被保護 */

            ENDIF

            上面這幾行其實是加密芯片用的, lpc21xx和lpc22xx系列的ARM7,當你的工程選擇RelInFlash時, 代碼寫進flash,芯片也同時被加密, 加密狀態(tài)下JTAG也讀不到芯片, 也不能單步調試, 要解密的話必須要用ISP完全擦除一下. 上面的代碼的意思就是在地址0x1fc處放數據0x87654321, 從而實現加密的功能, 但前提是IF :DEF: EN_CRP, 也就是定義了EN_CPP這個宏. 而這個宏是在當選擇了RelInFlash時ADS自動定義的. 然后,再說一下0x87654321的問題. LPC2100 系列ARM7微控制器是世界首款可加密的ARM芯片,對其加密的方法是通過用戶程序在指定地址上設置規(guī)定的數據。PHILIPS公司規(guī)定,對于 LPC2100芯片(除LPC2106/2105/2104外),當片內FLASH地址0x000001FC處的數據為0x87654321時,芯片即被加密. 所以問題搞定.



            評論


            技術專區(qū)

            關閉