ARM處理器系統(tǒng)初始化過程_第1頁(yè)
ARM處理器系統(tǒng)初始化過程_第2頁(yè)
ARM處理器系統(tǒng)初始化過程_第3頁(yè)
ARM處理器系統(tǒng)初始化過程_第4頁(yè)
ARM處理器系統(tǒng)初始化過程_第5頁(yè)
已閱讀5頁(yè),還剩56頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、ARM處理器系統(tǒng)初始化過程 1 禁止MMU,關(guān)閉中斷,禁止cache;2 根據(jù)硬件設(shè)計(jì)配制好處理器時(shí)鐘、DRAM時(shí)鐘、定時(shí)器時(shí)鐘;3 根據(jù)系統(tǒng)中所用的flash和DRAM芯片容量和電氣參數(shù)設(shè)置它們的起始地址、容量、刷新頻率等;4 將固化在flash芯片中的程序搬移到DRAM內(nèi)存中;5 使能cache,使能MMU,跳轉(zhuǎn)到DRAM內(nèi)存中運(yùn)行繼續(xù)初始化,包括根據(jù)具體應(yīng)用以及系統(tǒng)中的硬件配置初始化各個(gè)功能模塊、安裝好異 常中斷處理程序、使能中斷等;6 進(jìn)行操作系統(tǒng)相關(guān)初始化;禁止MMU,關(guān)閉中斷,禁止cache通過寫系統(tǒng)控制協(xié)處理器的寄存器1 的第0 位可以允許和禁止MMU。在復(fù)位后這位是0,MMU

2、被禁止。關(guān)閉中斷與打開中斷中斷是一種高效的對(duì)話機(jī)制,但有時(shí)并不想程序運(yùn)行的過程中中斷運(yùn)行,比如正在打印東西,但程序突然中斷了,又讓另外一個(gè)程序輸出打印內(nèi)容,這樣在打印機(jī)上就會(huì)亂得不得了,同時(shí)有兩份以上的文件交錯(cuò)地打印在一張紙上。像不可剝奪的資源,就一定要關(guān)閉中斷,讓它占有這個(gè)資源。在ARM里,沒有像x86那樣有清除中斷指令CLI。那么在ARM里是怎么樣實(shí)現(xiàn)關(guān)中斷和開中斷的呢?下面就來看看ARM的關(guān)中斷和開中斷實(shí)現(xiàn)。void Lock(void)stmdbsp!, r0mrsr0, cpsrorr r0,r0,#0xC0msr cpsr_cxsf,r0ldmia sp!,r0上面這段程序是通過設(shè)

3、置CPSR的第6,7位來實(shí)現(xiàn)的,因?yàn)榈?,7位是設(shè)置為1時(shí),就不再響應(yīng)中斷。void UnLock(void)stmdbsp!, r0mrsr0, cpsrbic r0,r0,#0xC0msr cpsr_cxsf,r0ldmia sp!,r0上面是重新開中斷的命令,同樣是設(shè)置CPSR的第6,7位,但它的值是0,就可接收中斷了。如果在多個(gè)任務(wù)之間進(jìn)行共享數(shù)據(jù),一般是需要使用關(guān)中斷和開中斷實(shí)現(xiàn)數(shù)據(jù)同步的,其實(shí)中這種關(guān)中斷和開中斷,就是進(jìn)入臨界區(qū)和退出臨界區(qū)。如果是像PC機(jī)那樣有多個(gè)CPU的話,關(guān)中斷并不能防止這種情況。系統(tǒng)的在應(yīng)用編程(IAP)以及在系統(tǒng)編程功能(ISP)等。中斷向量表ARM要求中

4、斷向量表必須放置在從0地址開始,連續(xù)8X4字節(jié)的空間內(nèi)。每當(dāng)一個(gè)中斷發(fā)生以后,ARM處理器便強(qiáng)制把PC指針置為向量表中對(duì)應(yīng)中斷類型的地址值。因?yàn)槊總€(gè)中斷只占據(jù)向量表中1個(gè)字的存儲(chǔ)空間,只能放置一條ARM指令,使程序跳轉(zhuǎn)到存儲(chǔ)器的其他地方,再執(zhí)行中斷處理。中斷向量表的程序?qū)崿F(xiàn)通常如下表示:AREA Boot ,CODE, READONLYENTRYB ResetHandlerB UndefHandlerB SWIHandlerB PreAbortHandlerB DataAbortHandlerBB IRQHandlerB FIQHandler其中關(guān)鍵字ENTRY是指定編譯器保留這段代碼,因?yàn)榫?/p>

5、譯器可能會(huì)認(rèn)為這是一段亢余代碼而加以優(yōu)化。鏈接的時(shí)候要確保這段代碼被鏈接在0地址處,并且作為整個(gè)程序的入口。Q:為什么在中斷向量表中不直接LDR PC,異常地址.而是使用一個(gè)標(biāo)號(hào),然有再在后面使用DCD定義這個(gè)標(biāo)號(hào)A:因?yàn)長(zhǎng)DR指令只能跳到當(dāng)前PC 4kB范圍內(nèi),而B指令能跳轉(zhuǎn)到32MB范圍,而現(xiàn)在這樣在LDR PC, xxxx這條指令不遠(yuǎn)處用xxxxDCD定義一個(gè)字,而這個(gè)字里面存放最終異常服務(wù)程序的地址,這樣可以實(shí)現(xiàn)4GB全范圍跳轉(zhuǎn).Q: LDR 不是可以全空間跳轉(zhuǎn)的嗎 ARM微控制器基礎(chǔ)與實(shí)戰(zhàn)程序清單5.3.A: LDR偽指令通過設(shè)置指令緩沖池才能實(shí)現(xiàn)全范圍跳轉(zhuǎn),而LDR指令則只能實(shí)現(xiàn)4

6、KB范圍跳轉(zhuǎn).MEMMAP=0:開機(jī)默認(rèn)值,Boot裝載模式-向量表(0x00000000-0x0000003c)映射的是BootBlock中的0x7FFFE000-0x7FFFF03c中的值;芯片復(fù)位時(shí),啟動(dòng)boot裝載程序,boot裝載程序檢查P0.14口的狀態(tài)和用戶的異常向量,判斷是進(jìn)入ISP狀態(tài)還是啟動(dòng)用戶程序,若啟動(dòng)用戶程序,則自動(dòng)設(shè)置MEMMAP=1(片內(nèi)flash啟動(dòng))或3(片外程序存儲(chǔ)器啟動(dòng))。很奇怪的,我在實(shí)驗(yàn)中,當(dāng)使用無片內(nèi)flash的LPC2210時(shí)即使設(shè)置P0.14為高低都沒關(guān)系,芯片會(huì)跳過繼而執(zhí)行片外flash中的代碼. MEMMAP=1:中斷向量表就在片內(nèi)flash

