历史上的今天
返回首页

历史上的今天

今天是:2025年04月26日(星期六)

2019年04月26日 | S3C2440裸机实战 之一 创建初始工程

2019-04-26 来源:eefocus

好几年没玩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) {

 

//

 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

推荐阅读

史海拾趣

BELDEN公司的发展小趣事

在20世纪初,BELDEN公司在技术创新方面取得了显著突破。公司不仅将塑料绝缘材料应用于电线和电缆制造,还着眼于精密和高质量产品的需求,致力于高附加值的绝缘材料、电缆、防护和护套材料的生产。这些技术创新使得BELDEN的产品在性能和质量上都有了显著提升,进一步巩固了公司在市场中的地位。同时,公司还不断扩大产品线,增加了橡胶绝缘材料等多种新产品,满足了不同客户的需求。

East Texas Integrated Circuits公司的发展小趣事

随着ETIC的产品在市场上逐渐获得认可,公司面临着市场拓展的挑战。为了扩大市场份额,ETIC决定进入国际市场。他们首先选择了亚洲市场作为突破口,通过深入了解当地市场需求和竞争环境,制定了一系列有针对性的营销策略。经过几年的努力,ETIC成功地在亚洲市场建立了稳定的客户基础,并逐渐将业务拓展到了欧洲和北美市场。

CLANDELL公司的发展小趣事

CLANDELL公司初创时,市场上已有众多成熟的电子产品制造商。面对激烈的竞争,CLANDELL公司创始人凭借对技术的敏锐洞察和对市场的深入理解,决定专注于研发高性能、高可靠性的电子产品。初创期资金匮乏,但团队凭借对技术的执着和对市场的信念,不断攻克技术难关,逐步在市场上站稳脚跟。

CWIND公司的发展小趣事

随着全球对环保和可持续发展的重视程度不断提高,CWIND公司积极响应这一趋势,将绿色环保理念融入到产品研发和生产过程中。公司投入大量资金和资源,研发出了一系列符合环保标准的电子产品,并优化了生产工艺,减少了废弃物和污染物的排放。这一举措不仅提升了CWIND的品牌形象,还为公司赢得了更多的市场份额。

ebm-papst公司的发展小趣事

在巩固欧洲市场的基础上,ebm-papst不断拓展全球市场,特别是亚洲市场。近年来,公司在亚洲市场的营收增长率一直保持在较高水平。为了进一步拓展亚洲市场,ebm-papst加大了在中国的产能建设,陆续在上海、西安等地进行扩建和新建产能。这些措施使得ebm-papst能够更好地满足亚洲市场的需求,并为其在全球市场的进一步发展奠定了坚实基础。

Benchmarq Microelectronics Inc公司的发展小趣事

在国内市场取得一定成绩后,Benchmarq Microelectronics Inc开始积极拓展国际市场。公司积极参加国际电子展会和交流活动,与国际同行建立合作关系,将产品打入国际市场。同时,公司还加强品牌建设,提升品牌知名度和美誉度。通过广告宣传、媒体报道等多种方式,公司成功塑造了专业、可靠的品牌形象,赢得了客户的信任和认可。

问答坊 | AI 解惑

技术教程:面向汽车应用的线性调整器与开关调整器的比较

多年来,人们一直预测低压差线性调整器(LDO)要退出在汽车领域的应用。但是,LDO调整器持续生存着甚至茁壮成长,因为它们的价格便宜且使用方便。本文中,我将阐述LDO调整器的复杂性,考察市场上的最新进展(确实有一些进展),并分析随着汽车电源需求 ...…

查看全部问答>

DDS的资料和使用程序

DDS芯片AD9851的一些资料和一种做好的模块调试程序…

查看全部问答>

如何选用热继电器、?实际为电机额定电流多少

选用热继电器一般以电机额定电流为准.如电机额定电流为3A,而选择热继电器为1.5~3.5间.设定时以电机的负载为准.如负载比较稳定时,热继电器设定的电流为电机额定电流.如负载波动比较大时可稍微加大些. 如果是电机直接启动开关设备热继电器电流应选 ...…

查看全部问答>

请问rom和bootloader是什么关系?

我公司的开发板上既有rom又有bootloader,我搞不懂这两者的关系了 请各位帮忙解释下好吗?谢谢。…

查看全部问答>

问个WINCE调试的基本方法问题

我在PB5.0中调试单一的工程可以么?就是我不想每次都生成新的系统镜像。就像在VS2005中调试一样,修改代码、F5就开始编译链接、部署、断点,这样就方便多了阿,要不我不是在PB中每次都得从新生成系统镜像了?多麻烦…

查看全部问答>

急需人员加盟

本公司因业务需要,急需招聘WincE开发工程师,待遇从优。有意者请将简历发送至liuyh0105@126.com刘月红收。有IC卡、条形码行业工作经验者优先。电话:010-51265035、68219720、68219760…

查看全部问答>

STM8S103K使用I2C通信经常出错

103K作为从属, 另外一块CPU作为主控, 时钟频率大概200HZ 在103K这边经常会收到错误的地址 但使用逻辑分析仪看波形是正确的 可能是哪里出错了呢?…

查看全部问答>

关于触屏问题!

DK-LM3S9B96第一次搞触屏谁有关于触摸屏的详解! #include \"grlib/widget.h\"           #include \"grlib/canvas.h\"        #include \"grlib/pushbutton.h\" 这几个头文件是啥意思? ...…

查看全部问答>

镁海水燃料电池

由古河电池和日本东北大学合作开发的镁燃料电池实现商业化。 图为Green House公司LED手提灯(内有碳棒和镁金属棒组成镁燃料电池), 加入一次350ml水和16g盐即可提供8小时电力,点亮内置LED灯或通过USB接口为手机充电, 工作120小时后更换内部镁 ...…

查看全部问答>

运放构成的压控恒流源的问题

本帖最后由 paulhyde 于 2014-9-15 03:19 编辑 这是我用OP07构成的简单恒流源,第一个运放是隔离输入端对恒流源的影响,但是发现当负载端接上电阻,无论输入端电压 怎么调,J4端电压都没改变,而且负载电阻变化时,J4端电压变化,达不到恒流源 ...…

查看全部问答>