1. 程式人生 > >ARM裸板程式的開發和編譯(以點亮LED燈為例)

ARM裸板程式的開發和編譯(以點亮LED燈為例)

製作好交叉編譯工具鏈後,怎麼確定是否有效呢,當然是編譯一個程式燒寫到板上跑一下了。這裡我們以點亮LED燈為例描述如何使用我們製作的交叉編譯工具鏈編譯裸板程式。

首先,需要了解下Nor flash,Nand flash,片內記憶體,片外記憶體,地址空間這幾個概念。其中,Nor flash是CPU可以直接通過硬體訊號讀取的,不需要配置,但是Norflash的寫操作是需要配置和實現驅動的。片內記憶體不需要配置,CPU可以直接通過硬體訊號讀寫。這是因為Nor flash和片內記憶體在硬體設計上就已經固化了他們的電氣特性。而Nand flash的讀寫都必須配置,並且需要實現驅動。CPU通過相應的Nand flash控制器間接的讀寫資料。片外記憶體的讀寫也是需要配置的,通過記憶體控制器進行配置,配置好後CPU就可以發出合適的硬體訊號進行直接讀寫。

        通常,Nor flash,片內記憶體,片外記憶體是統一編址的,他們在CPU的地址空間內,而Nand flash是獨立編址的。原因就是前面的描述,CPU無法直接訪問Nand flash的地址。S3C2440的地址空間如下,注意,不同啟動模式下,片內記憶體(Internal SRAM)的地址是不一樣的。


這裡的地址空間只是儲存器的地址空間,還有CPU內部的暫存器地址空間,這些地址也是可以直接訪問的,同常在高位地址。S3C2440的暫存器地址空間為0x4800000~0x5fffffff。

因為Norflash和片內記憶體不需要配置就可以讀取,因此開發板只能從這兩個地方啟動。具體就是把程式碼燒寫到Nor flash或者Nand flash處,如果在Nand flash,啟動時硬體會自動拷貝程式碼到4KB的內部RAM。GT2440開發板nGCS0接的是Norflash。無論哪種模式啟動,上電後CPU跳轉到0地址處開始執行。如果在片內記憶體中,我們必須用4KB的程式碼完成Nand flash,記憶體控制器的初始化,並且把程式碼搬運到片外記憶體中。如果在Nor flash中,我們同樣需要初始化記憶體控制器。由於裸板程式較小,不會超過4KB,因此我們暫時不需要做這些操作(如果在Norflash中我們可直接執行的程式碼量更大)。

此外,ARM處理器還有多種異常。系統上電和看門狗超時都會產生復位異常,跳轉到0地址處執行。因此如果沒有喂狗程式,我們必須先關閉看門狗,這是裸板程式必須實現的操作。此外,如果我們需要進入C語言程式碼,C語言都是由函式構成的。函式的呼叫需要堆疊,因此我們也要設定堆疊暫存器SP。注意SP必須指向我們當前CPU可以直接讀寫的記憶體(當前只有4KB內部RAM是可以直接讀寫的)。因此如果我們從Nor flash啟動,在沒有設定記憶體控制器前,我們是不能進入C程式碼的。這裡我們將從Nand flash啟動。

        下面,我們開始寫程式碼點亮LED等。GT2440的LED管腳如下:


        我們在彙編程式碼start.s中關閉看門狗,初始化堆疊SP。

.text
.global _start
_start:
	ldr r0,=0x53000000
    mov r1,#0
    str r1,[r0]     /*關閉看門狗*/
    ldr sp,=1024*4  /*不能超過內部ram,sdram還沒有初始化*/
    bl main
loop:
        b loop
        在C程式碼test.c中,我們點亮LED燈。注意GPIO暫存器是CPU內部暫存器,不需要配置即可直接讀寫。
#define GPBCON (*(volatile unsigned int *)0x56000010)
#define GPBDAT (*(volatile unsigned int *)0x56000014)

int main(int argc, char *argv[])
{
    GPBCON = 1 << 10 | 1 << 12 | 1 << 14 | 1 << 16;/*設定LED管腳為輸出模式*/
	GPBDAT = ~(0x1 << 5); /*點亮其中兩盞燈*/

	return 0;
}
Makefile如下:
ARCH=arm
CC=$(ARCH)-linux-gcc
LD=$(ARCH)-linux-ld
OBJCOPY=$(ARCH)-linux-objcopy
led.bin:start.s test.c
	$(CC) -g -c start.s test.c
	$(LD) -Ttext 0x0 -g start.o test.o -o led_elf
#裸板程式,非作業系統環境,必須去除ELF可執行檔案中的作業系統頭部,轉換為二進位制檔案
	$(OBJCOPY) -O binary -S led_elf led.bin
clean:
	rm -rf led.bin led_elf *.o
         為了使我們製作的交叉編譯工具可用,我們還需要設定環境變數。

        source setenv.sh

#!/bin/sh
#指向交叉編譯工具鏈
export PATH=${PATH}:/project/trunk/easyLinux/buildroot/ext/usr/bin
export LD_LIBRARY_PATH=/project/trunk/easyLinux/buildroot/ext/usr/lib

make, 即可得到led.bin。

        把led.bin燒寫到Nand flash中,設定開發板從Nand flash中啟動,我們發現LED燈被成功點亮了。