7、中,地址就是0x00000000-0x0000003c,相當(dāng)于沒有映射;MEMMAP=2:最為主要的設(shè)置,即是重映射的關(guān)鍵之所在,當(dāng)設(shè)置MEMMAP=2 時(shí),中斷向量表(0x00000000-0x0000003c)映射的是片內(nèi)SRAM中的0x40000000-0x4000003c中的值,而因?yàn)槭荢RAM,所以在程序運(yùn)行的過程中是可以改變的,這樣就可以達(dá)到重映射的目的啦(中斷向量表可以隨時(shí)修改)。 MEMMAP=3:中斷向量表就在片外flash中,中斷向量表(0x00000000-0x0000003c)映射到是片外flash中的0x80000000-0x8000003c中的值;功能上與MEMMA

8、P=1時(shí)的差不多,因?yàn)橐坏┏绦蚬袒絝lash中,即為只讀,只是數(shù)值映射而已!設(shè)置MEMMAP; Memory Mapping (when Interrupt Vectors are in RAM)MEMMAP EQU 0xE01FC040 ; Memory Mapping Control IF :DEF:REMAP LDR R0, =MEMMAP IF :DEF:EXTMEM_MODE MOV R1, #3 ELIF :DEF:RAM_MODE MOV R1, #2 ELSE MOV R1, #1 ENDIF STR R1, R0 ENDIFMEMMAP有兩個(gè)控制位 MEMMAP1:000

9、BOOT裝載程序模式01 User FLASH模式10 用戶RAM模式11 用戶外部存儲(chǔ)器模式10模式也就是RAM模式 我們?cè)L問地址0X00是跟訪問RAM地址0X40000000中的數(shù)據(jù)是完全一樣的 向RAM中寫進(jìn)數(shù)據(jù) 然后通過數(shù)據(jù)窗口觀察0X0地址的變化 應(yīng)該是同步變化的存儲(chǔ)器類型和時(shí)序配置 主要是對(duì)系統(tǒng)存儲(chǔ)器控制器(MMU)的初始化。由于存儲(chǔ)器控制器并不是ARM架構(gòu)的一部分,不同芯片的實(shí)現(xiàn)方式各不相同。由于運(yùn)算能力和尋址能力的強(qiáng)大,基于ARM內(nèi)核的微處理器系統(tǒng)一般都需要外擴(kuò)展各種類型的存儲(chǔ)器。對(duì)于存儲(chǔ)器系統(tǒng)的初始化一般包括如下幾個(gè)方面:存儲(chǔ)器類型、時(shí)序和總線寬度的配置存儲(chǔ)器地址的配置(1)

10、存儲(chǔ)器類型 基于ARM微處理系統(tǒng)的存儲(chǔ)器一般有如下幾類:SARM,DRAM,Flah,同時(shí),即使同類存儲(chǔ)器也有訪問速度上的不同。其中,SRAM和Flah屬于靜態(tài)存儲(chǔ)器,可以共用存儲(chǔ)器端口,而DRAM有動(dòng)態(tài)刷新和地址復(fù)用等特征,需要專門的存儲(chǔ)器端口。(2)時(shí)序 存儲(chǔ)器端口的接口時(shí)序優(yōu)化對(duì)系統(tǒng)性能影響非常大,因?yàn)橄到y(tǒng)運(yùn)行的速度瓶頸一般都存在于存儲(chǔ)器的訪問,因此希望存儲(chǔ)器的訪問盡可能快,但又要考慮由此帶來的系統(tǒng)穩(wěn)定性問題。(3)總線寬度 ARM微處理器架構(gòu)支持8/16/32位的數(shù)據(jù)總線寬度訪問存儲(chǔ)器和外設(shè),對(duì)于特定的存儲(chǔ)器來說,需要設(shè)定數(shù)據(jù)總線的寬度。(4)存儲(chǔ)器地址的配置 ARM微處理器架構(gòu)理論上

11、可以支持4GB的地址空間,而對(duì)于一個(gè)實(shí)際的系統(tǒng)來說,配置的物理地址遠(yuǎn)沒有這么多,因此,如何配置存儲(chǔ)器的地址,也是一個(gè)重要的問題。(5)存儲(chǔ)器地址重映射 存儲(chǔ)器地址重映射就是可以通過軟件配置來改變一塊存儲(chǔ)器物理地址的方法,是當(dāng)前許多先進(jìn)控制器所具有的功能。進(jìn)行地址重映射的原因:提高系統(tǒng)的運(yùn)行效率。進(jìn)行地址重映射的注意:保證程序流程的連續(xù)性。有的ARM處理器不具有地址重映射的功能,可以采樣代碼搬移加跳轉(zhuǎn)的方式完成上述功能。初始化堆棧因 為ARM有7種執(zhí)行狀態(tài),每一種狀態(tài)的堆棧指針寄存器(SP)都是獨(dú)立的。因此,對(duì)程序中需要用到的每一種模式都要給SP定義一個(gè)堆棧地址。方法是改變狀 態(tài)寄存器內(nèi)的狀態(tài)位

12、,使處理器切換到不同的狀態(tài),讓后給SP賦值。注意:不要切換到User模式進(jìn)行User模式的堆棧設(shè)置,因?yàn)檫M(jìn)入U(xiǎn)ser模式后就不 能再操作CPSR回到別的模式了,可能會(huì)對(duì)接下去的程序執(zhí)行造成影響。這是一段堆棧初始化的代碼示例,其中只定義了三種模式的SP指針:MRS R0,CPSRBIC R0,R0,#MODEMASK 安全起見,屏蔽模式位以外的其他位ORR R1,R0,#IRQMODEMSR CPSR_cxfs,R1LDR SP,=UndefStackORR R1,R0,#FIQMODEMSR CPSR_cxsf,R1LDR SP,=FIQStackORR R1,R0,#SVCMODEMSR C

