keyled代碼請參考我的博客網址:http://my.csdn.net/wfq0624/code/detail/7645
實驗環境
==================================================================================
Keyled實驗
開發板:mini2440 仿真器:Wiggler H-JTAG/HJTAG並口下載調試器 CPU:S3C2440
==================================================================================
Mini2440 Memory 配置:
NAND flash:K9F1208(64M x 8 Bit) 64MByte [0x00000000~0x03FFFFFF]
NOR flash:SST39VF1601(1M x16 Bit) 2MByte [0x0~0x001FFFFF]
SDRAM: HY57V561620 (2pcsX4Banks x 4M x16Bit) 64MByte [0x30000000~0x33FFFFFF]
==================================================================================
實驗內容
本實驗實現對mini2440開發板 led燈和按鍵點燈的操作。
在Build 工具欄---》Select Target 分別選擇下面三種Project Target,即可觀測到實驗結果
代碼完全一樣,三種Project Target對應三種不同的分散加載文件
[注意mini2440開發板上啓動開關選擇Nor Flash啓動]
RuninRAM 將程序下載到SDRAM中調試。
Runinnorflash 運行在norflash中
Two Section 將Keyled.c目標文件定位於地址0x1000處,運行時,搬運此代碼到SDRAM0x30000100執行
==================================================================================
依次點亮4顆LED,循環3次,然後全滅,等待按鍵按下,不同的按鍵點亮不同的燈號。
==================================================================================
[注意] MDK+ Wiggler H-JTAG/HJTAG並口下載調試器的搭配無法直接在MDK環境下調試,必須先將生成的
hex文件,通過H-JTAG代理軟件燒寫到norflash中,再在MDK環境中,啓動調試,即可runinflash單步調試
==================================================================================
實驗原理分析
以比較複雜的兩段加載域分散加載文件Two Section.sct爲例來說明
1.1.1 Two Section.sct分散加載文件解析
可以看出,有兩段加載域LR_ROM1和LR_ROM2,其中LR_ROM1是根域。
S3C2440A.o (RESET, +First):表示將中斷向量所在的段(段名RESET)放在0x0的位置,並且RESET段在S3C2440A.s文件裏。
LR_ROM2裝載域表示將keyled.c所生成的目標文件keyled.o的Code/RO data放在Norflash地址0x1000處,運行域地址在SDRAM中0x30000100處。
所以在運行之前,必須將keyled.o的代碼從Norflash 0x1000 處copy到SDRAM0x30000100處往後存放,因爲本實驗程序使用了MDK自帶的__main()函數,這部分的copy動作,__main()已經幫忙copy了,所以在程序中,根本看不到顯式的copy 代碼,請不要感覺到奇怪。
備註:如對上述還不太理解的,請察看我的博客文章,有幾篇較爲詳細的描述.http://blog.csdn.net/wfq0624
;**********************************************************************
; *** Scatter-Loading Description Filegenerated by uVision ***
;**********************************************************************
; Two Section
LR_ROM1 0x00000000
{
ER_ROM10x00000000 0x00200000
{
S3C2440A.o(RESET, +First)
*(InRoot$$Sections)
.ANY(+RO)
}
RW_RAM10x30050000 0x03000000
{
.ANY(+RW +ZI)
}
RW_IRAM10x40000000 0x00001000 {
.ANY(+RW +ZI)
}
}
LR_ROM2 0x00001000
{
ER_ROM20x30000100 0x00004000
{
keyled.o(+RO)
}
}
1.1.2 Keyled.bin文件分析
可以看出,使用TwoSection.sct分散加載文件能夠生成2個bin文件:ER_ROM1和ER_ROM2,分別對應兩個加載區所生成的二進制文件,ER_ROM1二進制文件必須下載到Norflash 起始地址0x0的位置,而ER_ROM2必須下載到Norflash 起始地址0x1000的位置.
不過生成的Hex文件還是隻有一個,因爲Hex文件本身就是有記錄地址信息的。如果將此Hex文件通過H-Converter轉化成一個bin文件,你會發現ER_ROM2的內容剛好在0x1000處的位置,毫無疑問ER_ROM1內容在0x0處.
1.1.3 Keyled程序堆棧分析
因爲使用了分散加載文件,所以啓動代碼裏一定要使用__user_initial_stackheap()來重新設置堆棧和堆。
與堆棧相關的代碼如下所示(初始化各種模式下SP相關的代碼就不列出來了,請參考源代碼即可):
UND_Stack_Size EQU 0x00000010
SVC_Stack_Size EQU 0x00000008
ABT_Stack_Size EQU 0x00000010
FIQ_Stack_Size EQU 0x00000010
IRQ_Stack_Size EQU 0x00000080
USR_Stack_Size EQU 0x00000400
ISR_Stack_Size EQU (UND_Stack_Size+ SVC_Stack_Size + ABT_Stack_Size + \
FIQ_Stack_Size +IRQ_Stack_Size)
AREA STACK, NOINIT,READWRITE, ALIGN=3
Stack_Mem SPACE USR_Stack_Size
__initial_sp SPACE ISR_Stack_Size
Stack_Top EQU Stack_Mem + ISR_Stack_Size
Heap_Size EQU 0x00000100
AREA HEAP, NOINIT,READWRITE, ALIGN=3
Heap_Mem SPACE Heap_Size
**********************************************************************************
; User Initial Stack & Heap
AREA |.text|, CODE, READONLY
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
__user_initial_stackheap
LDR R0, = Heap_Mem
LDR R1, =(Stack_Mem + USR_Stack_Size)
LDR R2, = (Heap_Mem + Heap_Size)
LDR R3, = Stack_Mem
BX LR
使用了IMPORT __use_two_region_memory,這種方式定義的堆棧和堆分別採用兩個不同存儲區。堆棧採用向下增長,FD類型。
可以看出堆棧段實際分配了0x4B8(1208)Byte空間,堆段分配了0x100(256)Byte空間。
用map文件來印證上述結論
Image Symbol Table
Local Symbols
Symbol Name Value Ov Type Size Object(Section)
HEAP 0x30050060 Section 256 s3c2440a.o(HEAP)
Heap_Mem 0x30050060 Data 256 s3c2440a.o(HEAP)
STACK 0x30050160 Section 1208 s3c2440a.o(STACK)
Stack_Mem 0x30050160 Data 1024 s3c2440a.o(STACK)
Stack_Top 0x30050218 Data 0 s3c2440a.o(STACK)
1.1.4 Keyled.map文件分析
Part1:Section Cross References
S3c2440a.o(STACK) refers (Special) toheapauxi.o(.text) for __use_two_region_memory
比如上面這句話,S3c2440a.o是S3c2440a.s生成的目標文件模塊,(STACK)是文件內定義的一個段,鏈接器把它視爲一個Section輸入節。它引用了模塊heapauxi.o輸入節(.text)裏面的一個全局符號__use_two_region_memory
s3c2440a.o(RESET) refers to __main.o(!!!main) for __main
__main.o(!!!main) refers to rtentry.o(.ARM.Collect$$rtentry$$00000000)for __rt_entry
rtentry2.o(.ARM.Collect$$rtentry$$0000000D)refers to keyled.o(.text) for main
上面這幾個對於程序意義比較重大用戶在啓動代碼s3c2440a.中調用了__main.o模塊中的__main函數,__main又調用了rtentry.o中的__rt_entry函數,最後rtentry2.o又調用了用戶定義的main主函數。
Part2:Adding Veneers to the image
Compiling code for interworking
Part3:Image Symbol Table
Local Symbols
符號表裏的局部符號:包括系統庫內部的局部符號和用戶的局部符號
Global Symbols
符號表裏的全局符號:包括系統庫內部的全局符號和用戶的全局符號
Part4:Memory Map of the image
Image Entry point :0x000001a0è也就是__main()函數的地址
Load Region LR_ROM1 (Base: 0x00000000, Size: 0x000003b4,Max: 0xffffffff, ABSOLUTE)
Execution Region ER_ROM1 (Base: 0x00000000,Size: 0x000003b4, Max: 0x00200000, ABSOLUTE)
Base Addr Size Type Attr Idx ESection Name Object
0x00000000 0x000001a0 Code RO 18 RESET s3c2440a.o
0x000001a0 0x00000008 Code RO 29 * !!!main c_t.l(__main.o)
0x000001a8 0x0000003c Code RO 188 !!!scatter c_t.l(__scatter.o)
0x000001e40x00000028 Code RO 190 !!handler_copy c_t.l(__scatter_copy.o)
0x0000020c 0x0000002c Code RO 192 !!handler_zi c_t.l(__scatter_zi.o)
è可以看出,s3c2440a.o和__main.o都放在該執行域
Execution RegionRW_RAM1 (Base: 0x30050000, Size: 0x00000618, Max: 0x03000000, ABSOLUTE)
Base Addr Size Type Attr Idx E Section Name Object
0x30050000 0x00000060 Zero RW 58 .bss c_t.l(libspace.o)
0x30050060 0x00000100 Zero RW 17 HEAP s3c2440a.o
0x30050160 0x000004b8 Zero RW 16 STACK s3c2440a.o
è可以看出,ZI和堆棧段都放在此執行域
ExecutionRegion RW_IRAM1 (Base: 0x40000000, Size: 0x00000000, Max: 0x00001000, ABSOLUTE)
**** No section assigned to this executionregion ****
è內部RAM沒有存放任何東西,起始可以再分散加載文件中把它刪掉
LoadRegion LR_ROM2 (Base: 0x00001000, Size: 0x00000160, Max: 0xffffffff, ABSOLUTE)
Execution Region ER_ROM2 (Base: 0x30000100,Size: 0x00000160, Max: 0x00004000, ABSOLUTE)
Base Addr Size Type Attr Idx ESection Name Object
0x30000100 0x00000160 Code RO 1 .text keyled.o
è該域放置的是keyled.o文件
Part5:Image component sizes
指出各模塊文件的大小
Code (inc. data):代碼和內聯數據 Size:804+464=1268
RO data:只讀的數據 Size:32+0=32
RW data:可讀寫的數據,存放的是初始化的全局變量和靜態變量 Size:0
ZI data:存放的是未被初始化的全局變量和靜態變量或是初始化爲零的全局變量和靜態變量
Size:1464+96=1560
Code (inc. data) RO Data RW Data ZI Data Debug Object Name
352 12 0 0 0 3031 keyled.o
452 148 0 0 1464 532 s3c2440a.o
----------------------------------------------------------------------
804 160 32 0 1464 3563 Object Totals
0 0 32 0 0 0 (incl. Generated)
0 0 0 0 0 0 (incl. Padding)
----------------------------------------------------------------------
Code (inc. data) RO Data RW Data ZI Data Debug Library Member Name
8 0 0 0 0 68 __main.o
60 8 0 0 0 0 __scatter.o
40 0 0 0 0 0 __scatter_copy.o
44 0 0 0 0 0 __scatter_zi.o
12 0 0 0 0 64 exit.o
6 0 0 0 0 136 heapauxi.o
0 0 0 0 0 0 indicate_semi.o
14 0 0 0 0 0 libinit.o
12 0 0 0 0 0 libinit2.o
12 0 0 0 0 0 libshutdown.o
6 0 0 0 0 0 libshutdown2.o
12 4 0 0 96 68 libspace.o
12 4 0 0 0 68 rt_fp_status_addr_intlibspace.o
0 0 0 0 0 0 rtentry.o
44 4 0 0 0 0 rtentry2.o
8 0 0 0 0 0 rtentry4.o
8 0 0 0 0 0 rtexit.o
12 0 0 0 0 0 rtexit2.o
20 4 0 0 0 60 sys_exit.o
96 0 0 0 0 80 sys_stackheap_outer.o
4 0 0 0 0 68 use_no_semi.o
28 0 0 0 0 80 fpinit.o
----------------------------------------------------------------------
464 24 0 0 96 692 Library Totals
6 0 0 0 0 0 (incl. Padding)
----------------------------------------------------------------------
==============================================================================
Code (inc. data) RO Data RW Data ZI Data Debug
1268 184 32 0 1560 3907 Grand Totals
1268 184 32 0 1560 3907 ELF Image Totals
1268 184 32 0 0 0 ROM Totals
==============================================================================
TotalRO Size (Code + RO Data) 1300 ( 1.27kB)
Total RW Size (RW Data + ZI Data) 1560( 1.52kB)
Total ROM Size (Code + RO Data + RWData) 1300 ( 1.27kB)
==============================================================================