在PROTEUS中使用ARM處理器及uC_第1頁
在PROTEUS中使用ARM處理器及uC_第2頁
在PROTEUS中使用ARM處理器及uC_第3頁
已閱讀5頁,還剩5頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、LPC2124是基于一個支持實(shí)時(shí)仿真和跟蹤的 16/32 位 ARM7TDMI-SC PU的微處理器,并帶有 256k 的嵌入的高速 Flash 存儲器和 16k 的片那靜態(tài) RAM。128 位寬度的存儲器接口和獨(dú)特的加速結(jié) 構(gòu)使得 32 位代碼能夠在最大的時(shí)鐘速率下運(yùn)行。對代碼規(guī)模有嚴(yán)格控制的應(yīng)用可使用 16 位 Thumb模式,將使得代碼規(guī)模降低超過30,而性能的損失卻很小。LPC2124片那 Boot 裝載程序?qū)崿F(xiàn)在系統(tǒng)編程( ISP)和在應(yīng)用編程( IAP)。1ms可以編程 512 字節(jié)。整片擦除只需要 400ms。此外還有 4路 A/D轉(zhuǎn)換器,轉(zhuǎn)換時(shí)間低于 2.24us ;2個 32

2、位 定時(shí)器, 6路 PWM輸出、 RTC、看門狗和多個串行接口。 LPC系列微處理器的抗干擾能力強(qiáng), 在很多應(yīng)用中得到了使用。三軟件分析1 LPC的 Memory Map、 Remap和 LPC2124的 Bootblock 程序Memory Map是把芯片中、芯片外的 Flash 、 RAM、外設(shè)、 BootBlock 等進(jìn)行統(tǒng)一編址,用地址 來表示對象。 LPC系列 ARM處理器的這個地址是出廠時(shí),由廠家規(guī)定的,用戶只能訪問,而 不能進(jìn)行更改。Remap和 Boot ,個人理解如下:在 Reset 信號周期內(nèi), LPC2124 運(yùn)行芯片內(nèi)部自帶的 Bootblock 程序,復(fù)位信號過后才是

3、運(yùn) 行用戶的程序。LPC 系列 ARM 處理器的 Bootblock 被固化在最高的 Flash 塊中,運(yùn)行時(shí)是被映射到 0x7FFFE0000x7FFFFFFF區(qū)域,這個程序是廠家寫入的,它由任何復(fù)位硬件激活,在任何復(fù) 位后都會先執(zhí)行 Boot 裝載程序。之所以要把 BootBlock 程序放在 Flash 塊的頂端, 是因?yàn)楦?芯片的 Flash 大小不一致, 廠家為了 BootBlock 在芯片中的位置固定, 在編址的 2G靠前的位 置虛擬劃分一個區(qū)域作為 BootBlock 區(qū)域。這就是 Remap。BootBlock 的工作如下:1 判斷 P0.14 是否為低,如果為低,進(jìn)入 ISP

4、 模式。2 若 P0.14 不為低,要判斷 Boot(1:0)這兩個腳,如果為 11,要設(shè)置 MEMAP=,1 即運(yùn)行 內(nèi)部 Flash 。否則設(shè) MEMAP 3,運(yùn)行外部 Flash 。3 如果是運(yùn)行外部 Flash ,那需要把外部 Flash 的起始地址重新映射到 0x00000000 ,以便 復(fù)位信號過后就開始運(yùn)行用戶程序。個人理解 BootBlock 相當(dāng)于 PC 中的 BIOS,由廠家固化,上電后首先完成映射,即把它的地 址映射到 0x00000000 處,當(dāng)初始化完成后, 就運(yùn)行內(nèi)部 Flash 或者外部 Flash 的程序, 通常 要以向量表開頭,這個過程就是Remap,也就是把

5、內(nèi)部 ROM或者外部 Flash 的地址映射到0x00000000 處。2啟動代碼分析運(yùn)行完 BootBlock 程序之后就是要運(yùn)行用戶自己編寫的啟動代碼了。啟動代碼中最重要的是 異常向量表。這個表包括復(fù)位、未定義指令、軟中斷、預(yù)取指中止、數(shù)據(jù)中止、 IRQ 中斷和 FIQ 中斷。ResetLDRPC, ResetAddrLDRPC, UndefinedAddrLDRPC, SWI_AddrLDRPC, PrefetchAddrLDRPC, DataAbortAddrDCD0xb9205f80 ;插入用戶代碼有效簽名LDRPC, PC, #-0xff0 ;從 VIC 處取得 IRQ 入口地址L

