久久ER99热精品一区二区-久久精品99国产精品日本-久久精品免费一区二区三区-久久综合九色综合欧美狠狠

新聞中心

EEPW首頁 > 嵌入式系統 > 設計應用 > ARM開發的問題總結

ARM開發的問題總結

作者: 時間:2016-11-09 來源:網絡 收藏
匯編代碼要注意有些要頂格,有些要加空格,否則編譯會有問題

本文引用地址:http://cqxgywz.com/article/201611/317740.htm

(一)堆的設置問題

在啟動代碼 B__mian指令后,程序沒有跳到main函數處,而是進入了異常中斷。

原因:通過反匯編,可以看到,在執行B__mian指令后,并不是立即跳到main函數處,而是先跳到__main庫函數入口,再執行一些堆棧的拷貝等初始化操作,最后跳到main函數處。出現異常,可能是堆或棧的設置有問題。(在一個例子中發現把堆得起始地址改小就可以了)

(二)ARM在RAM中調試問題

IROM1:0x4000000 0x10000 (必須將IROM1地址設置到RAM空間)

IRAM1:0x4010000 0x8000

RAM.ini 文件中

PC = 0x04000000;

(三)如何指定某段代碼的運行空間

選擇該文件(*.c),鼠標右鍵(options for File *.c)---->Memory Assignment 可指定該文件代碼運行的空間(可以運行在FLASH,也可以指定在RAM)

(四)MDK生成bin文件

可以用ARM自帶的fromelf.exe將*.axf文件轉換成*.bin文件

Options for Target---->user---->run #1----->

C:/Keil/ARM/BIN31/fromelf.exe --bin -o ./output/Axf_To_Bin.bin ./output/Axf_To_Bin.axf

(四)編譯后的代碼含義

Program Size: Code=2356 RO-data=32 RW-data=28 ZI-data=1292

================================================================================

Total RO Size (Code + RO Data) 2388 ( 2.33kB)
Total RW Size (RW Data + ZI Data) 1320 ( 1.29kB)
Total ROM Size (Code + RO Data + RW Data) 2416 ( 2.36kB)

================================================================================

Execution Region RW_IRAM1 (Base: 0x04000000, Size: 0x00000528, Max: 0x00018000, ABSOLUTE)

Base Addr Size Type Attr Idx E Section Name Object

0x04000000 0x0000001c Data RW 89 .data main.o
0x0400001c 0x00000004 PAD
0x04000020 0x00000508 Zero RW 1 STACK str91x.o

Code表示程序代碼量

RO-data 表示固定常量(const 變量)

RW-data 表示初始化常量(char gloab_test =5)

ZI -data 表示未初始化初始化常量,即是零(char gloab_test =0)

燒寫到FALSH的空間:Code + RO Data + RW Data

RAM空間: RW Data + ZI Data

啟動代碼中,顯然有個RW Data 拷貝過程,其實還應該包括初ZI -data 清零過程,堆和棧的初始化過程,這些應該在B__mian指令后實現,只有通過反匯編可以看到

(五)未對齊的數據指針

  C和C++編程標準規定,指向某一數據類型的指針,必須和該類型的數據地址對齊方式一致,所以ARM 編譯器期望程序中的 C 指針指向存儲器中字對齊地址,因為這可使編譯器生成更高效的代碼。

  比如,如果定義一個指向 int 數據類型的指針,用該指針讀取一個字,ARM 編譯器將使用LDR 指令來完成此操作。如果讀取的地址為四的倍數(即在一個字的邊界)即能正確讀取。但是,如果該地址不是四的倍數,那么,一條 LDR 指令返回一個循環移位結果,而不是執行真正的未對齊字載入。循環移位結果取決于該地址向對于字的邊界的偏移量和系統所使用的端序(Endianness)。例如,如果代碼要求從指針指向的地址 0x8006 載入數據,即要載入 0x8006、0x8007、0x8008 和 0x8009 四字節的內容。但是,在 ARM 處理器上,這個存取操作載入了0x8004、0x8005、0x8006 和 0x8007 字節的內容。這就是在未對齊的地址上使用指針存取所得到的循環移位結果。

  因而,如果想將指針定義到一個指定地址(即該地址為非自然邊界對齊),那么在定義該指針時,必須使用 __packed 限定符來定義指針: 例如,

  __packedint *pi; // 指針指向一個非字對其內存地址

  使用了_packed限定符限定之后,ARM 編譯器將產生字節存取命令(LDRB或STRB指令)來存取內存,這樣就不必考慮指針對齊問題。所生成的代碼是字節存取的一個序列,或者取決于編譯選項、跟變量對齊相關的移位和屏蔽。但這會導致系統性能和代碼密度的損失。

  值得注意的是,不能使用 __packed 限定的指針來存取存儲器映射的外圍寄存器,因為 ARM 編譯程序可使用多個存儲器存取來獲取數據。因而,可能對實際存取地址附近的位置進行存取,而這些附近的位置可能對應于其它外部寄存器。當使用了位字段(Bitfield)時, ARM 程序將訪問整個結構體,而非指定字段。

(六) Ro Base設置

鏈接文件選項中,應將映像文件的Ro Base地址設置到映像文件實際運行的起始地址。例如,將Ro Base設置成0x30000000,把它下載到0x0地址開始執行是不正確,必須將該代碼復制到0x30000000起始地址處才能開始正確執行,或者將Ro Base 設置到0x0地址

(七)__irq關鍵字

匯編調用C中斷函數

匯編文件相關代碼(*.s)

IMPORT IRQ_Handler ;不能頂格寫

IRQ_Addr DCD IRQ_Handler

C文件相關代碼(*.c)

__irq void IRQ_Handler (void) {
if (IRQSIG & 0x00000004) { // Timer 0 Interrupt
T0CLRI = 1; // Clear Timer 0 Interrupt
T0_Tick++; // Increment Timer 0 Tick
}
}

“__irq”專門用來聲明IRQ中斷服務程序,如果用“__irq”來聲明一個函數,那么該函數表示一個IRQ中斷服務程序,編譯器便會自動在該函數內部增加中斷現場保護的代碼



關鍵詞: ARM開發問題總

評論


技術專區

關閉