在前幾節的開發中,我們一直使用編輯器編輯程序,當程序文件比較多的時候,也不方便管理。本節將嘗試使用keil開發環境編寫S3C2440代碼
一、Keil5安裝
1.1 軟件安裝
Keil5的安裝就不介紹了,自己去網上下載mdk5軟件自行安裝即可,這里我使用的是mdk518a.exe。
安裝完后,記得設置字體編碼:
Edit -> configuration -> Editor
1.2 安裝開發包
MDK5以后的版本不在直接支持arm7、arm9的開發。因此我們需要下載相應的arm7、arm9的軟件支持包。
打開這個網頁 MDK Version 5 - Legacy Support 下載相應的軟件支持包就可以了。截圖如下,注意要選擇自己MDK對應版本的支持包。
下載完成后,雙擊安裝即可。
二、MDK工程建立
2.1 打開Keil,新建一個工程
新建一個工程目錄,用於存放一個工程的所有文件:並且取工程名為4.uart並保存,然后創建工程文件,你可以自己命名為uart:
2.2 選擇型號
接下來選擇CUP database:我們選擇samsung的S3C2440A,點擊OK:
之后會出現第二個圖問你是否拷貝’S3C2440.s’到工程文件夾並加入到工程里,S3C2440.s是啟動代碼我們選擇YES:
如果有興趣的話,你可以看看官方的S3C2440.s啟動程序是如何編寫的。
2.3 設置
然后我們需要對S3C2440.s進行一些必須的配置,打開此文件選擇編輯界面下面的Configuration wizard進行配置,這里我把全部都打上勾,這樣比較保險:
2.4 main.c
之后新建一個c文件並編寫代碼,我習慣新建一個main目錄用來保存這個存放入口函數的文件,然后把這個文件加到工程里:
/*GPIO registers*/ #define GPBCON (*(volatile unsigned long *)0x56000010) #define GPBDAT (*(volatile unsigned long *)0x56000014) void delay(int tim){ while(tim--); } int main(){ /* 清零 */ GPBCON &= ~(0x03 << 10); /* 設置為output */ GPBCON |= (0x01 << 10); while(1){ /* 將 GPB5 輸出低電平 */ GPBDAT &= ~(1<<5); delay(0x100000); /* 將 GPB5 輸出高電平 */ GPBDAT |= (1<<5); delay(0x100000); } return 0; }
2.5 其他設置
如果你需要通過Keil5編譯程序,那你還需要設置Options for Target,具體可以參考keil5(MDK5)配置S3C2440裸機開發調試環境。
由於我只是將Keil作為一個編輯器使用,使用其進行文件管理、語法檢查。並不使用其下載調試功能,就不做其他的配置了。
2.6 修改s3c2440.s文件為start.s
.text .global _start _start: /* 關閉看門狗 */ bl disable_watchdog /* 設置系統時鍾 */ bl system_clock_init /* 初始化棧 */ bl stack_init /* 跳到main函數執行 */ bl main loop: b loop /* 關閉開門狗(關閉門狗中斷,以及看門狗計數器,禁止復位信號輸出) */ #define WTCON 0x53000000 /* 看門狗控制寄存器地址 #define等價於標准匯編里的EQU 用來定義常量 */ disable_watchdog: ldr r0,=WTCON /* 偽指令加載WTCON值到r0 */ mov r1,#0x00 str r1,[r0] /* 把[WTCON]內存單元清零 */ mov pc,lr /* 初始化系統時鍾 FCLK = 400MHz,HCLK = 100MHz, PCLK = 50MHz, UPLL=48MHz */ #define LOCKTIME 0x4c000000 #define MPLLCON 0x4c000004 #define UPLLCON 0x4c000008 #define CLKDIVN 0x4c000014 #define M_MDIV 92 /* @Fin=12M UPLL=400M */ #define M_PDIV 1 #define M_SDIV 1 #define U_MDIV 56 /* @Fin=12M UPLL=48M */ #define U_PDIV 2 #define U_SDIV 2 #define DIVN_UPLL 0 /* FCLK:HCLK:PCLK=1:4:8 */ #define HDIVN 2 #define PDIVN 1 system_clock_init: /* 設置Lock Time */ ldr r0,=LOCKTIME ldr r1,=0xffffffff str r1,[r0] /* 設置分頻系數 */ ldr r0,=CLKDIVN ldr r1,=((DIVN_UPLL<<3) | HDIVN <<1 | PDIVN) str r1,[r0] /* CPU改為異步總線模式 */ mrc p15,0,r1,c1,c0,0 orr r1,r1,#0xC0000000 mcr p15,0,r1,c1,c0,0 /* 設置UPLL */ ldr r0,=UPLLCON ldr r1,=((U_MDIV<<12) | (U_PDIV<<4) | U_SDIV) str r1, [r0] nop nop nop nop nop nop nop /* 設置MPLL */ ldr r0,=MPLLCON ldr r1,=((M_MDIV << 12) | (M_PDIV << 4) | M_SDIV) str r1,[r0] mov pc,lr /* 設置棧 自動分辨是nor flash 啟動還是nand flash啟動 */ /* 先將一個數寫道0地址,然后讀出來判斷跟寫入的值是否一樣;跟寫入的一樣則是nand flash啟動,跟寫入的值不一樣則是nor flash 啟動 */ stack_init: mov r1, #0 ldr r0, [r1] /* 讀出原來的值備份 */ str r1, [r1] /* 0->[0] */ ldr r2, [r1] /* r2=[0] */ cmp r1, r2 /* r1==r2? 如果相等表示是NAND啟動 */ ldr sp, =0x40000000+0x1000 /* 先假設是nor啟動,0x40000000 + 4k處 */ moveq sp, #0x1000 /* nand啟動, 將棧設置在4k處 */ streq r0, [r1] /* 恢復原來的值 */ mov pc,lr
2.7 Makefile
新建Makefile文件:
all:start.o main.o # 鏈接 arm-linux-ld -Ttext 0x00000000 -o main.elf $^ # 轉為bin -S 不從源文件中復制重定位信息和符號信息到目標文件中 arm-linux-objcopy -O binary -S main.elf main.bin # 反匯編 -D反匯編所有段 arm-linux-objdump -D main.elf > main.dis %.o : %.S arm-linux-gcc -g -c $^ %.o : %.c arm-linux-gcc -g -c $^ .PHONY: clean clean: rm *.o *.elf *.bin *.dis
2.8 目錄結構調整
調整項目目錄結構如下圖: