日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

S3C2440 lds链接脚本解析

發(fā)布時(shí)間:2024/7/23 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 S3C2440 lds链接脚本解析 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. ?SECTIONS到底意味著什么

? ? 在一個(gè)裸版程序里面含有*.lds文件,而lds文件意味著如果你的程序燒錄在nandflash,那在nandflash的內(nèi)存將根據(jù)lds文件指定偏移來分布,下面從不同場景來解釋SECTIONS的內(nèi)容。


2. ?小于4K程序

? ? 若程序小于4K,那程序的整個(gè)重定位地址設(shè)置為0,可以沒有拷貝到sdram的處理。

????uart.lds

SECTIONS {. = 0x00000000;.text : { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4) : { *(.bss) *(COMMON) } }

????head.S

.text .global _start _start:ldr ? ? r0, =0x53000000 ? ? @ WATCHDOG寄存器地址mov ? ? r1, #0x0 ? ? ? ? ? ? ? ? ? ??str ? r1, [r0] ? ? ? ? ? ? ?@ 寫入0,禁止WATCHDOG,否則CPU會不斷重啟ldr ? ? sp, =1024*4 ? ? ? ? @ 設(shè)置堆棧,注意:不能大于4k, 因?yàn)楝F(xiàn)在可用的內(nèi)存只有4K@ nand flash中的代碼在復(fù)位后會移到內(nèi)部ram中,此ram只有4Kbl ? ? ?main ? ? ? ? ? ? ? ?@ 調(diào)用C程序中的main函數(shù) halt_loop:b ? ? ? halt_loop

????Nandflash其內(nèi)存結(jié)構(gòu)如下:


????一開始運(yùn)行之前,默認(rèn)會從NandFlash拷貝4K大小的程序代碼到芯片片內(nèi)內(nèi)存上面并且從0開始執(zhí)行,由于片內(nèi)內(nèi)存只有4K,所以鏈接腳本只適用于程序運(yùn)行空間小于4K的情況。


3. 大于4K程序

????若要支持程序大于4K,就需要考慮將程序拷貝到sdram中運(yùn)行,修改head.s文件,添加從片內(nèi)內(nèi)存拷貝到Sdram的操作,同時(shí)鏈接腳本設(shè)置重定位地址為0x30000000。

???uart.lds

SECTIONS {. = 0x30000000;.text : { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4) : { *(.bss) *(COMMON) } }

????head.S

.extern main .text .global _start _start: Reset: ldr sp, =4096 bl disable_watch_dog bl clock_init bl memsetup bl nand_initldr r0, =0x30000000 mov r1, #0 mov r2, #(1024*10) bl nand_read ldr pc, =on_sdram onsdram:ldr sp, =0x34000000 ldr lr, =halt_loop ldr pc, =main halt_loop:b halt_loop

? ? 此時(shí)NanFlash和Sdram內(nèi)存分布如下:


? ? 當(dāng)重定位0x30000000后,其內(nèi)存的指令碼后會發(fā)生什么變化呢?以main函數(shù)里面,獲取全局變量值為例,

? ? 重定位0x00的時(shí)候:

