zoukankan      html  css  js  c++  java
  • 【转载】S3C6410移植日记系列

    感受以前看见djyos同志到处发广告,我还批评他不懂宣传,唉,现在看看他的一些笔记,不仅感叹他的执着,可惜最近不见这位老兄了,不知道djyos最近进展如何了?表示关注啊。

    原文链接:http://hi.chinaunix.net/?uid-20582279

    作者:djyos
    
    

    S3C6410移植日记之一

    应深圳友坚科技之邀,这几天要把djyos移植到他们的idea6410上。

        现在发布的是si版本,是以单片机模式运行的,S3C6410这样强劲的cpu,运行si版本,就作为高速单片机用了,所有地址都是按照物理地址一一对应映射。cpu的状态也没有区分内核态和用户态。
    1、中断引擎最初的部分代码在IRQ态(还没决定是否使用FIQ)。
    2、中断引擎的大部分以及用户ISR运行在SVC态。
    3、所有其他代码运行在SYS态。

        移植碰到的第一个问题就是烧录代码到flash的问题,由于廉价的jtag烧录器不支持arm11,我们不能要求用户必须拥有昂贵的仿真烧录工具才能够在idea6410上使用djyos,这样不利于用户使用。

        我的第一个目标,就是弄清楚怎么下载程序的问题,也就是把一个最简单的闪灯程序运行起来,写了几行代码,如下:
        ldr     r0,=0x7f008820
        ldr     r1,=0x1111
        str     r1,[r0]
        ldr     r0,=0x7f008824
        ldr     r1,[r0]
        bic     r2,r1,#3
        orr     r2,r2,#0xc
        bic     r3,r1,#0xc
        orr     r3,r3,#3
    nn:
        str     r2,[r0]
        ldr     r4,=5000000
    delay1:
        sub     r4,r4,#1
        cmp     r4,#0
        bne     delay1
        str     r3,[r0]
        ldr     r4,=5000000
    delay2:
        sub     r4,r4,#1
        cmp     r4,#0
        bne     delay2
        b       nn


        6410的手册上说,可以从nandflash、onenand、SD卡启动,没有专用的烧录工具的情况下,只有SD卡启动是可以考虑的。手册上看到,SD卡启动,实际上是先执行片内IROM中的一段程序,该程序从SD卡中读取代码,写到stepping stone中,stepping stone是位于0x0c000000、size为8K的片内内存,代码写入stepping stone后,跳到0x0c000000处继续执行程序。那么,要实现从SD卡启动,就必须弄清楚:
    1、8K的代码保存在SD卡的什么位置。
    2、代码以什么格式存储。

        为弄清楚上述问题,依例google一番,没找到有用的资料,上三星的网站,6410的资料没有公开,申请了一下,第二天得到了批准,也没有关于怎样从SD卡启动的资料。找三星代理,似乎不太爱搭理我,也是,我势单力薄一个人,他们怎看得上眼。难道就没有办法了?

        山穷水尽疑无路,柳暗花明又一村,2450不是也可以从SD卡启动吗?找找2450的资料看有没有,谢天谢地,从网上找到一篇文档:
    896554S3C2450_IROM_ApplicationNote_Rev003.pdf
    我如获至宝,细细读之,虽然写得不太细,比如代码校验算法等都没有讲,总是可以试一下了。

        依葫芦画瓢,把编译好的代码写入到最后芯片末尾偏移-9216字节处,插入SD卡座,把开关拨到SD0卡启动的位置,上电,哈哈,成功了,几个蓝色的LED欢快地闪烁起来。试了两个SD卡,16M的可以,2G的不行,不知何故,暂且放一边吧。

        首战告捷,该歇歇了,待续。

    S3C6410移植日志之二

        上篇说道,用16M的SD卡启动可以,但用2G的卡却不行,反复试过,实在不知道怎么回事,也没有IROM中的加载程序的进一步资料,问题也就无从查起了,暂且先放一边,把后续的移植工作做完再说吧。

        移植操作系统,跟开发裸奔程序是不一样的,裸奔程序可以从main开始写程序,在执行main之前,编译器产生了大量的代码用于初始化cpu、内存清零、初始化堆和栈、直到建立main的执行环境。而操作系统往往有自己的运行环境要求,C编译器完成的这些环境往往不能符合要求,需要自己写初始化文件,即initcpu.s文件。

        初始化文件主要完成以下工作:
    1、从复位地址跳转到启动地址。
    2、设置cpu为特权模式,禁止看门狗和中断,禁止cache。
    3、设置时钟,有些cpu的时钟设置很复杂的,尤其是高速cpu,因为涉及到内核和外设匹配的问题,设置起来比较麻烦。
    4、设置内存总线,设置内存访问速度,要跟上一步的时钟设计配合,使cpu能正确读写内存和内存映射的外设。
    5、配置cache和mmu,然后使能cache和mmu。
    6、初始化栈,跳转到C代码。

        根据拿来主义的原则,写cpu初始化代码千万不能自己从0开始写,而是要找一个现成的来参考,因为各个系统的cpu初始化工作是大同小异的。而且,许多cpu厂商都会出example,会带一个文件名类似startup.s的文件,参考该文件来写即可。但是,三星不知从何年何月开始不公开其cpu的文档了,甚至连datasheet都要申请才给。当我千辛万苦找到三星提供的“6410_Test_Rev01”源代码包时,心都凉了,该代码包中虽然有start.s文件,但文件中只有几条指令,初始化过程都在"__rt_entry“函数中,而该函数在库中。对芯片应用资料的保密工作做得如此周密,不知三星所谋何事。

        没办法,继续找,实在不行再自己一行行写。好在天无绝人之路,终于在友坚提供的wince的eboot代码中,找到了eboot的start.s文件,打开一看,果然是一个详细的启动文件,心中不禁狂喜!

        接下来的工作,就是对照datasheet,看懂这个start.s,然后改造成适合djyos的。别看说的轻巧,这里面工作量还是很大的,6410的datasheet有1300多页,光时钟和总线配置相关的部分就有100多页,E文的,晕死。而且第一次用arm11,其mmu和cache配置和arm9有多大差别,还不可知。今天先写到这里,下回分解吧。

    S3C6410移植日志之三

    接续上回,开始啃start.s,跟所有的启动文件一样,开始部分是关闭cache、禁止中断等,没什么问题。这里稍稍解释一下为什么要做这些工作,禁止中断大家应该没什么异议,关键是为什么一定要禁止cache,原来,我们不知道程序为什么要重新启动,也不知道重新启动前cpu和cache处于什么状态,cache可能包含错误的信息,cpu可能会从中取得错误的指令,从而不能正常启动系统。eboot的start.s遗漏了一个很重要的过程,就是要重新把cpu设置成svc状态,因为就像我们不了解重启动前cache状态一样,cpu的状态也是未知的,须加上这几句确保cpu处于svc态:
        mrs     r0,cpsr                 @取CPSR
        bic     r0,r0,#MODEMASK         @清模式位
        orr     r1,r0,#SVCMODE|NOINT    @设置为管理态,并禁止中断
        msr     cpsr_cxsf,r1            @切换到管理态,可防止意外返回0地址时出错.
        实际上,这几句仍然不够保险,因为如果程序是从user态直接跳转到0地址的话,mrs和msr指令是无效的。保险的做法是用swi指令强制修改,既然是个简易的bootloader程序,暂且偷懒一下。
        依惯例,接下来是各种时钟初始化,S3C6410的时钟结构比较复杂,共有3个pll要设置,而且分频控制也较为复杂,虽然start.s有得抄,但还是要自己弄清楚,因为接下来的编程用得上。6410的时钟部分之所以如此复杂,完全是为了适应其内部丰富的外设,不同的外设需要不同的时钟。设置时钟,不外乎就是定义几个常用的主频,然后分别为这些主频定义锁相环(pll)的分频系数,再把这些分频系数填充到相应的寄存器中去,细节就不再赘述了,看代码吧。 
       初始化完时钟后,就轮到初始化内存总线了。依据用什么初始化什么的原则,这里只初始化了srom0和dram两个区域,这部分代码是用C语言实现的,参见memcfg.c文件,代码比较简单,不过是按照datasheet的要求,依次设置寄存器而已。
        接下来,你一定会想到,该初始化mmu了,初始化mmu本来是一项复杂的工作,但si版本是为单片机准备的,即使6410再强劲,也只能委屈一下,当高速单片机了。mmu在这里并没有用来做地址变换,而是把4G内存空间全部映射到其物理地址上了。这种映射效果跟禁止mmu是一样的,但是arm的mmu和cache是绑定在一起的,禁止mmu的同时也就禁止了cache,故只能打开mmu。页表的地址在0x50000000,占用16Kbytes,故应用程序的起始地址是0x50004000。
        又可以偷懒了,6410的核是arm11jzf-s的,2440的核是arm920T的,arm11jzf-s的mmu功能比arm920t的强很多,但都是arm公司的,做最简单映射的话,能否兼容呢?懒得读arm11的手册了,先试一下把2440版本的mmu初始化部分直接copy看行不行。事实证明是可行的,但我在这里绕了一个大大的圈子,浪费了许多时间。加入初始化mmu部分代码后,试了一下,发现灯不闪了,而把该段程序放到初始化页表的代码之前,则可以。仔细检查,发现是因为dram没有初始化,加上dram初始化后,先把闪灯程序放在dram初始化后面,发现可以了。这时候,不幸发生了,移动闪灯程序时,只copy了一半的代码,当然不闪了,可我没仔细检查代码,就怀疑是2440的mmu初始化代码不能用于6410的造成的(偷懒了,心虚),于是找来arm11jzf-s的手册猛啃,几百页的英文资料啊,费了好几天功夫,最后证明了一件事:原来的mmu初始化是正确的!!
        到这里,基本硬件的初始化就算完成了,接下来要搞norflash和uart的driver了。待续……

    S3C6410移植日至之四

        之三讲到,cpu的初始化已经完成,下一步的工作便是初始化uart,使之能够跟PC连接上。
        初始化6410的uart,有两个时钟必须区分清楚,即uartclk和baudclk,前者由系统控制寄存器CLK_SRC和CLK_DIV2控制,手册并没有说明这个时钟的用途,我猜测是用于uart模块本身运行的;另一个时钟是baudclk,用来控制baud,产生串行移位时钟的,在uart模块的控制寄存器UCON中设置,然后用UBRDIV和UDIVSLOT0两个寄存器设置baud。uart的工作方式为:
    baud=115200
    接收和发送fifo:开
    中断:关闭,以查询方式收发。
        接下来是norflash的驱动程序,也就是编写擦除和写入程序,根据am29lv160db的手册写就是了,没什么好说的。除了一些低级错误外,测试也几乎一次成功。
        至此,该轮到xmodem协议收发程序了,xmodem是一个简单的串口收发文件协议,它把文件分成128字节的一个个小包传送,最后一包数据如果不满128字节,则以0x1a填充。该协议是有缺陷的,用来传送文本文件没问题,因为文本文件不会出现0x1a,但传送2进制文件的话,就不行了,因为接收方无法分辨最后的0x1a是文件本身的内容,还是填充物。不过没关系,作为代码,最后多一些垃圾并不碍事,无非就是多占几个字节而已。
        xmodem本来是有差错控制的,通过逐帧应答和校验和(或者CRC)来确保传输正确,不过这里偷了下懒,所有这些都省略了,传错了就再传一次。
        至此,移植到S3C6410的第一步,sdbootloader就制作完成了,接下来就是移植整个操作系统了,sdbootloader的代码在这里下载:
       http://www.djyos.com/download/sdboot6410.zip

    6410的sdbootloader完成了

     sdbootloader说明:
    1、用winhex工具把boot_rom.bin写入SD卡,地址:SD卡末地址-9216。
    2、把开发板的拨码开关拨到从SD卡启动,上电即可。
    2、打开超级终端,用xmodem协议下载程序,保存到dram中。
    3、把下载的代码写入到norflash。
    4、把开发板的拨码开关拨到从norflash启动,复位或重新上电即可。
    5、省去了xmodem帧格式检查、校验和检查。

        但凡开发操作系统,无论是PC、服务器,还是嵌入式操作系统,第一个要解决的就是启动文件的存储问题。无论什么cpu,上电或者复位后,都会从指定的存储位置读取第一条指令予以执行,我们把这个地址成为启动向量,有些cpu可以通过跳线设置不同的启动向量地址。我们熟悉的PC,就是把bios烧录到启动向量处,再由bios逐步引导启动更高级的操作系统,比如windowslinux等。
        在嵌入式行业,以linux为例,linux映像可以通过网口或者其他通信口下载,但你拿到裸机的时候,必须先想办法把uboot或者vivi或者其他bootloader烧录到flash中。djyos也不例外,不同的是,现在发布的si版本的djyos,是没有单独的bootloader的,而是把bootloader的角色集成在可执行影像中了,所以,需要像烧录uboot那样,烧录整个djyos影像。
        在s3c6410之前,djyos发布了arm7(44b0)和arm9(2410和2440)两个版本,得益于廉价的arm7和arm9仿真烧录器,比如hjtag,arm这两个版本是通过hjtag或者jlink或其他工具直接烧录到norflash上的。但s3c6410是arm11的核,这些廉价工具不支持arm11,支持arm11的烧录工具都在数千元以上,这样势必影响大家使用djyos。要让6410执行djyos,必须解决在没有专用烧录工具的情况下,把djyos烧录到启动设备上的问题。
        6410一共支持4种启动设备:norflash、nandflash、SD卡、modem,其中norflash和nandflash必须使用专用烧录工具,modem则需要了解其通信协议,编写相应的PC端应用程序,相比之下,SD卡最为简单,可以用普通的读卡器+winhex工具就可以完成写入。但有一个限制,就是6410启动时只从SD卡中读取8K代码到内部ram中(6410手册第二章说4K,第八章说8K,实测是8K)。读入代码后,程序就跳转到内部ram中执行,这8K程序,只能做一个简易bootloader,用这个bootloader去加载整个操作系统,这时候,就有两种选择:
    1、把程序写到SD卡的其他地方,   但这种方法不现实。SD卡是用nandflash做的, 必然要做ECC校验,那么把代码写入SD卡时,要么用文件系统,但8K代码根本做不了文件系统;要么在PC端用支持ECC的专用写卡工具,可惜没有找到。
    2、用串口下载,这是传统方法,PC端的工具很多,最通用的是超级终端了。
        我们选择了超级终端,xmodem协议下载。
        代码比较简单,说明见“s3c6410移植日志之x”系列,下载源代码:http://www.djyos.com/download/sdboot6410.zip

  • 相关阅读:
    HDU 1018.Big Number-Stirling(斯特林)公式 取N阶乘近似值
    牛客网 Wannafly挑战赛9 C.列一列-sscanf()函数
    牛客网 Wannafly挑战赛9 A.找一找-数据处理
    Codeforces 919 C. Seat Arrangements
    Codeforces Round #374 (Div. 2) D. Maxim and Array 线段树+贪心
    Codeforces Round #283 (Div. 2) A ,B ,C 暴力,暴力,暴力
    Codeforces Round #283 (Div. 2) E. Distributing Parts 贪心+set二分
    Codeforces Round #280 (Div. 2) E. Vanya and Field 数学
    Codeforces Round #280 (Div. 2) D. Vanya and Computer Game 数学
    Codeforces Round #280 (Div. 2) A , B , C
  • 原文地址:https://www.cnblogs.com/gooogleman/p/2102898.html
Copyright © 2011-2022 走看看