6、DRPC, FIQ_AddrResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortNouse DCD 0IRQ_Addr DCD 0FIQ_Addr DCD FIQ_HandlerUndefinedB Undefined ; 未定義指令PrefetchAbortB PrefetchAbort ; 取指令中止; 取數(shù)據(jù)中止DataAbortB DataAbort ; 快速中斷未定

7、義指令、 取指令中止、 快速中斷使得 PC不跳轉(zhuǎn), 進(jìn)入死循環(huán), 等待看門狗復(fù)位用戶程序。 對于 ARM,9 有 MMU單元,應(yīng)該在 PrefetchAbort 和 DataAbort 處進(jìn)行處理,然后返回到發(fā)生 異常的指令處重新執(zhí)行一次。FIQ_HandlerSTMFD SP!, R0-R3, LR ;ADS 編譯器會自動保存 R4-R11IMPORT FIQ_Exception ; 也可以在 startup.s 的開頭引入BL FIQ_Exception ; 調(diào)用 C語言中的中斷服務(wù)程序LDMFD SP!, R0-R3, LR ; 出棧SUBS PC, LR, #4如果在 CPSR中沒有禁

8、止中斷, 那么每執(zhí)行一條指令, 處理器會檢查是否有 FIQ 或者 IRQ 中斷 發(fā)生。 若有中斷發(fā)生, 當(dāng)且僅當(dāng) PC指更新后, 即處理器對下一條指令進(jìn)行取指發(fā)生后,處理器才會進(jìn)入到中斷的服務(wù)程序中。因此保存在 LR 中的指是 PC-4,此處的 PC是更新后的 PC, 由于 ARM處理器是三級流水線的結(jié)構(gòu),因此返回地址是LR-4,返回到的地址是將要執(zhí)行,但是被中斷了指令。LDR只能實(shí)現(xiàn)當(dāng)前 PC 4KB范圍內(nèi)的跳轉(zhuǎn),而在 LDR的不遠(yuǎn)處用 DCD定義一個字,而在這個字 里存放最終的異常服務(wù)程序的入口地址,可以實(shí)現(xiàn)在4GB范圍內(nèi)的全范圍跳轉(zhuǎn)。要求整個向量表的累加和為 0 。_user_initi

9、al_stackheap函數(shù)是對用戶的堆棧進(jìn)行初始化, 對它的調(diào)用是在 _main 中完成的,對編程人員不可見。 _main 是 ADS編譯系統(tǒng)提供的一個庫函數(shù), 使用_main 標(biāo)號引導(dǎo)系 統(tǒng)時(shí),必須將應(yīng)用程序的入口定義為 main() 。 _main 完成代碼和數(shù)據(jù)的復(fù)制,并且把 ZI 數(shù) 據(jù)區(qū)清零。這一步當(dāng)代碼和數(shù)據(jù)區(qū)在存儲和運(yùn)行時(shí)處于不同的存儲器位置時(shí)有意義。_main保證了系統(tǒng)在進(jìn)入用戶的應(yīng)用程序前自動完成了系統(tǒng)調(diào)用。但是如果所有的初始化過程都已 經(jīng)被用戶代碼顯式地被完成,如堆棧初始化、加載映象、執(zhí)行映象、RW、 ZI 數(shù)據(jù)的復(fù)制等,那么用戶應(yīng)用程序的入口函數(shù)可以任意定義 any_n

10、ame() ,完成初始化后,直接 B any_name即可。個人建議使用 B _main 的方式,防止疏忽出現(xiàn)不必要的錯誤,比如出現(xiàn)程序中的全局 變量沒有被正確的初始化等錯誤。3.IRQ.S 分析 通過定義宏: $IRQ_Label HANDLER $IRQ_Exception_Function 來實(shí)現(xiàn) LPC 2124 的多個中斷源共用一段異 常處理代碼的目的。SUB LR, LR, #4 ; 計(jì)算返回地址STMFD SP!, R0-R3, R12, LR ; 保存任務(wù)環(huán)境進(jìn)入 IRQ中斷,首先計(jì)算中斷的返回地址,將LR減4,然后將 R0-R3,R12,LR 壓入堆棧。由于進(jìn)入了 IRQ 中