13、PSR_cxsf,R1LDR SP,=SVCStack初始化應(yīng)用程序執(zhí)行環(huán)境如果使用分散加載描述文件調(diào)整堆棧和堆放置,則鏈接器創(chuàng)建 _user_initial_stackheap() 函數(shù),并使用鏈接器定義的符號(hào)作為這些區(qū)域的名稱。映像一開始總是存儲(chǔ)在ROMFlash里面的,其RO部分即可以在ROMFlash里面執(zhí)行,也可以轉(zhuǎn)移到速度更快的RAM中執(zhí)行;而RW和 ZI這兩部分是必須轉(zhuǎn)移到可寫的RAM里去。所謂應(yīng)用程序執(zhí)行環(huán)境的初始化,就是完成必要的從ROM到RAM的數(shù)據(jù)傳輸和內(nèi)容清零。下面是在ADS下,一種常用存儲(chǔ)器模型的直接實(shí)現(xiàn):LDR r0,=|Image$RO$Limit| 得到RW數(shù)據(jù)

14、源的起始地址LDR r1,=|Image$RW$Base| RW區(qū)在RAM里的執(zhí)行區(qū)起始地址LDR r2,=|Image$ZI$Base| ZI區(qū)在RAM里面的起始地址CMP r0,r1 比較它們是否相等BEQ %F10 CMP r1,r3LDRCC r2,r0,#4STRCC r2,r1,#4BCC %B01 LDR r1,=|Image$ZI$Limit|MOV r2,#02 CMP r3,r1STRCC r2,r3,#4BCC %B2程序?qū)崿F(xiàn)了RW數(shù)據(jù)的拷貝和ZI區(qū)域的清零功能。其中引用到的4個(gè)符號(hào)是由鏈接器第一輸出的。|Image$RO$Limit|:表示RO區(qū)末地址后面的地址,即RW

15、數(shù)據(jù)源的起始地址|Image$RW$Base|:RW區(qū)在RAM里的執(zhí)行區(qū)起始地址,也就是編譯器選項(xiàng)RW_Base指定的地址|Image$ZI$Base|:ZI區(qū)在RAM里面的起始地址|Image$ZI$Limit|:ZI區(qū)在RAM里面的結(jié)束地址后面的一個(gè)地址程 序先把ROM里|Image$RO$Limt|開始的RW初始數(shù)據(jù)拷貝到RAM里面|Image$RW$Base|開始的地址,當(dāng)RAM這邊的目 標(biāo)地址到達(dá)|Image$ZI$Base|后就表示RW區(qū)的結(jié)束和ZI區(qū)的開始,接下去就對(duì)這片ZI區(qū)進(jìn)行清零操作,直到遇到結(jié)束地 址|Image$ZI$Limit|改變處理器模式因?yàn)樵诔跏蓟^程中,許多操

16、作需要在特權(quán)模式下才能進(jìn)行(比如對(duì)CPSR的修改),所以要特別注意不能過早的進(jìn)入用戶模式。內(nèi)核級(jí)的中斷使能也可以考慮在這一步進(jìn)行。如果系統(tǒng)中另外存在一個(gè)專門的中斷控制器,這么做總是安全的。呼叫主應(yīng)用程序當(dāng)所有的系統(tǒng)初始化工作完成之后,就需要把程序流程轉(zhuǎn)入主應(yīng)用程序。最簡(jiǎn)單的一種情況是:IMPORT mainB main直接從啟動(dòng)代碼跳轉(zhuǎn)到應(yīng)用程序的主函數(shù)入口,當(dāng)然主函數(shù)名字可以由用戶隨便定義。在ARM ADS環(huán)境中,還另外提供了一套系統(tǒng)級(jí)的呼叫機(jī)制。IMPORT _mainB _main_main()是編譯系統(tǒng)提供的一個(gè)函數(shù),負(fù)責(zé)完成庫(kù)函數(shù)的初始化和初始化應(yīng)用程序執(zhí)行環(huán)境,最后自動(dòng)跳轉(zhuǎn)到mai

17、n()函數(shù)。ARM 介紹ARM微處理器的工作狀態(tài)一般有兩種,并可在兩種狀態(tài)之間切換: 第一種為ARM狀態(tài),此時(shí)處理器執(zhí)行32位的字對(duì)齊的ARM指令; 第二種為Thumb狀態(tài),此時(shí)處理器執(zhí)行16位的、半字對(duì)齊的Thumb指令。 在程序的執(zhí)行過程中,微處理器可以隨時(shí)在兩種工作狀態(tài)之間切換,并且,處理器工作狀態(tài)的轉(zhuǎn)變并不影響處理器的工作模式和相應(yīng)寄存器中的內(nèi)容。但ARM微處理器在開始執(zhí)行代碼時(shí),應(yīng)該處于ARM狀態(tài)。 ARM處理器狀態(tài) 進(jìn) 入Thumb狀態(tài):當(dāng)操作數(shù)寄存器的狀態(tài)位(位0)為1時(shí),可以采用執(zhí)行BX指令的方法,使微處理器從ARM狀態(tài)切換到Thumb狀態(tài)。此外,當(dāng)處理器處 于Thumb狀態(tài)時(shí)

18、發(fā)生異常(如IRQ、FIQ、Undef、Abort、SWI等),則異常處理返回時(shí),自動(dòng)切換到Thumb狀態(tài)。 進(jìn)入ARM狀態(tài):當(dāng)操作數(shù)寄存器的狀態(tài)位為0時(shí),執(zhí)行BX指令時(shí)可以使微處理器從Thumb狀態(tài)切換到ARM狀態(tài)。此外,在處理器進(jìn)行異常處理時(shí),把PC指針放入異常模式鏈接寄存器中,并從異常向量地址開始執(zhí)行程序,也可以使處理器切換到ARM狀態(tài)。ARM處理器模式 ARM微處理器支持7種運(yùn)行模式,分別為: 用戶模式(usr):ARM處理器正常的程序執(zhí)行狀態(tài)。 快速中斷模式(fiq):用于高速數(shù)據(jù)傳輸或通道處理。 外部中斷模式(irq):用于通用的中斷處理。 管理模式(svc):操作系統(tǒng)使用的保護(hù)模

