單片機
返回首頁

S3c2440代碼重定位詳解4---拷貝代碼和鏈接腳本的改進

2021-09-10 來源:eefocus

本節進行拷貝代碼的改進和鏈接腳本的改進。

前面重定位時,需要ldrb命令從的Nor Flash讀取1字節數據,再用strb命令將1字節數據寫到SDRAM里面


cpy:

    ldrb r4, [r1] /*首先從flash讀出一個字節*/ 

    strb r4, [r2] /*讓后把數據寫到SDRAM*/

    add r1, r1, #1

    add r2, r2, #1

    cmp r2, r3

    bne cpy


JZ2440上的Nor Flash是16位,SDRAM是32位。

假設現在需要復制16byte數據,

采用ldrb命令每次只能加載1byte,因此CPU需要發出16次命令,內存控制器每次收到命令后,訪問硬件Nor Flash,因此需要訪問硬件16次;

同理,訪問SDRAM時,CPU需要執行strb 16次,內存控制器每次收到命令后,訪問硬件SDRAM,也要16次,這樣總共訪問硬件32次。


現在對其進行改進,使用ldr從Nor Flash中讀,ldr命令每次加載4字節數據,因此CPU只需執行4次,但由于Nor Flash是16位的,內存控制器每次收到CPU命令后,需要拆分成兩次訪問,因此需要訪問硬件8次;

使用str寫SDRAM,CPU只需執行4次,內存控制器每次收到命令后,直接硬件訪問32位的SDRAM,因此這里只需要4次,這樣總共訪問只需要12次。


在整個操作中,花費時間最長的就是硬件訪問,改進后代碼,減少了硬件訪問的次數,極大的提高了效率。

在這里插入圖片描述

根據上面原理修改代碼,修改start.S


cpy:

ldr r4, [r3]

str r4, [r0]

add r0, r0, #4

add r3, r3, #4

cmp r0, r1

ble cpy

/*清除BSS段*/

mov r0, #0

ldr r1, =bss_start

ldr r2, =bss_end

clear:

str r0, [r1]

add r1, r1, #4

cmp r1, r2

ble clear

bl main


然后編譯燒寫,發現啟動后沒有輸出字符。修改主程序,嘗試以整數格式輸出字符,發現輸出的數從0開始,應該是

全局變量被破壞了

在這里插入圖片描述
在這里插入圖片描述

由上圖可知:


str r0,[r1]    ===> 

把0存在0x30000002地址里面,

由于要4字節對齊,

所以把把0存在0x30000000地址里面.而0x30000000時數據g_char地址,所以破壞了全局變量


屏蔽掉start.S里面的清理命令,測試是否是清除bss段是清除了全局變量。


clean:

    //str r3, [r1] //注釋掉此句話,str不僅把bss段清除,把全局變量這些也清除了

    add r1, r1, #4

    cmp r1, r2

    ble clean


    bl main


屏蔽后,正常輸出,鎖定了問題大致位置。查看反匯編文件,原來是沒有向4取整。

修改鏈接腳本讓bss段,使用ALIGN(4)向4取整。


SECTIONS {

.text 0 : {*(.text)}

.rodata : {*(.rodata)}

.data 0x30000000 : AT(0x700)

{

data_load_addr = LOADADDR(.data);

data_start = . ;

*(.data)

data_end = . ;

}

. = ALIGN(4); 

bss_start = .;

.bss :{*(.bss) *(.COMMON)}

bss_end = .;

}


現在重新編譯燒寫,測試結果正常。

再次查看反匯編文件,發現現在bss段以4字節對齊,清理bss段也是正常的

在這里插入圖片描述

同樣的問題也會出在代碼重定位這里,如何保證data段起始地址也是向4對齊呢?

也是使用ALIGN(4)向4取整


SECTIONS

{

    . = 0x30000000;


    . = ALIGN(4);

    .text      :

    {

      *(.text)

    }


    . = ALIGN(4);

    .rodata : { *(.rodata) }


    . = ALIGN(4);

    .data : { *(.data) }


    . = ALIGN(4);

    __bss_start = .;

    .bss : { *(.bss) *(.COMMON) }

    _end = .;

}


Uboot是裸機的集大成者,可以參考uboot鏈接腳本也是類似的

進入單片機查看更多內容>>
相關視頻
  • TI 新一代 C2000? 微控制器:全方位助力伺服及馬達驅動應用

  • MSP430電容觸摸技術 - 防水Demo演示

  • 直播回放: Microchip Timberwolf? 音頻處理器在線研討會

  • 新唐 8051單片機教程

  • 基于靈動MM32W0系列MCU的指夾血氧儀控制及OTA升級應用方案分享

  • 基于靈動MM32SPIN系列MCU的無感FOC便攜冰箱應用方案分享

    相關電子頭條文章
萝卜大香蕉