天天看点

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