690: e59f2224 ldr r2, [pc, #548] ; 8bc <main+0x234> 8bc: 000009d4 ldrdeq r0, [r0], -r4 9d4: 00000000 andeq r0, r0, r0

? ? 重定位0x30000000的時(shí)候:

30000690: e59f2224 ldr r2, [pc, #548] ; 300008bc <main+0x234> 300008bc: 300009d4 ldrdcc r0, [r0], -r4 300009d4: 00000000 andeq r0, r0, r0

? ? 三句匯編代碼其作用是獲取全局變量的值,將其放入寄存器r2中??梢钥吹降谝粭l匯編指令碼和第三條匯編指令碼沒有變化,重點(diǎn)分析第二條匯編指令碼,第二條匯編指令碼實(shí)際上是第一條匯編寄存器尋址偏移, [pc, #548]的值需要找8bc或300008bc偏移的匯編指令,而其匯編指令又指向0x9d4或0x300009d4偏移,最終獲取在其偏移的內(nèi)容。由此推想若重定位到0x00,當(dāng)執(zhí)行到main函數(shù)時(shí),會導(dǎo)致執(zhí)行地址還在片內(nèi)范圍,假設(shè)9d4大于4K,則尋址大于片內(nèi)內(nèi)存4K,程序就會溢出。所以鏈接腳本需要設(shè)置重定位地址為0x30000000。


5. 大于4K程序并支持中斷

? ? 當(dāng)需要支持中斷時(shí),head.S需要加上中斷向量表,如下:

@****************************************************************************** @ File錕斤拷head.S @ 錕斤拷錕杰o拷錕斤拷錕斤拷SDRAM錕斤拷錕斤拷錕斤拷錕斤拷錕狡碉拷SDRAM錕斤拷然錕斤拷錕斤拷錕斤拷SDRAM錕斤拷錕斤拷執(zhí)錕斤拷 @****************************************************************************** .extern main .text .global _start _start: @****************************************************************************** @ 中斷向量,本程序中,除Reset和HandleIRQ外,其它異常都沒有使用 @******************************************************************************b Reset@ 0x04: 未定義指令中止模式的向量地? HandleUndef:b HandleUndef@ 0x08: 管理模式的向量地址,通過SWI指令進(jìn)入此模式 HandleSWI:b HandleSWI@ 0x0c: 指令預(yù)取終止導(dǎo)致的異常的向量地址 HandlePrefetchAbort:b HandlePrefetchAbort@ 0x10: 數(shù)據(jù)訪問終止導(dǎo)致的異常的向量地址 HandleDataAbort:b HandleDataAbort@ 0x14: 保留 HandleNotUsed:b HandleNotUsed@ 0x18: 中斷模式的向量地址b HandleIRQ@ 0x1c: 快中斷模式的向量地址 HandleFIQ:b HandleFIQReset: ldr sp, =4096 @ 錕斤拷錕斤拷棧指錕誡,錕斤拷錕鉸訛拷錕斤拷C錕斤拷錕斤拷錕斤拷錕斤拷錕斤拷前錕斤拷要錕斤拷錕秸�bl disable_watch_dog @ 錕截憋拷WATCHDOG錕斤拷錕斤拷錕斤拷CPU錕結(jié)不錕斤拷錕斤拷錕斤拷bl clock_init @ 錕斤拷錕斤拷MPLL錕斤拷錕僥憋拷FCLK錕斤拷HCLK錕斤拷PCLKbl memsetup @ 錕斤拷錕矯存儲錕斤拷錕斤拷錕斤拷錕斤拷使錕斤拷SDRAMbl nand_initldr r0, =0x30000000 @1. 鐩爣鍦板潃=0x30000000錛岃繖鏄疭DRAM鐨勮搗濮嬪湴鍧�mov r1, #4096 @2. 婧愬湴鍧� = 4096錛岃繛鎺ョ殑鏃跺�欙紝main.c涓殑浠g爜閮藉瓨鍦∟AND Flash鍦板潃4096寮�濮嬪mov r2, #(1024*20) @3. 澶嶅埗闀垮害= 1024(bytes)錛屽浜庢湰瀹為獙鐨刴ain.c錛岃繖鏄凍澶熶簡bl nand_read @璋冪敤C鍑芥暟nand_read_llldr pc, =on_sdram @ 跳到SDRAM中繼續(xù)執(zhí)行 on_sdram:msr cpsr_c, #0xd2 @ 進(jìn)入中斷模式ldr sp, =4096 @ 設(shè)置中斷模式棧指針msr cpsr_c, #0xdf @ 進(jìn)入系統(tǒng)模式ldr sp, =0x34000000 @ 錕斤拷錕斤拷棧指錕斤拷msr cpsr_c, #0x5f @ 設(shè)置I-bit=0,開IRQ中斷l(xiāng)dr lr, =halt_loop @ 錕斤拷錕矯鳳拷錕截碉拷址ldr pc, =main @ 錕斤拷錕斤拷main錕斤拷錕斤拷 halt_loop:b halt_loopHandleIRQ:sub lr, lr, #4 @ 計(jì)算返回地址stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器@ 注意,此時(shí)的sp是中斷模式的sp@ 初始值是上面設(shè)置的4096ldr lr, =int_return @ 設(shè)置調(diào)用ISR即EINT_Handle函數(shù)后的返回地址ldr pc, =Uart0_Handle @ 調(diào)用中斷服務(wù)函數(shù),在interrupt.c中int_return:ldmia sp!, { r0-r12,pc }^ @ 中斷返回, ^表示將spsr的值復(fù)制到cpsr

? 此時(shí)需要修改鏈接腳本,若延續(xù)上述寫法,如下:

SECTIONS {. = 0x30000000;.text : { *(.text) }.rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : { *(.data) }.bss ALIGN(4) : { *(.bss) *(COMMON) } }

? ?則會有嚴(yán)重的問題,這時(shí)看head.S生成的匯編指令

Disassembly of section .text:30000000 <_start>: 30000000: ea000006 b 30000020 <Reset>

? ? 第一條指令碼,直接程序跑飛,因?yàn)檫@條指令碼ea000006表示跳轉(zhuǎn)到30000020執(zhí)行,而30000020位于Sdram,還并沒有初始化,所以鏈接腳本應(yīng)該這樣寫:

SECTIONS {. = 0x00000000;.init : AT(0){ head.o init.o nand.o} . = 0x30000000;.text ALIGN(4) : AT(4096) { *(.text) } .rodata ALIGN(4) : {*(.rodata)}.data ALIGN(4) : { *(.data) }__bss_start = .;.bss ALIGN(4) : { *(.bss) *(COMMON) }__bss_end = .; }

? ? 可以看到main函數(shù)的重定位也以0x30000000為基準(zhǔn)。當(dāng)執(zhí)行到main函數(shù)時(shí),此時(shí)能保證在sdram里執(zhí)行,并且也能保證取數(shù)據(jù)段的時(shí)候,能得到偏移哪怕大于4K也能正確的重定位到,看如下main匯編指令碼:

300025a4 <main>: 300025a4: e92d4080 push {r7, lr} 300025a8: e24dd080 sub sp, sp, #128 ; 0x80 300025ac: e3a0207d mov r2, #125 ; 0x7d

? ? 此時(shí)看nandflash和sdram的內(nèi)存分布如下:

????

????

? ??


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的S3C2440 lds链接脚本解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。