19、式。 數(shù)據(jù)訪問終止模式(abt):當(dāng)數(shù)據(jù)或指令預(yù)取終止時(shí)進(jìn)入該模式,可用于虛擬存儲(chǔ)及存儲(chǔ)保護(hù)。 系統(tǒng)模式(sys):運(yùn)行具有特權(quán)的操作系統(tǒng)任務(wù)。 定義指令中止模式(und):當(dāng)未定義的指令執(zhí)行時(shí)進(jìn)入該模式,可用于支持硬件協(xié)處理器的軟件仿真。 ARM處理器模式 ARM微處理器的運(yùn)行模式可以通過軟件改變,也可以通過外部中斷或異常處理改變。大多數(shù)的應(yīng)用程序運(yùn)行在用戶模式下,當(dāng)處理器運(yùn)行在用戶模式下時(shí),某些被保護(hù)的系統(tǒng)資源是不能被訪問的。 除用戶模式以外,其余的所有6種模式稱之為非用戶模式,或特權(quán)模式;其中除去用戶模式和系統(tǒng)模式以外的5種又稱為異常模式,常用于處理中斷或異常,以及需要訪問受保護(hù)的系統(tǒng)資

20、源等情況。 ARM寄存器 ARM處理器共有37個(gè)寄存器。其中包括:31個(gè)通用寄存器,包括程序計(jì)數(shù)器(PC)在內(nèi)。這些寄存器都是32位寄存器。以及6個(gè)32位狀態(tài)寄存器。 關(guān)于寄存器這里就不詳細(xì)介紹了,有興趣的人可以上網(wǎng)找找,很多這方面的資料。 異常處理 當(dāng) 正常的程序執(zhí)行流程發(fā)生暫時(shí)的停止時(shí),稱之為異常,例如處理一個(gè)外部的中斷請(qǐng)求。在處理異常之前,當(dāng)前處理器的狀態(tài)必須保留,這樣當(dāng)異常處理完成之后,當(dāng) 前程序可以繼續(xù)執(zhí)行。處理器允許多個(gè)異常同時(shí)發(fā)生,它們將會(huì)按固定的優(yōu)先級(jí)進(jìn)行處理。當(dāng)一個(gè)異常出現(xiàn)以后,ARM微處理器會(huì)執(zhí)行以下幾步操作: 進(jìn)入異常處理的基本步驟: 將下一條指令的地址存入相應(yīng)連接寄存器

21、LR,以便程序在處理異常返回時(shí)能從正確的位置重新開始執(zhí)行。將CPSR復(fù)制到相應(yīng)的SPSR中。根據(jù)異常類型,強(qiáng)制設(shè)置CPSR的運(yùn)行模式位。 強(qiáng)制PC從相關(guān)的異常向量地址取下一條指令執(zhí)行,從而跳轉(zhuǎn)到相應(yīng)的異常處理程序處。如果異常發(fā)生時(shí),處理器處于Thumb狀態(tài),則當(dāng)異常向量地址加載入PC時(shí),處理器自動(dòng)切換到ARM狀態(tài)。 ARM微處理器對(duì)異常的響應(yīng)過程用偽碼可以描述為: R14_ = Return Link SPSR_= CPSR CPSR4:0 = Exception Mode Number CPSR5 = 0 ;當(dāng)運(yùn)行于 ARM 工作狀態(tài)時(shí) If = Reset or FIQ then;當(dāng)響應(yīng)

22、FIQ 異常時(shí),禁止新的 FIQ 異常 CPSR6 = 1 PSR7 = 1 PC = Exception Vector Address 異常處理完畢之后,ARM微處理器會(huì)執(zhí)行以下幾步操作從異常返回: 將連接寄存器LR的值減去相應(yīng)的偏移量后送到PC中。 將SPSR復(fù)制回CPSR中。 若在進(jìn)入異常處理時(shí)設(shè)置了中斷禁止位,要在此清除每一種異常模式擁有自己的物理的R13。應(yīng)用程序初始化該R13,使其指向該異常模式專用的棧地址。當(dāng)進(jìn)入異常模式時(shí),可以將需要使用的寄存器保存在R13所指的棧中;當(dāng)退出異常處理程序時(shí),將保存在R13所指的棧中的寄存器值彈出。這樣就使異常處理程序不會(huì)破壞被其中斷程序的運(yùn)行現(xiàn)場(chǎng)

23、。1。請(qǐng)問cache和write-buffer的關(guān)系,在WB和cache同時(shí)打開的時(shí)候,數(shù)據(jù)是如何流動(dòng)的呢?考慮到WB的特性,是不是較大段的數(shù)據(jù)被寫入WB? WB的設(shè)計(jì)是為了防止處理器流水線被寫數(shù)據(jù)總線操作(寫主存,寫外圍設(shè)備寄存器等)拉住。典型寫數(shù)據(jù)總線時(shí)機(jī)有三種:一是cache處于write through策略下的寫操作;二是cache處于write back策略下,dirty數(shù)據(jù)由于cache行替換或者被程序主動(dòng)清空而寫回主存,三是不經(jīng)過cache,直接對(duì)數(shù)據(jù)總線的寫操作。有了WB之后,被寫 回?cái)?shù)據(jù)總線的內(nèi)容在進(jìn)入WB之后,處理器和cache就可以立刻繼續(xù)使用了。這就是WB和cache的

24、關(guān)系。2。還有就是所謂“cachable bit”和“bufferable bit”的問題,這個(gè)問題來自于arm-armpartB 的5.4節(jié),那里有一張表,我對(duì)這個(gè)表死活不理解。這個(gè)問題以前也問過,但是沒有人回答。ARM各系列的處理器上的cache設(shè)計(jì)有所不同,所以有的cache只有write through策略,有的cache只有write back策略,還有的cache是write back策略但允許一定的write through行為,因此C和B位的四種組合對(duì)這三種cache而言有不同的含義。第一列和第二列分別針對(duì)write through型cache和write back型cache

25、進(jìn)行解釋,其含義可以參考我對(duì)第1個(gè)問題的回答,第三列針對(duì)write back策略但允許一定的write through行為的cache,第一行好理解,第二行之所以在B位為0的情況下依然是bufferable,應(yīng)該是因?yàn)橛布系脑O(shè)計(jì)原因(節(jié)省硬件資源 或者由于目標(biāo)設(shè)計(jì)頻率限制),第三行的含義是,當(dāng)C=1,B=0時(shí),cache使用write through策略,WB開啟,第四行的含義是,當(dāng)C=1,B=1時(shí),cache使用write back策略,WB開啟。 可以看到,對(duì)第 三種類型的cache,C和B位不再“嚴(yán)格”是其本來控制cacheable和bufferable的含義,而是利用這兩位的“組合”