11、斷,因此堆棧指針是 SP_IRQ,和用戶代碼運(yùn)行的 SP_SYS不是同一個寄存器。 至于只保存 R0-R3,R12,是因?yàn)槌绦蛟谡_\(yùn)行過程中,R4-R11 中裝載的是局部變量,在中斷跳轉(zhuǎn)是 ADS編譯器會自動將 R4-R11 入棧保護(hù)。保存狀態(tài) 保存用戶狀態(tài)的 R3,SP,LR, 注意不能回寫PC,的作用是保存用戶模式下的寄存器。此操作的目的是用進(jìn)行了堆棧保護(hù)后, 要保存進(jìn)入中斷之前的 CPSR寄存器, 以保證完成中斷處理后, 使處理器 狀態(tài)和沒有發(fā)生中斷一樣。MRS R3, SPSR ; STMFD SP, R3, SP, LR ; 若 STM的寄存器列表中不包含ADS編譯器會給出響應(yīng)的警

12、告。; 切換到系統(tǒng)模式調(diào)用 c 語言的中斷處理程序C 語言中定義的中斷復(fù)位函數(shù),才能達(dá)到中斷嵌在 uC/OS-II 的環(huán)境下考慮, 因?yàn)?IRQ 中斷發(fā)生之于中斷嵌套。通過定義 IRQ 模式的堆棧深度,可以控制中斷嵌套的深度。分析整段代碼,一 次中斷響應(yīng)需要占用 8個 32bit 的堆棧,定義堆棧深度為 n*8 ,可以允許 n 級中斷嵌套。 此處 操作符不允許回寫,經(jīng)過 AXD仿真驗(yàn)證,回寫操作會寫入 sp_usr 而不是 sp_irq ,此操 作屬于不安全的操作,并且編譯之后, MSR CPSR_c, #(NoInt | SYS32Mode) CMP R1, #1 LDREQ SP, =St

13、ackUsr BL $IRQ_Exception_Function ; 堆棧操作完成之后,切換到系統(tǒng)模式下運(yùn)行 套的目的。 當(dāng)中斷服務(wù)函數(shù)執(zhí)行完畢之后, 退出中斷。后,會改變?nèi)蝿?wù)就緒列表,因此需要在中斷退出時(shí)確定是否需要進(jìn)行任務(wù)切換。這點(diǎn)在下面 的 OS_cpu_a.s 中會涉及到。4 OS_cpu_a.s 分析移植 uC/OS-II ,需要改寫 os_cpu.h , OS_cpu_a.s , OS_cpu_a.c , includes.h 幾個文件。在 LPC 系列的平臺,任務(wù)級的任務(wù)切換和中斷級的任務(wù)切換是通過軟中斷(SWI, SoftwareInterrupt )來完成的。OS_CPU_

14、A.S中包括 SoftwareInterrupt 、OSIntCtxSw 、 OSIntCtxSw_1 和 _OSStartHighRdy 四個函數(shù)。 SoftwareInterrupt 定義了軟件中斷處理方法, OSIntCtxSw 對應(yīng)于中斷級任務(wù)切 換和任務(wù)級任務(wù)切換。而 _OSStartHighRdy 是 uC/OS-II 啟動時(shí)調(diào)用的,調(diào)用新建的優(yōu)先級 最高的任務(wù)。這四個函數(shù)的編寫需要很好的了解ARM7的內(nèi)核結(jié)構(gòu)和完全了解 uC/OS-II 內(nèi)核運(yùn)行的原理。在 SoftwareInterrupt 主要完成寄存器 R0-R3,R12,LR 在 SVC模式( Supervisor )的堆

