天天看點

S3C2440裸機實戰 之一 建立初始工程

S3C2440裸機實戰 之一 建立初始工程

2015-2-3

好幾年沒玩S3C2440,從單片機玩到嵌入式,就記得這個是我入門嵌入式比較早的一款晶片。

S3C2440是帶MMU的,可以上WinCE/Linux這些作業系統,适合做嵌入式開發,做單片機開發的話,總感覺有點浪費,但如果隻是玩玩應該沒問題。

最近業餘時間想把S3C2440拿來當單片機玩玩。

廢話少說,直接入主題。

第一步當然是建立初始工程。

既然是裸機實戰,想玩點什麼特色,看來彙編是不能少的了。ARM9彙編支援的好一點的當然是MDK,IAR的彙編文法和ARM官方的有一些差別,還是算了。

gcc 文法和ARM官方是差不多,不過編譯出來的代碼品質比不過MDK。這裡就選用MDK5.1

單片機的helloworld都是從LED開始,我這裡也不例外,就從Led開始,或者說從GPIO開始。

打開MDK5,如果已經有工程随MDK啟動時打開,就先關閉目前已經打開的工程。

1.建立新工程,要求選擇晶片型号,直接在搜尋框輸入S3C2440A,确認。

MDK會自動加入S3C2440.s啟動檔案,裡面用ARM彙編語言編寫的,對于不太熟悉彙編的童鞋來說,可能看懂還是有點難度。

這裡就先不用去看,直接使用它建立完整工程,否者後面編譯連結通不過。

到後面如果需要加入一些有趣的功能,再回到這個檔案中修改,或者按需要直接重寫。

2.設定

1)Target頁,

    IRAM1 Start 0x40000000 Size 0x1000

    去掉Use Cross-Module Optimization   代碼前期建議不要開優化

    去掉Use mirolib

2) Output頁

     勾上Create HEX File

3)User頁

     勾上 Run #1

    後面填上 fromelf.exe  --bin -o @p.bin @p.axf

 4)後面 Debug和 Unitiily頁按仿真器類型修改,其他頁預設不用修改。

3.初始工程當然還是先完成main函數,那就先建立個main.c的檔案,編寫基本的main函數。

int main(void)
{
    unsigned int a = 0;
    unsigned int b = 1;
    while(1){
        a = b ;
        b = a;
    }
    return 1;
}
           

編寫完後,當然首先想到的是編譯嘛。沒想到一編譯出來各種各樣奇怪的錯誤。

仔細看資訊,發現不是編譯錯誤,而是在連結階段出的錯誤。

好吧,估計是分散加載設定有問題了。

4.編寫分散加載腳本。

點選options for target,也就是工具欄中的設定鍵,到Linker一欄,去掉Use   Memory   Layout   from   Target  Dialog,這樣就可以用

Scatter File,也就是分散加載腳本方式。我個人的習慣是喜歡用分散加載腳本,上面點勾選的是簡單的設定方式,隻能支援比較簡單的分散加載要求。

複雜的分散加載,它就做不了了,分散加載腳本是簡單和複雜通吃。

去掉勾後,系統預設給出早工程檔案的同目錄下的同工程名的分散加載腳本名,點選後面的Edit。

用下面的代碼覆寫它,儲存後,重新全部編譯,通過。

ER_ROM1 0x40000000
{
    ER_ROM1 0x40000000
    {
        *.o (RESET, +First)
        *(InRoot$$Sections)
        * (+RO)
    }     
    
    RW_RAM1 0x40000800
    {
        ;S3C2440.o (MyStacks)
        .ANY (+RW,+ZI)  ; * (+RO)    
    }  

    HEAP +0 UNINIT
    {
        S3C2440.o (Heap)
    }

    STACK 0x40001000 UNINIT
    {
        S3C2440.o (STACK)
    }
}
           

那是不是到這裡就OK了呢,我也不知道,接下來先仿真下。

2015-2-9

5.仿真測試

一仿真才知道出了大問題,ARM的體系,系統棧是滿遞減方式的,是以棧頂不能超過0x40001000,棧底就更不能超了

計算了下棧容量,應該是0x488,看了map檔案,棧頂到了0x40001488,是以腳本要看一下

ER_ROM1 0x40000000
{
    ER_ROM1 0x40000000
    {
        *.o (RESET, +First)
		*(InRoot$$Sections)
        * (+RO)
    }     
	 
    RW_RAM1 0x40000800
    {
        ;S3C2440.o (MyStacks)
        .ANY (+RW,+ZI)  ; * (+RO)	
    }  

    HEAP +0 UNINIT
    {
        S3C2440.o (Heap)
    }

	STACK 0x40000B00 UNINIT
    {
        S3C2440.o (STACK)
    }
}
           

這會編譯下,仿真能進main函數了,但是卻老會重新開機,另外發現CPU跑的是自己之前燒寫到nandflash前4KB的程式,說明仿真時看到的代碼其實是

steppingstone的代碼,且在仿真時,指向第一條指令的位置是0x00000000,而不是0x40000000,看來仿真時仿真期沒有讓PC指向0x40000000,是以仿真時跑的是steppingstone的代碼。

在debug一欄中edit initization file中加上以下代碼,這裡隻是想讓PC直到0x40000000,把初始化時鐘,RAM等去掉,以後需要再加。

既然是裸機實戰,那還是盡量讓代碼來做我們需要的功能,腳本替我們做了初始化工作就沒意思了。當然PC的初始化是沒辦法了,隻能通過腳本來設定,畢竟現在在

nandflash前4KB的代碼還不是我們自己的代碼,不能掌控。

FUNC void SetupForStart (void) {

// <o> Program Entry Point
 PC = 0x40000000;//0x30000000
}


FUNC void Init (void) {

    // Clock Setup 
                                        // FCLK = 300 MHz, HCLK = 100 MHz, PCLK = 50 MHz
//  _WDWORD(0x4C000000, 0x0FFF0FFF);      // LOCKTIME
//  _WDWORD(0x4C000014, 0x0000000F);      // CLKDIVN
//  _WDWORD(0x4C000004, 0x00043011);      // MPLLCON
//  _WDWORD(0x4C000008, 0x00038021);      // UPLLCON
//  _WDWORD(0x4C00000C, 0x001FFFF0);      // CLKCON

}


// Reset chip with watchdog, because nRST line is routed on hardware in a way 
// that it can not be pulled low with ULINK

//_WDWORD(0x40000000, 0xEAFFFFFE);        // Load RAM addr 0 with branch to itself
CPSR = 0x000000D3;                      // Disable interrupts
PC   = 0x40000000;  //0x30000000        // Position PC to start of RAM
//_WDWORD(0x53000000, 0x00000021);        // Enable Watchdog
//g, 0                                    // Wait for Watchdog to reset chip

//Init();                                 // Initialize memory
LOAD project.axf INCREMENTAL         // Download program
SetupForStart();                        // Setup for Running
           

再次仿真,沒有問題了。

好,到此,S3C2440裸機的第一個工程已經差不多完成了。

在仿照CMSIS編寫了外設頭檔案後,再來操作Led。

這裡是借由MKD提供的彙編啟動代碼來做的,懂彙編的童鞋可以自己寫一個彙編啟動,如果不懂也沒什麼,可以照着ARM7的彙編啟動代碼寫,例如LPC213x/214x系列的彙編啟動代碼。

推薦個連結,對MDK提供的S3C2440彙編啟動代碼的解讀:

http://www.oschina.net/question/565065_115207