26、來控制cache和 WB的表現(xiàn)行為,這樣做比另外再增加一位來選擇cache的write back策略和write through策略硬件上節(jié)約了資源,效果上卻差不多,少了cache和WB幾種意義不大的組合,應(yīng)該說還是挺巧妙的。ARM啟動(dòng)代碼設(shè)計(jì)參考 收藏 基于ARM的芯片多數(shù)為復(fù)雜的片上系統(tǒng),這種復(fù)雜系統(tǒng)里的多數(shù)硬件模塊都是可配置的,需要由軟件來設(shè)置其需要的工作狀態(tài)。因此在用戶的應(yīng) 用程序之前,需要由專門的一段代碼來完成對(duì)系統(tǒng)的初始化。由于這類代碼直接面對(duì)處理器內(nèi)核和硬件控制器進(jìn)行編程,一般都是用匯編語言。一般通用的內(nèi)容包 括: 中斷向量表 初始化存儲(chǔ)器系統(tǒng) 初始化堆棧 初始化有特殊要求的斷口

27、,設(shè)備 初始化用戶程序執(zhí)行環(huán)境 改變處理器模式 呼叫主應(yīng)用程序 1.中斷向量表 ARM要求中斷向量表必須放置在從0地址開始,連續(xù)8X4字節(jié)的空間內(nèi)。 每當(dāng)一個(gè)中斷發(fā)生以后,ARM處理器便強(qiáng)制把PC指針置為向量表中對(duì)應(yīng)中斷類型的地址值。因?yàn)槊總€(gè)中斷只占據(jù)向量表中1個(gè)字的存儲(chǔ)空間,只能放置一條ARM指令,使程序跳轉(zhuǎn)到存儲(chǔ)器的其他地方,再執(zhí)行中斷處理。 中斷向量表的程序?qū)崿F(xiàn)通常如下表示: AREABoot,CODE,READONLY ENTRY BResetHandler BUndefHandler BSWIHandler BPreAbortHandler BDataAbortHandler B B

28、IRQHandler BFIQHandler 其中關(guān)鍵字ENTRY是指定編譯器保留這段代碼,因?yàn)榫幾g器可能會(huì)認(rèn)為這是一段亢余代碼而加以優(yōu)化。鏈接的時(shí)候要確保這段代碼被鏈接在0地址處,并且作為整個(gè)程序的入口。 2.初始化存儲(chǔ)器系統(tǒng) (1)存儲(chǔ)器類型和時(shí)序配置 通常Flash和SRAM同屬于靜態(tài)存儲(chǔ)器類型,可以合用同一個(gè)存儲(chǔ)器端口;而DRAM因?yàn)橛袆?dòng)態(tài)刷新和地址線復(fù)用等特性,通常配有專用的存儲(chǔ)器端口。 存儲(chǔ)器端口的接口時(shí)序優(yōu)化是非常重要的,這會(huì)影響到整個(gè)系統(tǒng)的性能。因?yàn)橐话阆到y(tǒng)運(yùn)行的速度瓶頸都存在于存儲(chǔ)器訪問,所以存儲(chǔ)器訪問時(shí)序應(yīng)盡可能的快;而同時(shí)又要考慮到由此帶來的穩(wěn)定性問題。 (2)存儲(chǔ)器地址

29、分布 一種典型的情況是啟動(dòng)ROM的地址重映射。3.初始化堆棧 因?yàn)锳RM有7種執(zhí)行狀態(tài),每一種狀態(tài)的堆棧指針寄存器(SP)都是獨(dú)立的。因此,對(duì)程序中需要用到的每一種模式都要給SP 定義一個(gè)堆棧地址。方法是改變狀態(tài)寄存器內(nèi)的狀態(tài)位,使處理器切換到不同的狀態(tài),讓后給SP賦值。注意:不要切換到User模式進(jìn)行User模式的堆棧設(shè) 置,因?yàn)檫M(jìn)入U(xiǎn)ser模式后就不能再操作CPSR回到別的模式了,可能會(huì)對(duì)接下去的程序執(zhí)行造成影響。 這是一段堆棧初始化的代碼示例,其中只定義了三種模式的SP指針: MRSR0,CPSR BICR0,R0,#MODEMASK安全起見,屏蔽模式位以外的其他位 ORRR1,R0,#

30、IRQMODE MSRCPSR_cxfs,R1 LDRSP,=UndefStack ORRR1,R0,#FIQMODE MSRCPSR_cxsf,R1 LDRSP,=FIQStack ORRR1,R0,#SVCMODE MSRCPSR_cxsf,R1 LDRSP,=SVCStack 4.初始化有特殊要求的端口,設(shè)備 5.初始化應(yīng)用程序執(zhí)行環(huán)境 映 像一開始總是存儲(chǔ)在ROMFlash里面的,其RO部分即可以在ROMFlash里面執(zhí)行,也可以轉(zhuǎn)移到速度更快的RAM中執(zhí)行;而RW和ZI這兩部 分是必須轉(zhuǎn)移到可寫的RAM里去。所謂應(yīng)用程序執(zhí)行環(huán)境的初始化,就是完成必要的從ROM到RAM的數(shù)據(jù)傳輸和內(nèi)容

31、清零。 下面是在ADS下,一種常用存儲(chǔ)器模型的直接實(shí)現(xiàn): LDRr0,=|Image$RO$Limit|;得到RW數(shù)據(jù)源的起始地址 LDRr1,=|Image$RW$Base|;RW區(qū)在RAM里的執(zhí)行區(qū)起始地址 LDRr2,=|Image$ZI$Base|;ZI區(qū)在RAM里面的起始地址 CMPr0,r1;比較它們是否相等 BEQ%F1 0CMPr1,r3 LDRCCr2,r0,#4 STRCCr2,r1,#4 BCC%B0 1LDRr1,=|Image$ZI$Limit| MOVr2,#0 2CMPr3,r1 STRCCr2,r3,#4 BCC%B2 程序?qū)崿F(xiàn)了RW數(shù)據(jù)的拷貝和ZI區(qū)域的清零功

32、能。其中引用到的4個(gè)符號(hào)是由鏈接器第一輸出的。 |Image$RO$Limit|:表示RO區(qū)末地址后面的地址,即RW數(shù)據(jù)源的起始地址 |Image$RW$Base|:RW區(qū)在RAM里的執(zhí)行區(qū)起始地址,也就是編譯器選項(xiàng)RW_Base指定的地址 |Image$ZI$Base|:ZI區(qū)在RAM里面的起始地址 |Image$ZI$Limit|:ZI區(qū)在RAM里面的結(jié)束地址后面的一個(gè)地址 程 序先把ROM里|Image$RO$Limt|開始的RW初始數(shù)據(jù)拷貝到RAM里面|Image$RW$Base|開始的地址,當(dāng)RAM這邊的目 標(biāo)地址到達(dá)|Image$ZI$Base|后就表示RW區(qū)的結(jié)束和ZI區(qū)的開始,

33、接下去就對(duì)這片ZI區(qū)進(jìn)行清零操作,直到遇到結(jié)束地 址|Image$ZI$Limit| 6.改變處理器模式 因?yàn)樵诔跏蓟^程中,許多操作需要在特權(quán)模式下才能進(jìn)行(比如對(duì)CPSR的修改),所以要特別注意不能過早的進(jìn)入用戶模式。 內(nèi)核級(jí)的中斷使能也可以考慮在這一步進(jìn)行。如果系統(tǒng)中另外存在一個(gè)專門的中斷控制器,這么做總是安全的。 7.呼叫主應(yīng)用程序 當(dāng)所有的系統(tǒng)初始化工作完成之后,就需要把程序流程轉(zhuǎn)入主應(yīng)用程序。最簡(jiǎn)單的一種情況是: IMPORTmain Bmain 直接從啟動(dòng)代碼跳轉(zhuǎn)到應(yīng)用程序的主函數(shù)入口,當(dāng)然主函數(shù)名字可以由用戶隨便定義。 在ARMADS環(huán)境中,還另外提供了一套系統(tǒng)級(jí)的呼叫機(jī)制。

34、IMPORT_main B_main _main()是編譯系統(tǒng)提供的一個(gè)函數(shù),負(fù)責(zé)完成庫(kù)函數(shù)的初始化和初始化應(yīng)用程序執(zhí)行環(huán)境,最后自動(dòng)跳轉(zhuǎn)到main()函數(shù)。ARM中B _Main和B Main的區(qū)別轉(zhuǎn)第一種答案如下: 在軟件仿真的情況下,執(zhí)行“B _main”指令,能使程序跳到C文件的main函數(shù),但用硬件仿真時(shí),還沒執(zhí)行到main函數(shù)時(shí)就進(jìn)入了異常中斷。 原因是執(zhí)行“B _main”指令后,程序先跳到_main庫(kù)函數(shù)的入口,再進(jìn)行一些初始化操作,最后再跳入用戶的main函數(shù)。但在初始化過程中,由于堆?;蚱渌?因造成程序出錯(cuò)。有兩種方法可以解決這個(gè)問題。第一:將“B _main”指令直接改

35、成“B main”,使程序不進(jìn)行初始化而直接跳入用戶的main()函數(shù)。第二:合理初始化堆棧。由于考慮到剛接觸ARM和將問題簡(jiǎn)單化,我選擇了第一種方法。第二種答案如下:IMPORT _main. .BL TargetResetInitB _main1、此后流程將跳轉(zhuǎn)到ADS提供的啟動(dòng)代碼_main函數(shù)處,負(fù)責(zé)完成庫(kù)函數(shù)的初始化及相關(guān)功能,并最終引導(dǎo)處理器入口用戶代碼main()函數(shù),其代碼流程為:嵌入式系統(tǒng)在進(jìn)入應(yīng)用主程序之前必須有一個(gè)初始化的過程,該過程完成系統(tǒng)的啟動(dòng)和初始化功能,初始化過程可以分成兩部分來看: _main負(fù)責(zé)設(shè)置運(yùn)行映像存儲(chǔ)器映射; _rt_entry負(fù)責(zé)庫(kù)函數(shù)的初始化。_

36、main完成代碼和數(shù)據(jù)的復(fù)制,并把ZI數(shù)據(jù)區(qū)清零,這一步當(dāng)代碼和數(shù)據(jù)區(qū)在存儲(chǔ)和運(yùn)行時(shí) 處于不同的存儲(chǔ)器位置時(shí)有意義。接著_main跳進(jìn)_rt_entry,進(jìn)行STACK和HEAP等的初始化。最后_rt_entry跳進(jìn)應(yīng)用程序的入口 main()。當(dāng)應(yīng)用程序執(zhí)行完時(shí),_rt_entry又將控制權(quán)交還給C庫(kù)函數(shù),函數(shù)main()在ADS中有特殊的意義。當(dāng)一個(gè)程序工程項(xiàng)目中存在 main()時(shí),連接器會(huì)把_main和_rt_entry中的初始化代碼連接進(jìn)來;如果沒有main()函數(shù),初始化過程就不會(huì)被連接,初始化過程中一 些標(biāo)準(zhǔn)的C庫(kù)函數(shù)失效。而用戶應(yīng)用程序初始化過程并未顯式的完成這些堆棧初始化及數(shù)

37、據(jù)拷貝操作,應(yīng)用程序?qū)?dòng)不成功。2、_main()為編譯系統(tǒng)提供的一個(gè)庫(kù)函數(shù),使用_main標(biāo)號(hào)引導(dǎo)系統(tǒng)時(shí)必須將應(yīng)用程序的入口數(shù)定義為main();3、若希望系統(tǒng)進(jìn)入應(yīng)用程序前自動(dòng)完成系統(tǒng)調(diào)用(如庫(kù)函數(shù)的初始化、RW、ZI數(shù)據(jù)從 Flash到RAM的拷貝(加載映像-執(zhí)行映像)等)的初始化過程,必須使用_main標(biāo)號(hào)以跳至ADS提供的初始化函數(shù)庫(kù),這種情況一般 需做一些庫(kù)函數(shù)移植及重定向問題解決;這一點(diǎn)上,應(yīng)用程序入口必須以main函數(shù)標(biāo)識(shí);4、若所有的初始化步驟都已顯式的完成(如堆棧初始化、加載映像到執(zhí)行映像RW、ZI數(shù)據(jù)的 拷貝等),應(yīng)用程序入口函數(shù)XXXX()可以任意定義(非main,這

38、樣可以避免自動(dòng)鏈接上_main,從而跳過_main),初始化完成后直接 B XXXX即可,這一點(diǎn)上,main()函數(shù)并不具有特殊性;5、若必須的初始化步驟都未顯示的完成,一意孤行的B XXXX,程序運(yùn)行的結(jié)果將不可預(yù)料。一個(gè)典型的例子是:若用戶并未顯示完成加載映像-執(zhí)行映像的數(shù)據(jù)初始化而直接B XXXX,則應(yīng)用程序中所有的全局變量并不會(huì)被預(yù)期的初始化,而所有的ZI變量也不會(huì)被預(yù)期的清零;6、本人在調(diào)試LPC2294 LCD模塊時(shí)才認(rèn)識(shí)到上述第五點(diǎn)(5、)的重要性:程序指令流并沒有錯(cuò),但LCD上顯示的全部是亂碼。我用兩種方法解決了這一bug:(1)將所有的字庫(kù)數(shù)據(jù)定義為const常量,程序運(yùn)行正