15、棧中的 保存、取得軟件中斷號并調(diào)用相應(yīng)的處理過程。在 OS_CPU.H中可以找到關(guān)于幾個函數(shù)的軟件中斷定義。任務(wù)級任務(wù)切換函數(shù) */ 運(yùn)行優(yōu)先級最高的任務(wù) */ 關(guān)中斷 */ 開中斷 */_swi(0x00) void OS_TASK_SW(void); /*_swi(0x01) void _OSStartHighRdy(void); /*_swi(0x02) void OS_ENTER_CRITICAL(void) /*_swi(0x03) void OS_EXIT_CRITICAL(void); /*由于 SWI中斷是由指令本身引起的,因此發(fā)生中斷時(shí),PC值并沒有更新,所以計(jì)算中斷返回地址

16、,并不需要將 LR 減 4,LR 指向的就是發(fā)生中斷指令的下一條指令。SWI中斷下堆棧的操作如下指令所示:LDR SP, StackSvc ; 重新設(shè)置堆棧指針STMFD SP!, R0-R3, R12, LR ; 寄存器入棧 ; 軟件中斷處理LDMFD SP!, R0-R3, R12, PC ; 寄存器出棧,返回OS_TASK_SW是任務(wù)級任務(wù)切換函數(shù), 引起 0x00 號軟中斷, 并最終會跳轉(zhuǎn)到 OSIntCtxSw 執(zhí)行, OSIntCtxSw 也是中斷級任務(wù)切換的函數(shù)。對 OSIntCtxSw 的理解, 實(shí)際上是要理解各個任務(wù)的堆棧設(shè)置。 一個任務(wù)正常運(yùn)行, 是運(yùn)行在 user 模式下

17、, 根據(jù) ARM7的體系結(jié)構(gòu), user 模式的所有寄存器和 system 模式下的所有寄存器 使用同一個物理地址。其他模式R13, R14不同物理地址, FIQ 模式 R8-R14 不同物理地址。其他模式相比 user/sys 模式,多一個 SPSR寄存器,用于保存發(fā)生中斷時(shí)的 CPSR的備份。 因 此,當(dāng)發(fā)生任務(wù)切換,需要保存當(dāng)前任務(wù)的所有寄存器,即R0-R14。OSIntCtxSwLDR R2, SP, #20 ;獲取 PC (LR_SVC)LDR R12, SP, #16 ; 獲取 R12MRS R0, CPSR ; 保存當(dāng)前 SVC模式到 R0MSR CPSR_c, #(NoInt

18、| SYS32Mode) ; 切換到系統(tǒng)模式MOV R1, LR ; 保存 LR_sysSTMFD SP!, R1-R2; 保存 LR_sys, PC (LR_SVC)STMFD SP!, R4-R12; 保存 R4-R12MSR CPSR_c, R0 ; 從 R0 中恢復(fù)到 SVC模式LDMFD SP!, R4-R7;獲取 R0-R3,SVC堆棧ADD SP, SP, #8 ;出棧 R12,PC,計(jì)算 SP_SVCMSR CPSR_c, #(NoInt | SYS32Mode) ; 切換到系統(tǒng)模式STMFD SP!, R4-R7; 保存 R0-R3需要注意,執(zhí)行 MSR CPSR_c, #(

19、NoInt | SYS32Mode) 之前的 SP 是指 SP_SVC,而模式切換之 后, SP對應(yīng)于 SP_user 。注意 ADS采用的是滿遞減堆棧。此段代碼的作用是在系統(tǒng)模式下,依次入棧PC,(即 LR_SVC),LR( LR_SYS)R12,R11,R4。然后切換回 SVC模式下出棧 R0-R3,在切換回 SYSTEM模式下入棧 R3,R2, R1,R0。 當(dāng)以上入棧工作完成之后,再保存 OSEnterSum和 CPSR即可完成當(dāng)前任務(wù)的上下文環(huán)境的保 存。LDR R1, =OsEnterSum ; 獲取 OsEnterSumLDR R2, R1STMFD SP!, R2, R3 ;

20、保存 CPSR,OsEnterSum 從上述程序分析可以看出,一個任務(wù)的上下文環(huán)境入棧如下圖所示:當(dāng)任務(wù)的入棧工作完成之后,需要把當(dāng)前的SP_SYS保存到當(dāng)前任務(wù) TCB塊的棧頂指針。LDR R1, =OSTCBCurLDR R1, R1STR SP, R1 至此,任務(wù)的上下文保存工作完成,下面需要進(jìn)行任務(wù)切換。第一步是把就緒列表中最高優(yōu) 先級 OSPrioHighRdy 賦值給 OSPrioCur ,然后把最高優(yōu)先級任務(wù)對應(yīng)的TCBO STCBHighRdy賦值給當(dāng)前任務(wù) TCBO STCBCu。r 之后運(yùn)行到 OSIntCtxSw_1 ,進(jìn)行新任務(wù)的數(shù)據(jù)出棧,切換到新 任務(wù)的運(yùn)行。這里值得

21、一提的是以下兩條語句:ADD SP, R4, #68LDR LR, SP, #-8之所以對于 SP進(jìn)行加 68 的操作,是因?yàn)榇颂幍?SP處理器在系統(tǒng)模式下的堆棧指針, 也就是 uC/OS-II 的用戶程序運(yùn)行的任務(wù)堆棧指針。 即將運(yùn)行的任務(wù)的數(shù)據(jù)在這兩條語句之后會通過 設(shè)置 SVC模式下的堆棧出棧, 然后就將 PC設(shè)置到新任務(wù)的入口處開始運(yùn)行任務(wù)代碼了。 這樣, 我們沒有機(jī)會再修改即將運(yùn)行的任務(wù)的堆棧指針了。若在恢復(fù)任務(wù)之前,不修改SP_SYS,會導(dǎo)致有數(shù)據(jù)壓棧,有數(shù)據(jù)出棧,但是堆棧指針卻一直向棧底方向運(yùn)動,沒有往棧頂方向運(yùn)動 的情況出現(xiàn),任務(wù)長期運(yùn)行,被切換,那么任務(wù)的堆棧會溢出,出現(xiàn)了內(nèi)

22、存泄漏。那么之所 以是 68,是因?yàn)槿蝿?wù)的上下文切換是 17 個寄存器的內(nèi)容,每個寄存器是 32bit ,所以是 68=17*4 。那么 LDR LR, SP, #-8 的原因又是什么呢?為什么在沒有恢復(fù)待運(yùn)行任務(wù)的數(shù)據(jù)之前, 要先恢復(fù)系統(tǒng)模式下的 LR寄存器呢?原因同上, 當(dāng)新任務(wù)運(yùn)行后, 程序再沒有機(jī)會修改系統(tǒng) 模式下的 LR 寄存器了,這樣會導(dǎo)致任務(wù)跑飛。 OSIntCtxSw_1 的最后一句: LDMFD SP!, R0-R12, LR, PC ,恢復(fù)了新任務(wù)。當(dāng)時(shí)仔細(xì)調(diào)試程序會發(fā)現(xiàn), MSR SPSR_cxsf, R5 , 恢復(fù)處理器模式是在把堆棧的數(shù)據(jù)恢復(fù)到 PC 之后才會改變到系

23、統(tǒng)模式下,因此可以得出結(jié) 論, 這里出棧的倒數(shù)第二個數(shù)據(jù), 就是寄存器列表中的 LR,是 SVC模式下的 LR,并不是系統(tǒng) 模式下的 LR。所以,需要在任務(wù)數(shù)據(jù)出棧之前先恢復(fù)LR_SYS。至此,關(guān)于 uC/OS-II 的移植部分的分析全部完畢。至于 OS_CPU_A.C中的一個函數(shù)是初始化 任務(wù)堆棧。值得注意的地方是, ADS 使用的是滿遞減堆棧。因此需要在OS_CPU.H中把OS_STK_GROW設(shè)TH置為 1。四 uC/OS-II 的使用 通過全部閱讀 uC/OS-II 的代碼,個人總結(jié)了一下 uC/OS-II 的核心算法。主要是通過對OSUnMapTbl這張表的讀取,才能確定優(yōu)先級最高的

24、就緒任務(wù)。這張表的編碼規(guī)則是:對應(yīng)偏移量的數(shù)值中, 出現(xiàn)第一個二進(jìn)制” 1”的位置。 由于算出優(yōu)先級最高的任務(wù)是通過查表完成的,因此任務(wù)個數(shù)的多少對于任務(wù)的調(diào)度沒有影響。同樣的道理,對于事件的管理,也是一樣通過 OSUnMapTbl 來完成的。只要理解了這張表,也就理解了OSRdyGrp、OSRdyTbl 和OSEventGrp、OSEventTbl 的使用。 唯一的一點(diǎn)不同在于, 新建任務(wù)的狀態(tài)是: OS_STAT_RD,Y 任務(wù)處于就緒態(tài)。 而新建事件之后, 比如郵箱: 新建一個郵箱調(diào)用 OSMboxCreate 完成, 返回OSMboxPend,通過從對應(yīng)的 uC/OS-II 的書籍上都會介紹,這

溫馨提示

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

評論

0/150

提交評論