39、確;(2)將B Main 修改成B _main接著將應(yīng)用入口改為int main(void) 而非int Main(void),程序也得到正確的執(zhí)行;Initializing memory required by C codeThe initial values for any initialized variables (RW) must be copied from ROM to RAM.All other ZI variables must be initialized to zero. The library initialization code calledat _main per

40、forms the copying and initialization.Using the main functionWhen the compiler compiles a function called main(), it generates a reference to thesymbol _main to force the linker to include the basic C run-time system from the ANSIC library. (The symbol _main is marked as an entry point.)建議和我一樣的初學(xué)者還是乖

41、乖的B _main接著將應(yīng)用入口設(shè)置為main()函數(shù)的好。ARM編程:Scatter文件的編寫、分析scatter基本點(diǎn):1. 編譯后輸出的映像文件中各段是首尾相連的,中間沒有空閑的區(qū)域,它們的先后關(guān)系是根據(jù)鏈接時(shí)參數(shù)的先后次序決定的 armlinker -file1.o file2.o 2. scatter用于將編譯后的映像文件中的特定段加載到多個(gè)分散的指定內(nèi)存區(qū)域3. 有2類域region:執(zhí)行域(execution region,一般是ram區(qū)域)和加載域(load region,一般是rom區(qū)域)4. 加載域:就是編譯之后得到的二進(jìn)制文件燒寫到rom中的這一段區(qū)域,所有的代碼RO、預(yù)

42、定義變量RW、堆棧之類清不清空無關(guān)緊要的大片內(nèi)存區(qū)域ZI,都包括在其中5. 執(zhí)行域:就是把加載域進(jìn)行解壓縮后的樣子。比如:RO沒有變動(dòng)還是在ROM中,RW被移到了SRAM中,而ZI被放置在SDRAM中6. scatter本身并不能對(duì)映像實(shí)現(xiàn)解壓縮,編譯器讀入scatter文件之后會(huì)根據(jù)其中的各種地址生成啟動(dòng)代碼,實(shí)現(xiàn)對(duì)映像的加載,而這一段代碼就 是* (InRoot$Sections)它是_main()的一部分。這就是在匯編啟動(dòng)代碼的最后跳轉(zhuǎn)到_main() 而不是跳向main()的原因之一。7. 起始地址與加載域重合的執(zhí)行域成為root region,* (InRoot$Sections)必

43、須放在這個(gè)執(zhí)行域中,否則鏈接的時(shí)候會(huì)報(bào)錯(cuò)。*(+RO)包含了* (InRoot$Sections),所以如果在root region中用到了*(+RO)可以不再指定* (InRoot$Sections),scatter語法:ROM_LOAD 0x00000000 ROM 0x00000000 0x003FFFFF vectors.o (+RO,+FIRST) * (InRoot$Sections) ; All library sections that must be in a root region *(+RO) SRAM 0x00400000 0x003FFFFF * (+RW,+ZI)

44、SDRAM1 0x41000000 UNINIT stack.o (+ZI) ; stack.s中定義了top_of_stack為長(zhǎng)度為1的space,指定棧頂?shù)刂?SDRAM2 +0 UNINIT heap.o (+ZI) 注解:1. ROM_LOAD是加載域。這里只有一個(gè),也可以有多個(gè)(rom地址不連續(xù)的情況)2. ROM、SRAM、SDRAM1、SDRAM2是執(zhí)行域,有多個(gè)。第一個(gè)執(zhí)行域必須和加載域地址重合,因?yàn)锳RM的復(fù)位地址就是加載域的起始地址(有bootstrap的話加載域址就是bootstrap執(zhí)行完后的跳轉(zhuǎn)地址)3. vectors.o (+RO, +FIRST) 中斷向量表放

45、在最開頭4. ROM 0x00000000 0x003FFFFF; 加載域名 起始地址 最大允許長(zhǎng)度;最大允許長(zhǎng)度也可以省略,但缺點(diǎn)是編譯器不會(huì)檢查段是否溢出和別的段重疊了。起始地址= +0表示緊接著上一段開始的連續(xù)地址。5. * (InRoot$Sections)是復(fù)制代碼的代碼6. UNINT關(guān)鍵字表示不進(jìn)行初始化清零值得注意的是:在一個(gè)scatter文件中,同一個(gè).o文件不能出現(xiàn)2次,即使是在2個(gè)不同的加載域中也不可以,否則會(huì)報(bào)錯(cuò):Ambiguous selectors found for *.o,錯(cuò)誤的例子:LOAD1 0x00000000 EXE1 Init.o LOAD2 0xFF

46、FF0000 EXE2 Init.o 想起了中學(xué)里哲學(xué)課上老師讓解釋為什么人不能兩次踏入同一條河流,當(dāng)年稀里糊涂的寫的答案,老師批了個(gè)大差,回去有沒有補(bǔ)上,今天居然在這里遇到了老問題。推測(cè)是編譯器自動(dòng)生成的scatter載入代碼InRoot$Sections不支持把同一obj搬移2次。這 就帶來一個(gè)問題:如果希望把同一段代碼(如中斷跳轉(zhuǎn)表)載入2份拷貝到不同的地址,咋整?一個(gè)笨辦法是自己寫一段代碼搬移程序來代替編譯器自動(dòng)生成的搬移 代碼,但前提是需要搞懂映像文件的組織,增加了工作量。投機(jī)一點(diǎn)的方法是在makefile中把一個(gè).o文件復(fù)制并重新起一個(gè)名字,然后把它們傳遞給 armlink。另外,

47、猜測(cè)scatter語法可能包含諸如+duplicate之類的關(guān)鍵字來允許同一段的多個(gè)副本,懶得翻ARM手冊(cè),請(qǐng)哪位知情者留 言告知,謝過將程序執(zhí)行到C文件的main函數(shù)我的第一個(gè)實(shí)驗(yàn) 將程序執(zhí)行到C文件的main函數(shù) 實(shí)驗(yàn)?zāi)康?運(yùn)用ADS編寫一個(gè)小程序,使程序能夠從起始的匯編代碼運(yùn)行到C程序的main()函數(shù)(這也可稱作非常簡(jiǎn)單的起動(dòng)代碼),并通過仿真器連接目標(biāo)板,最終能夠在AT91SAM7S64里正確運(yùn)行。 實(shí)驗(yàn)程序和參數(shù)設(shè)置 1連接器的選項(xiàng)設(shè)置 選項(xiàng)設(shè)置如圖2-1所示。因?yàn)樵贏T91SAM7S64中FLASH存儲(chǔ)器的地址是以0x0開始,而SRAM的地址是以0x00200000開始,所以我將

48、下圖中的RO Base和RW Base分別設(shè)置成了0x0和0x00200000。其它設(shè)置請(qǐng)參考有關(guān)書籍。 圖2-1. 選項(xiàng)設(shè)置圖 2啟動(dòng)代碼 在ARM應(yīng)用系統(tǒng)中,芯片復(fù)位后,在進(jìn)入C語言的 main()函數(shù)前,都要執(zhí)行一段啟動(dòng)代碼。該代碼一般都是用匯編語言編寫,用來完成系統(tǒng)運(yùn)行環(huán)境和應(yīng)用程序的初始化,詳情請(qǐng)參考有關(guān)書籍。由于本實(shí)驗(yàn)的 目的很簡(jiǎn)單,就是想讓程序復(fù)位后,進(jìn)入main()函數(shù),所以有些初始化代碼盡量精簡(jiǎn),留下了下述代碼。另外,_main是C語言的內(nèi)部庫(kù)函數(shù),可以在 進(jìn)入用戶main()之前完成內(nèi)部RAM的初始化工作,類似KeilC51中的startup.a51。當(dāng)執(zhí)行完_main這段

49、代碼后,再跳轉(zhuǎn)到 main()函數(shù)。 AREA init,CODE,READONLY CODE32 Mode_USR EQU 0x10 ;CPSR中各種處理器模式對(duì)應(yīng)的控制位 I_Bit EQU 0x80 ;CPSR中的中斷禁止位 F_Bit EQU 0x40 USR_Stack EQU 0x00203000 ;定義RAM的最高地址,無重映射 ENTRY B InitReset ; 0x00 Reset handler undefvec B undefvec ; 0x04 Undefined Instruction swivec B swivec ; 0x08 Software Interru

50、pt pabtvec B pabtvec ; 0x0C Prefetch Abort dabtvec B dabtvec ; 0x10 Data Abort rsvdvec B rsvdvec ; 0x14 reserved irqvec B irqvec ; 0x18 IRQ fiqvec B fiqvec ; 0x1c FIQ InitReset MSR CPSR_c,#Mode_USR | I_Bit | F_Bit ;改成用戶模式且禁止IRQ和FIQ中斷 LDR SP,=USR_Stack IMPORT _main b _main ;跳轉(zhuǎn)到_main執(zhí)行,它位于C運(yùn)行時(shí)庫(kù)中 END 3

51、C語言主函數(shù) 在C語言主函數(shù)中做了一個(gè)死循環(huán),如下述所示。 int main(void) while (1); 四出現(xiàn)的問題與解決方法 當(dāng)完成上述操作后,先用軟件仿真,很快達(dá)到了目的,但將程序通過仿真器在目標(biāo)板運(yùn)行時(shí)出現(xiàn)了下述問題。 1 當(dāng)執(zhí)行單步運(yùn)行時(shí),PC一直停留在0x0處,而且Debug Log窗口中顯示“RDI Warning 00148: Cant set point”。 原因是仿真器在ROM中設(shè)置的斷點(diǎn)數(shù)是有限的,且單步運(yùn)行時(shí)內(nèi)部還要占用斷點(diǎn)。可以使用“Option-Config Processor”打開“Processor Properties-ARM7TDMI”窗口,且按照下圖

52、設(shè)置以關(guān)斷相的斷點(diǎn)。圖222 裝載的代碼與實(shí)踐程序不一樣 原因是由于程序沒有裝載到AT91SAM7S64的 FLASH ROM里,在調(diào)試器中顯示的是FLASH ROM中原先就有的程序。因?yàn)樵谶B接器的選項(xiàng)設(shè)置中,將RO Base和Image entry point指向了0地址,而在AT91SAM7S64的這段空間為FLASH ROM區(qū),而仿真器不能直接將代碼下載到FLASH ROM里。用仿真器只能將代碼下載到AT91SAM7S64的內(nèi)部SRAM里進(jìn)行調(diào)試,必須將ARM Linker-Output-Simple image-RO Base和Image entry point的0,改成SRAM的地址

53、0x002000000。 3在軟件仿真的情況下,執(zhí)行“B _main”指令,能使程序跳到C文件的main函數(shù),但用硬件仿真時(shí),還沒執(zhí)行到main函數(shù)時(shí)就進(jìn)入了異常中斷。 原因是執(zhí)行“B _main”指令后,程序先跳到_main庫(kù)函數(shù)的入口,再進(jìn)行一些初始化操作,最后再跳入用戶的main函數(shù)。但在初始化過程中,由于堆?;蚱渌?因造成程序出錯(cuò)。有兩種方法可以解決這個(gè)問題。第一:將“B _main”指令直接改成“B main”,使程序不進(jìn)行初始化而直接跳入用戶的main()函數(shù)。第二:合理初始化堆棧。由于考慮到剛接觸ARM和將問題簡(jiǎn)單化,我選擇了第一種方法。 五總結(jié) 1 在用仿真器時(shí),必須將程序下載到AT91SAM7S64的內(nèi)部SRAM中,而不是Flash ROM。 2 從匯編代碼進(jìn)入C文件函數(shù)時(shí),可以直接使用C語言中的標(biāo)號(hào)(可參考書中混合編程部分),如執(zhí)行“B main”則直接跳到C語

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論